@intentic/sandbox-contract 1.228.3 → 1.230.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentic/sandbox-contract",
3
- "version": "1.228.3",
3
+ "version": "1.230.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.228.3",
93
- "@intentic/extension-manifest": "1.228.3",
94
- "@intentic/registry": "1.228.3"
92
+ "@intentic/constants": "1.230.0",
93
+ "@intentic/extension-manifest": "1.230.0",
94
+ "@intentic/registry": "1.230.0"
95
95
  },
96
96
  "devDependencies": {
97
97
  "@types/node": "24.13.2",
@@ -165,6 +165,27 @@ export const agentsContract = {
165
165
  })
166
166
  .input(AgentIdSchema)
167
167
  .output(AgentSummarySchema),
168
+ /* DISARM EVERY CONDITION WATCH THIS CONVERSATION IS PARKED ON (AgentSummary.watches), the way off the one
169
+ * standing arrangement an agent can enter into on the user's behalf without being asked again.
170
+ *
171
+ * ALL OF THEM, NOT ONE. The id of an individual watch is on the card, but the press a person makes about a
172
+ * card means "stop this conversation waking itself up", and picking watches off a submenu one at a time is a
173
+ * chore invented by the data shape rather than wanted by anybody. A conversation that should go on watching
174
+ * one thing and not another can be told so in the chat, which is where the watches were armed.
175
+ *
176
+ * No wake fires for what this disarms, which is the whole point: a watch left armed keeps a hosted machine
177
+ * awake and eventually starts a turn nobody is expecting. Nothing else about the conversation moves, so the
178
+ * card it hands back differs only by having lost its watches. */
179
+ stopWatching: oc
180
+ .route({
181
+ method: "POST",
182
+ path: "/agents/{id}/stop-watching",
183
+ summary: "Stop every condition watch a conversation is parked on",
184
+ description:
185
+ "Disarms all of this conversation's outside-condition watches, so none of them will wake it. All of them rather than one, because that is what the press means when it is made about a card. Nothing else about the conversation changes.",
186
+ })
187
+ .input(AgentIdSchema)
188
+ .output(AgentSummarySchema),
168
189
  seenAll: oc
169
190
  .route({
170
191
  method: "POST",
package/src/schemas.ts CHANGED
@@ -1322,6 +1322,42 @@ export const AgentSummarySchema = z.object({
1322
1322
  .describe(
1323
1323
  "The workflow run this conversation is a step of. Without it, a four-step run reads as four unrelated conversations that happen to have started together.",
1324
1324
  ),
1325
+ /* THE OUTSIDE CONDITIONS THIS CONVERSATION IS PARKED ON, the armed condition watches (the daemon's
1326
+ * agent/watchers.ts), projected onto the card for the same reason the loop and the workflow above are.
1327
+ *
1328
+ * IT IS THE ONE PROMISE THE BOARD USED TO KEEP SILENTLY. An agent that arms a watch ends its turn: nothing
1329
+ * is running, nothing is owed to the user, so every surface filed it under finished and drew the resting
1330
+ * `idle`. Then, some hours later, the daemon's check exits 0 and that same conversation starts working
1331
+ * again, on its own, in front of somebody who had been told it was done. The wake is the feature; the card
1332
+ * saying nothing about it beforehand is what made it read as the sandbox acting unasked.
1333
+ *
1334
+ * It also has a bill attached, which no other projection here does. An armed watch keeps a hosted machine
1335
+ * awake (system/idle-stop.ts counts them, deliberately: stopping the box is how a watch silently never
1336
+ * fires), so an invisible watch is invisible compute. A user looking at a board of finished agents,
1337
+ * wondering why the machine will not go quiet, could not have found the answer anywhere.
1338
+ *
1339
+ * WHAT IS ON THE WIRE IS WHAT A CARD CAN ACT ON, and nothing else. The note (the agent's own line on what
1340
+ * it is waiting for), the cadence, and the deadline, which is what turns "waiting" into a countdown with an
1341
+ * end. Deliberately NOT the check command: it is shell text the reader cannot run, judge or fix from a
1342
+ * board, and it is the one field that could carry a secret reference into a surface that is read over
1343
+ * shoulders. Deliberately NOT the check COUNT either, which would move every interval and buy a whole
1344
+ * roster broadcast to advance a number nobody is reading.
1345
+ *
1346
+ * Absent ⇒ nothing armed, which is nearly every conversation. Empty is never sent: the daemon clears the
1347
+ * projection instead, so the field's PRESENCE is the signal. */
1348
+ watches: z
1349
+ .array(
1350
+ z.object({
1351
+ id: z.string().describe("The daemon's handle for this watch, the same one the agent was given when it armed it."),
1352
+ note: z.string().describe("The agent's own line on what it is waiting for."),
1353
+ intervalSeconds: z.number().int().min(1).describe("How often the check runs."),
1354
+ deadlineAt: z.number().describe("When it gives up and wakes the conversation anyway, in milliseconds. Every watch has one."),
1355
+ }),
1356
+ )
1357
+ .optional()
1358
+ .describe(
1359
+ "Outside conditions this conversation is parked on, each of which will wake it. Absent means none, which is nearly every conversation: an armed watch is why a finished-looking agent starts working by itself, and why a hosted machine will not go idle.",
1360
+ ),
1325
1361
  // When the agent was ARCHIVED (ms epoch), off the board, but nothing lost: its checkout was retired
1326
1362
  // (worktree removed) while the agent/<id> branch, the transcript, and every counter stayed. Absent ⇒ live
1327
1363
  // on the board. Archived agents are excluded from the roster the fleet renders; `agents.archived` lists
@@ -1334,6 +1370,9 @@ export const AgentSummarySchema = z.object({
1334
1370
  ),
1335
1371
  });
1336
1372
  export type AgentSummary = z.infer<typeof AgentSummarySchema>;
1373
+ // One armed condition watch as a card carries it (AgentSummarySchema.watches). Named off the summary rather
1374
+ // than declared beside it, so the shape the daemon publishes and the shape the wire promises cannot drift.
1375
+ export type AgentWatch = NonNullable<AgentSummary["watches"]>[number];
1337
1376
  // AgentsListSchema lives further down, after AutomationApprovalSchema, the fleet list carries the held wakes,
1338
1377
  // and zod declaration order forces the ride-along to be declared first.
1339
1378
  export const AgentIdSchema = z.object({ id: z.string().min(1).describe("Which conversation.") });
@@ -2373,8 +2412,8 @@ export const SkillRemoveSchema = z.object({
2373
2412
  // workspaceMap , computes an AREA index of the project a run starts in and prepends it to the
2374
2413
  // conversation's opening message, so the turn does not have to buy its own orientation
2375
2414
  // with a directory listing. Generated from the filesystem every time, never stored.
2376
- // outputCleaners , the Bash output-cleaner spec (agent-output-filter): "off" = filter disabled (default),
2377
- // "" = all cleaners on, else an iq-style allow-list / default-minus
2415
+ // outputCleaners , the Bash output-cleaner spec (agent-output-filter): "off" = filter disabled,
2416
+ // "" = all cleaners on (default), else an iq-style allow-list / default-minus
2378
2417
  // spec ("git,pnpm" = only those; "-cap" = all except). Threaded to the filter via env.
2379
2418
  // outputHoldout , measurement control: a fraction [0,1] of Bash commands whose output bypasses cleaning
2380
2419
  // (recorded raw as `heldOut`), so the savings report compares a real cleaned-vs-raw
@@ -2386,8 +2425,8 @@ export const SkillRemoveSchema = z.object({
2386
2425
  // firing forever; 0 (default) ⇒ never.
2387
2426
  // subagentsAtOnce / subagentsPerTurn / subagentDepth, the harness's own ceilings on delegation, raised or
2388
2427
  // lowered from one place; each defaults to what the CLI enforces on its own.
2389
- // The booleans default off, outputCleaners defaults "off" (cleaning off) and outputHoldout 0, a fresh sandbox
2390
- // starts with cleaning and iq off until the owner enables them. `skills` is the exception and defaults to the
2428
+ // The booleans default off, outputCleaners defaults "" (cleaning on) and outputHoldout 0; iqSearch stays off
2429
+ // until the owner enables it. `skills` is the exception and defaults to the
2391
2430
  // baked tools worth having on: a skill file is the ONLY thing that tells the agent a baked binary exists, and
2392
2431
  // with the list empty `lsp` went used once in 866 sessions, not declined, never learned about.
2393
2432
  //
@@ -2498,7 +2537,7 @@ export const SandboxSettingsSchema = z.object({
2498
2537
  ),
2499
2538
  outputCleaners: z
2500
2539
  .string()
2501
- .default("off")
2540
+ .default("")
2502
2541
  .describe("Which command outputs to trim before the agent reads them, cutting the noise a build tool prints without cutting what it said."),
2503
2542
  outputHoldout: z
2504
2543
  .number()