@stigmer/cli 3.12.8 → 3.12.9
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/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/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
|
@@ -32,6 +32,15 @@ export type ServiceTierFlag = "" | "standard" | "fast";
|
|
|
32
32
|
*/
|
|
33
33
|
export type ThinkingFlag = "" | "disabled" | "enabled";
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* The `--harness` flag's value space (oss#293): empty means unset — the
|
|
37
|
+
* account preference may fill it (see {@link prepareAgentExec}), and when
|
|
38
|
+
* nothing resolves the server defaults the session to native. Deliberately
|
|
39
|
+
* only the two shipped engines, mirroring the proto validation on
|
|
40
|
+
* `IdentityAccountPreferences.default_harness`.
|
|
41
|
+
*/
|
|
42
|
+
export type HarnessFlag = "" | "native" | "cursor";
|
|
43
|
+
|
|
35
44
|
/** Raw agent-execution flags shared by `run` and `draft` (Go's agentExecFlags). */
|
|
36
45
|
export interface AgentExecFlags {
|
|
37
46
|
readonly message: string;
|
|
@@ -51,6 +60,7 @@ export interface AgentExecFlags {
|
|
|
51
60
|
readonly mode: RunMode;
|
|
52
61
|
readonly serviceTier: ServiceTierFlag;
|
|
53
62
|
readonly thinking: ThinkingFlag;
|
|
63
|
+
readonly harness: HarnessFlag;
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
/**
|
|
@@ -71,6 +81,13 @@ export interface PreparedRun {
|
|
|
71
81
|
readonly mode: RunMode;
|
|
72
82
|
readonly serviceTier: ServiceTierFlag;
|
|
73
83
|
readonly thinking: ThinkingFlag;
|
|
84
|
+
/**
|
|
85
|
+
* The RESOLVED harness for the new session: the explicit flag, else the
|
|
86
|
+
* account preference (when the caller opted in), else "" — which stays off
|
|
87
|
+
* the wire so the server default (native) applies. Also drives the header's
|
|
88
|
+
* visibility row: a cursor session is never entered silently.
|
|
89
|
+
*/
|
|
90
|
+
readonly harness: HarnessFlag;
|
|
74
91
|
}
|
|
75
92
|
|
|
76
93
|
/** Optional behavior switches for {@link prepareAgentExec}. */
|
|
@@ -78,11 +95,24 @@ export interface PrepareAgentExecOptions {
|
|
|
78
95
|
/**
|
|
79
96
|
* When `true` (the caller's backend is Stigmer Cloud) and `--model` is
|
|
80
97
|
* omitted, the model is filled from the caller's account preference
|
|
81
|
-
* (`IdentityAccountPreferences.
|
|
82
|
-
* Local mode has no IdentityAccount, so callers pass
|
|
83
|
-
* the omitted model keeps resolving to the platform
|
|
98
|
+
* (`IdentityAccountPreferences.default_*_model` for the resolved harness)
|
|
99
|
+
* via `whoAmI()`. Local mode has no IdentityAccount, so callers pass
|
|
100
|
+
* `false` there and the omitted model keeps resolving to the platform
|
|
101
|
+
* default.
|
|
84
102
|
*/
|
|
85
103
|
readonly cloudBackend?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* When `true` and `--harness` is omitted, the harness is filled from the
|
|
106
|
+
* caller's account preference (`IdentityAccountPreferences.default_harness`)
|
|
107
|
+
* on cloud. `run` opts in; `draft` deliberately does not: draft executes the
|
|
108
|
+
* seedpack's system creator agents (a utility flow, not the user's own
|
|
109
|
+
* conversation), which are built and exercised on the native harness —
|
|
110
|
+
* silently rerouting them onto the cursor engine (different toolset,
|
|
111
|
+
* premium billing tier) would fail the least-surprise test. An explicit
|
|
112
|
+
* `--harness` on draft still wins; only the silent preference fill is
|
|
113
|
+
* scoped out. Owner-ratified (D5, 2026-08-23).
|
|
114
|
+
*/
|
|
115
|
+
readonly applyAccountHarnessDefault?: boolean;
|
|
86
116
|
}
|
|
87
117
|
|
|
88
118
|
/**
|
|
@@ -100,16 +130,28 @@ export async function prepareAgentExec(
|
|
|
100
130
|
validateMode(flags.mode);
|
|
101
131
|
validateServiceTier(flags.serviceTier);
|
|
102
132
|
validateThinking(flags.thinking);
|
|
133
|
+
validateHarness(flags.harness);
|
|
103
134
|
|
|
104
|
-
// Layered
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
135
|
+
// Layered seeds (oss#293, DD-003): explicit flag > account preference
|
|
136
|
+
// (cloud only) > platform default. Harness resolves first because the model
|
|
137
|
+
// fill is harness-aware: a cursor session fills from default_cursor_model,
|
|
138
|
+
// everything else from default_native_model. `run` and `draft` always
|
|
139
|
+
// create a NEW session (threading lives in `resume`, which does not pass
|
|
140
|
+
// through here), so neither fill can ever contradict an existing session's
|
|
141
|
+
// immutable harness. One whoAmI round trip serves both fills, and it is
|
|
142
|
+
// skipped entirely when explicit flags leave nothing to fill.
|
|
143
|
+
const wantsHarnessFill = flags.harness === "" && options?.applyAccountHarnessDefault === true;
|
|
144
|
+
const wantsModelFill = flags.model === "";
|
|
145
|
+
const accountDefaults =
|
|
146
|
+
options?.cloudBackend === true && (wantsHarnessFill || wantsModelFill)
|
|
147
|
+
? await resolveAccountExecutionDefaults(client)
|
|
148
|
+
: NO_ACCOUNT_DEFAULTS;
|
|
149
|
+
const harness = flags.harness !== "" ? flags.harness : wantsHarnessFill ? accountDefaults.harness : "";
|
|
150
|
+
const model = wantsModelFill
|
|
151
|
+
? harness === "cursor"
|
|
152
|
+
? accountDefaults.cursorModel
|
|
153
|
+
: accountDefaults.nativeModel
|
|
154
|
+
: flags.model;
|
|
113
155
|
|
|
114
156
|
const workspaceEntries = parseWorkspaceEntries(flags.workspace, flags.branch, flags.commit);
|
|
115
157
|
|
|
@@ -144,23 +186,43 @@ export async function prepareAgentExec(
|
|
|
144
186
|
mode: flags.mode,
|
|
145
187
|
serviceTier: flags.serviceTier,
|
|
146
188
|
thinking: flags.thinking,
|
|
189
|
+
harness,
|
|
147
190
|
};
|
|
148
191
|
}
|
|
149
192
|
|
|
193
|
+
/** The account's execution defaults, "" for anything undeclared. */
|
|
194
|
+
interface AccountExecutionDefaults {
|
|
195
|
+
readonly harness: HarnessFlag;
|
|
196
|
+
readonly nativeModel: string;
|
|
197
|
+
readonly cursorModel: string;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const NO_ACCOUNT_DEFAULTS: AccountExecutionDefaults = { harness: "", nativeModel: "", cursorModel: "" };
|
|
201
|
+
|
|
150
202
|
/**
|
|
151
|
-
* Best-effort read of the caller's
|
|
152
|
-
* (
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
203
|
+
* Best-effort read of the caller's execution defaults
|
|
204
|
+
* (`IdentityAccountPreferences.default_harness` / `default_*_model`) in one
|
|
205
|
+
* whoAmI round trip. Any failure — network, auth, a backend without
|
|
206
|
+
* IdentityAccount — resolves to no defaults and the run proceeds exactly as
|
|
207
|
+
* unfilled flags do today: a missing preference must never fail a run.
|
|
208
|
+
*
|
|
209
|
+
* The persisted harness value is allowlist-guarded to the shipped engines
|
|
210
|
+
* (the same guard the web launcher's useAccountExecutionDefaults applies):
|
|
211
|
+
* a client must not trust stored data it did not write, so anything outside
|
|
212
|
+
* native/cursor is treated as undeclared rather than stamped on the wire.
|
|
157
213
|
*/
|
|
158
|
-
async function
|
|
214
|
+
async function resolveAccountExecutionDefaults(client: Stigmer): Promise<AccountExecutionDefaults> {
|
|
159
215
|
try {
|
|
160
216
|
const account = await client.identityAccount.whoAmI();
|
|
161
|
-
|
|
217
|
+
const prefs = account.spec?.preferences;
|
|
218
|
+
const declared = prefs?.defaultHarness;
|
|
219
|
+
return {
|
|
220
|
+
harness: declared === "native" || declared === "cursor" ? declared : "",
|
|
221
|
+
nativeModel: prefs?.defaultNativeModel ?? "",
|
|
222
|
+
cursorModel: prefs?.defaultCursorModel ?? "",
|
|
223
|
+
};
|
|
162
224
|
} catch {
|
|
163
|
-
return
|
|
225
|
+
return NO_ACCOUNT_DEFAULTS;
|
|
164
226
|
}
|
|
165
227
|
}
|
|
166
228
|
|
|
@@ -227,3 +289,19 @@ export function validateThinking(mode: string): asserts mode is ThinkingFlag {
|
|
|
227
289
|
);
|
|
228
290
|
}
|
|
229
291
|
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Validate the `--harness` flag. Empty means "use default": the account
|
|
295
|
+
* preference when the caller opted in, else the platform default (native).
|
|
296
|
+
* Only the shipped engines are accepted — other harness names that appear in
|
|
297
|
+
* UI metadata (copilot, codex, ...) have no proto mapping yet, so rejecting
|
|
298
|
+
* them here is honest, and this check catches spelling errors before a
|
|
299
|
+
* network round trip.
|
|
300
|
+
*/
|
|
301
|
+
export function validateHarness(harness: string): asserts harness is HarnessFlag {
|
|
302
|
+
if (harness !== "" && harness !== "native" && harness !== "cursor") {
|
|
303
|
+
throw new UsageError(
|
|
304
|
+
`invalid --harness value "${harness}": must be "native" or "cursor"`,
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
}
|