@intentic/sandbox-contract 1.245.0 → 1.246.1
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 +17 -1
- package/dist/command-classes.d.ts +6 -3
- package/dist/command-classes.d.ts.map +1 -1
- package/dist/command-classes.js +43 -18
- package/dist/command-classes.js.map +1 -1
- package/dist/contracts/{cursor.contract.d.ts → accounts.contract.d.ts} +102 -3
- package/dist/contracts/accounts.contract.d.ts.map +1 -0
- package/dist/contracts/accounts.contract.js +61 -0
- package/dist/contracts/accounts.contract.js.map +1 -0
- package/dist/contracts/agents.contract.d.ts +121 -0
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.js +4 -4
- package/dist/contracts/agents.contract.js.map +1 -1
- package/dist/contracts/ci.contract.d.ts +2 -0
- package/dist/contracts/ci.contract.d.ts.map +1 -1
- package/dist/contracts/host.contract.d.ts +35 -0
- package/dist/contracts/host.contract.d.ts.map +1 -1
- package/dist/contracts/host.contract.js +3 -2
- package/dist/contracts/host.contract.js.map +1 -1
- package/dist/contracts/personas.contract.d.ts +4 -2
- package/dist/contracts/personas.contract.d.ts.map +1 -1
- package/dist/contracts/runner.contract.d.ts +2 -2
- package/dist/contracts/settings.contract.d.ts +2 -51
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.d.ts +80 -30
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.js +26 -17
- package/dist/contracts/system.contract.js.map +1 -1
- package/dist/definition.d.ts +4 -8
- package/dist/definition.d.ts.map +1 -1
- package/dist/documents.d.ts +0 -1
- package/dist/documents.d.ts.map +1 -1
- package/dist/documents.js +1 -2
- package/dist/documents.js.map +1 -1
- package/dist/embed.d.ts +23 -0
- package/dist/embed.d.ts.map +1 -0
- package/dist/embed.js +84 -0
- package/dist/embed.js.map +1 -0
- package/dist/events.d.ts +21 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +5 -2
- package/dist/events.js.map +1 -1
- package/dist/history-state.d.ts.map +1 -1
- package/dist/history-state.js +2 -0
- package/dist/history-state.js.map +1 -1
- package/dist/index.d.ts +354 -335
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -13
- package/dist/index.js.map +1 -1
- package/dist/peer-dial.d.ts +33 -0
- package/dist/peer-dial.d.ts.map +1 -0
- package/dist/peer-dial.js +79 -0
- package/dist/peer-dial.js.map +1 -0
- package/dist/peer-mcp-server.d.ts +36 -0
- package/dist/peer-mcp-server.d.ts.map +1 -0
- package/dist/peer-mcp-server.js +71 -0
- package/dist/peer-mcp-server.js.map +1 -0
- package/dist/provider-specs.d.ts +38 -20
- package/dist/provider-specs.d.ts.map +1 -1
- package/dist/provider-specs.js +39 -13
- package/dist/provider-specs.js.map +1 -1
- package/dist/quick-model.d.ts.map +1 -1
- package/dist/quick-model.js +2 -1
- package/dist/quick-model.js.map +1 -1
- package/dist/runtime-state.d.ts +1 -1
- package/dist/runtime-state.js +1 -1
- package/dist/runtime-state.js.map +1 -1
- package/dist/safety-policy.d.ts +12 -3
- package/dist/safety-policy.d.ts.map +1 -1
- package/dist/safety-policy.js +30 -5
- package/dist/safety-policy.js.map +1 -1
- package/dist/schemas/agent.d.ts +6 -6
- package/dist/schemas/agent.d.ts.map +1 -1
- package/dist/schemas/agent.js +6 -2
- package/dist/schemas/agent.js.map +1 -1
- package/dist/schemas/agents.d.ts +42 -0
- package/dist/schemas/agents.d.ts.map +1 -1
- package/dist/schemas/agents.js +25 -4
- package/dist/schemas/agents.js.map +1 -1
- package/dist/schemas/automations.d.ts +11 -2
- package/dist/schemas/automations.d.ts.map +1 -1
- package/dist/schemas/automations.js +1 -1
- package/dist/schemas/automations.js.map +1 -1
- package/dist/schemas/ci.d.ts +6 -0
- package/dist/schemas/ci.d.ts.map +1 -1
- package/dist/schemas/ci.js +3 -2
- package/dist/schemas/ci.js.map +1 -1
- package/dist/schemas/context.d.ts +30 -0
- package/dist/schemas/context.d.ts.map +1 -0
- package/dist/schemas/context.js +34 -0
- package/dist/schemas/context.js.map +1 -0
- package/dist/schemas/{computers.d.ts → devices.d.ts} +154 -60
- package/dist/schemas/devices.d.ts.map +1 -0
- package/dist/schemas/devices.js +157 -0
- package/dist/schemas/devices.js.map +1 -0
- package/dist/schemas/hosts.d.ts +12 -0
- package/dist/schemas/hosts.d.ts.map +1 -1
- package/dist/schemas/hosts.js +1 -0
- package/dist/schemas/hosts.js.map +1 -1
- package/dist/schemas/issues.d.ts +0 -5
- package/dist/schemas/issues.d.ts.map +1 -1
- package/dist/schemas/issues.js +0 -1
- package/dist/schemas/issues.js.map +1 -1
- package/dist/schemas/personas.d.ts +5 -3
- package/dist/schemas/personas.d.ts.map +1 -1
- package/dist/schemas/personas.js +3 -2
- package/dist/schemas/personas.js.map +1 -1
- package/dist/schemas/provider-oauth.d.ts +48 -16
- package/dist/schemas/provider-oauth.d.ts.map +1 -1
- package/dist/schemas/provider-oauth.js +22 -20
- package/dist/schemas/provider-oauth.js.map +1 -1
- package/dist/schemas/settings.d.ts +1 -52
- package/dist/schemas/settings.d.ts.map +1 -1
- package/dist/schemas/settings.js +8 -11
- package/dist/schemas/settings.js.map +1 -1
- package/dist/schemas/terminal.js +9 -9
- package/dist/schemas/terminal.js.map +1 -1
- package/dist/schemas/usage.d.ts +0 -2
- package/dist/schemas/usage.d.ts.map +1 -1
- package/dist/schemas/usage.js +0 -2
- package/dist/schemas/usage.js.map +1 -1
- package/dist/shell-regions.d.ts +4 -0
- package/dist/shell-regions.d.ts.map +1 -0
- package/dist/shell-regions.js +156 -0
- package/dist/shell-regions.js.map +1 -0
- package/dist/workspace-state.d.ts +8 -0
- package/dist/workspace-state.d.ts.map +1 -1
- package/dist/workspace-state.js +13 -5
- package/dist/workspace-state.js.map +1 -1
- package/package.json +37 -4
- package/src/agent-catalog.ts +1 -1
- package/src/arrival.ts +3 -3
- package/src/command-classes.test.ts +195 -71
- package/src/command-classes.ts +148 -46
- package/src/contracts/accounts.contract.ts +94 -0
- package/src/contracts/agents.contract.ts +4 -3
- package/src/contracts/exit.contract.ts +2 -2
- package/src/contracts/host.contract.ts +17 -5
- package/src/contracts/settings.contract.ts +1 -1
- package/src/contracts/system.contract.ts +43 -24
- package/src/contracts/vpn.contract.ts +2 -2
- package/src/documents.test.ts +2 -1
- package/src/documents.ts +7 -11
- package/src/embed.test.ts +68 -0
- package/src/embed.ts +164 -0
- package/src/events.ts +30 -3
- package/src/history-state.ts +12 -3
- package/src/host-protocol.ts +2 -2
- package/src/index.ts +6 -14
- package/src/model-order.ts +1 -1
- package/src/peer-dial.test.ts +203 -0
- package/src/peer-dial.ts +163 -0
- package/src/peer-mcp-server.test.ts +104 -0
- package/src/peer-mcp-server.ts +144 -0
- package/src/provider-specs.test.ts +44 -17
- package/src/provider-specs.ts +147 -67
- package/src/quick-model.ts +10 -3
- package/src/routes.test.ts +6 -3
- package/src/runner-protocol.ts +1 -1
- package/src/runtime-state.ts +2 -2
- package/src/safety-policy.test.ts +88 -0
- package/src/safety-policy.ts +84 -14
- package/src/schemas/agent.ts +41 -13
- package/src/schemas/agents.ts +65 -4
- package/src/schemas/automations.ts +6 -4
- package/src/schemas/capabilities.ts +4 -4
- package/src/schemas/ci.ts +23 -6
- package/src/schemas/context.ts +87 -0
- package/src/schemas/{computers.ts → devices.ts} +190 -107
- package/src/schemas/hosts.ts +5 -1
- package/src/schemas/issues.ts +0 -4
- package/src/schemas/personas.ts +8 -3
- package/src/schemas/provider-oauth.ts +49 -52
- package/src/schemas/settings.ts +30 -54
- package/src/schemas/terminal.ts +12 -12
- package/src/schemas/usage.ts +3 -27
- package/src/schemas/version-seam.test.ts +0 -1
- package/src/shell-regions.ts +289 -0
- package/src/versions.ts +2 -2
- package/src/webext-links.ts +2 -2
- package/src/webext-protocol.ts +2 -2
- package/src/workspace-state.test.ts +48 -1
- package/src/workspace-state.ts +48 -11
- package/dist/contracts/claude.contract.d.ts +0 -91
- package/dist/contracts/claude.contract.d.ts.map +0 -1
- package/dist/contracts/claude.contract.js +0 -50
- package/dist/contracts/claude.contract.js.map +0 -1
- package/dist/contracts/cursor.contract.d.ts.map +0 -1
- package/dist/contracts/cursor.contract.js +0 -50
- package/dist/contracts/cursor.contract.js.map +0 -1
- package/dist/contracts/grok.contract.d.ts +0 -36
- package/dist/contracts/grok.contract.d.ts.map +0 -1
- package/dist/contracts/grok.contract.js +0 -31
- package/dist/contracts/grok.contract.js.map +0 -1
- package/dist/contracts/keys.contract.d.ts +0 -81
- package/dist/contracts/keys.contract.d.ts.map +0 -1
- package/dist/contracts/keys.contract.js +0 -51
- package/dist/contracts/keys.contract.js.map +0 -1
- package/dist/schemas/computers.d.ts.map +0 -1
- package/dist/schemas/computers.js +0 -135
- package/dist/schemas/computers.js.map +0 -1
- package/src/contracts/claude.contract.ts +0 -71
- package/src/contracts/cursor.contract.ts +0 -74
- package/src/contracts/grok.contract.ts +0 -41
- package/src/contracts/keys.contract.ts +0 -79
|
@@ -64,68 +64,65 @@ export const AccountListQuerySchema = z.object({
|
|
|
64
64
|
});
|
|
65
65
|
// Address one account of a provider (disconnect, and the turn's `account`).
|
|
66
66
|
export const AccountIdSchema = z.object({ id: z.string().min(1).describe("Which account.") });
|
|
67
|
-
// Rename one account of a provider whose credential the sandbox owns
|
|
68
|
-
//
|
|
69
|
-
// row. Grok is absent for the same reason it holds one account: OpenCode owns that credential, not this store.
|
|
67
|
+
// Rename one account of a provider whose credential the sandbox owns. Blank ⇒ the daemon falls back to the
|
|
68
|
+
// derived name, so clearing a label restores the sign-in identity rather than leaving a nameless row.
|
|
70
69
|
export const AccountRenameSchema = z.object({
|
|
71
70
|
id: z.string().min(1).describe("Which account."),
|
|
72
71
|
label: z.string().max(80).describe("The new name. Blank restores the one derived from the sign-in, rather than leaving a nameless row."),
|
|
73
72
|
});
|
|
74
|
-
|
|
75
|
-
// or a provider default).
|
|
76
|
-
export const OauthExchangeSchema = z.object({
|
|
77
|
-
code: z.string().min(1).describe("The code the sign-in handed back."),
|
|
78
|
-
verifier: z.string().min(1).describe("The proof from the start of the handshake, which is what stops somebody else's code being redeemed here."),
|
|
79
|
-
state: z.string().min(1).describe("The handshake this belongs to. A mismatch is refused."),
|
|
80
|
-
label: z.string().optional().describe("What to call the account. Blank derives one from the sign-in."),
|
|
81
|
-
});
|
|
82
|
-
export const AuthorizeChallengeSchema = z.object({
|
|
83
|
-
authorizeUrl: z.string().describe("Where to send somebody to sign in."),
|
|
84
|
-
verifier: z.string().describe("Keep this and send it back when finishing. It is what proves the code that comes back belongs to this handshake."),
|
|
85
|
-
state: z.string().describe("The handshake's own id, sent back with it."),
|
|
86
|
-
});
|
|
87
|
-
/* CURSOR'S SIGN-IN START. A third login shape, and the reason it is not one of the two above is where the
|
|
88
|
-
* SECRET lives during the handshake.
|
|
73
|
+
/* ONE SIGN-IN SHAPE FOR EVERY ACCOUNT THE SANDBOX ITSELF HOLDS, whatever the vendor's mechanism underneath.
|
|
89
74
|
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* verifier must never leave the process that generated it
|
|
93
|
-
* durable key, so the daemon
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
export const
|
|
101
|
-
|
|
75
|
+
* Four handshakes used to answer four shapes, and the shapes differed in where the SECRET lived during the
|
|
76
|
+
* handshake. Anthropic's is paste-back: the browser shows a code and the user brings it here. Cursor's PKCE
|
|
77
|
+
* verifier must never leave the process that generated it (anyone holding it can redeem the login and mint a
|
|
78
|
+
* durable key), so the daemon runs the whole flow and the caller only watches the account list. xAI's is a
|
|
79
|
+
* device code. Meta's and Z.ai's mint the vendor's own key, by a device poll or by a redirect that dead-ends in
|
|
80
|
+
* the user's address bar. Every one of them is now the daemon's to hold: nothing redeemable is on this shape,
|
|
81
|
+
* and the one thing the caller can hand back (a code off a page, or the address a redirect landed on) goes to
|
|
82
|
+
* `complete` with the attempt's handshake. `flow` says how the attempt ENDS, which is the only thing a card
|
|
83
|
+
* cannot infer from the fields: a device sign-in finishes upstream and the account appears on its own; a
|
|
84
|
+
* redirect needs the landing address brought back; a paste needs the code the page showed. */
|
|
85
|
+
export const LoginFlowSchema = z.enum(["device", "redirect", "paste"]);
|
|
86
|
+
export type LoginFlow = z.infer<typeof LoginFlowSchema>;
|
|
87
|
+
export const LoginStartSchema = z.object({
|
|
88
|
+
url: z.string().describe("The page to open and sign in on."),
|
|
89
|
+
code: z.string().describe("The one-time code the page will ask for, where the vendor issues one. Blank when the page is already addressed to this attempt."),
|
|
90
|
+
state: z
|
|
91
|
+
.string()
|
|
92
|
+
.describe("For a redirect sign-in, the marker in the address the browser lands on, so a pasted URL can be recognised as this attempt's. Blank otherwise."),
|
|
93
|
+
flow: LoginFlowSchema.describe(
|
|
94
|
+
"How this attempt ends. A device sign-in finishes by itself and you watch the account list; a redirect needs the address it landed on handed back; a paste needs the code the page showed.",
|
|
95
|
+
),
|
|
96
|
+
variant: z.string().describe("Which of the provider's estates this attempt signs in to. Blank for a provider with one."),
|
|
102
97
|
handshake: z
|
|
103
98
|
.string()
|
|
104
|
-
.describe(
|
|
105
|
-
"This attempt's id, for abandoning it. Not a credential and not redeemable: the proof that finishes the sign-in never leaves the sandbox.",
|
|
106
|
-
),
|
|
99
|
+
.describe("This attempt's id, for finishing or abandoning it. Not a credential and not redeemable: the proof that completes the sign-in never leaves the sandbox."),
|
|
107
100
|
expiresAt: z.number().describe("When this attempt stops being answerable, in milliseconds, so a card can stop waiting instead of spinning."),
|
|
108
101
|
});
|
|
109
|
-
export type
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
export const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
102
|
+
export type LoginStart = z.infer<typeof LoginStartSchema>;
|
|
103
|
+
// The estate to sign in to, where a provider has more than one (Z.ai's international and mainland plans). Absent
|
|
104
|
+
// takes the provider's default, which is what a provider with a single estate always sends.
|
|
105
|
+
export const LoginRequestSchema = z.object({
|
|
106
|
+
variant: z.string().min(1).optional().describe("Which estate to sign in to. Absent takes the provider's default."),
|
|
107
|
+
});
|
|
108
|
+
/* The half a person brings back, for the two flows that have one: the code the page showed (a paste), or the
|
|
109
|
+
* whole address a redirect landed on. Not the handshake's state, unlike the translator's version below: that
|
|
110
|
+
* one addresses a session CLIProxyAPI holds, so the state has to travel, while this handshake is held right
|
|
111
|
+
* here and taking the caller's word for its own state would be checking a claim against itself. */
|
|
112
|
+
export const LoginCompleteSchema = z.object({
|
|
113
|
+
handshake: z.string().min(1).describe("Which attempt this belongs to."),
|
|
114
|
+
code: z.string().optional().describe("The code the sign-in page showed, for a paste sign-in."),
|
|
115
|
+
redirectUrl: z.string().optional().describe("The address the browser was sent to, whole, for a redirect sign-in. The grant is inside it."),
|
|
116
|
+
label: z.string().optional().describe("What to call the account. Blank derives one from the sign-in."),
|
|
117
|
+
});
|
|
118
|
+
// What finishing hands back: the account, where the exchange answers with one at once (a paste); absent where
|
|
119
|
+
// the daemon still has a mint to do behind the answer and the row lands in the account list minutes later.
|
|
120
|
+
export const LoginCompletedSchema = z.object({
|
|
121
|
+
account: OauthAccountSchema.optional().describe("The account it connected, where the sign-in ends here. Absent means keep watching the account list."),
|
|
128
122
|
});
|
|
123
|
+
// Abandon a sign-in nobody completed, so the daemon stops polling the vendor for it. Ordinary tidiness rather
|
|
124
|
+
// than a security boundary: an unanswered attempt also times out on its own (see `expiresAt`).
|
|
125
|
+
export const LoginCancelSchema = z.object({ handshake: z.string().min(1).describe("Which attempt to stop waiting on.") });
|
|
129
126
|
// A routed-provider subscription login start (codex/grok/kimi/gemini via CLIProxyAPI). Device flows poll to
|
|
130
127
|
// completion after the user approves upstream; redirect flows need the browser's landing URL pasted back. The
|
|
131
128
|
// explicit flow discriminator matters even when a provider's verification URL already embeds its optional code.
|
package/src/schemas/settings.ts
CHANGED
|
@@ -251,8 +251,6 @@ export const SkillRemoveSchema = z.object({
|
|
|
251
251
|
// tool is one daemon-side registry entry, not a new settings field.
|
|
252
252
|
// hashlineEdits , swaps the native Read/Edit/Write for hash-anchored edits on the Claude path (stale-file
|
|
253
253
|
// guard + fewer output tokens); off ⇒ the native file tools.
|
|
254
|
-
// terseOutput , appends a concise-response steer to the end of the system prompt (a stable suffix, so it
|
|
255
|
-
// composes with stableSystemPrompt) to cut the model's OWN output tokens.
|
|
256
254
|
// systemPromptMode , which base the agent's prompt is: "intentic" (default), "claude", or "custom".
|
|
257
255
|
// systemPrompt , the owner's own prompt text, used only by "custom" mode, where it is the ENTIRE system
|
|
258
256
|
// prompt and nothing the daemon would otherwise append rides with it, see its own note.
|
|
@@ -306,28 +304,24 @@ export const SandboxSettingsSchema = z.object({
|
|
|
306
304
|
"Keep the instructions identical between turns so the provider can cache them, moving anything that varies into the message instead. Cheaper, at the cost of some flexibility.",
|
|
307
305
|
),
|
|
308
306
|
skills: z.array(z.string()).default(["lsp", "fileq"]).describe("Which skills are switched on."),
|
|
307
|
+
/* WHICH CONTEXT SHELF A CONVERSATION OPENS ON when nothing closer to it says (schemas/context.ts). A persona
|
|
308
|
+
* card's own `context` wins where a turn wears one; this is the sandbox's answer for the turns that do not.
|
|
309
|
+
* Empty means no shelf, so a conversation carries every repository the workspace has, which is what every
|
|
310
|
+
* conversation did before shelves existed. Empty rather than optional because a settings object is parsed
|
|
311
|
+
* from `{}` until the owner first changes something, and every field here has to answer to that. */
|
|
312
|
+
contextShelf: z
|
|
313
|
+
.string()
|
|
314
|
+
.max(60)
|
|
315
|
+
.default("")
|
|
316
|
+
.describe(
|
|
317
|
+
"Which context shelf a conversation opens on when its persona names none: the part of the workspace it carries. Empty means every repository, as before shelves existed.",
|
|
318
|
+
),
|
|
309
319
|
hashlineEdits: z
|
|
310
320
|
.boolean()
|
|
311
321
|
.default(false)
|
|
312
322
|
.describe(
|
|
313
323
|
"Have the agent edit files by line number rather than by quoting the text it wants replaced. Cheaper on large files, and less forgiving of a stale read.",
|
|
314
324
|
),
|
|
315
|
-
terseOutput: z.boolean().default(false).describe("Ask the agent to say less. It changes how much it narrates, not how much it does."),
|
|
316
|
-
/* Measurement control for the terse steer, at TURN level, the same trick `outputHoldout` plays over
|
|
317
|
-
* commands, one layer up. A fraction [0,1] of otherwise-eligible turns run WITHOUT the steer and record
|
|
318
|
-
* which arm they ran on (UsageTurn.terse), so the savings report can compare two real populations.
|
|
319
|
-
*
|
|
320
|
-
* It has to be an experiment: unlike a cleaned command, which yields its own raw baseline in the same
|
|
321
|
-
* event, a turn cannot be re-run to see what it would have said unsteered. 0 ⇒ no measurement (every
|
|
322
|
-
* eligible turn is steered), which is the default because the control costs the very tokens it measures. */
|
|
323
|
-
terseHoldout: z
|
|
324
|
-
.number()
|
|
325
|
-
.min(0)
|
|
326
|
-
.max(1)
|
|
327
|
-
.default(0)
|
|
328
|
-
.describe(
|
|
329
|
-
"What share of turns to run without that instruction, so the two can be compared honestly. It has to be measured this way, because a turn cannot be re-run to see what it would have said. Zero means no measurement, which is the default, since the comparison costs the very tokens it is measuring.",
|
|
330
|
-
),
|
|
331
325
|
/* WHICH SYSTEM PROMPT THE AGENT RUNS ON, the base, before anything this turn composes.
|
|
332
326
|
*
|
|
333
327
|
* intentic. Intentic's own prompt, tuned for this harness (intentic-prompt.ts). The default.
|
|
@@ -337,15 +331,14 @@ export const SandboxSettingsSchema = z.object({
|
|
|
337
331
|
*
|
|
338
332
|
* The first two are peers: both get the harness's own guidance appended (the AskUserQuestion/plan blocks
|
|
339
333
|
* the chat's cards need, the checklist guidance behind the todo panel, the browser-tool guidance), plus the
|
|
340
|
-
* delegation note
|
|
341
|
-
* see the field below. */
|
|
334
|
+
* delegation note. `custom` is the one that does not, by the owner's explicit choice, see the field below. */
|
|
342
335
|
systemPromptMode: SystemPromptModeSchema.default("intentic").describe(
|
|
343
336
|
"Which instructions the agent starts from: intentic's own, the ones the installed Claude Code carries, or your own. The first two both get this product's own guidance added on top; your own gets nothing added, which is the point of it.",
|
|
344
337
|
),
|
|
345
338
|
/* The owner's own prompt, used only when `systemPromptMode` is "custom". Then it is the ENTIRE system
|
|
346
|
-
* prompt: both built-in bases are gone and so is everything the daemon would otherwise append,
|
|
347
|
-
* guidance the chat's cards are driven by
|
|
348
|
-
*
|
|
339
|
+
* prompt: both built-in bases are gone and so is everything the daemon would otherwise append, including
|
|
340
|
+
* the widget guidance the chat's cards are driven by. That is the price of total control, and the UI states
|
|
341
|
+
* it at the moment of the edit rather than letting the
|
|
349
342
|
* widgets go quietly dark. Only the cross-provider delegation note survives, because it has a home outside
|
|
350
343
|
* the system prompt already (the user-message preamble stableSystemPrompt puts it in).
|
|
351
344
|
*
|
|
@@ -777,7 +770,7 @@ export const SandboxSettingsSchema = z.object({
|
|
|
777
770
|
* The refusal an agent sees names the env var (`ask them to raise CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS`),
|
|
778
771
|
* which is why these three exist as settings at all: without them the only answer to that ask is editing
|
|
779
772
|
* the container's environment and restarting the daemon. */
|
|
780
|
-
subagentsAtOnce: z.number().min(1).max(200).default(20).describe("How many
|
|
773
|
+
subagentsAtOnce: z.number().min(1).max(200).default(20).describe("How many subagents may work at the same time."),
|
|
781
774
|
subagentsPerTurn: z.number().min(1).max(2000).default(200).describe("How many a single turn may start in total."),
|
|
782
775
|
// Depth 1 = an agent may delegate, but its children may not. The CLI's own default is 3, and it is the one
|
|
783
776
|
// of the three whose runaway case is unbounded rather than merely wide, each level multiplies the last.
|
|
@@ -786,7 +779,7 @@ export const SandboxSettingsSchema = z.object({
|
|
|
786
779
|
.min(1)
|
|
787
780
|
.max(10)
|
|
788
781
|
.default(3)
|
|
789
|
-
.describe("How many levels deep the delegation may go, since a
|
|
782
|
+
.describe("How many levels deep the delegation may go, since a subagent can start subagents of its own."),
|
|
790
783
|
});
|
|
791
784
|
export type SandboxSettings = z.infer<typeof SandboxSettingsSchema>;
|
|
792
785
|
// One of the two built-in bases, as text: Intentic's own prompt, or Claude Code's preset read out of the CLI
|
|
@@ -800,19 +793,9 @@ export const BuiltinPromptTextSchema = z.object({ text: z.string(), version: z.s
|
|
|
800
793
|
export type BuiltinPromptText = z.infer<typeof BuiltinPromptTextSchema>;
|
|
801
794
|
/* ---- savings report: what each token-reduction mechanism actually saved ----
|
|
802
795
|
*
|
|
803
|
-
*
|
|
804
|
-
*
|
|
805
|
-
*
|
|
806
|
-
* input , shell output the cleaners trimmed before the model ever saw it. Both sides of the comparison come
|
|
807
|
-
* off the SAME command (raw in, emitted out), so the counterfactual is observed rather than
|
|
808
|
-
* estimated: exact, per command, no sample size to argue about.
|
|
809
|
-
* output, the model's own tokens under the terse steer. There is no second run of the same turn to compare
|
|
810
|
-
* against, so the only honest number is an experiment: a turn-level holdout, an n per arm, and a
|
|
811
|
-
* margin. It is absent entirely until both arms are large enough for the delta to mean anything.
|
|
812
|
-
*
|
|
813
|
-
* The two are also in different units of value, a saved tool-output token is saved again on every later
|
|
814
|
-
* request of that conversation, an output token is saved once but costs several times as much, which is the
|
|
815
|
-
* other reason they are separate sections with separate totals rather than one number.
|
|
796
|
+
* Input-side savings: shell output the cleaners trimmed before the model ever saw it. Both sides of the
|
|
797
|
+
* comparison come off the SAME command (raw in, emitted out), so the counterfactual is observed rather than
|
|
798
|
+
* estimated: exact, per command, no sample size to argue about.
|
|
816
799
|
*/
|
|
817
800
|
|
|
818
801
|
// One mechanism's realized saving, biggest first. `savedTokens` is what THIS stage removed from what reached
|
|
@@ -851,15 +834,12 @@ export const SavingsArmSchema = z.object({ turns: z.number(), mean: z.number() }
|
|
|
851
834
|
* stand behind. An experiment can carry several, see TurnExperimentSchema.
|
|
852
835
|
*
|
|
853
836
|
* `metric` says what `mean` counts and what `deltaPct` is a delta in, and choosing it is most of the work.
|
|
854
|
-
* proseChars , the terse steer: the thing it steers, and the only part of the model's output that
|
|
855
|
-
* responds to being asked to be brief (UsageTurn.proseChars has why output tokens cannot).
|
|
856
837
|
* searchCalls , the search teaching: the searches a turn ran, which the teaching directly changes.
|
|
857
838
|
* openingSearches, the same, narrower: the searches before the turn first touched a file.
|
|
858
839
|
* Search mechanisms must not be judged on COST. Cost is a whole turn's work, a search mechanism moves one part
|
|
859
|
-
* of it, and the part sits inside the noise of the rest
|
|
860
|
-
* tool-call arguments. */
|
|
840
|
+
* of it, and the part sits inside the noise of the rest. */
|
|
861
841
|
export const TurnMetricReadingSchema = z.object({
|
|
862
|
-
metric: z.enum(["
|
|
842
|
+
metric: z.enum(["searchCalls", "openingSearches"]),
|
|
863
843
|
on: SavingsArmSchema,
|
|
864
844
|
off: SavingsArmSchema,
|
|
865
845
|
/* HOW MUCH LONGER, when the margin spans zero and the honest answer is "keep collecting": the additional
|
|
@@ -886,23 +866,20 @@ export const TurnMetricReadingSchema = z.object({
|
|
|
886
866
|
/* THE CLAIM, present only once there is one. Both together, and only when the margin does NOT span zero.
|
|
887
867
|
*
|
|
888
868
|
* A schema that can't express a half-measured experiment is how a 34%-that-becomes-8%-tomorrow never
|
|
889
|
-
* reaches the screen, and clearing `minTurns` turned out not to be enough to buy that.
|
|
890
|
-
* crossed its thirtieth control turn and immediately reported +31.2% ± 35.1pp: a confidence interval
|
|
869
|
+
* reaches the screen, and clearing `minTurns` turned out not to be enough to buy that. An early search
|
|
870
|
+
* teaching run crossed its thirtieth control turn and immediately reported +31.2% ± 35.1pp: a confidence interval
|
|
891
871
|
* running from −3.4% to +66.7%, which is to say no effect was measured at all, rendered as an alarming
|
|
892
872
|
* number pointing the wrong way. Thirty turns is where the normal approximation starts to hold, not where
|
|
893
873
|
* this much per-turn spread resolves an effect; requiring the interval to exclude zero is the same
|
|
894
874
|
* withhold-until-it-means-something rule applied to the thing that actually decides whether it does.
|
|
895
875
|
* deltaPct, change in the metric's mean per turn under the mechanism; negative is a saving.
|
|
896
876
|
* saved , what the delta is worth over the turns that actually ran with it, in this window, in the
|
|
897
|
-
* metric's own unit (
|
|
877
|
+
* metric's own unit (searches). */
|
|
898
878
|
deltaPct: z.number().optional(),
|
|
899
879
|
saved: z.number().optional(),
|
|
900
880
|
});
|
|
901
881
|
export type TurnMetricReading = z.infer<typeof TurnMetricReadingSchema>;
|
|
902
|
-
/* A turn-level A/B, the
|
|
903
|
-
* nothing but which flag flips and what the turns are judged on. Only turns the mechanism was ELIGIBLE for are
|
|
904
|
-
* counted: a turn under a custom system prompt drops the terse steer along with everything else the daemon
|
|
905
|
-
* appends, so it belongs to neither arm.
|
|
882
|
+
/* A turn-level A/B, the shape the iq search teaching experiment reports in.
|
|
906
883
|
*
|
|
907
884
|
* ONE COIN FLIP, SEVERAL READINGS. `metrics` is a list because the search teaching is judged on two, the
|
|
908
885
|
* searches a turn ran, and the ones it ran before touching a file, and they are two readings of the SAME
|
|
@@ -927,9 +904,9 @@ export const TurnExperimentSchema = z.object({
|
|
|
927
904
|
cohort: z.string().optional(),
|
|
928
905
|
});
|
|
929
906
|
export type TurnExperiment = z.infer<typeof TurnExperimentSchema>;
|
|
930
|
-
// `
|
|
931
|
-
//
|
|
932
|
-
//
|
|
907
|
+
// `search` is absent when that experiment isn't running at all (its flag off, or no holdout set), a section
|
|
908
|
+
// that isn't there reads as "not measured", which is the truth, while zeros would read as "measured, worth
|
|
909
|
+
// nothing".
|
|
933
910
|
/* WHAT THE COMPLEXITY JUDGE HAS BEEN SAYING, read back off the spend ledger's tier fields (UsageTurn.tierScore
|
|
934
911
|
* and friends) over the requested window. The three numbers docs/model-routing-design.md §4 says the feature
|
|
935
912
|
* cannot be defended without, plus the veto count, and nothing else: no counterfactual "you would have saved
|
|
@@ -964,7 +941,6 @@ export const TierReportSchema = z.object({
|
|
|
964
941
|
export type TierReport = z.infer<typeof TierReportSchema>;
|
|
965
942
|
export const SavingsReportSchema = z.object({
|
|
966
943
|
input: InputSavingsSchema,
|
|
967
|
-
output: TurnExperimentSchema.optional(),
|
|
968
944
|
search: TurnExperimentSchema.optional(),
|
|
969
945
|
// Automatic tier selection's readout, see TierReportSchema. Absent ⇒ nothing was judged in the window.
|
|
970
946
|
tier: TierReportSchema.optional(),
|
package/src/schemas/terminal.ts
CHANGED
|
@@ -194,14 +194,14 @@ export type SubagentKind = z.infer<typeof SubagentKindSchema>;
|
|
|
194
194
|
// an operator acts on differently from "the child is working".
|
|
195
195
|
export const SubagentStatusSchema = z.enum(["pending", "running", "blocked", "completed", "failed", "killed", "paused"]);
|
|
196
196
|
export type SubagentStatus = z.infer<typeof SubagentStatusSchema>;
|
|
197
|
-
/* WHETHER ANYTHING CHECKED WHAT THE
|
|
198
|
-
* assume. Computed from the
|
|
197
|
+
/* WHETHER ANYTHING CHECKED WHAT THE SUBAGENT DID, carried beside its report rather than left for the reader to
|
|
198
|
+
* assume. Computed from the subagent's own tool calls, the files it edited against the checks that ran after
|
|
199
199
|
* them (the daemon's child-verification.ts), so it holds on every provider rather than only where the Claude
|
|
200
200
|
* hooks reach.
|
|
201
201
|
*
|
|
202
202
|
* The four states are deliberately not two. `verified` and `failing` each name the command that spoke, so a
|
|
203
203
|
* targeted test is never read as the suite; `unproven` is the one that matters most, work changed and nothing
|
|
204
|
-
* ran; and `no-code` says the
|
|
204
|
+
* ran; and `no-code` says the subagent edited nothing, which is the honest answer for a research subagent and
|
|
205
205
|
* must not be rendered as approval. Absent ⇒ the daemon saw no tool calls from it at all. */
|
|
206
206
|
export const SubagentVerificationSchema = z.object({
|
|
207
207
|
state: z
|
|
@@ -222,10 +222,10 @@ export const SubagentSessionSchema = z.object({
|
|
|
222
222
|
id: z
|
|
223
223
|
.string()
|
|
224
224
|
.describe(
|
|
225
|
-
"The id of the tool call that started it (an SDK child) or the child's own conversation id (a spawned one); either way both sides already hold it, so a card links to its
|
|
225
|
+
"The id of the tool call that started it (an SDK child) or the child's own conversation id (a spawned one); either way both sides already hold it, so a card links to its subagent with the id it has and the subagent points back the same way.",
|
|
226
226
|
),
|
|
227
227
|
kind: SubagentKindSchema.describe(
|
|
228
|
-
"What sort of
|
|
228
|
+
"What sort of subagent: one the runtime's own Task tool spawned in-process, or a full child agent the daemon started for the turn. It changes only how you watch it.",
|
|
229
229
|
),
|
|
230
230
|
// The conversation whose turn spawned this, what the area groups its rows by, and the way back to the chat
|
|
231
231
|
// the card lives in.
|
|
@@ -233,19 +233,19 @@ export const SubagentSessionSchema = z.object({
|
|
|
233
233
|
// What it is and what it was asked to do: the subagent type (`Explore`, `general-purpose`) or a spawned
|
|
234
234
|
// child's provider label, and the caller's one-line description. The area's row and the card's title read
|
|
235
235
|
// as `Explore · Locate claimIndexer definition`.
|
|
236
|
-
agentType: z.string().optional().describe("What kind of
|
|
236
|
+
agentType: z.string().optional().describe("What kind of subagent it is."),
|
|
237
237
|
description: z.string().optional().describe("What it was asked to do, in one line."),
|
|
238
238
|
model: z.string().optional().describe("Which model it runs on."),
|
|
239
239
|
// Which provider serves a `spawned` child (its AgentProvider id), so the row can wear the right logo. An
|
|
240
240
|
// SDK subagent implies its own: it runs on its parent's provider.
|
|
241
|
-
provider: z.string().optional().describe("Which provider serves it, for a
|
|
241
|
+
provider: z.string().optional().describe("Which provider serves it, for a child agent spawned across providers."),
|
|
242
242
|
// How deep in the spawn tree (1 = spawned by the turn itself). From the SDK's meta.json; a subagent may
|
|
243
243
|
// itself delegate, and a flat list that cannot say so reads as though the turn started all of them.
|
|
244
244
|
spawnDepth: z
|
|
245
245
|
.number()
|
|
246
246
|
.optional()
|
|
247
247
|
.describe(
|
|
248
|
-
"How deep in the chain it sits, where one means the turn itself started it. A
|
|
248
|
+
"How deep in the chain it sits, where one means the turn itself started it. A subagent can start subagents, and a flat list that could not say so would read as though the turn started all of them.",
|
|
249
249
|
),
|
|
250
250
|
// Backgrounded: the parent went on working instead of waiting for it. This is the whole reason the list
|
|
251
251
|
// exists, a backgrounded child used to be invisible until its result landed, sometimes minutes later.
|
|
@@ -253,7 +253,7 @@ export const SubagentSessionSchema = z.object({
|
|
|
253
253
|
.boolean()
|
|
254
254
|
.optional()
|
|
255
255
|
.describe(
|
|
256
|
-
"The parent carried on working instead of waiting for it. This is the whole reason the list exists: such a
|
|
256
|
+
"The parent carried on working instead of waiting for it. This is the whole reason the list exists: such a subagent used to be invisible until its result landed, sometimes minutes later.",
|
|
257
257
|
),
|
|
258
258
|
status: SubagentStatusSchema.describe(
|
|
259
259
|
"How it is going. Blocked means it needs an answer, which a parent and an operator act on differently from it simply working.",
|
|
@@ -266,7 +266,7 @@ export const SubagentSessionSchema = z.object({
|
|
|
266
266
|
tokens: z
|
|
267
267
|
.number()
|
|
268
268
|
.optional()
|
|
269
|
-
.describe("What it has spent. Its own, so a parent's cost and the sum of its
|
|
269
|
+
.describe("What it has spent. Its own, so a parent's cost and the sum of its subagents' are two different true numbers."),
|
|
270
270
|
toolUses: z.number().optional().describe("How many tools it has used."),
|
|
271
271
|
lastTool: z.string().optional().describe("The last one it reached for."),
|
|
272
272
|
// Its report, the last assistant message (SubagentStop) or the task summary. The answer to "what did it
|
|
@@ -274,7 +274,7 @@ export const SubagentSessionSchema = z.object({
|
|
|
274
274
|
summary: z
|
|
275
275
|
.string()
|
|
276
276
|
.optional()
|
|
277
|
-
.describe("Its report: what it concluded, without opening its record. The question a finished
|
|
277
|
+
.describe("Its report: what it concluded, without opening its record. The question a finished subagent gets read for."),
|
|
278
278
|
error: z.string().optional().describe("Why it failed, when it did."),
|
|
279
279
|
// Whether anything checked the work behind that report (SubagentVerificationSchema). Filled once it ends:
|
|
280
280
|
// a standing read while it is still working would be a verdict on a job half done.
|
|
@@ -282,7 +282,7 @@ export const SubagentSessionSchema = z.object({
|
|
|
282
282
|
});
|
|
283
283
|
export type SubagentSession = z.infer<typeof SubagentSessionSchema>;
|
|
284
284
|
export const SubagentsListSchema = z.object({
|
|
285
|
-
sessions: z.array(SubagentSessionSchema).describe("Every
|
|
285
|
+
sessions: z.array(SubagentSessionSchema).describe("Every subagent and child agent this sandbox's conversations have started."),
|
|
286
286
|
});
|
|
287
287
|
export type SubagentsList = z.infer<typeof SubagentsListSchema>;
|
|
288
288
|
export const SubagentIdParamSchema = z.object({ id: z.string() });
|
package/src/schemas/usage.ts
CHANGED
|
@@ -83,14 +83,6 @@ export const UsageTurnSchema = z.object({
|
|
|
83
83
|
cacheCreationTokens: z.number().describe("Tokens written to cache, which cost more up front and less afterwards."),
|
|
84
84
|
costUsd: z.number().describe("What it cost, in dollars."),
|
|
85
85
|
durationMs: z.number().describe("How long it took, in milliseconds."),
|
|
86
|
-
/* Which arm of the terse experiment this turn ran on (settings.terseHoldout), the only record of it, and
|
|
87
|
-
* the reason the savings report can say what the steer is worth instead of guessing.
|
|
88
|
-
*
|
|
89
|
-
* ABSENT means "not part of the experiment", not "off": a turn under a custom system prompt drops the
|
|
90
|
-
* steer along with everything else the daemon appends, and a turn run with the experiment switched off has
|
|
91
|
-
* no control to be compared against. Pooling those into the off-arm would compare steered turns against a
|
|
92
|
-
* population selected by something other than the coin flip, which is not a control at all. */
|
|
93
|
-
terse: z.boolean().optional(),
|
|
94
86
|
/* Which arm of the iq SEARCH-TEACHING experiment this conversation runs on
|
|
95
87
|
* (settings.iqSearchHoldout). Stable for every turn in one conversation: the treatment is instruction
|
|
96
88
|
* loaded into a provider session, so flipping it per turn would call a remembered treatment a control.
|
|
@@ -99,25 +91,9 @@ export const UsageTurnSchema = z.object({
|
|
|
99
91
|
// Hash of the plugin nudge + skill body used for this arm. Control turns carry it too, so a report can keep
|
|
100
92
|
// both sides of one treatment revision together and exclude older wording after an upgrade.
|
|
101
93
|
iqSearchCohort: z.string().optional(),
|
|
102
|
-
/* Characters of the model's own PROSE this turn, the `delta` frames only, so no tool-call arguments and no
|
|
103
|
-
* thinking. What the terse steer is judged on, and the reason it can be judged at all.
|
|
104
|
-
*
|
|
105
|
-
* `outputTokens` cannot serve: measured over a day of real turns it is 91.6% tool-call arguments (an Edit's
|
|
106
|
-
* old_string and new_string, a Write's whole file body) and 7.8% prose. The steer moves prose. So a fifth
|
|
107
|
-
* off the model's narration moves the total by 1.6%, against a margin of ±35 points, which is to say the
|
|
108
|
-
* experiment was structurally unable to see its own treatment, and the number it printed instead was
|
|
109
|
-
* whichever arm happened to draw the bigger tasks.
|
|
110
|
-
*
|
|
111
|
-
* CHARACTERS, not tokens, because the provider bills a total and never breaks it down, a token figure here
|
|
112
|
-
* would be chars÷4 wearing a unit it had not earned. For a comparison of two arms the constant cancels
|
|
113
|
-
* anyway, and the honest unit is the one actually counted.
|
|
114
|
-
*
|
|
115
|
-
* Absent ⇒ the turn predates this being measured; `armOf` drops it from the population rather than reading
|
|
116
|
-
* it as a silent turn. */
|
|
117
|
-
proseChars: z.number().optional(),
|
|
118
94
|
/* SEARCHES THIS TURN RAN, every tool call that went looking for code, the dedicated search tools and the
|
|
119
95
|
* CLI searches alike (isSearchCall owns the rule; `iq q` is Bash and would otherwise not be counted at all).
|
|
120
|
-
* What the search teaching is judged on
|
|
96
|
+
* What the search teaching is judged on.
|
|
121
97
|
*
|
|
122
98
|
* COST PER TURN CANNOT SERVE: cost is a whole turn's worth of work, a search mechanism touches one part of
|
|
123
99
|
* it, and the part lives inside the noise of the rest, exactly the shape that made output tokens unable to
|
|
@@ -128,8 +104,8 @@ export const UsageTurnSchema = z.object({
|
|
|
128
104
|
* rather than being filtered out, they dilute both arms equally, while selecting on "did it search" would
|
|
129
105
|
* select on the treatment itself.
|
|
130
106
|
*
|
|
131
|
-
* Absent ⇒ the turn predates this being measured;
|
|
132
|
-
* searched nothing. */
|
|
107
|
+
* Absent ⇒ the turn predates this being measured; the arm's mean drops it (turn-experiments.ts, the filter
|
|
108
|
+
* inside `conversationExperimentOf`) rather than reading it as a turn that searched nothing. */
|
|
133
109
|
searchCalls: z.number().optional(),
|
|
134
110
|
/* …and how many of them came BEFORE the turn first opened or changed a file, the orientation burst. A turn
|
|
135
111
|
* that already knows where to look starts working; one that doesn't goes hunting first.
|