@stigmer/cli 3.12.8 → 3.13.0
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/commands/agent-exec-flags.d.ts +1 -0
- package/commands/agent-exec-flags.d.ts.map +1 -1
- package/commands/agent-exec-flags.js +3 -1
- package/commands/agent-exec-flags.js.map +1 -1
- package/commands/run.js +3 -0
- package/commands/run.js.map +1 -1
- package/commands/up.d.ts.map +1 -1
- package/commands/up.js +22 -6
- package/commands/up.js.map +1 -1
- package/config/resolve.d.ts +5 -2
- package/config/resolve.d.ts.map +1 -1
- package/config/resolve.js +7 -4
- package/config/resolve.js.map +1 -1
- package/local/constants.d.ts +8 -3
- package/local/constants.d.ts.map +1 -1
- package/local/constants.js +8 -3
- package/local/constants.js.map +1 -1
- package/local/daemon/components.d.ts.map +1 -1
- package/local/daemon/components.js +4 -2
- package/local/daemon/components.js.map +1 -1
- package/local/daemon/env.d.ts +16 -3
- package/local/daemon/env.d.ts.map +1 -1
- package/local/daemon/env.js +16 -3
- package/local/daemon/env.js.map +1 -1
- package/local/daemon/launch.d.ts.map +1 -1
- package/local/daemon/launch.js +5 -4
- package/local/daemon/launch.js.map +1 -1
- package/local/daemon/process.d.ts.map +1 -1
- package/local/daemon/process.js +8 -5
- package/local/daemon/process.js.map +1 -1
- package/local/runtime/index.d.ts +2 -2
- package/local/runtime/index.d.ts.map +1 -1
- package/local/runtime/index.js +4 -2
- package/local/runtime/index.js.map +1 -1
- package/local/runtime/node.d.ts +8 -0
- package/local/runtime/node.d.ts.map +1 -1
- package/local/runtime/node.js +74 -23
- package/local/runtime/node.js.map +1 -1
- package/local/runtime/runner.d.ts +2 -1
- package/local/runtime/runner.d.ts.map +1 -1
- package/local/runtime/runner.js +4 -31
- package/local/runtime/runner.js.map +1 -1
- package/local/runtime/runtimes-install.d.ts +13 -0
- package/local/runtime/runtimes-install.d.ts.map +1 -0
- package/local/runtime/runtimes-install.js +60 -0
- package/local/runtime/runtimes-install.js.map +1 -0
- package/local/runtime/server.d.ts +26 -30
- package/local/runtime/server.d.ts.map +1 -1
- package/local/runtime/server.js +106 -108
- package/local/runtime/server.js.map +1 -1
- package/local/status.d.ts.map +1 -1
- package/local/status.js +4 -2
- package/local/status.js.map +1 -1
- package/local/webconsole/index.d.ts +2 -3
- package/local/webconsole/index.d.ts.map +1 -1
- package/local/webconsole/index.js +24 -10
- package/local/webconsole/index.js.map +1 -1
- package/package.json +5 -5
- package/resources/run/agent-exec.d.ts.map +1 -1
- package/resources/run/agent-exec.js +2 -0
- package/resources/run/agent-exec.js.map +1 -1
- package/resources/run/create.d.ts +2 -1
- package/resources/run/create.d.ts.map +1 -1
- package/resources/run/create.js +21 -3
- package/resources/run/create.js.map +1 -1
- package/resources/run/header.d.ts +9 -1
- package/resources/run/header.d.ts.map +1 -1
- package/resources/run/header.js +3 -0
- package/resources/run/header.js.map +1 -1
- package/resources/run/prepare.d.ts +41 -3
- package/resources/run/prepare.d.ts.map +1 -1
- package/resources/run/prepare.js +53 -16
- package/resources/run/prepare.js.map +1 -1
- package/src/commands/agent-exec-flags.ts +5 -2
- package/src/commands/run.ts +3 -0
- package/src/commands/up.ts +24 -6
- package/src/config/resolve.test.ts +1 -1
- package/src/config/resolve.ts +7 -4
- package/src/local/constants.ts +8 -4
- package/src/local/daemon/components.test.ts +9 -1
- package/src/local/daemon/components.ts +4 -2
- package/src/local/daemon/daemon.integration.test.ts +1 -1
- package/src/local/daemon/env.test.ts +15 -4
- package/src/local/daemon/env.ts +33 -5
- package/src/local/daemon/launch.ts +5 -4
- package/src/local/daemon/process.ts +7 -4
- package/src/local/runtime/index.ts +6 -5
- package/src/local/runtime/node.ts +99 -23
- package/src/local/runtime/runner.ts +5 -36
- package/src/local/runtime/runtime.test.ts +58 -14
- package/src/local/runtime/runtimes-install.test.ts +56 -0
- package/src/local/runtime/runtimes-install.ts +72 -0
- package/src/local/runtime/server.test.ts +178 -114
- package/src/local/runtime/server.ts +149 -129
- package/src/local/status.ts +4 -2
- package/src/local/webconsole/index.ts +27 -10
- package/src/resources/connect/oauth.test.ts +1 -1
- package/src/resources/run/agent-exec.test.ts +25 -0
- package/src/resources/run/agent-exec.ts +2 -0
- package/src/resources/run/create.test.ts +92 -1
- package/src/resources/run/create.ts +25 -6
- package/src/resources/run/header.test.ts +18 -0
- package/src/resources/run/header.ts +11 -1
- package/src/resources/run/prepare.test.ts +247 -5
- package/src/resources/run/prepare.ts +99 -21
- package/src/resources/share.test.ts +2 -2
package/resources/run/header.js
CHANGED
|
@@ -27,6 +27,9 @@ export function renderSessionHeader(out, info) {
|
|
|
27
27
|
lines.push(row(s, "Subject", info.subject ?? ""));
|
|
28
28
|
if (info.model !== "")
|
|
29
29
|
lines.push(row(s, "Model", info.model));
|
|
30
|
+
// Only "cursor" is surfaced; native/"" is the default and stays implicit.
|
|
31
|
+
if (info.harness === "cursor")
|
|
32
|
+
lines.push(row(s, "Harness", "Cursor"));
|
|
30
33
|
// Only "plan" is surfaced; "agent"/"" is the default and stays implicit.
|
|
31
34
|
if (info.mode === "plan")
|
|
32
35
|
lines.push(row(s, "Mode", "Plan (read-only)"));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"header.js","sourceRoot":"","sources":["../../../src/resources/run/header.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,qEAAqE;AACrE,EAAE;AACF,4EAA4E;AAC5E,wEAAwE;AACxE,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,+EAA+E;AAC/E,4EAA4E;AAG5E,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"header.js","sourceRoot":"","sources":["../../../src/resources/run/header.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,qEAAqE;AACrE,EAAE;AACF,4EAA4E;AAC5E,wEAAwE;AACxE,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,+EAA+E;AAC/E,4EAA4E;AAG5E,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAqB/D,8EAA8E;AAC9E,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAuD,EAAE,IAAuB;IAClH,MAAM,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IACtC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,IAAI,CAAC,SAAS,KAAK,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACvE,IAAI,IAAI,CAAC,SAAS,KAAK,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACzE,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IACnF,IAAI,IAAI,CAAC,KAAK,KAAK,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/D,0EAA0E;IAC1E,IAAI,IAAI,CAAC,OAAO,KAAK,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvE,yEAAyE;IACzE,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACzE,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACvC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,EAAE,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC/B,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,GAAG,CAAC,CAA4B,EAAE,KAAa,EAAE,KAAa;IACrE,MAAM,MAAM,GAAG,GAAG,KAAK,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,EAAE,CAAC;AACpC,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,cAAc,CAAC,OAAkC;IAC/D,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -17,6 +17,14 @@ export type ServiceTierFlag = "" | "standard" | "fast";
|
|
|
17
17
|
* unset — distinct from an explicit "disabled" for the same ledger reason.
|
|
18
18
|
*/
|
|
19
19
|
export type ThinkingFlag = "" | "disabled" | "enabled";
|
|
20
|
+
/**
|
|
21
|
+
* The `--harness` flag's value space (oss#293): empty means unset — the
|
|
22
|
+
* account preference may fill it (see {@link prepareAgentExec}), and when
|
|
23
|
+
* nothing resolves the server defaults the session to native. Deliberately
|
|
24
|
+
* only the two shipped engines, mirroring the proto validation on
|
|
25
|
+
* `IdentityAccountPreferences.default_harness`.
|
|
26
|
+
*/
|
|
27
|
+
export type HarnessFlag = "" | "native" | "cursor";
|
|
20
28
|
/** Raw agent-execution flags shared by `run` and `draft` (Go's agentExecFlags). */
|
|
21
29
|
export interface AgentExecFlags {
|
|
22
30
|
readonly message: string;
|
|
@@ -36,6 +44,7 @@ export interface AgentExecFlags {
|
|
|
36
44
|
readonly mode: RunMode;
|
|
37
45
|
readonly serviceTier: ServiceTierFlag;
|
|
38
46
|
readonly thinking: ThinkingFlag;
|
|
47
|
+
readonly harness: HarnessFlag;
|
|
39
48
|
}
|
|
40
49
|
/**
|
|
41
50
|
* The validated, resolved inputs ready for create + stream. Mirrors Go's
|
|
@@ -55,17 +64,37 @@ export interface PreparedRun {
|
|
|
55
64
|
readonly mode: RunMode;
|
|
56
65
|
readonly serviceTier: ServiceTierFlag;
|
|
57
66
|
readonly thinking: ThinkingFlag;
|
|
67
|
+
/**
|
|
68
|
+
* The RESOLVED harness for the new session: the explicit flag, else the
|
|
69
|
+
* account preference (when the caller opted in), else "" — which stays off
|
|
70
|
+
* the wire so the server default (native) applies. Also drives the header's
|
|
71
|
+
* visibility row: a cursor session is never entered silently.
|
|
72
|
+
*/
|
|
73
|
+
readonly harness: HarnessFlag;
|
|
58
74
|
}
|
|
59
75
|
/** Optional behavior switches for {@link prepareAgentExec}. */
|
|
60
76
|
export interface PrepareAgentExecOptions {
|
|
61
77
|
/**
|
|
62
78
|
* When `true` (the caller's backend is Stigmer Cloud) and `--model` is
|
|
63
79
|
* omitted, the model is filled from the caller's account preference
|
|
64
|
-
* (`IdentityAccountPreferences.
|
|
65
|
-
* Local mode has no IdentityAccount, so callers pass
|
|
66
|
-
* the omitted model keeps resolving to the platform
|
|
80
|
+
* (`IdentityAccountPreferences.default_*_model` for the resolved harness)
|
|
81
|
+
* via `whoAmI()`. Local mode has no IdentityAccount, so callers pass
|
|
82
|
+
* `false` there and the omitted model keeps resolving to the platform
|
|
83
|
+
* default.
|
|
67
84
|
*/
|
|
68
85
|
readonly cloudBackend?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* When `true` and `--harness` is omitted, the harness is filled from the
|
|
88
|
+
* caller's account preference (`IdentityAccountPreferences.default_harness`)
|
|
89
|
+
* on cloud. `run` opts in; `draft` deliberately does not: draft executes the
|
|
90
|
+
* seedpack's system creator agents (a utility flow, not the user's own
|
|
91
|
+
* conversation), which are built and exercised on the native harness —
|
|
92
|
+
* silently rerouting them onto the cursor engine (different toolset,
|
|
93
|
+
* premium billing tier) would fail the least-surprise test. An explicit
|
|
94
|
+
* `--harness` on draft still wins; only the silent preference fill is
|
|
95
|
+
* scoped out. Owner-ratified (D5, 2026-08-23).
|
|
96
|
+
*/
|
|
97
|
+
readonly applyAccountHarnessDefault?: boolean;
|
|
69
98
|
}
|
|
70
99
|
/**
|
|
71
100
|
* Validate flags and resolve all execution inputs. The `org` is used to inject
|
|
@@ -98,4 +127,13 @@ export declare function validateServiceTier(tier: string): asserts tier is Servi
|
|
|
98
127
|
* before a network round trip.
|
|
99
128
|
*/
|
|
100
129
|
export declare function validateThinking(mode: string): asserts mode is ThinkingFlag;
|
|
130
|
+
/**
|
|
131
|
+
* Validate the `--harness` flag. Empty means "use default": the account
|
|
132
|
+
* preference when the caller opted in, else the platform default (native).
|
|
133
|
+
* Only the shipped engines are accepted — other harness names that appear in
|
|
134
|
+
* UI metadata (copilot, codex, ...) have no proto mapping yet, so rejecting
|
|
135
|
+
* them here is honest, and this check catches spelling errors before a
|
|
136
|
+
* network round trip.
|
|
137
|
+
*/
|
|
138
|
+
export declare function validateHarness(harness: string): asserts harness is HarnessFlag;
|
|
101
139
|
//# sourceMappingURL=prepare.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../../../src/resources/run/prepare.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8DAA8D,CAAC;AAC/F,OAAO,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAC;AAC9F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4DAA4D,CAAC;AACjG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAG5D,8EAA8E;AAC9E,MAAM,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,GAAG,MAAM,CAAC;AAE5C;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,EAAE,GAAG,UAAU,GAAG,MAAM,CAAC;AAEvD;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,EAAE,GAAG,UAAU,GAAG,SAAS,CAAC;AAEvD,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../../../src/resources/run/prepare.ts"],"names":[],"mappings":"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"}
|
package/resources/run/prepare.js
CHANGED
|
@@ -20,13 +20,25 @@ export async function prepareAgentExec(flags, client, org, progress, options) {
|
|
|
20
20
|
validateMode(flags.mode);
|
|
21
21
|
validateServiceTier(flags.serviceTier);
|
|
22
22
|
validateThinking(flags.thinking);
|
|
23
|
-
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
validateHarness(flags.harness);
|
|
24
|
+
// Layered seeds (oss#293, DD-003): explicit flag > account preference
|
|
25
|
+
// (cloud only) > platform default. Harness resolves first because the model
|
|
26
|
+
// fill is harness-aware: a cursor session fills from default_cursor_model,
|
|
27
|
+
// everything else from default_native_model. `run` and `draft` always
|
|
28
|
+
// create a NEW session (threading lives in `resume`, which does not pass
|
|
29
|
+
// through here), so neither fill can ever contradict an existing session's
|
|
30
|
+
// immutable harness. One whoAmI round trip serves both fills, and it is
|
|
31
|
+
// skipped entirely when explicit flags leave nothing to fill.
|
|
32
|
+
const wantsHarnessFill = flags.harness === "" && options?.applyAccountHarnessDefault === true;
|
|
33
|
+
const wantsModelFill = flags.model === "";
|
|
34
|
+
const accountDefaults = options?.cloudBackend === true && (wantsHarnessFill || wantsModelFill)
|
|
35
|
+
? await resolveAccountExecutionDefaults(client)
|
|
36
|
+
: NO_ACCOUNT_DEFAULTS;
|
|
37
|
+
const harness = flags.harness !== "" ? flags.harness : wantsHarnessFill ? accountDefaults.harness : "";
|
|
38
|
+
const model = wantsModelFill
|
|
39
|
+
? harness === "cursor"
|
|
40
|
+
? accountDefaults.cursorModel
|
|
41
|
+
: accountDefaults.nativeModel
|
|
30
42
|
: flags.model;
|
|
31
43
|
const workspaceEntries = parseWorkspaceEntries(flags.workspace, flags.branch, flags.commit);
|
|
32
44
|
const runtimeEnv = loadAndMergeEnv({
|
|
@@ -53,23 +65,35 @@ export async function prepareAgentExec(flags, client, org, progress, options) {
|
|
|
53
65
|
mode: flags.mode,
|
|
54
66
|
serviceTier: flags.serviceTier,
|
|
55
67
|
thinking: flags.thinking,
|
|
68
|
+
harness,
|
|
56
69
|
};
|
|
57
70
|
}
|
|
71
|
+
const NO_ACCOUNT_DEFAULTS = { harness: "", nativeModel: "", cursorModel: "" };
|
|
58
72
|
/**
|
|
59
|
-
* Best-effort read of the caller's
|
|
60
|
-
* (
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
73
|
+
* Best-effort read of the caller's execution defaults
|
|
74
|
+
* (`IdentityAccountPreferences.default_harness` / `default_*_model`) in one
|
|
75
|
+
* whoAmI round trip. Any failure — network, auth, a backend without
|
|
76
|
+
* IdentityAccount — resolves to no defaults and the run proceeds exactly as
|
|
77
|
+
* unfilled flags do today: a missing preference must never fail a run.
|
|
78
|
+
*
|
|
79
|
+
* The persisted harness value is allowlist-guarded to the shipped engines
|
|
80
|
+
* (the same guard the web launcher's useAccountExecutionDefaults applies):
|
|
81
|
+
* a client must not trust stored data it did not write, so anything outside
|
|
82
|
+
* native/cursor is treated as undeclared rather than stamped on the wire.
|
|
65
83
|
*/
|
|
66
|
-
async function
|
|
84
|
+
async function resolveAccountExecutionDefaults(client) {
|
|
67
85
|
try {
|
|
68
86
|
const account = await client.identityAccount.whoAmI();
|
|
69
|
-
|
|
87
|
+
const prefs = account.spec?.preferences;
|
|
88
|
+
const declared = prefs?.defaultHarness;
|
|
89
|
+
return {
|
|
90
|
+
harness: declared === "native" || declared === "cursor" ? declared : "",
|
|
91
|
+
nativeModel: prefs?.defaultNativeModel ?? "",
|
|
92
|
+
cursorModel: prefs?.defaultCursorModel ?? "",
|
|
93
|
+
};
|
|
70
94
|
}
|
|
71
95
|
catch {
|
|
72
|
-
return
|
|
96
|
+
return NO_ACCOUNT_DEFAULTS;
|
|
73
97
|
}
|
|
74
98
|
}
|
|
75
99
|
/**
|
|
@@ -127,4 +151,17 @@ export function validateThinking(mode) {
|
|
|
127
151
|
throw new UsageError(`invalid --thinking value "${mode}": must be "disabled" or "enabled"`);
|
|
128
152
|
}
|
|
129
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Validate the `--harness` flag. Empty means "use default": the account
|
|
156
|
+
* preference when the caller opted in, else the platform default (native).
|
|
157
|
+
* Only the shipped engines are accepted — other harness names that appear in
|
|
158
|
+
* UI metadata (copilot, codex, ...) have no proto mapping yet, so rejecting
|
|
159
|
+
* them here is honest, and this check catches spelling errors before a
|
|
160
|
+
* network round trip.
|
|
161
|
+
*/
|
|
162
|
+
export function validateHarness(harness) {
|
|
163
|
+
if (harness !== "" && harness !== "native" && harness !== "cursor") {
|
|
164
|
+
throw new UsageError(`invalid --harness value "${harness}": must be "native" or "cursor"`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
130
167
|
//# sourceMappingURL=prepare.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare.js","sourceRoot":"","sources":["../../../src/resources/run/prepare.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,8EAA8E;AAC9E,EAAE;AACF,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,gFAAgF;AAChF,oEAAoE;AAGpE,OAAO,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAC;AAG9F,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAqB,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAmB,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"prepare.js","sourceRoot":"","sources":["../../../src/resources/run/prepare.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,8EAA8E;AAC9E,EAAE;AACF,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,gFAAgF;AAChF,oEAAoE;AAGpE,OAAO,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAC;AAG9F,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAqB,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAmB,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAqG5E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAqB,EACrB,MAAe,EACf,GAAW,EACX,QAAuB,EACvB,OAAiC;IAEjC,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAChE,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzB,mBAAmB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACvC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACjC,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE/B,sEAAsE;IACtE,4EAA4E;IAC5E,2EAA2E;IAC3E,sEAAsE;IACtE,yEAAyE;IACzE,2EAA2E;IAC3E,wEAAwE;IACxE,8DAA8D;IAC9D,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,KAAK,EAAE,IAAI,OAAO,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC9F,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC;IAC1C,MAAM,eAAe,GACnB,OAAO,EAAE,YAAY,KAAK,IAAI,IAAI,CAAC,gBAAgB,IAAI,cAAc,CAAC;QACpE,CAAC,CAAC,MAAM,+BAA+B,CAAC,MAAM,CAAC;QAC/C,CAAC,CAAC,mBAAmB,CAAC;IAC1B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACvG,MAAM,KAAK,GAAG,cAAc;QAC1B,CAAC,CAAC,OAAO,KAAK,QAAQ;YACpB,CAAC,CAAC,eAAe,CAAC,WAAW;YAC7B,CAAC,CAAC,eAAe,CAAC,WAAW;QAC/B,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;IAEhB,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE5F,MAAM,UAAU,GAAG,eAAe,CAAC;QACjC,QAAQ,EAAE,KAAK,CAAC,GAAG;QACnB,WAAW,EAAE,KAAK,CAAC,MAAM;QACzB,QAAQ,EAAE,KAAK,CAAC,OAAO;QACvB,WAAW,EAAE,KAAK,CAAC,UAAU;KAC9B,CAAC,CAAC;IACH,IAAI,UAAU,CAAC,cAAc,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;QAC1D,UAAU,CAAC,cAAc,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC9D,CAAC;IAED,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,GAAG,MAAM,kBAAkB,CACjE,MAAM,CAAC,cAAc,EACrB,KAAK,CAAC,MAAM,EACZ,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,QAAQ,CACT,CAAC;IAEF,OAAO;QACL,aAAa;QACb,gBAAgB;QAChB,UAAU;QACV,WAAW;QACX,iBAAiB;QACjB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK;QACL,cAAc,EAAE,KAAK,CAAC,WAAW;QACjC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO;KACR,CAAC;AACJ,CAAC;AASD,MAAM,mBAAmB,GAA6B,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AAExG;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,+BAA+B,CAAC,MAAe;IAC5D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC;QACxC,MAAM,QAAQ,GAAG,KAAK,EAAE,cAAc,CAAC;QACvC,OAAO;YACL,OAAO,EAAE,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;YACvE,WAAW,EAAE,KAAK,EAAE,kBAAkB,IAAI,EAAE;YAC5C,WAAW,EAAE,KAAK,EAAE,kBAAkB,IAAI,EAAE;SAC7C,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,mBAAmB,CAAC;IAC7B,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,cAAc,CAAC,WAAW,CAAC;IAC3D,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACnC,KAAK,SAAS;YACZ,OAAO,cAAc,CAAC,OAAO,CAAC;QAChC,KAAK,MAAM;YACT,OAAO,cAAc,CAAC,IAAI,CAAC;QAC7B,KAAK,QAAQ;YACX,OAAO,cAAc,CAAC,MAAM,CAAC;QAC/B,KAAK,aAAa,CAAC;QACnB,KAAK,aAAa,CAAC;QACnB,KAAK,YAAY;YACf,OAAO,cAAc,CAAC,WAAW,CAAC;QACpC;YACE,MAAM,IAAI,UAAU,CAClB,oCAAoC,KAAK,uDAAuD,CACjG,CAAC;IACN,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACvD,MAAM,IAAI,UAAU,CAAC,yBAAyB,IAAI,8BAA8B,CAAC,CAAC;IACpF,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1D,MAAM,IAAI,UAAU,CAClB,iCAAiC,IAAI,iCAAiC,CACvE,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7D,MAAM,IAAI,UAAU,CAClB,6BAA6B,IAAI,oCAAoC,CACtE,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACnE,MAAM,IAAI,UAAU,CAClB,4BAA4B,OAAO,iCAAiC,CACrE,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// execution flag is added here once and both surfaces pick it up.
|
|
4
4
|
|
|
5
5
|
import type { Command } from "commander";
|
|
6
|
-
import type { AgentExecFlags, RunMode, ServiceTierFlag, ThinkingFlag } from "../resources/run/prepare.js";
|
|
6
|
+
import type { AgentExecFlags, HarnessFlag, RunMode, ServiceTierFlag, ThinkingFlag } from "../resources/run/prepare.js";
|
|
7
7
|
|
|
8
8
|
/** Commander collector for repeatable string options. */
|
|
9
9
|
export const collect = (value: string, previous: string[]): string[] => [...previous, value];
|
|
@@ -27,6 +27,7 @@ export interface AgentExecOptions {
|
|
|
27
27
|
mode?: string;
|
|
28
28
|
serviceTier?: string;
|
|
29
29
|
thinking?: string;
|
|
30
|
+
harness?: string;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
/**
|
|
@@ -54,7 +55,8 @@ export function addAgentExecFlags(command: Command, requireMessage = false): Com
|
|
|
54
55
|
.option("--auto-approve", "automatically approve all tool executions")
|
|
55
56
|
.option("--mode <mode>", 'interaction mode: "agent" (default) or "plan" (read-only)')
|
|
56
57
|
.option("--service-tier <tier>", 'model service tier: "standard" (default) or "fast" (requires --model naming a model with a fast tier; billed at fast rates)')
|
|
57
|
-
.option("--thinking <mode>", 'extended reasoning: "disabled" (default) or "enabled" (requires --model naming a thinking-capable model; billed at base rates, uses more output tokens)')
|
|
58
|
+
.option("--thinking <mode>", 'extended reasoning: "disabled" (default) or "enabled" (requires --model naming a thinking-capable model; billed at base rates, uses more output tokens)')
|
|
59
|
+
.option("--harness <harness>", 'execution harness for the new session: "native" (default) or "cursor"');
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
/** Map parsed commander options onto the shared {@link AgentExecFlags} shape. */
|
|
@@ -77,5 +79,6 @@ export function toAgentExecFlags(options: AgentExecOptions): AgentExecFlags {
|
|
|
77
79
|
mode: (options.mode ?? "") as RunMode,
|
|
78
80
|
serviceTier: (options.serviceTier ?? "") as ServiceTierFlag,
|
|
79
81
|
thinking: (options.thinking ?? "") as ThinkingFlag,
|
|
82
|
+
harness: (options.harness ?? "") as HarnessFlag,
|
|
80
83
|
};
|
|
81
84
|
}
|
package/src/commands/run.ts
CHANGED
|
@@ -173,6 +173,9 @@ async function runResolvedAgent(
|
|
|
173
173
|
|
|
174
174
|
const prepared = await prepareAgentExec(toAgentExecFlags(options), client.stigmer, org, stderrProgress(), {
|
|
175
175
|
cloudBackend: isCloudMode(client.config),
|
|
176
|
+
// run opts into the account default_harness fill; draft deliberately
|
|
177
|
+
// does not (see the option's doc comment for the D5 rationale).
|
|
178
|
+
applyAccountHarnessDefault: true,
|
|
176
179
|
});
|
|
177
180
|
await executeResolvedAgent({
|
|
178
181
|
agent,
|
package/src/commands/up.ts
CHANGED
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
// outcome. The launcher (and the heavy resolvers it pulls in) load lazily so
|
|
7
7
|
// `--help` stays fast (DD-001).
|
|
8
8
|
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
9
11
|
import type { Command } from "commander";
|
|
10
12
|
import { CommandResult, type OutputFlags, renderResult } from "../output/index.js";
|
|
11
|
-
import { SERVER_PORT } from "../local/constants.js";
|
|
13
|
+
import { HEALTH_STATE_FILE, SERVER_PORT } from "../local/constants.js";
|
|
12
14
|
import { addResultFlags, resultFormat } from "./shared.js";
|
|
13
15
|
|
|
14
16
|
interface UpFlags extends OutputFlags {
|
|
@@ -16,15 +18,17 @@ interface UpFlags extends OutputFlags {
|
|
|
16
18
|
web?: boolean; // false when --no-web is passed
|
|
17
19
|
}
|
|
18
20
|
|
|
21
|
+
// The server serves the web console from its unified port (DD-012); the
|
|
22
|
+
// flag suppresses probing/reporting it, not the serving itself (one
|
|
23
|
+
// process, one origin — there is no separate console to not-start).
|
|
24
|
+
const NO_WEB_HELP = "don't report the web console URL";
|
|
25
|
+
|
|
19
26
|
export function registerUp(program: Command): void {
|
|
20
27
|
const up = program
|
|
21
28
|
.command("up")
|
|
22
29
|
.description("start the local Stigmer stack (server, runner, Temporal)")
|
|
23
30
|
.option("--server-only", "start only the control plane (no runners)")
|
|
24
|
-
|
|
25
|
-
// local web console, so the stack is headless either way (use the cloud
|
|
26
|
-
// console at app.stigmer.ai for a UI).
|
|
27
|
-
.option("--no-web", "no-op: this CLI does not serve a local web console")
|
|
31
|
+
.option("--no-web", NO_WEB_HELP)
|
|
28
32
|
.action((options: UpFlags) =>
|
|
29
33
|
runUp({ serverOnly: options.serverOnly === true, noWeb: options.web === false }, options),
|
|
30
34
|
);
|
|
@@ -33,7 +37,7 @@ export function registerUp(program: Command): void {
|
|
|
33
37
|
const server = up
|
|
34
38
|
.command("server")
|
|
35
39
|
.description("start only the control plane (no runners)")
|
|
36
|
-
.option("--no-web",
|
|
40
|
+
.option("--no-web", NO_WEB_HELP)
|
|
37
41
|
.action((options: UpFlags) => runUp({ serverOnly: true, noWeb: options.web === false }, options));
|
|
38
42
|
addResultFlags(server);
|
|
39
43
|
}
|
|
@@ -46,6 +50,20 @@ async function runUp(opts: { serverOnly: boolean; noWeb: boolean }, flags: Outpu
|
|
|
46
50
|
const result = CommandResult.success(opts.serverOnly ? "Stigmer control plane is up" : "Stigmer local stack is up");
|
|
47
51
|
const section = result.addSection("Endpoints");
|
|
48
52
|
section.field("server", `http://localhost:${SERVER_PORT}`);
|
|
53
|
+
if (await consoleReported()) {
|
|
54
|
+
// Same origin as the API: the server serves the console (DD-012). Only
|
|
55
|
+
// printed when the daemon's probe found a bundled export — a dev-tree
|
|
56
|
+
// server without one must not advertise a dead URL.
|
|
57
|
+
section.field("console", `http://localhost:${SERVER_PORT}`);
|
|
58
|
+
}
|
|
49
59
|
result.hint("Check status with: stigmer status").hint("Stop it with: stigmer down");
|
|
50
60
|
renderResult(result, resultFormat(flags));
|
|
51
61
|
}
|
|
62
|
+
|
|
63
|
+
/** Whether the daemon recorded the web console as running (its own probe). */
|
|
64
|
+
async function consoleReported(): Promise<boolean> {
|
|
65
|
+
const { dataDir } = await import("../local/paths.js");
|
|
66
|
+
const { loadHealthState } = await import("../local/state/health-state.js");
|
|
67
|
+
const health = loadHealthState(join(dataDir(homedir()), HEALTH_STATE_FILE));
|
|
68
|
+
return health?.components["web-console"]?.state === "running";
|
|
69
|
+
}
|
|
@@ -109,7 +109,7 @@ describe("resolveConsoleURL", () => {
|
|
|
109
109
|
});
|
|
110
110
|
|
|
111
111
|
it("uses the local web-console port for the local backend", () => {
|
|
112
|
-
expect(resolveConsoleURL("local", {} as NodeJS.ProcessEnv)).toBe("http://localhost:
|
|
112
|
+
expect(resolveConsoleURL("local", {} as NodeJS.ProcessEnv)).toBe("http://localhost:7234");
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
it("uses the cloud console URL for the cloud backend", () => {
|
package/src/config/resolve.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// precedence keeps every call site consistent (mirrors the Go CLI's Resolve*).
|
|
4
4
|
|
|
5
5
|
import { CliExitError, ExitCode } from "../errors/index.js";
|
|
6
|
-
import {
|
|
6
|
+
import { SERVER_PORT } from "../local/constants.js";
|
|
7
7
|
import { type BackendType, type Config, isCloudMode } from "./config.js";
|
|
8
8
|
|
|
9
9
|
const DEFAULT_CLOUD_ENDPOINT = "api.stigmer.ai:443";
|
|
@@ -76,17 +76,20 @@ export function resolveOrganization(config: Config, flagOrg?: string): string {
|
|
|
76
76
|
/**
|
|
77
77
|
* Resolve the web console URL:
|
|
78
78
|
* 1. `STIGMER_CONSOLE_URL` (explicit override)
|
|
79
|
-
* 2. local backend → `http://localhost:{
|
|
79
|
+
* 2. local backend → `http://localhost:{SERVER_PORT}` — the server's own
|
|
80
|
+
* unified port serves the console since DD-012 (one origin for UI and
|
|
81
|
+
* API; the Go-era separate 8234 listener is retired)
|
|
80
82
|
* 3. cloud backend → {@link DEFAULT_CLOUD_CONSOLE_URL}
|
|
81
83
|
*
|
|
82
84
|
* The console origin is also the app origin that serves the hosted chat
|
|
83
85
|
* page (`/chat/<org>/<slug>`) and the embed loader (`/embed.js`), so
|
|
84
|
-
* share-link builders use this same resolver
|
|
86
|
+
* share-link builders use this same resolver — both routes live in the
|
|
87
|
+
* same static export the server serves.
|
|
85
88
|
*/
|
|
86
89
|
export function resolveConsoleURL(backendType: BackendType, env: NodeJS.ProcessEnv = process.env): string {
|
|
87
90
|
const override = env.STIGMER_CONSOLE_URL;
|
|
88
91
|
if (override !== undefined && override !== "") return override;
|
|
89
|
-
if (backendType === "local") return `http://localhost:${
|
|
92
|
+
if (backendType === "local") return `http://localhost:${SERVER_PORT}`;
|
|
90
93
|
return DEFAULT_CLOUD_CONSOLE_URL;
|
|
91
94
|
}
|
|
92
95
|
|
package/src/local/constants.ts
CHANGED
|
@@ -7,12 +7,16 @@
|
|
|
7
7
|
// runner-poll can never drift (see the T05 plan's "Critical correctness
|
|
8
8
|
// finding").
|
|
9
9
|
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Port `stigmer-server` listens on (gRPC). Matches the Go CLI's `DaemonPort`.
|
|
12
|
+
*
|
|
13
|
+
* This is also the web console's origin: since DD-012 the server serves the
|
|
14
|
+
* console's static export on this same unified port (lane 4), so the Go-era
|
|
15
|
+
* WEB_CONSOLE_PORT (8234, a separate CLI-embedded listener) is retired —
|
|
16
|
+
* one process, one origin, no CORS hop.
|
|
17
|
+
*/
|
|
11
18
|
export const SERVER_PORT = 7234;
|
|
12
19
|
|
|
13
|
-
/** Port the embedded web console is served on (7xxx=API, 8xxx=UI convention). */
|
|
14
|
-
export const WEB_CONSOLE_PORT = 8234;
|
|
15
|
-
|
|
16
20
|
/** Temporal frontend gRPC port (dev server default). */
|
|
17
21
|
export const TEMPORAL_PORT = 7233;
|
|
18
22
|
|
|
@@ -11,7 +11,7 @@ const config: DaemonConfig = {
|
|
|
11
11
|
temporalAddress: "127.0.0.1:7233",
|
|
12
12
|
serverOnly: false,
|
|
13
13
|
noWeb: false,
|
|
14
|
-
|
|
14
|
+
server: { nodeBin: "/bin/node", entryPath: "/repo/server/dist/main.js", appDir: "/repo/server" },
|
|
15
15
|
runner: { nodeBin: "/bin/node", entryPath: "/repo/runner/dist/main.js", appDir: "/repo/runner" },
|
|
16
16
|
};
|
|
17
17
|
|
|
@@ -133,6 +133,14 @@ describe("buildComponents", () => {
|
|
|
133
133
|
expect(runner.resolve().args).toEqual(["/repo/runner/dist/main.js"]);
|
|
134
134
|
});
|
|
135
135
|
|
|
136
|
+
// The TS server child is `node <entry>` — the runner's launch shape.
|
|
137
|
+
it("spawns the node-shape server as node + entry", () => {
|
|
138
|
+
const [server] = buildComponents(config, {});
|
|
139
|
+
const spawn = server.resolve();
|
|
140
|
+
expect(spawn.command).toBe("/bin/node");
|
|
141
|
+
expect(spawn.args).toEqual(["/repo/server/dist/main.js"]);
|
|
142
|
+
});
|
|
143
|
+
|
|
136
144
|
it("omits the runner in server-only mode", () => {
|
|
137
145
|
const components = buildComponents({ ...config, serverOnly: true }, {});
|
|
138
146
|
expect(components.map((c) => c.name)).toEqual(["stigmer-server"]);
|
|
@@ -91,9 +91,11 @@ export function buildComponents(config: DaemonConfig, base: NodeJS.ProcessEnv =
|
|
|
91
91
|
name: "stigmer-server",
|
|
92
92
|
pidFile: join(config.dataDir, SERVER_PID_FILE),
|
|
93
93
|
critical: true,
|
|
94
|
+
// The server is `node <entry>` — the runner's launch shape, one child
|
|
95
|
+
// contract for both components.
|
|
94
96
|
resolve: () => ({
|
|
95
|
-
command: config.
|
|
96
|
-
args: [],
|
|
97
|
+
command: config.server.nodeBin,
|
|
98
|
+
args: [config.server.entryPath],
|
|
97
99
|
env: buildServerEnv(config, base),
|
|
98
100
|
logFile: join(config.logDir, "stigmer-server.log"),
|
|
99
101
|
}),
|
|
@@ -128,7 +128,7 @@ describe("runInternalDaemon (full body with fakes)", () => {
|
|
|
128
128
|
temporalAddress: "127.0.0.1:7233",
|
|
129
129
|
serverOnly: false,
|
|
130
130
|
noWeb: true,
|
|
131
|
-
|
|
131
|
+
server: { nodeBin: "node-cmd", entryPath: join(data, "server-entry.js"), appDir: data },
|
|
132
132
|
runner: { nodeBin: "node-cmd", entryPath: join(data, "entry.js"), appDir: data },
|
|
133
133
|
};
|
|
134
134
|
|
|
@@ -8,7 +8,11 @@ const baseInputs: DaemonEnvInputs = {
|
|
|
8
8
|
temporalAddress: "127.0.0.1:7233",
|
|
9
9
|
serverOnly: false,
|
|
10
10
|
noWeb: false,
|
|
11
|
-
|
|
11
|
+
server: {
|
|
12
|
+
nodeBin: "/usr/bin/node",
|
|
13
|
+
entryPath: "/repo/server/dist/main.js",
|
|
14
|
+
appDir: "/repo/server",
|
|
15
|
+
},
|
|
12
16
|
runner: { nodeBin: "/usr/bin/node", entryPath: "/repo/runner/dist/main.js", appDir: "/repo/runner" },
|
|
13
17
|
};
|
|
14
18
|
|
|
@@ -23,7 +27,11 @@ describe("buildDaemonEnv + readDaemonConfig", () => {
|
|
|
23
27
|
temporalAddress: "127.0.0.1:7233",
|
|
24
28
|
serverOnly: false,
|
|
25
29
|
noWeb: false,
|
|
26
|
-
|
|
30
|
+
server: {
|
|
31
|
+
nodeBin: "/usr/bin/node",
|
|
32
|
+
entryPath: "/repo/server/dist/main.js",
|
|
33
|
+
appDir: "/repo/server",
|
|
34
|
+
},
|
|
27
35
|
runner: { nodeBin: "/usr/bin/node", entryPath: "/repo/runner/dist/main.js", appDir: "/repo/runner" },
|
|
28
36
|
cursorApiKey: undefined,
|
|
29
37
|
anthropicApiKey: undefined,
|
|
@@ -90,8 +98,11 @@ describe("buildDaemonEnv + readDaemonConfig", () => {
|
|
|
90
98
|
expect(readDaemonConfig(env)).not.toHaveProperty("openaiApiKey");
|
|
91
99
|
});
|
|
92
100
|
|
|
93
|
-
it("requires the data dir and server
|
|
101
|
+
it("requires the data dir and the full server launch triple", () => {
|
|
94
102
|
expect(() => readDaemonConfig({})).toThrow(/STIGMER_DATA_DIR/);
|
|
95
|
-
expect(() => readDaemonConfig({ STIGMER_DATA_DIR: "/x" })).toThrow(/
|
|
103
|
+
expect(() => readDaemonConfig({ STIGMER_DATA_DIR: "/x" })).toThrow(/STIGMER_SERVER_NODE_BIN/);
|
|
104
|
+
expect(() => readDaemonConfig({ STIGMER_DATA_DIR: "/x", STIGMER_SERVER_NODE_BIN: "/usr/bin/node" })).toThrow(
|
|
105
|
+
/STIGMER_SERVER_ENTRY/,
|
|
106
|
+
);
|
|
96
107
|
});
|
|
97
108
|
});
|
package/src/local/daemon/env.ts
CHANGED
|
@@ -12,7 +12,9 @@ export const DaemonEnvVar = {
|
|
|
12
12
|
TemporalAddress: "TEMPORAL_SERVICE_ADDRESS",
|
|
13
13
|
ServerOnly: "STIGMER_SERVER_ONLY",
|
|
14
14
|
NoWeb: "STIGMER_NO_WEB",
|
|
15
|
-
|
|
15
|
+
ServerNodeBin: "STIGMER_SERVER_NODE_BIN",
|
|
16
|
+
ServerEntry: "STIGMER_SERVER_ENTRY",
|
|
17
|
+
ServerAppDir: "STIGMER_SERVER_APP_DIR",
|
|
16
18
|
RunnerNodeBin: "STIGMER_RUNNER_NODE_BIN",
|
|
17
19
|
RunnerEntry: "STIGMER_RUNNER_ENTRY",
|
|
18
20
|
RunnerAppDir: "STIGMER_RUNNER_APP_DIR",
|
|
@@ -30,6 +32,18 @@ export interface RunnerLaunch {
|
|
|
30
32
|
appDir: string;
|
|
31
33
|
}
|
|
32
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Resolved server launch coordinates: a node binary + bundled entry — the
|
|
37
|
+
* same launch shape as the runner. (Until #25 go-server-retirement this was
|
|
38
|
+
* a discriminated union whose "binary" variant carried the Go rollback
|
|
39
|
+
* executable.)
|
|
40
|
+
*/
|
|
41
|
+
export interface ServerLaunch {
|
|
42
|
+
nodeBin: string;
|
|
43
|
+
entryPath: string;
|
|
44
|
+
appDir: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
33
47
|
/** The daemon's resolved configuration, parsed from the environment. */
|
|
34
48
|
export interface DaemonConfig {
|
|
35
49
|
dataDir: string;
|
|
@@ -38,7 +52,7 @@ export interface DaemonConfig {
|
|
|
38
52
|
temporalAddress: string;
|
|
39
53
|
serverOnly: boolean;
|
|
40
54
|
noWeb: boolean;
|
|
41
|
-
|
|
55
|
+
server: ServerLaunch;
|
|
42
56
|
runner?: RunnerLaunch;
|
|
43
57
|
cursorApiKey?: string;
|
|
44
58
|
anthropicApiKey?: string;
|
|
@@ -55,7 +69,7 @@ export interface DaemonEnvInputs {
|
|
|
55
69
|
temporalAddress: string;
|
|
56
70
|
serverOnly: boolean;
|
|
57
71
|
noWeb: boolean;
|
|
58
|
-
|
|
72
|
+
server: ServerLaunch;
|
|
59
73
|
runner?: RunnerLaunch;
|
|
60
74
|
// Anthropic API key resolved by the launcher (env > config file). Must be
|
|
61
75
|
// written into the daemon env explicitly: unlike a shell-exported key, a key
|
|
@@ -83,7 +97,9 @@ export function buildDaemonEnv(inputs: DaemonEnvInputs, base: NodeJS.ProcessEnv
|
|
|
83
97
|
env[DaemonEnvVar.LogDir] = inputs.logDir;
|
|
84
98
|
env[DaemonEnvVar.TemporalManaged] = String(inputs.temporalManaged);
|
|
85
99
|
env[DaemonEnvVar.TemporalAddress] = inputs.temporalAddress;
|
|
86
|
-
env[DaemonEnvVar.
|
|
100
|
+
env[DaemonEnvVar.ServerNodeBin] = inputs.server.nodeBin;
|
|
101
|
+
env[DaemonEnvVar.ServerEntry] = inputs.server.entryPath;
|
|
102
|
+
env[DaemonEnvVar.ServerAppDir] = inputs.server.appDir;
|
|
87
103
|
if (inputs.serverOnly) env[DaemonEnvVar.ServerOnly] = "true";
|
|
88
104
|
if (inputs.noWeb) env[DaemonEnvVar.NoWeb] = "1";
|
|
89
105
|
if (inputs.runner !== undefined && !inputs.serverOnly) {
|
|
@@ -112,7 +128,7 @@ export function readDaemonConfig(env: NodeJS.ProcessEnv = process.env): DaemonCo
|
|
|
112
128
|
temporalAddress: env[DaemonEnvVar.TemporalAddress] ?? "127.0.0.1:7233",
|
|
113
129
|
serverOnly,
|
|
114
130
|
noWeb: env[DaemonEnvVar.NoWeb] === "1",
|
|
115
|
-
|
|
131
|
+
server: readServer(env),
|
|
116
132
|
runner: serverOnly ? undefined : runner,
|
|
117
133
|
cursorApiKey: nonEmpty(env[DaemonEnvVar.CursorApiKey]),
|
|
118
134
|
anthropicApiKey: nonEmpty(env[DaemonEnvVar.AnthropicApiKey]),
|
|
@@ -122,6 +138,18 @@ export function readDaemonConfig(env: NodeJS.ProcessEnv = process.env): DaemonCo
|
|
|
122
138
|
};
|
|
123
139
|
}
|
|
124
140
|
|
|
141
|
+
function readServer(env: NodeJS.ProcessEnv): ServerLaunch {
|
|
142
|
+
const nodeBin = env[DaemonEnvVar.ServerNodeBin];
|
|
143
|
+
const entryPath = env[DaemonEnvVar.ServerEntry];
|
|
144
|
+
const appDir = env[DaemonEnvVar.ServerAppDir];
|
|
145
|
+
if (!nodeBin || !entryPath || !appDir) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
`the ${DaemonEnvVar.ServerNodeBin}/${DaemonEnvVar.ServerEntry}/${DaemonEnvVar.ServerAppDir} triple is required for the daemon process`,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
return { nodeBin, entryPath, appDir };
|
|
151
|
+
}
|
|
152
|
+
|
|
125
153
|
function readRunner(env: NodeJS.ProcessEnv): RunnerLaunch | undefined {
|
|
126
154
|
const nodeBin = env[DaemonEnvVar.RunnerNodeBin];
|
|
127
155
|
const entryPath = env[DaemonEnvVar.RunnerEntry];
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// `down` (signal + wait + safety-net cleanup), and a liveness check.
|
|
3
3
|
//
|
|
4
4
|
// `up` resolves every heavy dependency in the foreground (Temporal binary,
|
|
5
|
-
// server
|
|
5
|
+
// server launch, runner entry) so failures surface with a clear message before
|
|
6
6
|
// a detached daemon is spawned, then re-execs this same CLI as the hidden
|
|
7
7
|
// `internal-daemon` and waits until the server's gRPC port answers.
|
|
8
8
|
|
|
@@ -24,7 +24,7 @@ import { rotateLogs } from "../state/log-rotation.js";
|
|
|
24
24
|
import { resolveApiKey, resolveProvider } from "../llm-config.js";
|
|
25
25
|
import { resolveOperatorIdentity } from "../operator-config.js";
|
|
26
26
|
import { ensureRunner } from "../runtime/runner.js";
|
|
27
|
-
import {
|
|
27
|
+
import { ensureServer } from "../runtime/server.js";
|
|
28
28
|
import { TemporalManager } from "../temporal/manager.js";
|
|
29
29
|
import { buildDaemonEnv, type DaemonEnvInputs } from "./env.js";
|
|
30
30
|
|
|
@@ -64,7 +64,8 @@ export async function up(options: UpOptions = {}, home: string = homedir()): Pro
|
|
|
64
64
|
await temporal.ensureInstalled();
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
// Resolves the server (repo tree or the acquired @stigmer/server-slim).
|
|
68
|
+
const server = ensureServer({ home });
|
|
68
69
|
const runner = options.serverOnly === true ? undefined : ensureRunner({ home });
|
|
69
70
|
|
|
70
71
|
const env = buildDaemonEnv(
|
|
@@ -75,7 +76,7 @@ export async function up(options: UpOptions = {}, home: string = homedir()): Pro
|
|
|
75
76
|
temporalAddress: temporal.address,
|
|
76
77
|
serverOnly: options.serverOnly === true,
|
|
77
78
|
noWeb: options.noWeb === true,
|
|
78
|
-
|
|
79
|
+
server,
|
|
79
80
|
runner,
|
|
80
81
|
...resolveLlmKeyInputs(config),
|
|
81
82
|
...resolveOperatorIdentityInputs(config),
|