diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 306f4d0..5af1801 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -19,6 +19,7 @@ "@inlang/paraglide-sveltekit": "0.15.5", "@kksh/extension": "workspace:*", "@kksh/supabase": "workspace:*", + "@kksh/script-command": "workspace:*", "@kksh/svelte5": "^0.1.15", "@kksh/ui": "workspace:*", "@kksh/utils": "workspace:*", diff --git a/packages/script-command/.gitignore b/packages/script-command/.gitignore new file mode 100644 index 0000000..9b1ee42 --- /dev/null +++ b/packages/script-command/.gitignore @@ -0,0 +1,175 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/packages/script-command/README.md b/packages/script-command/README.md new file mode 100644 index 0000000..48de034 --- /dev/null +++ b/packages/script-command/README.md @@ -0,0 +1 @@ +# script-command diff --git a/packages/script-command/index.ts b/packages/script-command/index.ts new file mode 100644 index 0000000..d5dfe9b --- /dev/null +++ b/packages/script-command/index.ts @@ -0,0 +1,2 @@ +export * from "./src/parser" +export * from "./src/models" diff --git a/packages/script-command/package.json b/packages/script-command/package.json new file mode 100644 index 0000000..7994b90 --- /dev/null +++ b/packages/script-command/package.json @@ -0,0 +1,14 @@ +{ + "name": "@kksh/script-command", + "module": "index.ts", + "type": "module", + "devDependencies": { + "@types/bun": "latest" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "valibot": "1.0.0-rc.2" + } +} diff --git a/packages/script-command/samples/kunkun/bash.sh b/packages/script-command/samples/kunkun/bash.sh new file mode 100755 index 0000000..4f800b3 --- /dev/null +++ b/packages/script-command/samples/kunkun/bash.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Required parameters: +# @kunkun.schemaVersion 1 +# @kunkun.title bash script cmd +# @kunkun.mode fullOutput + +# Optional parameters: +# @kunkun.icon 🤖 + +# Documentation: +# @kunkun.author huakunshen +# @kunkun.authorURL https://raycast.com/huakunshen + +echo "Hello World!" + diff --git a/packages/script-command/samples/kunkun/node.js b/packages/script-command/samples/kunkun/node.js new file mode 100755 index 0000000..cd5abd7 --- /dev/null +++ b/packages/script-command/samples/kunkun/node.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node + +// Required parameters: +// @kunkun.schemaVersion 1 +// @kunkun.title Test Script cmd +// @kunkun.mode compact + +// Optional parameters: +// @kunkun.icon 🤖 +// @kunkun.argument1 { "type": "text", "placeholder": "Placeholder" } +// @kunkun.packageName hahaha +// @kunkun.needsConfirmation true + +// Documentation: +// @kunkun.description describe +// @kunkun.author huakunshen +// @kunkun.authorURL https://raycast.com/huakunshen + +console.log("Hello World! Argument1 value: " + process.argv.slice(2)[0]) + diff --git a/packages/script-command/samples/kunkun/python.py b/packages/script-command/samples/kunkun/python.py new file mode 100755 index 0000000..d14b18b --- /dev/null +++ b/packages/script-command/samples/kunkun/python.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +# Required parameters: +# @kunkun.schemaVersion 1 +# @kunkun.title Test Py Script +# @kunkun.mode compact + +# Optional parameters: +# @kunkun.icon 🤖 +# @kunkun.packageName pypy + +# Documentation: +# @kunkun.description py py py +# @kunkun.author huakunshen +# @kunkun.authorURL https://raycast.com/huakunshen + +print("Hello World!") + diff --git a/packages/script-command/samples/kunkun/ruby.rb b/packages/script-command/samples/kunkun/ruby.rb new file mode 100755 index 0000000..79094f0 --- /dev/null +++ b/packages/script-command/samples/kunkun/ruby.rb @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby + +# Required parameters: +# @kunkun.schemaVersion 1 +# @kunkun.title ruby cmd +# @kunkun.mode fullOutput + +# Optional parameters: +# @kunkun.icon 🤖 + +# Documentation: +# @kunkun.author huakunshen +# @kunkun.authorURL https://raycast.com/huakunshen + +puts "Hello World!" + diff --git a/packages/script-command/samples/raycast/bash.sh b/packages/script-command/samples/raycast/bash.sh new file mode 100755 index 0000000..5fdcbcf --- /dev/null +++ b/packages/script-command/samples/raycast/bash.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Required parameters: +# @raycast.schemaVersion 1 +# @raycast.title bash script cmd +# @raycast.mode fullOutput + +# Optional parameters: +# @raycast.icon 🤖 + +# Documentation: +# @raycast.author huakunshen +# @raycast.authorURL https://raycast.com/huakunshen + +echo "Hello World!" + diff --git a/packages/script-command/samples/raycast/node.js b/packages/script-command/samples/raycast/node.js new file mode 100755 index 0000000..56388db --- /dev/null +++ b/packages/script-command/samples/raycast/node.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node + +// Required parameters: +// @raycast.schemaVersion 1 +// @raycast.title Test Script cmd +// @raycast.mode compact + +// Optional parameters: +// @raycast.icon 🤖 +// @raycast.argument1 { "type": "text", "placeholder": "Placeholder" } +// @raycast.packageName hahaha +// @raycast.needsConfirmation true + +// Documentation: +// @raycast.description describe +// @raycast.author huakunshen +// @raycast.authorURL https://raycast.com/huakunshen + +console.log("Hello World! Argument1 value: " + process.argv.slice(2)[0]) + diff --git a/packages/script-command/samples/raycast/python.py b/packages/script-command/samples/raycast/python.py new file mode 100755 index 0000000..a35347f --- /dev/null +++ b/packages/script-command/samples/raycast/python.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +# Required parameters: +# @raycast.schemaVersion 1 +# @raycast.title Test Py Script +# @raycast.mode compact + +# Optional parameters: +# @raycast.icon 🤖 +# @raycast.packageName pypy + +# Documentation: +# @raycast.description py py py +# @raycast.author huakunshen +# @raycast.authorURL https://raycast.com/huakunshen + +print("Hello World!") + diff --git a/packages/script-command/samples/raycast/ruby.rb b/packages/script-command/samples/raycast/ruby.rb new file mode 100755 index 0000000..6275244 --- /dev/null +++ b/packages/script-command/samples/raycast/ruby.rb @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby + +# Required parameters: +# @raycast.schemaVersion 1 +# @raycast.title ruby cmd +# @raycast.mode fullOutput + +# Optional parameters: +# @raycast.icon 🤖 + +# Documentation: +# @raycast.author huakunshen +# @raycast.authorURL https://raycast.com/huakunshen + +puts "Hello World!" + diff --git a/packages/script-command/src/__tests__/parse.test.ts b/packages/script-command/src/__tests__/parse.test.ts new file mode 100644 index 0000000..0612b20 --- /dev/null +++ b/packages/script-command/src/__tests__/parse.test.ts @@ -0,0 +1,27 @@ +import { describe, expect, test } from "bun:test" +import * as v from "valibot" +import { ScriptCommandConfig } from "../models" +import { parseScriptCommand } from "../parser" + +describe("parseScriptCommand", () => { + test("should parse script command", async () => { + for (const filePath of [ + "./samples/raycast/python.py", + "./samples/raycast/node.js", + "./samples/raycast/ruby.rb", + "./samples/raycast/bash.sh", + // kunkun + "./samples/kunkun/python.py", + "./samples/kunkun/node.js", + "./samples/kunkun/ruby.rb", + "./samples/kunkun/bash.sh" + ]) { + const content = await Bun.file(filePath).text() + const scriptCommand = parseScriptCommand( + content, + filePath.split(".").pop() as "py" | "js" | "ts" | "swift" | "scpt" + ) + expect(v.is(ScriptCommandConfig, scriptCommand)).toBe(true) + } + }) +}) diff --git a/packages/script-command/src/models.ts b/packages/script-command/src/models.ts new file mode 100644 index 0000000..231d03a --- /dev/null +++ b/packages/script-command/src/models.ts @@ -0,0 +1,22 @@ +import * as v from "valibot" + +export const ScriptCommandMode = v.union([ + v.literal("compact"), + v.literal("fullOutput"), + v.literal("inline"), + v.literal("silent") +]) +export const ScriptCommandConfig = v.object({ + scriptPath: v.nullable(v.string()), + schemaVersion: v.optional(v.number(), 1), + title: v.string(), + mode: v.optional(ScriptCommandMode, "fullOutput"), + icon: v.optional(v.string()), + packageName: v.optional(v.string()), + needsConfirmation: v.optional(v.boolean(), false), + description: v.optional(v.string()), + author: v.optional(v.string()), + authorURL: v.optional(v.string()) +}) + +export type ScriptCommandConfig = v.InferOutput diff --git a/packages/script-command/src/parser.ts b/packages/script-command/src/parser.ts new file mode 100644 index 0000000..fb7c0f7 --- /dev/null +++ b/packages/script-command/src/parser.ts @@ -0,0 +1,66 @@ +import * as v from "valibot" +import { ScriptCommandConfig } from "./models" + +/** + * Parse script command from comments of file content + * @param fileContent + * @param fileType + */ +export function parseScriptCommand( + fileContent: string, + fileType: "js" | "py" | "rb" | "sh" | "swift" | "ts" | "scpt" +): ScriptCommandConfig { + const config: any = { scriptPath: null } + + // Split content into lines and process each line + const lines = fileContent.split("\n") + + for (const line of lines) { + // Look for lines containing @raycast. or @kunkun. metadata + if (line.includes("@raycast.") || line.includes("@kunkun.")) { + const trimmedLine = line.trim() + // Remove any comment markers based on file type + const cleanedLine = trimmedLine + .replace(/^#\s*/, "") // Python/Ruby style comments + .replace(/^\/\/\s*/, "") // JavaScript/TypeScript style comments + .trim() + + // Extract parameter name and value, supporting both @raycast and @kunkun + const match = cleanedLine.match(/@(raycast|kunkun)\.(\w+)\s+(.+)/) + if (match) { + const [, prefix, param, value] = match + switch (param) { + case "schemaVersion": + config.schemaVersion = parseInt(value, 10) + break + case "title": + config.title = value + break + case "mode": + config.mode = value as any + break + case "packageName": + config.packageName = value + break + case "icon": + config.icon = value + break + case "description": + config.description = value + break + case "author": + config.author = value + break + case "authorURL": + config.authorURL = value + break + case "needsConfirmation": + config.needsConfirmation = value.toLowerCase() === "true" + break + } + } + } + } + + return v.parse(ScriptCommandConfig, config) +} diff --git a/packages/script-command/tsconfig.json b/packages/script-command/tsconfig.json new file mode 100644 index 0000000..238655f --- /dev/null +++ b/packages/script-command/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} diff --git a/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md b/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md index 43a78fd..0475fc5 100644 --- a/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md +++ b/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md @@ -1,4 +1,3 @@ - ## Permission Table @@ -7,7 +6,6 @@ -
Description
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1e54018..7df7b4d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -335,7 +335,7 @@ importers: version: 8.23.0(eslint@9.21.0(jiti@2.4.0))(typescript@5.6.3) autoprefixer: specifier: ^10.4.20 - version: 10.4.20(postcss@8.4.49) + version: 10.4.20(postcss@8.5.1) bits-ui: specifier: 1.0.0-next.86 version: 1.0.0-next.86(svelte@5.16.6) @@ -769,6 +769,19 @@ importers: specifier: 1.0.0-beta.4 version: 1.0.0-beta.4(valibot@1.0.0-beta.10(typescript@5.7.3)) + packages/script-command: + dependencies: + typescript: + specifier: ^5.0.0 + version: 5.7.3 + valibot: + specifier: 1.0.0-rc.2 + version: 1.0.0-rc.2(typescript@5.7.3) + devDependencies: + '@types/bun': + specifier: latest + version: 1.2.3 + packages/supabase: dependencies: '@kksh/api': @@ -11386,6 +11399,14 @@ packages: typescript: optional: true + valibot@1.0.0-rc.2: + resolution: {integrity: sha512-Tnnp7dydpihvoUbJiaxuYfsCAgAFKuFMex7PTaI25XSjRWkU70DmJPlAO1W6sF1/WUx4RNWyM2hdmBSMIUSZFA==} + peerDependencies: + typescript: '>=5' + peerDependenciesMeta: + typescript: + optional: true + validate-npm-package-name@5.0.1: resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -18156,6 +18177,16 @@ snapshots: postcss: 8.4.49 postcss-value-parser: 4.2.0 + autoprefixer@10.4.20(postcss@8.5.1): + dependencies: + browserslist: 4.24.2 + caniuse-lite: 1.0.30001676 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.5.1 + postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -23678,14 +23709,14 @@ snapshots: tauri-plugin-network-api@2.0.5(typescript@5.7.2): dependencies: '@tauri-apps/api': 2.2.0 - valibot: 1.0.0-beta.11(typescript@5.7.2) + valibot: 1.0.0-beta.12(typescript@5.7.2) transitivePeerDependencies: - typescript tauri-plugin-network-api@2.0.5(typescript@5.7.3): dependencies: '@tauri-apps/api': 2.2.0 - valibot: 1.0.0-beta.11(typescript@5.7.3) + valibot: 1.0.0-beta.12(typescript@5.7.3) transitivePeerDependencies: - typescript @@ -24297,6 +24328,10 @@ snapshots: optionalDependencies: typescript: 5.6.3 + valibot@1.0.0-rc.2(typescript@5.7.3): + optionalDependencies: + typescript: 5.7.3 + validate-npm-package-name@5.0.1: {} validator@13.12.0: