@intentic/sandbox-contract 1.223.0 → 1.225.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/README.md +14 -14
- package/dist/agent-catalog.js +3 -3
- package/dist/agent-catalog.js.map +1 -1
- package/dist/chores/chores.js +43 -43
- package/dist/chores/chores.js.map +1 -1
- package/dist/chores/extension-update.js +2 -2
- package/dist/chores/extension-update.js.map +1 -1
- package/dist/chores/fix-deps.js +1 -1
- package/dist/chores/fix-deps.js.map +1 -1
- package/dist/chores/probes.js +1 -1
- package/dist/chores/probes.js.map +1 -1
- package/dist/chores/prompt.d.ts.map +1 -1
- package/dist/chores/prompt.js +3 -3
- package/dist/chores/prompt.js.map +1 -1
- package/dist/chores/verdict.js +2 -2
- package/dist/chores/verdict.js.map +1 -1
- package/dist/contracts/capabilities.contract.d.ts +41 -0
- package/dist/contracts/capabilities.contract.d.ts.map +1 -1
- package/dist/contracts/exit.contract.d.ts +80 -0
- package/dist/contracts/exit.contract.d.ts.map +1 -0
- package/dist/contracts/exit.contract.js +13 -0
- package/dist/contracts/exit.contract.js.map +1 -0
- package/dist/contracts/ports.contract.d.ts +11 -0
- package/dist/contracts/ports.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.d.ts +12 -0
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/events.d.ts +4 -4
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +5 -5
- package/dist/events.js.map +1 -1
- package/dist/fast-tier.d.ts +9 -0
- package/dist/fast-tier.d.ts.map +1 -0
- package/dist/fast-tier.js +19 -0
- package/dist/fast-tier.js.map +1 -0
- package/dist/history-state.js +3 -3
- package/dist/history-state.js.map +1 -1
- package/dist/index.d.ts +214 -68
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/model-order.d.ts +1 -0
- package/dist/model-order.d.ts.map +1 -1
- package/dist/model-order.js +5 -0
- package/dist/model-order.js.map +1 -1
- package/dist/output-fields.d.ts.map +1 -1
- package/dist/output-fields.js +2 -2
- package/dist/output-fields.js.map +1 -1
- package/dist/prompt-complexity.d.ts +19 -0
- package/dist/prompt-complexity.d.ts.map +1 -0
- package/dist/prompt-complexity.js +83 -0
- package/dist/prompt-complexity.js.map +1 -0
- package/dist/publish-drafts.js +2 -2
- package/dist/publish-drafts.js.map +1 -1
- package/dist/schemas.d.ts +236 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +116 -2
- package/dist/schemas.js.map +1 -1
- package/dist/workflow-faults.js +3 -3
- package/dist/workflow-faults.js.map +1 -1
- package/dist/workspace-state.d.ts +20 -20
- package/dist/workspace-state.d.ts.map +1 -1
- package/dist/workspace-state.js +20 -20
- package/dist/workspace-state.js.map +1 -1
- package/package.json +5 -5
- package/src/agent-catalog.test.ts +25 -25
- package/src/agent-catalog.ts +81 -81
- package/src/agent-run-model.test.ts +3 -3
- package/src/agent-run-model.ts +8 -8
- package/src/capability-env.ts +3 -3
- package/src/capability-ledger.test.ts +13 -13
- package/src/capability-secrets.ts +5 -5
- package/src/chores/chores.test.ts +1 -1
- package/src/chores/chores.ts +109 -109
- package/src/chores/digest.test.ts +1 -1
- package/src/chores/digest.ts +3 -3
- package/src/chores/extension-update.ts +5 -5
- package/src/chores/fix-deps.ts +4 -4
- package/src/chores/probes.test.ts +6 -6
- package/src/chores/probes.ts +17 -17
- package/src/chores/prompt.ts +9 -9
- package/src/chores/stack.test.ts +3 -3
- package/src/chores/stack.ts +17 -17
- package/src/chores/verdict.test.ts +20 -20
- package/src/chores/verdict.ts +25 -25
- package/src/contract-lock.test.ts +1 -1
- package/src/contract-lock.ts +7 -7
- package/src/contracts/activity.contract.ts +1 -1
- package/src/contracts/agent.contract.ts +2 -2
- package/src/contracts/agents.contract.ts +11 -11
- package/src/contracts/automations.contract.ts +5 -5
- package/src/contracts/capabilities.contract.ts +7 -7
- package/src/contracts/chores.contract.ts +3 -3
- package/src/contracts/ci.contract.ts +2 -2
- package/src/contracts/claude.contract.ts +3 -3
- package/src/contracts/drafts.contract.ts +1 -1
- package/src/contracts/endpoints.contract.ts +2 -2
- package/src/contracts/exit.contract.ts +42 -0
- package/src/contracts/extensions.contract.ts +8 -8
- package/src/contracts/git.contract.ts +6 -6
- package/src/contracts/grok.contract.ts +4 -4
- package/src/contracts/host.contract.ts +5 -5
- package/src/contracts/intentic.contract.ts +2 -2
- package/src/contracts/logs.contract.ts +1 -1
- package/src/contracts/loops.contract.ts +8 -8
- package/src/contracts/personas.contract.ts +8 -8
- package/src/contracts/ports.contract.ts +1 -1
- package/src/contracts/prepush.contract.ts +2 -2
- package/src/contracts/providers.contract.ts +4 -4
- package/src/contracts/public.contract.ts +1 -1
- package/src/contracts/push.contract.ts +2 -2
- package/src/contracts/secrets.contract.ts +2 -2
- package/src/contracts/sessions.contract.ts +2 -2
- package/src/contracts/settings.contract.ts +3 -3
- package/src/contracts/share.contract.ts +1 -1
- package/src/contracts/skills.contract.ts +2 -2
- package/src/contracts/system.contract.ts +9 -9
- package/src/contracts/usage.contract.ts +1 -1
- package/src/contracts/vpn.contract.ts +5 -5
- package/src/contracts/workflows.contract.ts +12 -12
- package/src/contracts/workspace.contract.ts +13 -13
- package/src/conversation-ids.ts +8 -8
- package/src/events.test.ts +3 -3
- package/src/events.ts +142 -142
- package/src/fast-tier.test.ts +88 -0
- package/src/fast-tier.ts +72 -0
- package/src/history-state.ts +15 -15
- package/src/host-protocol.ts +7 -7
- package/src/hostnames.test.ts +1 -1
- package/src/hostnames.ts +15 -15
- package/src/index.ts +13 -8
- package/src/listener-protocol.ts +12 -12
- package/src/model-order.test.ts +11 -11
- package/src/model-order.ts +52 -30
- package/src/output-fields.ts +11 -11
- package/src/path-refs.test.ts +4 -4
- package/src/path-refs.ts +6 -6
- package/src/prompt-complexity.test.ts +160 -0
- package/src/prompt-complexity.ts +271 -0
- package/src/publish-drafts.ts +8 -8
- package/src/quick-model.test.ts +11 -11
- package/src/quick-model.ts +15 -15
- package/src/routes.test.ts +11 -5
- package/src/routes.ts +19 -19
- package/src/runtime-state.test.ts +1 -1
- package/src/runtime-state.ts +22 -22
- package/src/schemas.test.ts +8 -8
- package/src/schemas.ts +1238 -921
- package/src/search-globs.test.ts +2 -2
- package/src/search-globs.ts +6 -6
- package/src/session-names.ts +5 -5
- package/src/share-paths.test.ts +1 -1
- package/src/share-paths.ts +7 -7
- package/src/sse.ts +1 -1
- package/src/state-portability.ts +8 -8
- package/src/terminal-protocol.ts +3 -3
- package/src/title.test.ts +9 -9
- package/src/title.ts +21 -21
- package/src/tunnel-ids.test.ts +3 -3
- package/src/tunnel-ids.ts +7 -7
- package/src/versions.test.ts +3 -3
- package/src/versions.ts +6 -6
- package/src/workflow-faults.test.ts +6 -6
- package/src/workflow-faults.ts +14 -14
- package/src/workspace-state.test.ts +32 -32
- package/src/workspace-state.ts +139 -139
|
@@ -26,7 +26,7 @@ import type { AgentHarness, AgentProvider, PermissionMode } from "./schemas.js";
|
|
|
26
26
|
* drops the field. The record is what fixed that, and this is what keeps it honest.
|
|
27
27
|
*
|
|
28
28
|
* By SHAPE, not by a list: PROVIDERS × HARNESSES comes from the catalog itself, so a provider added tomorrow is
|
|
29
|
-
* covered the day it is added. If a pair fails here, the answer is a row in capabilitiesOf
|
|
29
|
+
* covered the day it is added. If a pair fails here, the answer is a row in capabilitiesOf: never a special
|
|
30
30
|
* case in the surface that asked. */
|
|
31
31
|
|
|
32
32
|
const pairs: { provider: AgentProvider; harness: AgentHarness }[] = PROVIDERS.flatMap((provider) =>
|
|
@@ -42,20 +42,20 @@ describe("every provider/harness pair declares what it can do", () => {
|
|
|
42
42
|
expect(["claude-code", "codex", "opencode", "opencode-gemini", "acp", "pi"]).toContain(capabilities.runtime);
|
|
43
43
|
expect(["modes", "plan"]).toContain(capabilities.permissions);
|
|
44
44
|
expect(["full", "browser", "http", "none"]).toContain(capabilities.mcp);
|
|
45
|
-
// Every runtime executes SOMETHING
|
|
45
|
+
// Every runtime executes SOMETHING: a record listing no backend would hide the shell every loop has.
|
|
46
46
|
expect(capabilities.execution).toContain("shell");
|
|
47
47
|
for (const backend of capabilities.execution) {
|
|
48
48
|
expect(["shell", "js"]).toContain(backend);
|
|
49
49
|
}
|
|
50
50
|
expect(["namespace", "cwd"]).toContain(capabilities.isolation);
|
|
51
51
|
expect(["replace", "append", "none"]).toContain(capabilities.instructions);
|
|
52
|
-
// The permission modes offered must include the mode a clamp falls back to
|
|
52
|
+
// The permission modes offered must include the mode a clamp falls back to: a floor that isn't in the
|
|
53
53
|
// list would leave the composer showing a posture the runtime can't hold.
|
|
54
54
|
expect(modesFor(capabilities)).toContain(clampMode("default", capabilities));
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
-
// An ACP provider is an installed capability's id
|
|
58
|
+
// An ACP provider is an installed capability's id: any string that isn't a native provider. It gets the ACP
|
|
59
59
|
// floor whatever harness the client happened to send, because the agent IS its own loop.
|
|
60
60
|
test("an unknown provider id is an ACP agent, on either harness", () => {
|
|
61
61
|
for (const harness of HARNESSES) {
|
|
@@ -63,12 +63,12 @@ test("an unknown provider id is an ACP agent, on either harness", () => {
|
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
/* THE `pi` ID IS RESERVED for the Pi coding agent's own RPC runtime
|
|
66
|
+
/* THE `pi` ID IS RESERVED for the Pi coding agent's own RPC runtime: an `agent`-kind capability like any ACP
|
|
67
67
|
* agent, but served over Pi's JSONL protocol, which carries abilities the ACP floor cannot: real mid-turn
|
|
68
68
|
* steering, the thinking-level scale, a published command list. Falling to the ACP record instead would strip
|
|
69
69
|
* exactly the abilities that justify a fifth runtime. */
|
|
70
70
|
describe("the pi provider", () => {
|
|
71
|
-
it("runs the pi runtime on either harness
|
|
71
|
+
it("runs the pi runtime on either harness: pi is its own loop", () => {
|
|
72
72
|
for (const harness of HARNESSES) {
|
|
73
73
|
expect(capabilitiesOf("pi", harness.value).runtime).toBe("pi");
|
|
74
74
|
}
|
|
@@ -96,7 +96,7 @@ describe("the pi provider", () => {
|
|
|
96
96
|
* "there is nothing to choose". Claude is always its own Claude Code loop. Kimi has no native runtime at all
|
|
97
97
|
* (Moonshot speaks the Anthropic protocol directly), so it runs Claude Code whatever the client sent. Gemini is
|
|
98
98
|
* Kimi's mirror: it has no CLAUDE CODE road, because that loop announces itself in every request and Google's
|
|
99
|
-
* Antigravity channel refuses on the announcement
|
|
99
|
+
* Antigravity channel refuses on the announcement: every account, every time, reported as a spent quota it
|
|
100
100
|
* never was. */
|
|
101
101
|
test("only codex and grok change runtime with the harness", () => {
|
|
102
102
|
const switched = PROVIDERS.filter((provider) => capabilitiesOf(provider.value, "native") !== capabilitiesOf(provider.value, "claude-code"));
|
|
@@ -105,26 +105,26 @@ test("only codex and grok change runtime with the harness", () => {
|
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
/* THE RULE THAT KEEPS CLAUDE CODE TRAFFIC AWAY FROM GOOGLE, asserted where it is decided rather than at each of
|
|
108
|
-
* the surfaces that obey it. Everything downstream
|
|
109
|
-
* quick helper's choice of loop
|
|
108
|
+
* the surfaces that obey it. Everything downstream: the adapter that serves a turn, the transcript store, the
|
|
109
|
+
* quick helper's choice of loop: reads the runtime off this record, so a Gemini turn asking for Claude Code and
|
|
110
110
|
* getting it back would put the refused loop on the road again everywhere at once. */
|
|
111
111
|
test("gemini answers with its own runtime whatever harness is asked for", () => {
|
|
112
112
|
const native = capabilitiesOf("gemini", "native");
|
|
113
113
|
|
|
114
114
|
expect(native.runtime).toBe("opencode-gemini");
|
|
115
115
|
expect(capabilitiesOf("gemini", "claude-code")).toEqual(native);
|
|
116
|
-
// Same abilities as the Grok loop it shares
|
|
116
|
+
// Same abilities as the Grok loop it shares: only the runtime id, which keys adapter health, differs.
|
|
117
117
|
expect({ ...native, runtime: "opencode" }).toEqual(capabilitiesOf("grok", "native"));
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
-
test("codex and grok under the Claude Code harness get the full ceiling
|
|
120
|
+
test("codex and grok under the Claude Code harness get the full ceiling, it is the same loop", () => {
|
|
121
121
|
for (const provider of ["codex", "grok"] as const) {
|
|
122
122
|
expect(capabilitiesOf(provider, "claude-code")).toEqual(capabilitiesOf("claude", "native"));
|
|
123
123
|
}
|
|
124
124
|
});
|
|
125
125
|
|
|
126
126
|
// The composer's four modes describe behaviours the Claude Code loop actually has. A runtime whose every tool
|
|
127
|
-
// call is pre-approved has two postures, so it is offered two names
|
|
127
|
+
// call is pre-approved has two postures, so it is offered two names, not four names for two behaviours.
|
|
128
128
|
test("a plan-only runtime offers the two postures it has", () => {
|
|
129
129
|
expect(modesFor(capabilitiesOf("codex", "native"))).toEqual(["plan", "bypassPermissions"]);
|
|
130
130
|
expect(modesFor(capabilitiesOf("claude", "native"))).toEqual(["default", "acceptEdits", "plan", "bypassPermissions"]);
|
|
@@ -138,7 +138,7 @@ test("a mode the runtime can't hold falls back to the one it runs; one it can ho
|
|
|
138
138
|
expect(clampMode("acceptEdits", capabilitiesOf("claude", "native"))).toBe("acceptEdits");
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
-
/* The user-facing half. The full ceiling says nothing
|
|
141
|
+
/* The user-facing half. The full ceiling says nothing: an empty list is what hides the picker's block, and
|
|
142
142
|
* every axis the record carries has a sentence here, because a capability nobody can read is how this started. */
|
|
143
143
|
test("the ceiling has nothing to disclose; a floor names what it lacks", () => {
|
|
144
144
|
expect(limitationsOf(capabilitiesOf("claude", "native"))).toEqual([]);
|
|
@@ -149,15 +149,15 @@ test("the ceiling has nothing to disclose; a floor names what it lacks", () => {
|
|
|
149
149
|
expect(grok).toContain("no effort control");
|
|
150
150
|
expect(grok).toContain("worktree by working directory only");
|
|
151
151
|
|
|
152
|
-
// ACP takes our http MCP tools when it advertises them, so its line is a narrowing rather than an absence
|
|
152
|
+
// ACP takes our http MCP tools when it advertises them, so its line is a narrowing rather than an absence:
|
|
153
153
|
// and it publishes commands and terminals, which must NOT be listed as missing.
|
|
154
154
|
const acp = limitationsOf(capabilitiesOf("some-installed-agent", "native"));
|
|
155
|
-
expect(acp).toContain("MCP tools only
|
|
155
|
+
expect(acp).toContain("MCP tools only: no plugins or browser");
|
|
156
156
|
expect(acp).not.toContain("no slash commands");
|
|
157
157
|
expect(acp).not.toContain("no terminal panel");
|
|
158
158
|
|
|
159
159
|
const codex = limitationsOf(capabilitiesOf("codex", "native"));
|
|
160
|
-
expect(codex).toContain("browser tools only
|
|
160
|
+
expect(codex).toContain("browser tools only: no plugins or other MCP tools");
|
|
161
161
|
expect(codex).not.toContain("no MCP tools or plugins");
|
|
162
162
|
});
|
|
163
163
|
|
|
@@ -179,7 +179,7 @@ test("every axis a record can lack has words for it", () => {
|
|
|
179
179
|
};
|
|
180
180
|
|
|
181
181
|
// Eleven DISCLOSABLE axes, eleven sentences: an axis added to the interface without one would silently
|
|
182
|
-
// never be disclosed. fastMode is the deliberate twelfth
|
|
182
|
+
// never be disclosed. fastMode is the deliberate twelfth: a record alone can't tell the truth about it (a
|
|
183
183
|
// translator-routed turn reads true here and still can't go fast), so it is answered by fastAllowed
|
|
184
184
|
// instead. Anything else added to the interface has to move this number.
|
|
185
185
|
expect(limitationsOf(nothing)).toHaveLength(11);
|
|
@@ -196,12 +196,12 @@ test("the instruction axis discloses its two weaker answers, differently", () =>
|
|
|
196
196
|
expect(grok).toContain("added to theirs");
|
|
197
197
|
expect(grok).not.toContain("isn't applied");
|
|
198
198
|
expect(acp).toContain("isn't applied");
|
|
199
|
-
// Codex on its own runtime replaces, like the Claude Code loop
|
|
199
|
+
// Codex on its own runtime replaces, like the Claude Code loop, so it has nothing to disclose here.
|
|
200
200
|
expect(limitationsOf(capabilitiesOf("codex", "native")).join(" ")).not.toContain("system prompt");
|
|
201
201
|
});
|
|
202
202
|
|
|
203
203
|
/* The JS backend is hosted by the one loop the daemon can put its own execution seam through. Pinned as a test
|
|
204
|
-
* rather than left to the records because turn planning gates the backend on this axis
|
|
204
|
+
* rather than left to the records because turn planning gates the backend on this axis: a runtime gaining it
|
|
205
205
|
* here without a seam behind it would advertise code runs that can never execute. */
|
|
206
206
|
test("only the Claude Code loop hosts the js execution backend", () => {
|
|
207
207
|
for (const { provider, harness } of pairs) {
|
|
@@ -230,7 +230,7 @@ describe("the max-effort rule", () => {
|
|
|
230
230
|
expect(effortAllowed("high", "kimi", false)).toBe(true);
|
|
231
231
|
});
|
|
232
232
|
|
|
233
|
-
it("is repaired, not refused, on the way to the API
|
|
233
|
+
it("is repaired, not refused, on the way to the API: the tier drops, the user's thinking choice does not", () => {
|
|
234
234
|
expect(sendableEffort("max", false)).toBe("high");
|
|
235
235
|
expect(sendableEffort("max", undefined)).toBe("high");
|
|
236
236
|
expect(sendableEffort("max", true)).toBe("max");
|
|
@@ -241,7 +241,7 @@ describe("the max-effort rule", () => {
|
|
|
241
241
|
|
|
242
242
|
/* AN `endpoint/<id>` PROVIDER is a model API the user configured, and the one thing this record has to get right
|
|
243
243
|
* about it is that it is NOT an ACP agent. Both are minted by installing a capability and both are unknown to
|
|
244
|
-
* NATIVE_PROVIDERS, so the id is the only thing that tells them apart
|
|
244
|
+
* NATIVE_PROVIDERS, so the id is the only thing that tells them apart, and they want opposite records: an ACP
|
|
245
245
|
* agent brings its own loop and gets the documented floor, while an endpoint is driven BY the Claude Code loop
|
|
246
246
|
* and gets its full ceiling. Getting this backwards would strip steering, per-tool approvals, MCP and the mount
|
|
247
247
|
* namespace from every turn on a user's own model. */
|
|
@@ -262,7 +262,7 @@ describe("a configured model endpoint", () => {
|
|
|
262
262
|
expect(endpointProvider("gpu-box")).toBe("endpoint/gpu-box");
|
|
263
263
|
expect(endpointIdOf(endpointProvider("gpu-box"))).toBe("gpu-box");
|
|
264
264
|
expect(isEndpointProvider("endpoint/gpu-box")).toBe(true);
|
|
265
|
-
// A bare id that merely starts with the word is not one
|
|
265
|
+
// A bare id that merely starts with the word is not one: the separator is what makes the namespace.
|
|
266
266
|
expect(isEndpointProvider("endpoints-r-us")).toBe(false);
|
|
267
267
|
expect(endpointIdOf("claude")).toBeUndefined();
|
|
268
268
|
// Its credential was configured with the endpoint, so there is nothing left for a connect gate to offer.
|
|
@@ -271,7 +271,7 @@ describe("a configured model endpoint", () => {
|
|
|
271
271
|
});
|
|
272
272
|
|
|
273
273
|
/* FAST SPEED IS OFFERED ON THREE CONDITIONS AT ONCE, and the interesting cases are the ones where two of them
|
|
274
|
-
* hold. A translator-routed provider runs the Claude Code loop
|
|
274
|
+
* hold. A translator-routed provider runs the Claude Code loop: same record, same ceiling, and still cannot go
|
|
275
275
|
* fast, because the harness refuses a non-Anthropic endpoint; a Claude model that publishes no `fast` badge
|
|
276
276
|
* cannot either. Both would be silent failures if the composer offered the control anyway: the turn runs, the
|
|
277
277
|
* answer arrives, and only the bill says it was standard speed. */
|
|
@@ -281,7 +281,7 @@ describe("offering fast speed", () => {
|
|
|
281
281
|
});
|
|
282
282
|
|
|
283
283
|
it("is refused for a routed provider on the Claude Code loop, whose endpoint is not first-party", () => {
|
|
284
|
-
// Grok under the claude-code harness reads the FULL Claude Code record
|
|
284
|
+
// Grok under the claude-code harness reads the FULL Claude Code record: the capability alone would say
|
|
285
285
|
// yes. It is served through the sandbox's translator, so the harness would report `not_first_party`.
|
|
286
286
|
expect(capabilitiesOf("grok", "claude-code").fastMode).toBe(true);
|
|
287
287
|
expect(fastAllowed(capabilitiesOf("grok", "claude-code"), "grok", ["fast"])).toBe(false);
|
|
@@ -291,7 +291,7 @@ describe("offering fast speed", () => {
|
|
|
291
291
|
|
|
292
292
|
it("is refused for a Claude model whose catalog row doesn't publish it", () => {
|
|
293
293
|
expect(fastAllowed(capabilitiesOf("claude", "native"), "claude", ["reasoning"])).toBe(false);
|
|
294
|
-
// The seed floor and any provider that reports ids only
|
|
294
|
+
// The seed floor and any provider that reports ids only: no capabilities published, nothing claimed.
|
|
295
295
|
expect(fastAllowed(capabilitiesOf("claude", "native"), "claude", undefined)).toBe(false);
|
|
296
296
|
});
|
|
297
297
|
|