@awak-app/simy-cli 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/package.json +2 -2
- package/src/cli-contract.js +1 -1
- package/src/desktop-host.js +9 -4
- package/src/hook-runtime.js +29 -0
- package/src/login-shell-path.js +67 -0
- package/src/sqm/agent-skill.js +2 -12
- package/src/sqm/claude-plugin.js +2 -4
package/README.md
CHANGED
|
@@ -104,6 +104,10 @@ Detached daemon and desktop-host diagnostics are saved to
|
|
|
104
104
|
(`SIMY_HOME` defaults to `~/.simy`). Each log is limited to 1 MiB plus two
|
|
105
105
|
backups; credentials, Cookie headers and URL queries are redacted. Installer
|
|
106
106
|
handoff diagnostics remain in `~/.simy/installer/desktop-update.log`.
|
|
107
|
+
The macOS window also saves the latest nonzero background-host exit in
|
|
108
|
+
`$SIMY_HOME/logs/desktop-host-exit.log`, including its timestamp, exit status and
|
|
109
|
+
up to 16 KiB of stderr. Credential-bearing lines are omitted; each abnormal exit
|
|
110
|
+
replaces the previous record. This includes failures before JavaScript starts.
|
|
107
111
|
`simy --version` or `simy -v` prints the package version without starting work.
|
|
108
112
|
|
|
109
113
|
Closing the window keeps the agent running. Open the app again or choose
|
|
@@ -188,6 +192,16 @@ checks the bundled CLI in ChatGPT and Codex apps in system and user Applications
|
|
|
188
192
|
Claude discovery likewise falls back to a compatible native or Desktop bundle
|
|
189
193
|
when an older PATH installation cannot meet its version requirement.
|
|
190
194
|
|
|
195
|
+
On macOS and Linux, the desktop host reads the user's interactive login-shell
|
|
196
|
+
PATH once at startup, so providers installed through nvm, Volta or custom prefixes
|
|
197
|
+
can be found from GUI launches, including Finder or the Dock on macOS. Shell paths
|
|
198
|
+
take priority; existing launcher paths remain available. If the five-second shell
|
|
199
|
+
probe cannot read PATH, startup uses the launcher PATH. Windows keeps its existing PATH.
|
|
200
|
+
|
|
201
|
+
Installed Codex and Claude hooks use an absolute Node runtime path. When available,
|
|
202
|
+
the SIMY installer's `current` link or Homebrew's `opt` link replaces a versioned
|
|
203
|
+
runtime path, allowing hooks to follow updates without relying on the provider's PATH.
|
|
204
|
+
|
|
191
205
|
Use `simy delivery activity --watch` for a read-only local snapshot every minute,
|
|
192
206
|
or add `--json` for one JSON object per sample. It separates execution, waits,
|
|
193
207
|
stops, failures and repeated attempts without new verified outcomes, with task
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awak-app/simy-cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Local SIMY executor for non-coding Local Tasks and Agentic Loop runs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"check:workflow-observation-sender": "node --check ./src/workflow-observation-sender.js",
|
|
44
44
|
"check:sqm": "node --check ./src/sqm/canonical.js && node --check ./src/sqm/validation.js && node --check ./src/sqm/reliability.js && node --check ./src/sqm/repository.js && node --check ./src/sqm/checkers.js && node --check ./src/sqm/bundle-store.js && node --check ./src/sqm/proof.js && node --check ./src/sqm/evidence-client.js && node --check ./src/sqm/session.js && node --check ./src/sqm/index.js && node --check ./src/sqm/command.js && node --check ./src/sqm/agent-skill.js && node --check ./src/sqm/workflow-onboarding.js && node --check ./src/sqm/workflow-update.js && node --check ./src/sqm/history-store.js && node --check ./src/sqm/review-worker.js && node --check ./scripts/sqm-complete-loop-e2e.js && node --check ./scripts/sqm-local-review-e2e.js",
|
|
45
45
|
"check:real-provider-syntax": "node --check ./scripts/real-codex-probe.js && node --check ./scripts/real-claude-probe.js && node --check ./scripts/real-provider-console-fixture.js && node --check ./scripts/real-provider-console-e2e.js && node --check ./scripts/claude-parity-runtime-e2e.js && node --check ./scripts/claude-plugin-runtime-e2e.js",
|
|
46
|
-
"check:syntax": "node --check ./src/purpose-local-proof.js && node --check ./src/device-signing-identity.js && node --check ./src/index.js && node --check ./src/install-update.js && node --check ./src/agent.js && node --check ./src/connection-discovery.js && node --check ./src/codex-plugins/simy/hooks/connection-reminder.mjs && node --check ./src/codex-plugins/simy/hooks/dev-work.mjs && node --check ./src/dev-work-events.js && node --check ./src/browser.js && node --check ./src/web-api.js && node --check ./src/durable-local-task-worker.js && node --check ./src/durable-local-task-steps-contract.js && node --check ./src/bounded-local-task-subtasks-contract.js && node --check ./src/bounded-local-task-subtask-pool.js && node --check ./src/local-task-artifact-contract.js && node --check ./src/execution-capability-contract.js && node --check ./src/shutdown.js && node --check ./src/run-registry.js && node --check ./src/direct-executor.js && node --check ./src/execution-guardrail.js && node --check ./src/backend-executable.js && node --check ./src/provider-stream.js && node --check ./src/console/index.js && node --check ./src/console/app.js && node --check ./src/console/commands.js && node --check ./src/local-attachments.js && node --check ./src/repository-inventory.js && node --check ./src/session-store.js && node --check ./src/web-origin.js && node --check ./src/workspace-context.js && node --check ./src/orchestrator/index.js && node --check ./src/orchestrator/shared.js && node --check ./src/orchestrator/recovery.js && node --check ./src/orchestrator/risk.js && node --check ./src/orchestrator/contract.js && node --check ./src/orchestrator/completion-contract.js && node --check ./src/orchestrator/pr-preparation.js && node --check ./src/orchestrator/minimum-completion.js && node --check ./src/orchestrator/delivery/scripts/check-minimum-completion.mjs && node --check ./src/orchestrator/instruction.js && node --check ./src/orchestrator/problem-solving.js && node --check ./src/orchestrator/budget.js && node --check ./src/orchestrator/execution-io.js && node --check ./src/orchestrator/presentation.js && node --check ./src/orchestrator/result.js && node --check ./src/orchestrator/retry.js && node --check ./src/orchestrator/evidence.js && node --check ./src/orchestrator/independent-audit.js && node --check ./src/orchestrator/audit.js && node --check ./src/orchestrator/loop.js && node --check ./src/runner.js && node --check ./src/coding-run-store.js && node --check ./scripts/fixtures/completion-contract-fixture.js && node --check ./scripts/fixtures/fake-coding-backend.js && node --check ./scripts/e2e-terminal-evidence.js && node --check ./scripts/audit-gate-e2e.js && node --check ./scripts/completion-contract-e2e.js && node --check ./scripts/retry-circuit-e2e.js && node --check ./scripts/follow-up-charter-e2e.js && node --check ./scripts/task-routing-e2e.js && node --check ./scripts/executor-version-preflight-e2e.js && node --check ./scripts/blocked-recovery-e2e.js && node --check ./scripts/process-localization-e2e.js && node --check ./scripts/hypothesis-retries-e2e.js && node --check ./scripts/budget-enforcement-e2e.js && node --check ./scripts/local-task-default-workspace-e2e.js && node --check ./scripts/local-task-idempotency-e2e.js && node --check ./scripts/console-e2e-fixture.js && node --check ./scripts/console-e2e.js && node --check ./scripts/console-recovery-e2e-fixture.js && node --check ./scripts/console-recovery-e2e.js && node --check ./scripts/real-provider-console-fixture.js && node --check ./scripts/real-provider-console-e2e.js && node --check ./scripts/fullstack-cli-smoke.js && node --check ./scripts/check-package-contents.js && node --check ./src/codex-plugins/simy/hooks/delivery-loop.mjs && node --check ./src/delivery-hooks/command.js && node --check ./src/delivery-hooks/desktop.js && node --check ./src/delivery-hooks/supervisor.js && node --check ./src/session-supervision/automatic-continuation.js",
|
|
46
|
+
"check:syntax": "node --check ./src/purpose-local-proof.js && node --check ./src/device-signing-identity.js && node --check ./src/index.js && node --check ./src/install-update.js && node --check ./src/agent.js && node --check ./src/connection-discovery.js && node --check ./src/codex-plugins/simy/hooks/connection-reminder.mjs && node --check ./src/codex-plugins/simy/hooks/dev-work.mjs && node --check ./src/dev-work-events.js && node --check ./src/browser.js && node --check ./src/web-api.js && node --check ./src/durable-local-task-worker.js && node --check ./src/durable-local-task-steps-contract.js && node --check ./src/bounded-local-task-subtasks-contract.js && node --check ./src/bounded-local-task-subtask-pool.js && node --check ./src/local-task-artifact-contract.js && node --check ./src/execution-capability-contract.js && node --check ./src/shutdown.js && node --check ./src/run-registry.js && node --check ./src/direct-executor.js && node --check ./src/execution-guardrail.js && node --check ./src/backend-executable.js && node --check ./src/login-shell-path.js && node --check ./src/hook-runtime.js && node --check ./src/provider-stream.js && node --check ./src/console/index.js && node --check ./src/console/app.js && node --check ./src/console/commands.js && node --check ./src/local-attachments.js && node --check ./src/repository-inventory.js && node --check ./src/session-store.js && node --check ./src/web-origin.js && node --check ./src/workspace-context.js && node --check ./src/orchestrator/index.js && node --check ./src/orchestrator/shared.js && node --check ./src/orchestrator/recovery.js && node --check ./src/orchestrator/risk.js && node --check ./src/orchestrator/contract.js && node --check ./src/orchestrator/completion-contract.js && node --check ./src/orchestrator/pr-preparation.js && node --check ./src/orchestrator/minimum-completion.js && node --check ./src/orchestrator/delivery/scripts/check-minimum-completion.mjs && node --check ./src/orchestrator/instruction.js && node --check ./src/orchestrator/problem-solving.js && node --check ./src/orchestrator/budget.js && node --check ./src/orchestrator/execution-io.js && node --check ./src/orchestrator/presentation.js && node --check ./src/orchestrator/result.js && node --check ./src/orchestrator/retry.js && node --check ./src/orchestrator/evidence.js && node --check ./src/orchestrator/independent-audit.js && node --check ./src/orchestrator/audit.js && node --check ./src/orchestrator/loop.js && node --check ./src/runner.js && node --check ./src/coding-run-store.js && node --check ./scripts/fixtures/completion-contract-fixture.js && node --check ./scripts/fixtures/fake-coding-backend.js && node --check ./scripts/e2e-terminal-evidence.js && node --check ./scripts/audit-gate-e2e.js && node --check ./scripts/completion-contract-e2e.js && node --check ./scripts/retry-circuit-e2e.js && node --check ./scripts/follow-up-charter-e2e.js && node --check ./scripts/task-routing-e2e.js && node --check ./scripts/executor-version-preflight-e2e.js && node --check ./scripts/blocked-recovery-e2e.js && node --check ./scripts/process-localization-e2e.js && node --check ./scripts/hypothesis-retries-e2e.js && node --check ./scripts/budget-enforcement-e2e.js && node --check ./scripts/local-task-default-workspace-e2e.js && node --check ./scripts/local-task-idempotency-e2e.js && node --check ./scripts/console-e2e-fixture.js && node --check ./scripts/console-e2e.js && node --check ./scripts/console-recovery-e2e-fixture.js && node --check ./scripts/console-recovery-e2e.js && node --check ./scripts/real-provider-console-fixture.js && node --check ./scripts/real-provider-console-e2e.js && node --check ./scripts/fullstack-cli-smoke.js && node --check ./scripts/check-package-contents.js && node --check ./src/codex-plugins/simy/hooks/delivery-loop.mjs && node --check ./src/delivery-hooks/command.js && node --check ./src/delivery-hooks/desktop.js && node --check ./src/delivery-hooks/supervisor.js && node --check ./src/session-supervision/automatic-continuation.js",
|
|
47
47
|
"check:package": "node ./scripts/check-package-contents.js",
|
|
48
48
|
"build:macos-installer:dev": "bash packaging/build-macos-arm64.sh --unsigned-dev",
|
|
49
49
|
"build:macos-installer": "bash packaging/build-macos-arm64.sh --production",
|
package/src/cli-contract.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "./durable-local-task-steps-contract.js";
|
|
14
14
|
import { buildExecutionCapabilityContract } from "./execution-capability-contract.js";
|
|
15
15
|
|
|
16
|
-
export const CLI_VERSION = "0.6.
|
|
16
|
+
export const CLI_VERSION = "0.6.2";
|
|
17
17
|
export const CLI_API_CONTRACT_VERSION = 10;
|
|
18
18
|
|
|
19
19
|
export function withCliContract(
|
package/src/desktop-host.js
CHANGED
|
@@ -23,7 +23,8 @@ import { dirname, join } from "node:path";
|
|
|
23
23
|
import { homedir } from "node:os";
|
|
24
24
|
import { chmod, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
25
25
|
import { startAgent } from "./agent.js";
|
|
26
|
-
import { createRuntimeDiagnostics } from "./runtime-diagnostics.js";
|
|
26
|
+
import { createRuntimeDiagnostics, captureRuntimeOutput } from "./runtime-diagnostics.js";
|
|
27
|
+
import { applyLoginShellPath } from "./login-shell-path.js";
|
|
27
28
|
import { createCliAutoUpdater, readCliPackageInfo } from "./auto-update.js";
|
|
28
29
|
import { createAgentShutdown } from "./shutdown.js";
|
|
29
30
|
import { resolveWebOrigin } from "./web-origin.js";
|
|
@@ -735,7 +736,7 @@ export async function openProviderLogin(provider, root, {
|
|
|
735
736
|
const directory = await mkdtemp(join(root, `${provider}-login-`));
|
|
736
737
|
const script = join(directory, `Sign in to ${label}.command`);
|
|
737
738
|
const quote = (s) => `'${s.replaceAll("'", "'\\''")}'`;
|
|
738
|
-
await writeFile(script, `#!/bin/bash\nexport PATH
|
|
739
|
+
await writeFile(script, `#!/bin/bash\nexport PATH=${quote(env.PATH || "/usr/bin:/bin")}\n${quote(executable.executable)} ${args.join(" ")}\nresult=$?\nrm -f -- ${quote(script)}\nrmdir -- ${quote(directory)}\nexit "$result"\n`, { mode: 0o700 });
|
|
739
740
|
await chmod(script, 0o700);
|
|
740
741
|
try { await execFileImpl("/usr/bin/open", ["-a", "Terminal", script], { timeout: 10_000 }); }
|
|
741
742
|
catch (error) { await rm(directory, { recursive: true, force: true }); throw error; }
|
|
@@ -750,8 +751,12 @@ if (isDesktopHostEntry()) {
|
|
|
750
751
|
let host;
|
|
751
752
|
const stop = () => { void host?.close().finally(() => process.exit(0)); };
|
|
752
753
|
process.once("SIGTERM", stop); process.once("SIGINT", stop);
|
|
753
|
-
|
|
754
|
-
|
|
754
|
+
const diagnostics = createRuntimeDiagnostics(process.env.SIMY_HOME?.trim() || join(homedir(), ".simy"), { name: "desktop-host" });
|
|
755
|
+
// stdout is the native JSONL channel; stderr is the only unstructured output
|
|
756
|
+
// and the native window does not display it, so keep it for support.
|
|
757
|
+
captureRuntimeOutput(diagnostics, { stderr: process.stderr });
|
|
758
|
+
applyLoginShellPath({ diagnostics }).catch(() => {}).then(() => startDesktopHost()).then((value) => { host = value; }).catch((error) => {
|
|
759
|
+
diagnostics.write(`startup failed: ${error?.stack || error}`);
|
|
755
760
|
const conflict = error?.code === PROCESS_CONFLICT_CODE;
|
|
756
761
|
process.stdout.write(`${JSON.stringify({
|
|
757
762
|
type: "error",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
// Version-specific runtimes are replaced by the stable alias that follows
|
|
4
|
+
// upgrades: the installer's `current` release link and Homebrew's `opt` link.
|
|
5
|
+
const STABLE_RUNTIME_ALIASES = [
|
|
6
|
+
[/^(.*)\/installer\/releases\/[^/]+\/[^/]+\.app\/(Contents\/Resources\/runtime\/bin\/node)$/, "$1/installer/current/$2"],
|
|
7
|
+
[/^(.*)\/Cellar\/([^/]+)\/[^/]+\/(bin\/node)$/, "$1/opt/$2/$3"],
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
// Provider hooks are persisted into Codex/Claude configuration and run long
|
|
11
|
+
// after this process exits, often from GUI apps without the user's shell PATH.
|
|
12
|
+
// They must therefore name an absolute runtime that survives SIMY and Node updates.
|
|
13
|
+
export function stableHookRuntime({ execPath = process.execPath, fileExists = existsSync } = {}) {
|
|
14
|
+
for (const [pattern, replacement] of STABLE_RUNTIME_ALIASES) {
|
|
15
|
+
if (!pattern.test(execPath)) continue;
|
|
16
|
+
const alias = execPath.replace(pattern, replacement);
|
|
17
|
+
if (fileExists(alias)) return alias;
|
|
18
|
+
}
|
|
19
|
+
return execPath;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function hookRuntimeCommand(command, { platform = process.platform, ...options } = {}) {
|
|
23
|
+
if (typeof command !== "string" || !command.startsWith("node ")) return command;
|
|
24
|
+
return `${quoteRuntime(stableHookRuntime(options), platform)} ${command.slice("node ".length)}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function quoteRuntime(value, platform) {
|
|
28
|
+
return platform === "win32" ? `"${value.replaceAll('"', '""')}"` : `'${value.replaceAll("'", "'\\''")}'`;
|
|
29
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
const START = "__SIMY_LOGIN_PATH_START__";
|
|
6
|
+
const END = "__SIMY_LOGIN_PATH_END__";
|
|
7
|
+
|
|
8
|
+
// Apps opened from Finder or the Dock inherit launchd's minimal PATH, not the
|
|
9
|
+
// user's shell profile. Provider CLIs installed through nvm, volta, fnm, asdf,
|
|
10
|
+
// pnpm or custom prefixes are therefore invisible unless we ask the user's own
|
|
11
|
+
// login shell once. A slow or broken profile must never prevent startup.
|
|
12
|
+
export async function resolveLoginShellPath({
|
|
13
|
+
platform = process.platform,
|
|
14
|
+
env = process.env,
|
|
15
|
+
execFileImpl = execFile,
|
|
16
|
+
fileExists = existsSync,
|
|
17
|
+
timeoutMs = 5_000,
|
|
18
|
+
} = {}) {
|
|
19
|
+
if (platform === "win32") return null;
|
|
20
|
+
const shell = loginShell({ platform, env, fileExists });
|
|
21
|
+
if (!shell) return null;
|
|
22
|
+
const output = await new Promise((resolve) => {
|
|
23
|
+
// Read the exported environment rather than expanding $PATH in the shell:
|
|
24
|
+
// fish expands a quoted $PATH with spaces, but exports it colon-separated.
|
|
25
|
+
const child = execFileImpl(shell, ["-l", "-i", "-c", `echo ${START}; /usr/bin/env; echo ${END}`], {
|
|
26
|
+
env: { ...env, TERM: "dumb", DISABLE_AUTO_UPDATE: "true" },
|
|
27
|
+
timeout: timeoutMs,
|
|
28
|
+
killSignal: "SIGKILL",
|
|
29
|
+
maxBuffer: 1024 * 1024,
|
|
30
|
+
}, (_error, stdout) => resolve(String(stdout || "")));
|
|
31
|
+
child?.stdin?.end();
|
|
32
|
+
});
|
|
33
|
+
const start = output.lastIndexOf(START);
|
|
34
|
+
const end = output.indexOf(END, start);
|
|
35
|
+
if (start < 0 || end < 0) return null;
|
|
36
|
+
const line = output.slice(start + START.length, end).split(/\r?\n/).find((item) => item.startsWith("PATH="));
|
|
37
|
+
return line?.slice("PATH=".length) || null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Login-shell entries take priority, matching what the user sees in Terminal.
|
|
41
|
+
// Existing entries (including the launcher's fallback directories) are kept.
|
|
42
|
+
export function mergePathEntries(...values) {
|
|
43
|
+
const entries = [];
|
|
44
|
+
for (const value of values) {
|
|
45
|
+
for (const entry of String(value || "").split(path.delimiter)) {
|
|
46
|
+
if (path.isAbsolute(entry) && !entries.includes(entry)) entries.push(entry);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return entries.join(path.delimiter);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function applyLoginShellPath({ env = process.env, platform = process.platform, diagnostics, ...options } = {}) {
|
|
53
|
+
if (platform === "win32") return false;
|
|
54
|
+
const loginPath = await resolveLoginShellPath({ env, platform, ...options });
|
|
55
|
+
if (!loginPath) {
|
|
56
|
+
diagnostics?.write("login shell PATH unavailable; using launcher PATH");
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
env.PATH = mergePathEntries(loginPath, env.PATH);
|
|
60
|
+
diagnostics?.write(`login shell PATH applied (${env.PATH.split(path.delimiter).length} entries)`);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function loginShell({ platform, env, fileExists }) {
|
|
65
|
+
const candidates = [env.SHELL, platform === "darwin" ? "/bin/zsh" : null, "/bin/sh"];
|
|
66
|
+
return candidates.find((candidate) => candidate && path.isAbsolute(candidate) && fileExists(candidate)) || null;
|
|
67
|
+
}
|
package/src/sqm/agent-skill.js
CHANGED
|
@@ -3,6 +3,7 @@ import { cp, lstat, mkdir, readFile, readdir, rename, rm, writeFile } from "node
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { hookRuntimeCommand } from "../hook-runtime.js";
|
|
6
7
|
|
|
7
8
|
import { inspectClaudePlugin, installClaudePlugin } from "./claude-plugin.js";
|
|
8
9
|
|
|
@@ -328,25 +329,14 @@ async function bundledPluginManifest({ overrides = new Map() } = {}) {
|
|
|
328
329
|
async function installedPluginOverrides() {
|
|
329
330
|
const relative = "hooks/hooks.json";
|
|
330
331
|
const source = JSON.parse(await readFile(path.join(BUNDLED_CODEX_PLUGIN_ROOT, relative), "utf8"));
|
|
331
|
-
const commandPrefix = "node ";
|
|
332
|
-
const runtime = shellQuote(process.execPath);
|
|
333
332
|
for (const groups of Object.values(source.hooks || {})) {
|
|
334
333
|
for (const group of groups || []) {
|
|
335
|
-
for (const hook of group.hooks || [])
|
|
336
|
-
if (typeof hook.command === "string" && hook.command.startsWith(commandPrefix)) {
|
|
337
|
-
hook.command = `${runtime} ${hook.command.slice(commandPrefix.length)}`;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
334
|
+
for (const hook of group.hooks || []) hook.command = hookRuntimeCommand(hook.command);
|
|
340
335
|
}
|
|
341
336
|
}
|
|
342
337
|
return new Map([[relative, `${JSON.stringify(source, null, 2)}\n`]]);
|
|
343
338
|
}
|
|
344
339
|
|
|
345
|
-
function shellQuote(value) {
|
|
346
|
-
if (process.platform === "win32") return `"${value.replaceAll('"', '""')}"`;
|
|
347
|
-
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
340
|
async function directoryDigest(root, { missing = "throw", manifest, overrides = new Map() } = {}) {
|
|
351
341
|
let rootStat;
|
|
352
342
|
try {
|
package/src/sqm/claude-plugin.js
CHANGED
|
@@ -3,6 +3,7 @@ import { mkdir, readFile, readdir, rename, rm, lstat, writeFile } from "node:fs/
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { hookRuntimeCommand } from "../hook-runtime.js";
|
|
6
7
|
|
|
7
8
|
const SOURCE = fileURLToPath(new URL("../codex-plugins/simy/", import.meta.url));
|
|
8
9
|
export const CLAUDE_MARKETPLACE = "simy-local";
|
|
@@ -43,7 +44,7 @@ export async function claudePluginFiles() {
|
|
|
43
44
|
} else if (event === "Notification") {
|
|
44
45
|
hook.statusMessage = "SIMY Delivery Loop permission-notification tracking";
|
|
45
46
|
}
|
|
46
|
-
hook.command = hook.command
|
|
47
|
+
hook.command = hookRuntimeCommand(hook.command)
|
|
47
48
|
.replaceAll("process.env.PLUGIN_ROOT", "process.env.CLAUDE_PLUGIN_ROOT")
|
|
48
49
|
.replaceAll("hook.main('codex')", "hook.main('claude')");
|
|
49
50
|
}
|
|
@@ -136,6 +137,3 @@ function json(value) { return `${JSON.stringify(value, null, 2)}\n`; }
|
|
|
136
137
|
async function optionalRead(file) {
|
|
137
138
|
try { return await readFile(file, "utf8"); } catch (error) { if (error.code === "ENOENT") return null; throw error; }
|
|
138
139
|
}
|
|
139
|
-
function quoteRuntime(value) {
|
|
140
|
-
return process.platform === "win32" ? `"${value.replaceAll('"', '""')}"` : `'${value.replaceAll("'", "'\\''")}'`;
|
|
141
|
-
}
|