@awak-app/simy-cli 0.5.79 → 0.5.81
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
CHANGED
|
@@ -181,6 +181,13 @@ app-server session and checks writer ownership before each continuation. Claude
|
|
|
181
181
|
can continue through a verified live SIMY hook in its original process; sessions
|
|
182
182
|
without that hook support monitoring only, and cold takeover remains unavailable. See [session supervision](docs/session-supervision.md).
|
|
183
183
|
|
|
184
|
+
Provider discovery skips outdated or unversioned executables while looking for a
|
|
185
|
+
compatible installation. Codex session supervision requires `0.158.0` or newer,
|
|
186
|
+
independently of the lower general execution minimum. On macOS, discovery also
|
|
187
|
+
checks the bundled CLI in ChatGPT and Codex apps in system and user Applications.
|
|
188
|
+
Claude discovery likewise falls back to a compatible native or Desktop bundle
|
|
189
|
+
when an older PATH installation cannot meet its version requirement.
|
|
190
|
+
|
|
184
191
|
The plugin also provides an opt-in, hook-based Delivery Loop in the user's existing
|
|
185
192
|
Codex or Claude Code conversation. Install the plugin, review and enable SIMY hooks
|
|
186
193
|
with `/hooks`, then request `/simy:delivery-loop` for the task. Installing or updating
|
package/package.json
CHANGED
|
@@ -4,8 +4,7 @@ import { readdir } from "node:fs/promises";
|
|
|
4
4
|
import { readdirSync, statSync } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
const MACOS_CODEX_BUNDLED_BINARY = "/Applications/ChatGPT.app/Contents/Resources/codex-cli/bin/codex";
|
|
7
|
+
export const CODEX_WRITER_LOCK_MINIMUM_VERSION = "0.158.0";
|
|
9
8
|
|
|
10
9
|
export const BACKEND_VERSION_POLICIES = Object.freeze({
|
|
11
10
|
codex: Object.freeze({
|
|
@@ -27,50 +26,45 @@ export async function resolveBackendExecutable(backend, options = {}) {
|
|
|
27
26
|
|
|
28
27
|
export async function inspectBackendExecutable(
|
|
29
28
|
backend,
|
|
30
|
-
{ spawnImpl = spawn, candidates, timeoutMs = 5_000, signal, discoveryOptions = {} } = {},
|
|
29
|
+
{ spawnImpl = spawn, candidates, timeoutMs = 5_000, signal, discoveryOptions = {}, minimumVersion } = {},
|
|
31
30
|
) {
|
|
32
31
|
const assertActive = () => { if (signal?.aborted) throw Object.assign(new Error('Backend inspection was cancelled.'), { code: 'cancelled' }); };
|
|
33
32
|
assertActive();
|
|
34
33
|
const policy = versionPolicy(backend);
|
|
34
|
+
const requiredVersion = minimumVersion || policy.minimumVersion;
|
|
35
35
|
candidates ??= [...backendCandidates(backend, discoveryOptions), ...await bundledClaudeCandidates(backend, discoveryOptions)];
|
|
36
|
+
let fallback = null;
|
|
36
37
|
for (const candidate of [...new Set(candidates.filter(Boolean))]) {
|
|
37
38
|
assertActive();
|
|
38
39
|
const probe = await probeExecutable(candidate, { spawnImpl, timeoutMs, signal });
|
|
39
40
|
assertActive();
|
|
40
41
|
if (!probe.available) continue;
|
|
41
42
|
const installedVersion = parseBackendVersion(probe.output);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
backend,
|
|
45
|
-
executable: candidate,
|
|
46
|
-
available: true,
|
|
47
|
-
compatible: false,
|
|
48
|
-
status: "unknown_version",
|
|
49
|
-
installed_version: null,
|
|
50
|
-
minimum_version: policy.minimumVersion,
|
|
51
|
-
update_command: policy.updateCommand,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
const compatible = compareVersions(installedVersion, policy.minimumVersion) >= 0;
|
|
55
|
-
return {
|
|
43
|
+
const compatible = Boolean(installedVersion) && compareVersions(installedVersion, requiredVersion) >= 0;
|
|
44
|
+
const inspection = {
|
|
56
45
|
backend,
|
|
57
46
|
executable: candidate,
|
|
58
47
|
available: true,
|
|
59
48
|
compatible,
|
|
60
|
-
status: compatible ? "compatible" : "outdated",
|
|
49
|
+
status: compatible ? "compatible" : installedVersion ? "outdated" : "unknown_version",
|
|
61
50
|
installed_version: installedVersion,
|
|
62
|
-
minimum_version:
|
|
51
|
+
minimum_version: requiredVersion,
|
|
63
52
|
update_command: policy.updateCommand,
|
|
64
53
|
};
|
|
54
|
+
// An executable that starts may still be too old for the requested feature.
|
|
55
|
+
// Preserve candidate priority among compatible installs, and retain the
|
|
56
|
+
// first runnable failure for actionable diagnostics if none qualifies.
|
|
57
|
+
if (compatible) return inspection;
|
|
58
|
+
fallback ??= inspection;
|
|
65
59
|
}
|
|
66
|
-
return {
|
|
60
|
+
return fallback || {
|
|
67
61
|
backend,
|
|
68
62
|
executable: null,
|
|
69
63
|
available: false,
|
|
70
64
|
compatible: false,
|
|
71
65
|
status: "missing",
|
|
72
66
|
installed_version: null,
|
|
73
|
-
minimum_version:
|
|
67
|
+
minimum_version: requiredVersion,
|
|
74
68
|
update_command: policy.updateCommand,
|
|
75
69
|
};
|
|
76
70
|
}
|
|
@@ -94,7 +88,13 @@ export function backendCandidates(backend, {
|
|
|
94
88
|
return [
|
|
95
89
|
environment.SIMY_CODEX_BIN,
|
|
96
90
|
"codex",
|
|
97
|
-
...(platform === "darwin" ? [
|
|
91
|
+
...(platform === "darwin" ? ["/Applications", path.posix.join(home, "Applications")].flatMap(directory =>
|
|
92
|
+
["ChatGPT.app", "Codex.app"].flatMap(app => {
|
|
93
|
+
const resources = path.posix.join(directory, app, "Contents", "Resources");
|
|
94
|
+
return [path.posix.join(resources, "codex-cli", "bin", "codex"),
|
|
95
|
+
path.posix.join(resources, "codex-cli", "CodexCLI.app", "Contents", "MacOS", "codex"),
|
|
96
|
+
path.posix.join(resources, "codex")];
|
|
97
|
+
})) : []),
|
|
98
98
|
];
|
|
99
99
|
}
|
|
100
100
|
|
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.5.
|
|
16
|
+
export const CLI_VERSION = "0.5.81";
|
|
17
17
|
export const CLI_API_CONTRACT_VERSION = 10;
|
|
18
18
|
|
|
19
19
|
export function withCliContract(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { associationContract } from '../codex-plugins/simy/hooks/action-association.mjs';
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
3
|
import { realpath } from 'node:fs/promises';
|
|
4
|
-
import { inspectBackendExecutable } from '../backend-executable.js';
|
|
4
|
+
import { CODEX_WRITER_LOCK_MINIMUM_VERSION, compareVersions, inspectBackendExecutable } from '../backend-executable.js';
|
|
5
5
|
import { assessedCheckpointContract, deliveryBudgetState, understandingCheckpointContract } from '../codex-plugins/simy/hooks/delivery-loop.mjs';
|
|
6
6
|
import { boundConversation, boundProviderGoal, textContent } from './conversation-context.js';
|
|
7
7
|
import { JsonDataUrlFilter } from './json-data-url-filter.js';
|
|
@@ -149,13 +149,13 @@ export class CodexAppServerClient {
|
|
|
149
149
|
export function supportsCodexWriterLock(version) {
|
|
150
150
|
const match = String(version || '').match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
151
151
|
if (!match) return false;
|
|
152
|
-
|
|
153
|
-
return parts[0] > 0 || parts[1] > 158 || parts[1] === 158 && parts[2] >= 0;
|
|
152
|
+
return compareVersions(version, CODEX_WRITER_LOCK_MINIMUM_VERSION) >= 0;
|
|
154
153
|
}
|
|
155
154
|
|
|
156
155
|
export async function openCodexAppServer({ inspectExecutable = inspectBackendExecutable, spawnImpl = spawn, signal, maxLineBytes, omitInlineAttachments = false, cancelOnAbort = false } = {}) {
|
|
157
156
|
if (signal?.aborted) throw new CodexAppServerError('cancelled', 'Codex app-server was cancelled.');
|
|
158
|
-
const inspection = await inspectExecutable('codex',
|
|
157
|
+
const inspection = await inspectExecutable('codex', { minimumVersion: CODEX_WRITER_LOCK_MINIMUM_VERSION,
|
|
158
|
+
...(cancelOnAbort ? { signal } : {}) });
|
|
159
159
|
if (!inspection?.available || !inspection.executable) throw new CodexAppServerError('unavailable', 'Codex executable is unavailable.');
|
|
160
160
|
if (!supportsCodexWriterLock(inspection.installed_version)) throw new CodexAppServerError('unsupported', 'Codex version does not have a verified app-server writer lock.');
|
|
161
161
|
if (signal?.aborted) throw new CodexAppServerError('cancelled', 'Codex app-server was cancelled.');
|