@intentic/sandbox-contract 1.212.0 → 1.214.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/dist/agent-catalog.d.ts.map +1 -1
- package/dist/agent-catalog.js +4 -4
- package/dist/agent-catalog.js.map +1 -1
- package/dist/contracts/agent.contract.d.ts +2 -0
- package/dist/contracts/agent.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.d.ts +150 -0
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.js +5 -1
- package/dist/contracts/agents.contract.js.map +1 -1
- package/dist/contracts/system.contract.d.ts +2 -0
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/events.d.ts +5 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +1 -0
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +154 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/schemas.d.ts +124 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +39 -0
- package/dist/schemas.js.map +1 -1
- package/dist/workspace-state.d.ts +8 -5
- package/dist/workspace-state.d.ts.map +1 -1
- package/dist/workspace-state.js +7 -7
- package/dist/workspace-state.js.map +1 -1
- package/package.json +4 -4
- package/src/agent-catalog.ts +13 -6
- package/src/contracts/agents.contract.ts +12 -0
- package/src/events.ts +11 -3
- package/src/schemas.ts +126 -4
- package/src/workspace-state.test.ts +42 -1
- package/src/workspace-state.ts +128 -29
|
@@ -10,7 +10,8 @@ export interface WorkspaceStateFile extends StateFile {
|
|
|
10
10
|
declare const STATE_FILES: readonly [{
|
|
11
11
|
readonly path: ".intentic/capabilities.json";
|
|
12
12
|
readonly invalidates: readonly ["capabilities", "environment", "panels", "manifests"];
|
|
13
|
-
readonly portability: "
|
|
13
|
+
readonly portability: "carry";
|
|
14
|
+
readonly versioned: true;
|
|
14
15
|
}, {
|
|
15
16
|
readonly path: ".intentic/capability-dismissals.json";
|
|
16
17
|
readonly invalidates: readonly ["capabilities"];
|
|
@@ -59,6 +60,7 @@ declare const STATE_FILES: readonly [{
|
|
|
59
60
|
readonly path: ".intentic/drafts/";
|
|
60
61
|
readonly invalidates: readonly ["drafts"];
|
|
61
62
|
readonly portability: "carry";
|
|
63
|
+
readonly versioned: true;
|
|
62
64
|
readonly authored: true;
|
|
63
65
|
}, {
|
|
64
66
|
readonly path: ".intentic/automations.json";
|
|
@@ -121,8 +123,8 @@ declare const STATE_FILES: readonly [{
|
|
|
121
123
|
readonly path: ".intentic/extension-settings.json";
|
|
122
124
|
readonly invalidates: readonly [];
|
|
123
125
|
readonly why: "Held in a module-level shallowRef store per extension (web's extensionSettingsStore) with no query observer, and deliberately so: api.settings.get must answer SYNCHRONOUSLY from an extension's first activate() line, and the store outlives every component scope. A module-level QueryObserver is the one shape that would make invalidation refetch, and this app already ruled it out — it detaches on the queryClient.clear() at logout (see useSandbox's sandbox-list mirror). So a remote member's setting edit reaches this browser on its next load, not live.";
|
|
124
|
-
readonly portability: "
|
|
125
|
-
readonly
|
|
126
|
+
readonly portability: "carry";
|
|
127
|
+
readonly versioned: true;
|
|
126
128
|
}, {
|
|
127
129
|
readonly path: ".intentic/extension-enablement.json";
|
|
128
130
|
readonly invalidates: readonly ["extensions"];
|
|
@@ -132,6 +134,7 @@ declare const STATE_FILES: readonly [{
|
|
|
132
134
|
readonly path: ".intentic/workspace-extensions/";
|
|
133
135
|
readonly invalidates: readonly ["extensions"];
|
|
134
136
|
readonly portability: "carry";
|
|
137
|
+
readonly versioned: true;
|
|
135
138
|
readonly authored: true;
|
|
136
139
|
}, {
|
|
137
140
|
readonly path: ".intentic/extension-updates.json";
|
|
@@ -156,9 +159,9 @@ declare const STATE_FILES: readonly [{
|
|
|
156
159
|
}, {
|
|
157
160
|
readonly path: ".intentic/auth/";
|
|
158
161
|
readonly invalidates: readonly [];
|
|
159
|
-
readonly why: "AI-provider credentials and runtime homes; each account is rendered through owner-gated provider routes.";
|
|
162
|
+
readonly why: "AI-provider credentials and runtime homes, plus the capability and extension-settings secret vaults; each account is rendered through owner-gated provider routes.";
|
|
160
163
|
readonly portability: "secret";
|
|
161
|
-
readonly note: "Sign the agent's AI accounts in again on the Agent tab.";
|
|
164
|
+
readonly note: "Sign the agent's AI accounts in again on the Agent tab, then re-enter each connection's credential on Capabilities and each extension's secret settings on Extensions — both arrived listed but unauthenticated.";
|
|
162
165
|
}, {
|
|
163
166
|
readonly path: ".intentic/sessions/claude/";
|
|
164
167
|
readonly invalidates: readonly [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-state.d.ts","sourceRoot":"","sources":["../src/workspace-state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AA0CxD,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IAKjD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAExC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"workspace-state.d.ts","sourceRoot":"","sources":["../src/workspace-state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AA0CxD,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IAKjD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAExC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAgCtB,QAAQ,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC;IAY1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC;IAKzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACnC;AAOD,QAAA,MAAM,WAAW;mBA2BL,6BAA6B;;0BAAoF,OAAO;;;mBAOxH,sCAAsC;;0BAA8C,OAAO;;;mBAO3F,4BAA4B;;0BAAyC,OAAO;;mBAc5E,yBAAyB;;0BAAuE,OAAO;;;mBAYvG,yCAAyC;;0BAA6C,OAAO;;;mBAC7F,kCAAkC;;0BAA6C,OAAO;;;mBACtF,0BAA0B;;0BAA6C,OAAO;;;mBAE5E,2CAA2C;;0BAEpC,SAAS;mBAChB,oGAAoG;;mBAGtG,yBAAyB;;0BAAuD,OAAO;;;mBAKrF,6BAA6B;;0BAEtB,SAAS;mBAChB,qFAAqF;;mBAiBvF,mBAAmB;;0BAAwC,OAAO;;;;mBAMhE,4BAA4B;;kBAE7B,kHAAkH;0BAC1G,OAAO;;;mBAiBd,gCAAgC;;kBAEjC,kHAAkH;0BAC1G,OAAO;;mBAGd,sBAAsB;;kBAEvB,2HAA2H;0BACnH,OAAO;;mBAQd,mBAAmB;;kBAEpB,8IAA8I;0BACtI,OAAO;;mBAOd,iBAAiB;;kBAElB,6IAA6I;0BACrI,OAAO;;4BAEL,sEAAsE;;mBASjF,0BAA0B;;0BAA2C,OAAO;;;mBAC5E,8BAA8B;;0BAA4D,OAAO;;mBAOjG,6BAA6B;;0BAA8C,OAAO;;;mBAEhF,sBAAsB;;kBAEvB,4cAA4c;0BACpc,OAAO;;mBAUd,iCAAiC;;kBAElC,gYAAgY;0BACxX,OAAO;;mBAGd,gCAAgC;;kBAEjC,+eAA+e;0BACve,OAAO;;mBAwBd,mCAAmC;;kBAEpC,2iBAA2iB;0BACniB,OAAO;;;mBAQd,qCAAqC;;0BAE9B,OAAO;;;mBAsBhB,iCAAiC;;0BAA4C,OAAO;;;;mBAIpF,kCAAkC;;0BAA4C,OAAO;;mBAGrF,wCAAwC;;0BAA4C,OAAO;;;mBAIzF,gCAAgC;;kBAEjC,qdAAqd;0BAC7c,OAAO;;mBAcd,wBAAwB;;kBAEzB,sVAAsV;0BAC9U,UAAU;mBACjB,uHAAuH;;mBAgBvH,iBAAiB;;kBAElB,oKAAoK;0BAC5J,QAAQ;mBACf,kNAAkN;;mBAalN,4BAA4B;;kBAE7B,8FAA8F;0BACtF,OAAO;;mBAGd,sBAAsB;;kBAEvB,6LAA6L;0BACrL,OAAO;;mBAGd,kBAAkB;;kBAEnB,+JAA+J;0BACvJ,SAAS;;mBAQhB,oBAAoB;;kBAErB,kHAAkH;0BAC1G,SAAS;4BACP,+CAA+C;;mBAGxD,gBAAgB;;kBAEjB,+JAA+J;0BACvJ,SAAS;;mBAQhB,wBAAwB;;kBAEzB,oHAAoH;0BAC5G,SAAS;4BACP,wDAAwD;;mBAGjE,2BAA2B;;kBAE5B,kJAAkJ;0BAC1I,SAAS;mBAChB,yDAAyD;;mBAGzD,uBAAuB;;kBAExB,4IAA4I;0BACpI,OAAO;;mBAGd,mBAAmB;;kBAEpB,2GAA2G;0BACnG,SAAS;;mBAGhB,mBAAmB;;kBAEpB,iGAAiG;0BACzF,QAAQ;mBACf,0EAA0E;;mBAG1E,+BAA+B;;kBAEhC,oIAAoI;0BAC5H,UAAU;mBACjB,mFAAmF;;mBAGnF,sBAAsB;;kBAEvB,uGAAuG;0BAC/F,UAAU;;mBAGjB,0BAA0B;;kBAE3B,kFAAkF;0BAC1E,UAAU;;mBAGjB,0BAA0B;;kBAE3B,0DAA0D;0BAClD,OAAO;;;mBAQd,oBAAoB;;kBAErB,sGAAsG;0BAC9F,SAAS;mBAChB,+EAA+E;;mBAG/E,uBAAuB;;kBAExB,mIAAmI;0BAC3H,SAAS;mBAChB,kFAAkF;;mBAEpF,oBAAoB;;kBAAwB,wDAAwD;0BAAe,OAAO;;mBAS1H,mBAAmB;;0BAAwC,OAAO;;;mBAclE,qBAAqB;;0BAA0C,OAAO;;EAChC,CAAC;AAEnD,eAAO,MAAM,qBAAqB,EAAE,SAAS,kBAAkB,EAAgB,CAAC;AAShF,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAAoF,CAAC;AAgBxI,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAEnD,CAAC;AAUF,eAAO,MAAM,mBAAmB,cAAe,MAAM,KAAG,MAA4F,CAAC;AAmBrJ,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAEpD,CAAC;AAIF,eAAO,MAAM,kBAAkB,YAAa,MAAM,KAAG,OAA0E,CAAC;AAShI,eAAO,MAAM,4BAA4B;aACrC,MAAM,YAAG,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;aAC1D,OAAO,YAAG,IAAI,EAAE,oBAAoB,EAAE,SAAS,EAAE,gBAAgB;aACjE,SAAS,YAAG,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,aAAa;CAC1E,CAAC;AAmCX,eAAO,MAAM,qBAAqB,YAAa,MAAM,KAAG,OAMvD,CAAC;AAaF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AActE,eAAO,MAAM,cAAc,UAAW,SAAS,MAAM,EAAE,eAAe,SAAS,gBAAgB,EAAE,KAAG,SAAS,MAAM,EAMlH,CAAC;AAOF,eAAO,MAAM,kBAAkB,gBAAiB,SAAS,gBAAgB,EAAE,KAAG,SAAS,MAAM,EAE5F,CAAC"}
|
package/dist/workspace-state.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { STATE_DIR } from "@intentic/constants";
|
|
2
2
|
const STATE_FILES = [
|
|
3
|
-
{ path: ".intentic/capabilities.json", invalidates: ["capabilities", "environment", "panels", "manifests"], portability: "
|
|
3
|
+
{ path: ".intentic/capabilities.json", invalidates: ["capabilities", "environment", "panels", "manifests"], portability: "carry", versioned: true },
|
|
4
4
|
{ path: ".intentic/capability-dismissals.json", invalidates: ["capabilities"], portability: "carry", versioned: true },
|
|
5
5
|
{ path: ".intentic/secret-uses.json", invalidates: ["secrets"], portability: "carry" },
|
|
6
6
|
{ path: ".intentic/personas.json", invalidates: ["personas", "capabilities", "manifests"], portability: "carry", versioned: true },
|
|
@@ -20,7 +20,7 @@ const STATE_FILES = [
|
|
|
20
20
|
portability: "derived",
|
|
21
21
|
note: "Stamps of when each rule last did something; the new sandbox starts its own record.",
|
|
22
22
|
},
|
|
23
|
-
{ path: ".intentic/drafts/", invalidates: ["drafts"], portability: "carry", authored: true },
|
|
23
|
+
{ path: ".intentic/drafts/", invalidates: ["drafts"], portability: "carry", versioned: true, authored: true },
|
|
24
24
|
{
|
|
25
25
|
path: ".intentic/automations.json",
|
|
26
26
|
invalidates: [],
|
|
@@ -79,8 +79,8 @@ const STATE_FILES = [
|
|
|
79
79
|
path: ".intentic/extension-settings.json",
|
|
80
80
|
invalidates: [],
|
|
81
81
|
why: "Held in a module-level shallowRef store per extension (web's extensionSettingsStore) with no query observer, and deliberately so: api.settings.get must answer SYNCHRONOUSLY from an extension's first activate() line, and the store outlives every component scope. A module-level QueryObserver is the one shape that would make invalidation refetch, and this app already ruled it out — it detaches on the queryClient.clear() at logout (see useSandbox's sandbox-list mirror). So a remote member's setting edit reaches this browser on its next load, not live.",
|
|
82
|
-
portability: "
|
|
83
|
-
|
|
82
|
+
portability: "carry",
|
|
83
|
+
versioned: true,
|
|
84
84
|
},
|
|
85
85
|
{
|
|
86
86
|
path: ".intentic/extension-enablement.json",
|
|
@@ -88,7 +88,7 @@ const STATE_FILES = [
|
|
|
88
88
|
portability: "carry",
|
|
89
89
|
versioned: true,
|
|
90
90
|
},
|
|
91
|
-
{ path: ".intentic/workspace-extensions/", invalidates: ["extensions"], portability: "carry", authored: true },
|
|
91
|
+
{ path: ".intentic/workspace-extensions/", invalidates: ["extensions"], portability: "carry", versioned: true, authored: true },
|
|
92
92
|
{ path: ".intentic/extension-updates.json", invalidates: ["extensions"], portability: "carry" },
|
|
93
93
|
{ path: ".intentic/extension-update-policy.json", invalidates: ["extensions"], portability: "carry", versioned: true },
|
|
94
94
|
{
|
|
@@ -107,9 +107,9 @@ const STATE_FILES = [
|
|
|
107
107
|
{
|
|
108
108
|
path: ".intentic/auth/",
|
|
109
109
|
invalidates: [],
|
|
110
|
-
why: "AI-provider credentials and runtime homes; each account is rendered through owner-gated provider routes.",
|
|
110
|
+
why: "AI-provider credentials and runtime homes, plus the capability and extension-settings secret vaults; each account is rendered through owner-gated provider routes.",
|
|
111
111
|
portability: "secret",
|
|
112
|
-
note: "Sign the agent's AI accounts in again on the Agent tab.",
|
|
112
|
+
note: "Sign the agent's AI accounts in again on the Agent tab, then re-enter each connection's credential on Capabilities and each extension's secret settings on Extensions — both arrived listed but unauthenticated.",
|
|
113
113
|
},
|
|
114
114
|
{
|
|
115
115
|
path: ".intentic/sessions/claude/",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-state.js","sourceRoot":"","sources":["../src/workspace-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"workspace-state.js","sourceRoot":"","sources":["../src/workspace-state.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentic/sandbox-contract",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.214.0",
|
|
4
4
|
"description": "oRPC wire contract for the intentic sandbox daemon — shared by the daemon and its browser client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -89,9 +89,9 @@
|
|
|
89
89
|
"@orpc/contract": "1.14.13",
|
|
90
90
|
"tslib": "2.8.1",
|
|
91
91
|
"zod": "4.4.3",
|
|
92
|
-
"@intentic/constants": "1.
|
|
93
|
-
"@intentic/
|
|
94
|
-
"@intentic/
|
|
92
|
+
"@intentic/constants": "1.214.0",
|
|
93
|
+
"@intentic/registry": "1.214.0",
|
|
94
|
+
"@intentic/extension-manifest": "1.214.0"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
97
|
"@types/node": "24.13.2",
|
package/src/agent-catalog.ts
CHANGED
|
@@ -293,19 +293,26 @@ const CLAUDE_CODE: AgentCapabilities = {
|
|
|
293
293
|
instructions: "replace",
|
|
294
294
|
};
|
|
295
295
|
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
/* Codex app-server: item-level events, process-backed MCP servers, and the four interactive seams its protocol
|
|
297
|
+
* actually publishes — `turn/steer` for mid-turn injection, the experimental `item/tool/requestUserInput` server
|
|
298
|
+
* request behind a question card, `skills/list` for the `/` popover (a picked command rides back as a structured
|
|
299
|
+
* skill input), and the same mount namespace the Claude Code loop gets, because app-server is a child process
|
|
300
|
+
* the adapter spawns and nsenter can put it in the turn's namespace like any other.
|
|
301
|
+
*
|
|
302
|
+
* Browser servers ride the per-thread config; daemon-side SDK servers, plugins and server-initiated APPROVALS
|
|
303
|
+
* stay unwired — the container is the isolation boundary, so approvals are declined by design rather than
|
|
304
|
+
* missing (codex-app-server.ts refuses every server request but the question one). */
|
|
298
305
|
const CODEX: AgentCapabilities = {
|
|
299
306
|
runtime: "codex",
|
|
300
|
-
steering:
|
|
307
|
+
steering: true,
|
|
301
308
|
permissions: "plan",
|
|
302
|
-
questions:
|
|
309
|
+
questions: true,
|
|
303
310
|
mcp: "browser",
|
|
304
311
|
execution: ["shell"],
|
|
305
312
|
effort: true,
|
|
306
313
|
fastMode: false,
|
|
307
|
-
isolation: "
|
|
308
|
-
commands:
|
|
314
|
+
isolation: "namespace",
|
|
315
|
+
commands: true,
|
|
309
316
|
terminals: false,
|
|
310
317
|
recovery: false,
|
|
311
318
|
/* Both halves, through the per-thread `config` block the adapter already sends: `model_instructions_file`
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
AgentLandSchema,
|
|
11
11
|
AgentPlaceSchema,
|
|
12
12
|
AgentRenameSchema,
|
|
13
|
+
AgentResumeAfterOutageSchema,
|
|
13
14
|
AgentSearchQuerySchema,
|
|
14
15
|
AgentSearchResultSchema,
|
|
15
16
|
AgentsListSchema,
|
|
@@ -67,6 +68,17 @@ export const agentsContract = {
|
|
|
67
68
|
// clears it back to "inherit". Legal mid-turn on purpose: the setting is read at turn COMPLETION, so
|
|
68
69
|
// flipping it while the agent works is exactly "hold THIS turn's work for review", the press that matters.
|
|
69
70
|
autoLand: oc.route({ method: "POST", path: "/agents/{id}/auto-land" }).input(AgentAutoLandSchema).output(AgentSummarySchema),
|
|
71
|
+
/* THIS conversation's answer to a provider outage — an override of the sandbox-wide `resumeAfterOutage`
|
|
72
|
+
* setting; null clears it back to "inherit". The chat's offer at the moment a turn dies writes this and
|
|
73
|
+
* never the global: the press happens inside one conversation and means "finish this piece of work", so
|
|
74
|
+
* its honest blast radius is that conversation. Sandbox ▸ Agent owns the default for everything else.
|
|
75
|
+
*
|
|
76
|
+
* Legal mid-turn, and unlike autoLand it is legal for a WORKSPACE conversation too — an outage kills a
|
|
77
|
+
* main-tree chat exactly as readily as an isolated one, and there is no branch involved either way. */
|
|
78
|
+
resumeAfterOutage: oc
|
|
79
|
+
.route({ method: "POST", path: "/agents/{id}/resume-after-outage" })
|
|
80
|
+
.input(AgentResumeAfterOutageSchema)
|
|
81
|
+
.output(AgentSummarySchema),
|
|
70
82
|
seen: oc.route({ method: "POST", path: "/agents/{id}/seen" }).input(AgentIdSchema).output(AgentSummarySchema),
|
|
71
83
|
seenAll: oc.route({ method: "POST", path: "/agents/seen" }).output(AgentsListSchema),
|
|
72
84
|
diff: oc.route({ method: "GET", path: "/agents/{id}/diff" }).input(AgentIdSchema).output(AgentChangesSchema),
|
package/src/events.ts
CHANGED
|
@@ -66,6 +66,11 @@ export const ServiceOfferSchema = z.object({
|
|
|
66
66
|
publisher: z.string(),
|
|
67
67
|
description: z.string(),
|
|
68
68
|
creditsPerRun: z.number(),
|
|
69
|
+
/* Whether the platform still has this listing on probation — a new provider that passed admission's
|
|
70
|
+
* mechanical gates but has not yet served enough runs cleanly to graduate. It rides the card because
|
|
71
|
+
* probation is the honest form of "listed automatically, not vouched for": the member approving the
|
|
72
|
+
* spend is the person who should know that, and the platform is the only party that can say it. */
|
|
73
|
+
probation: z.boolean().optional(),
|
|
69
74
|
// The owner's meter as the platform stated it with the catalog — what "N left today" renders from. Absent
|
|
70
75
|
// when the platform sent none (it answers a meter only to a member, and membership was already checked
|
|
71
76
|
// before this card went up, so in practice it is present; the field stays honest about the wire).
|
|
@@ -694,9 +699,12 @@ export const AgentEventSchema = z.discriminatedUnion("kind", [
|
|
|
694
699
|
resetsAt: z.number().optional(),
|
|
695
700
|
// Where the daemon's resume of THIS turn stands, for the two codes that have one (provider-outage,
|
|
696
701
|
// claude-token-refused). "scheduled" = the resume is armed and this turn comes back by itself;
|
|
697
|
-
// "available" = the daemon remembered the failed turn and
|
|
698
|
-
// resume, which is what the chat's offer
|
|
699
|
-
//
|
|
702
|
+
// "available" = the daemon remembered the failed turn and arming THIS conversation
|
|
703
|
+
// (AgentSummarySchema.resumeAfterOutage) picks up that same resume, which is what the chat's offer
|
|
704
|
+
// banner hangs off — outage only, since a renewal is never gated on a posture at all. The two words
|
|
705
|
+
// are read against the effective posture (the conversation's override, else the sandbox default), so a
|
|
706
|
+
// chat armed on its own says "scheduled" while the unarmed board around it says "available".
|
|
707
|
+
// Absent means there is nothing automatic to resume: a spent usage limit never has one,
|
|
700
708
|
// and a refused credential has none once re-minting it has already been tried and failed.
|
|
701
709
|
autoResume: z.enum(["scheduled", "available"]).optional(),
|
|
702
710
|
/* provider-outage only: the shape of the wait. `retryAt` (epoch seconds) is when the next attempt is
|
package/src/schemas.ts
CHANGED
|
@@ -832,6 +832,19 @@ export const AgentSummarySchema = z.object({
|
|
|
832
832
|
// the global toggle meaningful: an agent that never expressed an opinion follows the sandbox wherever it
|
|
833
833
|
// is pointed next. Written by `agents.autoLand`; the UI shows the EFFECTIVE value (this ?? the setting).
|
|
834
834
|
autoLand: z.boolean().optional(),
|
|
835
|
+
/* This agent's own answer to "re-run my turn when the model provider was what failed?" — the same
|
|
836
|
+
* two-level shape as `autoLand` above, and here for a sharper reason than symmetry.
|
|
837
|
+
*
|
|
838
|
+
* The press that writes this is offered INSIDE one conversation, at the moment that conversation's turn
|
|
839
|
+
* died, and what a person means by it is "finish THIS piece of work". It used to write the sandbox-wide
|
|
840
|
+
* setting, so one impatient click at 2 a.m. quietly armed every agent on the board — a blast radius
|
|
841
|
+
* nothing on screen had asked about. So the chat's offer writes this, the settings toggle writes the
|
|
842
|
+
* default, and the two stay honestly different things.
|
|
843
|
+
*
|
|
844
|
+
* ABSENT ⇒ inherit the sandbox setting, which is what keeps that default meaningful: a conversation that
|
|
845
|
+
* never expressed an opinion follows the sandbox wherever it is pointed next. Written by
|
|
846
|
+
* `agents.resumeAfterOutage`; every surface shows the EFFECTIVE value (this ?? the setting). */
|
|
847
|
+
resumeAfterOutage: z.boolean().optional(),
|
|
835
848
|
// A collaborator asked for this agent's work to be landed (agents.requestLand) — collaborators may drive
|
|
836
849
|
// agents but not merge into the main tree, so the ask rides the summary where every maintainer's board
|
|
837
850
|
// sees it. Cleared by the land or discard that answers it. Absent ⇒ nobody is waiting.
|
|
@@ -1048,6 +1061,11 @@ export const AgentPlaceSchema = z.object({ id: z.string().min(1), text: z.string
|
|
|
1048
1061
|
// the sandbox setting" — the browser sends it whenever the user toggles back to what the global already says,
|
|
1049
1062
|
// so agents don't accumulate frozen overrides that quietly stop following the global toggle.
|
|
1050
1063
|
export const AgentAutoLandSchema = z.object({ id: z.string().min(1), autoLand: z.boolean().nullable() });
|
|
1064
|
+
// resumeAfterOutage's input: this ONE conversation's answer to a provider outage. `null` clears the override
|
|
1065
|
+
// back to "inherit the sandbox setting" — sent whenever the user toggles back to what the global already says,
|
|
1066
|
+
// on the same reasoning as autoLand's null: an agent holding a frozen copy of a default has quietly stopped
|
|
1067
|
+
// following it, and nothing on screen would say so.
|
|
1068
|
+
export const AgentResumeAfterOutageSchema = z.object({ id: z.string().min(1), resumeAfterOutage: z.boolean().nullable() });
|
|
1051
1069
|
export const AgentFileDiffQuerySchema = z.object({ id: z.string().min(1), repo: z.string().min(1), path: z.string().min(1) });
|
|
1052
1070
|
/* WHY a path would not land. The distinction is the whole difference between an actionable report and a dead
|
|
1053
1071
|
* end, because the three have nothing in common but their symptom:
|
|
@@ -1852,15 +1870,23 @@ export const SandboxSettingsSchema = z.object({
|
|
|
1852
1870
|
// terminal state: without a sweep the Finished lane grows for the life of the sandbox, and each card it
|
|
1853
1871
|
// holds is a live worktree checkout, not just a row.
|
|
1854
1872
|
agentRetentionDays: z.number().min(0).max(365).default(3),
|
|
1855
|
-
/*
|
|
1856
|
-
* socket), re-run it on an escalating backoff until it goes through or the
|
|
1873
|
+
/* THE SANDBOX-WIDE DEFAULT for "when a turn dies because the MODEL PROVIDER was failing (500/502/503, a
|
|
1874
|
+
* 529 at capacity, a dropped socket), re-run it on an escalating backoff until it goes through or the
|
|
1875
|
+
* attempts are spent".
|
|
1876
|
+
*
|
|
1877
|
+
* A DEFAULT, not the whole answer: any one conversation may override it (AgentSummarySchema
|
|
1878
|
+
* .resumeAfterOutage), and the chat's own offer at the moment of failure writes THAT rather than this.
|
|
1879
|
+
* This toggle is the standing policy for every agent that has not said otherwise, which is why it lives in
|
|
1880
|
+
* settings and is not reachable by a single press from inside one chat — flipping how the whole board
|
|
1881
|
+
* behaves should be a thing somebody went to do.
|
|
1857
1882
|
*
|
|
1858
1883
|
* OFF by default, on the same reasoning that keeps a spent usage limit out of this pair entirely: a resume
|
|
1859
1884
|
* re-runs a turn the user sent once, on their own allowance, and only they can say whether the turn was
|
|
1860
1885
|
* worth paying for twice. Starting off costs nothing, because the failed turn is remembered whatever the
|
|
1861
1886
|
* toggle says (recordOutageFailure) — the failure frame reports an "available" resume and the chat's offer
|
|
1862
|
-
* arms that very turn the moment it is
|
|
1863
|
-
* nobody in the room (automation wakes, Discord, webhooks), which is the case no browser
|
|
1887
|
+
* arms that very turn the moment it is armed for that conversation. Worth turning ON for a sandbox whose
|
|
1888
|
+
* turns mostly have nobody in the room (automation wakes, Discord, webhooks), which is the case no browser
|
|
1889
|
+
* could rescue and the case a per-conversation press cannot reach. */
|
|
1864
1890
|
resumeAfterOutage: z.boolean().default(false),
|
|
1865
1891
|
/* When the daemon dies under a running turn, re-run that turn once it is back (agent/turn-journal.ts records
|
|
1866
1892
|
* every in-flight turn; the boot pass in agent/turn-resume.ts re-runs what survived). OFF by default, like
|
|
@@ -5995,6 +6021,102 @@ export const ImportReportSchema = z.object({
|
|
|
5995
6021
|
});
|
|
5996
6022
|
export type ImportReport = z.infer<typeof ImportReportSchema>;
|
|
5997
6023
|
|
|
6024
|
+
/* ---- migrations: importing a FOREIGN assistant's setup (Hermes, OpenClaw) ----
|
|
6025
|
+
*
|
|
6026
|
+
* A different crossing than a bundle restore, and deliberately a different surface: a bundle is our own format,
|
|
6027
|
+
* re-derived entry by entry against the state manifests, while a migration reads a directory some OTHER
|
|
6028
|
+
* program laid out (`~/.hermes`) and TRANSLATES it into native things — skills, automations, capabilities,
|
|
6029
|
+
* merged memory. Nothing foreign is executed or copied verbatim into daemon state; every item lands through the
|
|
6030
|
+
* same write paths the settings/skills/automations/capabilities surfaces use, which is what keeps an imported
|
|
6031
|
+
* setup editable and deletable in the ordinary UI the day after (docs/assistant-import-design.md).
|
|
6032
|
+
*
|
|
6033
|
+
* The flow is PREVIEW-FIRST, mirroring what these tools' own `migrate` commands taught their users to expect:
|
|
6034
|
+
* `plan` parses the uploaded archive into an itemized checklist and holds the upload in memory under a token;
|
|
6035
|
+
* `apply` names the ticked item ids and the token. The plan is RE-DERIVED from the held archive at apply — the
|
|
6036
|
+
* wire plan is a rendering for the owner, never the input the write trusts (restore.ts's rule, kept). */
|
|
6037
|
+
export const MigrationSourceSchema = z.enum(["hermes", "openclaw"]);
|
|
6038
|
+
export type MigrationSource = z.infer<typeof MigrationSourceSchema>;
|
|
6039
|
+
|
|
6040
|
+
// What an item becomes here, not what it was there — the apply loop dispatches on this, and the checklist
|
|
6041
|
+
// groups by it so the owner reads "3 skills, 2 automations" rather than a foreign directory listing.
|
|
6042
|
+
export const MigrationTargetSchema = z.enum(["memory", "skill", "automation", "capability", "secret", "file"]);
|
|
6043
|
+
export type MigrationTarget = z.infer<typeof MigrationTargetSchema>;
|
|
6044
|
+
|
|
6045
|
+
export const MigrationItemSchema = z.object({
|
|
6046
|
+
// Deterministic (derived from the source artifact, e.g. `skill:weather`), so the ids the owner ticked name
|
|
6047
|
+
// the same items when the plan is re-derived at apply.
|
|
6048
|
+
id: z.string(),
|
|
6049
|
+
target: MigrationTargetSchema,
|
|
6050
|
+
// The checklist line, plain words: "Skill — weather", "Nightly digest (9:00 every day)".
|
|
6051
|
+
label: z.string(),
|
|
6052
|
+
detail: z.string().optional(),
|
|
6053
|
+
/* The default tick. False marks the items the owner should read before taking — a server URL that points at
|
|
6054
|
+
* localhost on the OLD machine, an .env key that looks like tuning rather than a credential. They still
|
|
6055
|
+
* import fine when ticked; the flag is the adapter's judgment, not a gate. */
|
|
6056
|
+
recommended: z.boolean(),
|
|
6057
|
+
// Names of the secrets this item would store (never values — values stay in the held archive until apply,
|
|
6058
|
+
// and only move when the apply says includeSecrets). Empty for items that carry none.
|
|
6059
|
+
secrets: z.array(z.string()),
|
|
6060
|
+
});
|
|
6061
|
+
export type MigrationItem = z.infer<typeof MigrationItemSchema>;
|
|
6062
|
+
|
|
6063
|
+
export const MigrationNeedsActionSchema = z.object({ subject: z.string(), detail: z.string() });
|
|
6064
|
+
|
|
6065
|
+
export const MigrationPlanSchema = z.object({
|
|
6066
|
+
source: MigrationSourceSchema,
|
|
6067
|
+
// Names the held upload for the apply call. Minted per plan; a new upload replaces the held one.
|
|
6068
|
+
token: z.string(),
|
|
6069
|
+
items: z.array(MigrationItemSchema),
|
|
6070
|
+
// What the adapter saw and will not move — sessions, logs, pairing state — listed rather than silent.
|
|
6071
|
+
refused: z.array(z.string()),
|
|
6072
|
+
// What is already known not to move mechanically (channels to reconnect, a model to pick) — the same
|
|
6073
|
+
// honesty ImportReportSchema carries, surfaced at PREVIEW time so the owner ticks with open eyes.
|
|
6074
|
+
needsAction: z.array(MigrationNeedsActionSchema),
|
|
6075
|
+
});
|
|
6076
|
+
export type MigrationPlan = z.infer<typeof MigrationPlanSchema>;
|
|
6077
|
+
|
|
6078
|
+
/* One of the owner's own computers, as an import SOURCE — the answer to "where is my setup" that needs no
|
|
6079
|
+
* packing at all. Read on the card's first render for every enrolled machine, so the offer appears before the
|
|
6080
|
+
* owner has read a single instruction.
|
|
6081
|
+
*
|
|
6082
|
+
* `found` absent means "connected, and nothing to import here" — which is a real answer worth rendering
|
|
6083
|
+
* quietly, not an error: the machine may simply be a different one from the machine the assistant runs on. */
|
|
6084
|
+
export const MigrationHostSchema = z.object({
|
|
6085
|
+
id: z.string(),
|
|
6086
|
+
online: z.boolean(),
|
|
6087
|
+
found: MigrationSourceSchema.optional(),
|
|
6088
|
+
// Why this machine cannot be read right now, when it cannot — offline, or its own refusal, in its words.
|
|
6089
|
+
detail: z.string().optional(),
|
|
6090
|
+
});
|
|
6091
|
+
export const MigrationHostsSchema = z.object({ hosts: z.array(MigrationHostSchema) });
|
|
6092
|
+
export type MigrationHost = z.infer<typeof MigrationHostSchema>;
|
|
6093
|
+
|
|
6094
|
+
// Read the setup off a connected computer instead of an upload. Answers with a plan, exactly as the upload
|
|
6095
|
+
// route does — everything after this point is identical whichever door the setup came through.
|
|
6096
|
+
export const MigrationScanSchema = z.object({ host: z.string().min(1) });
|
|
6097
|
+
|
|
6098
|
+
export const MigrationApplySchema = z.object({
|
|
6099
|
+
token: z.string(),
|
|
6100
|
+
// The ticked item ids. Ids the re-derived plan does not contain are ignored rather than erroring — the
|
|
6101
|
+
// archive is the truth, and a stale checklist must not block the items that still exist.
|
|
6102
|
+
items: z.array(z.string()),
|
|
6103
|
+
// The owner's explicit consent to move credential VALUES (mirrors the bundle export's `?secrets=`, and the
|
|
6104
|
+
// `--include-secrets` these tools' own migrate commands require). Off: secret items are skipped and
|
|
6105
|
+
// capability configs land without their keys.
|
|
6106
|
+
includeSecrets: z.boolean(),
|
|
6107
|
+
});
|
|
6108
|
+
export type MigrationApply = z.infer<typeof MigrationApplySchema>;
|
|
6109
|
+
|
|
6110
|
+
export const MigrationReportSchema = z.object({
|
|
6111
|
+
applied: z.array(z.object({ id: z.string(), target: MigrationTargetSchema, label: z.string() })),
|
|
6112
|
+
// Items that were ticked and did not land, each with the reason — a full disk, an env store that needs
|
|
6113
|
+
// DevOps active. Distinct from `refused`, which is the class of things never attempted.
|
|
6114
|
+
failed: z.array(z.object({ id: z.string(), label: z.string(), error: z.string() })),
|
|
6115
|
+
refused: z.array(z.string()),
|
|
6116
|
+
needsAction: z.array(MigrationNeedsActionSchema),
|
|
6117
|
+
});
|
|
6118
|
+
export type MigrationReport = z.infer<typeof MigrationReportSchema>;
|
|
6119
|
+
|
|
5998
6120
|
/* One export sitting in the daemon's export directory — the ARTIFACT a bundle is, rather than the request that
|
|
5999
6121
|
* produced it. Packing takes minutes over a real workspace, so tying it to a response made it a property of one
|
|
6000
6122
|
* browser tab: a refresh abandoned the work and left nothing to come back to. It is a file now, and every field
|
|
@@ -265,14 +265,30 @@ describe(`VERSIONED_STATE_PATHS`, () => {
|
|
|
265
265
|
|
|
266
266
|
/* Spelled out rather than derived, so ADDING a tracked entry is a visible edit to this list and not a silent
|
|
267
267
|
* consequence of editing the table above — the review the flag itself exists to force. */
|
|
268
|
-
it(`tracks exactly the configuration slice`, () => {
|
|
268
|
+
it(`tracks exactly the configuration slice plus the agent's own authored output`, () => {
|
|
269
269
|
expect(VERSIONED_STATE_PATHS.toSorted()).toEqual([
|
|
270
270
|
`.intentic/automations.json`,
|
|
271
|
+
/* The connections themselves, and the entry that took the longest to earn its place — it was classed
|
|
272
|
+
* `secret` on the strength of holding each capability's credential, which stopped being true when the
|
|
273
|
+
* vault took the values out and left the shape behind. Connecting a deployment orchestrator, or
|
|
274
|
+
* granting a connected computer shell and screen control, is the largest change made to what this
|
|
275
|
+
* sandbox can DO, and it used to leave no diff. */
|
|
276
|
+
`.intentic/capabilities.json`,
|
|
271
277
|
`.intentic/capability-dismissals.json`,
|
|
278
|
+
/* The two entries the AGENT authors on its own initiative, and the reason `versioned` is not read as
|
|
279
|
+
* config-only. Both are the sandbox acting outward — a draft publishes words under the owner's name,
|
|
280
|
+
* a workspace extension is code that runs in the app and can serve HTTP with the workspace under
|
|
281
|
+
* node:fs — and both used to reach that far with no diff anywhere. Kept rather than consumed, one
|
|
282
|
+
* small file at a time, so tracking them yields a record instead of churn. */
|
|
283
|
+
`.intentic/drafts/`,
|
|
272
284
|
`.intentic/environment.Dockerfile`,
|
|
273
285
|
`.intentic/environment.custom.Dockerfile`,
|
|
274
286
|
`.intentic/environment.d/`,
|
|
275
287
|
`.intentic/extension-enablement.json`,
|
|
288
|
+
/* Its twin, and the pair is the argument: the SWITCH was already tracked while the configuration
|
|
289
|
+
* behind it was not, so a commit could record turning an extension on and say nothing about what it
|
|
290
|
+
* was told to do. Tracked once its declared-secret values moved to the vault. */
|
|
291
|
+
`.intentic/extension-settings.json`,
|
|
276
292
|
// The owner's per-extension update posture (notify / agent / auto) — a standing decision about
|
|
277
293
|
// what may run unattended, which is exactly the kind of edit worth a line in `git log`.
|
|
278
294
|
`.intentic/extension-update-policy.json`,
|
|
@@ -287,9 +303,34 @@ describe(`VERSIONED_STATE_PATHS`, () => {
|
|
|
287
303
|
`.intentic/skills/`,
|
|
288
304
|
`.intentic/templates.json`,
|
|
289
305
|
`.intentic/workflows.json`,
|
|
306
|
+
`.intentic/workspace-extensions/`,
|
|
290
307
|
]);
|
|
291
308
|
});
|
|
292
309
|
|
|
310
|
+
/* THE ASYMMETRY THIS CLOSED, kept as its own assertion because it is the failure rather than a detail of it:
|
|
311
|
+
* the switch was tracked and the thing it switched was not, so a commit could record turning on an extension
|
|
312
|
+
* whose code nobody else could read — and a workspace extension has no install moment to review at instead. */
|
|
313
|
+
it(`tracks a workspace extension's code, not just the switch that enables it`, () => {
|
|
314
|
+
expect(VERSIONED_STATE_PATHS).toContain(`.intentic/extension-enablement.json`);
|
|
315
|
+
expect(VERSIONED_STATE_PATHS).toContain(`.intentic/workspace-extensions/`);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
/* A QUEUE IS A LEDGER, which is the distinction the two entries above turn on. A draft is kept after it
|
|
319
|
+
* settles (`posted`, with postedAt/postedUrl stamped on it), so tracking it leaves a durable record of what
|
|
320
|
+
* went out; a held wake is REMOVED once answered, so tracking it would leave an add and a delete describing
|
|
321
|
+
* a decision whose outcome lives elsewhere. Same for the staged docs: publishing copies them into the repo,
|
|
322
|
+
* where they are tracked as ordinary content, so tracking the staging tree too would double every page. */
|
|
323
|
+
it(`leaves the consumed queues and the staging trees out even though they are authored`, () => {
|
|
324
|
+
for (const path of [`.intentic/approvals/`, `.intentic/docs/`]) {
|
|
325
|
+
expect([path, VERSIONED_STATE_PATHS.includes(path)]).toEqual([path, false]);
|
|
326
|
+
}
|
|
327
|
+
// Both still reach workspace search — searchability is a property of the content, not of tracking.
|
|
328
|
+
for (const path of [`.intentic/approvals/`, `.intentic/docs/`]) {
|
|
329
|
+
const entry = WORKSPACE_STATE_FILES.find((file) => file.path === path);
|
|
330
|
+
expect([path, entry?.versioned === true || entry?.authored === true]).toEqual([path, path === `.intentic/docs/`]);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
293
334
|
/* The composed overlay is `derived` — recomposed on every boot from the custom file that IS tracked, against
|
|
294
335
|
* whatever base image this container happens to be on. Tracking it would put a rewritten-at-startup file in
|
|
295
336
|
* front of the owner as a change they made. */
|