@intentic/sandbox-contract 1.240.0 → 1.243.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 +52 -16
- package/dist/agent-catalog.d.ts +5 -28
- package/dist/agent-catalog.d.ts.map +1 -1
- package/dist/agent-catalog.js +21 -157
- package/dist/agent-catalog.js.map +1 -1
- package/dist/agent-run-model.d.ts +3 -2
- package/dist/agent-run-model.d.ts.map +1 -1
- package/dist/agent-run-model.js +9 -6
- package/dist/agent-run-model.js.map +1 -1
- package/dist/agent-runtimes.d.ts +27 -0
- package/dist/agent-runtimes.d.ts.map +1 -0
- package/dist/agent-runtimes.js +113 -0
- package/dist/agent-runtimes.js.map +1 -0
- package/dist/approvals-execution.d.ts +11 -0
- package/dist/approvals-execution.d.ts.map +1 -0
- package/dist/approvals-execution.js +44 -0
- package/dist/approvals-execution.js.map +1 -0
- package/dist/arrival.d.ts +151 -0
- package/dist/arrival.d.ts.map +1 -0
- package/dist/arrival.js +56 -0
- package/dist/arrival.js.map +1 -0
- package/dist/card-status.d.ts +5 -0
- package/dist/card-status.d.ts.map +1 -0
- package/dist/card-status.js +74 -0
- package/dist/card-status.js.map +1 -0
- package/dist/chores/chores.d.ts.map +1 -1
- package/dist/chores/chores.js +1 -1
- package/dist/chores/chores.js.map +1 -1
- package/dist/command-classes.d.ts +0 -1
- package/dist/command-classes.d.ts.map +1 -1
- package/dist/command-classes.js +9 -2
- package/dist/command-classes.js.map +1 -1
- package/dist/command-run.d.ts +10 -0
- package/dist/command-run.d.ts.map +1 -0
- package/dist/command-run.js +46 -0
- package/dist/command-run.js.map +1 -0
- package/dist/contracts/agent.contract.d.ts +991 -771
- package/dist/contracts/agent.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.d.ts +345 -337
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.js +20 -2
- package/dist/contracts/agents.contract.js.map +1 -1
- package/dist/contracts/approvals.contract.d.ts +99 -0
- package/dist/contracts/approvals.contract.d.ts.map +1 -0
- package/dist/contracts/approvals.contract.js +32 -0
- package/dist/contracts/approvals.contract.js.map +1 -0
- package/dist/contracts/ci.contract.d.ts +1 -4
- package/dist/contracts/ci.contract.d.ts.map +1 -1
- package/dist/contracts/ci.contract.js +1 -9
- package/dist/contracts/ci.contract.js.map +1 -1
- package/dist/contracts/claude.contract.d.ts +9 -0
- package/dist/contracts/claude.contract.d.ts.map +1 -1
- package/dist/contracts/cursor.contract.d.ts +6 -0
- package/dist/contracts/cursor.contract.d.ts.map +1 -1
- package/dist/contracts/git.contract.d.ts +63 -1
- package/dist/contracts/git.contract.d.ts.map +1 -1
- package/dist/contracts/git.contract.js +22 -4
- package/dist/contracts/git.contract.js.map +1 -1
- package/dist/contracts/grok.contract.d.ts +3 -0
- package/dist/contracts/grok.contract.d.ts.map +1 -1
- package/dist/contracts/keys.contract.d.ts +81 -0
- package/dist/contracts/keys.contract.d.ts.map +1 -0
- package/dist/contracts/keys.contract.js +51 -0
- package/dist/contracts/keys.contract.js.map +1 -0
- package/dist/contracts/panels.contract.d.ts +7 -0
- package/dist/contracts/panels.contract.d.ts.map +1 -1
- package/dist/contracts/prepush.contract.js +2 -2
- package/dist/contracts/providers.contract.d.ts +2 -0
- package/dist/contracts/providers.contract.d.ts.map +1 -1
- package/dist/contracts/runner.contract.d.ts +84 -86
- package/dist/contracts/runner.contract.d.ts.map +1 -1
- package/dist/contracts/safety.contract.d.ts +35 -0
- package/dist/contracts/safety.contract.d.ts.map +1 -0
- package/dist/contracts/safety.contract.js +32 -0
- package/dist/contracts/safety.contract.js.map +1 -0
- package/dist/contracts/sessions.contract.d.ts +73 -337
- package/dist/contracts/sessions.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.d.ts +30 -32
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.d.ts +139 -337
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/contracts/translator.contract.d.ts +31 -3
- package/dist/contracts/translator.contract.d.ts.map +1 -1
- package/dist/contracts/usage.contract.d.ts +29 -20
- package/dist/contracts/usage.contract.d.ts.map +1 -1
- package/dist/contracts/usage.contract.js +13 -0
- package/dist/contracts/usage.contract.js.map +1 -1
- package/dist/contracts/workspace.contract.d.ts +8 -0
- package/dist/contracts/workspace.contract.d.ts.map +1 -1
- package/dist/conversation-ids.d.ts +2 -0
- package/dist/conversation-ids.d.ts.map +1 -1
- package/dist/conversation-ids.js +8 -0
- package/dist/conversation-ids.js.map +1 -1
- package/dist/credential-material.d.ts +1 -0
- package/dist/credential-material.d.ts.map +1 -1
- package/dist/credential-material.js +24 -2
- package/dist/credential-material.js.map +1 -1
- package/dist/definition.d.ts +51 -93
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +6 -28
- package/dist/definition.js.map +1 -1
- package/dist/events.d.ts +1831 -2285
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +155 -55
- package/dist/events.js.map +1 -1
- package/dist/history-state.d.ts.map +1 -1
- package/dist/history-state.js +1 -0
- package/dist/history-state.js.map +1 -1
- package/dist/index.d.ts +1959 -1903
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/ingress-protocol.d.ts +13 -1
- package/dist/ingress-protocol.d.ts.map +1 -1
- package/dist/ingress-protocol.js +19 -0
- package/dist/ingress-protocol.js.map +1 -1
- package/dist/mentions.d.ts +3 -0
- package/dist/mentions.d.ts.map +1 -0
- package/dist/mentions.js +13 -0
- package/dist/mentions.js.map +1 -0
- package/dist/needs-action.d.ts +7 -0
- package/dist/needs-action.d.ts.map +1 -0
- package/dist/needs-action.js +3 -0
- package/dist/needs-action.js.map +1 -0
- package/dist/overlay-lint.d.ts +7 -0
- package/dist/overlay-lint.d.ts.map +1 -0
- package/dist/overlay-lint.js +68 -0
- package/dist/overlay-lint.js.map +1 -0
- package/dist/owner-ticket.d.ts +18 -0
- package/dist/owner-ticket.d.ts.map +1 -0
- package/dist/owner-ticket.js +51 -0
- package/dist/owner-ticket.js.map +1 -0
- package/dist/plan-pools.d.ts +13 -0
- package/dist/plan-pools.d.ts.map +1 -0
- package/dist/plan-pools.js +31 -0
- package/dist/plan-pools.js.map +1 -0
- package/dist/provider-specs.d.ts +228 -0
- package/dist/provider-specs.d.ts.map +1 -0
- package/dist/provider-specs.js +124 -0
- package/dist/provider-specs.js.map +1 -0
- 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/runner-protocol.js +2 -2
- package/dist/runner-protocol.js.map +1 -1
- package/dist/runtime-state.d.ts +2 -2
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +1 -1
- package/dist/runtime-state.js.map +1 -1
- package/dist/safety-policy.d.ts +49 -0
- package/dist/safety-policy.d.ts.map +1 -0
- package/dist/safety-policy.js +52 -0
- package/dist/safety-policy.js.map +1 -0
- package/dist/schemas/agent.d.ts +21 -3
- package/dist/schemas/agent.d.ts.map +1 -1
- package/dist/schemas/agent.js +18 -8
- package/dist/schemas/agent.js.map +1 -1
- package/dist/schemas/agents.d.ts +19 -0
- package/dist/schemas/agents.d.ts.map +1 -1
- package/dist/schemas/agents.js +15 -0
- package/dist/schemas/agents.js.map +1 -1
- package/dist/schemas/approvals.d.ts +241 -0
- package/dist/schemas/approvals.d.ts.map +1 -0
- package/dist/schemas/approvals.js +63 -0
- package/dist/schemas/approvals.js.map +1 -0
- package/dist/schemas/automations.d.ts +5 -0
- package/dist/schemas/automations.d.ts.map +1 -1
- package/dist/schemas/ci.d.ts +5 -9
- package/dist/schemas/ci.d.ts.map +1 -1
- package/dist/schemas/ci.js +3 -10
- package/dist/schemas/ci.js.map +1 -1
- package/dist/schemas/computers.d.ts +40 -5
- package/dist/schemas/computers.d.ts.map +1 -1
- package/dist/schemas/computers.js +16 -5
- package/dist/schemas/computers.js.map +1 -1
- package/dist/schemas/environment.d.ts +11 -131
- package/dist/schemas/environment.d.ts.map +1 -1
- package/dist/schemas/environment.js +5 -42
- package/dist/schemas/environment.js.map +1 -1
- package/dist/schemas/git-history.d.ts +4 -0
- package/dist/schemas/git-history.d.ts.map +1 -1
- package/dist/schemas/git.d.ts +179 -0
- package/dist/schemas/git.d.ts.map +1 -1
- package/dist/schemas/git.js +39 -1
- package/dist/schemas/git.js.map +1 -1
- package/dist/schemas/panels.d.ts +21 -0
- package/dist/schemas/panels.d.ts.map +1 -1
- package/dist/schemas/panels.js +5 -0
- package/dist/schemas/panels.js.map +1 -1
- package/dist/schemas/plan-limits.d.ts +50 -3
- package/dist/schemas/plan-limits.d.ts.map +1 -1
- package/dist/schemas/plan-limits.js +11 -6
- package/dist/schemas/plan-limits.js.map +1 -1
- package/dist/schemas/provider-oauth.d.ts +6 -0
- package/dist/schemas/provider-oauth.d.ts.map +1 -1
- package/dist/schemas/provider-subscriptions.d.ts +2 -1
- package/dist/schemas/provider-subscriptions.d.ts.map +1 -1
- package/dist/schemas/provider-subscriptions.js +2 -1
- package/dist/schemas/provider-subscriptions.js.map +1 -1
- package/dist/schemas/settings.d.ts +29 -16
- package/dist/schemas/settings.d.ts.map +1 -1
- package/dist/schemas/settings.js +13 -20
- package/dist/schemas/settings.js.map +1 -1
- package/dist/schemas/system.d.ts +3 -0
- package/dist/schemas/system.d.ts.map +1 -1
- package/dist/schemas/system.js +5 -1
- package/dist/schemas/system.js.map +1 -1
- package/dist/schemas/workspace-repos.d.ts +14 -0
- package/dist/schemas/workspace-repos.d.ts.map +1 -1
- package/dist/schemas/workspace-repos.js +5 -0
- package/dist/schemas/workspace-repos.js.map +1 -1
- package/dist/schemas/workspace-tree.d.ts +1 -0
- package/dist/schemas/workspace-tree.d.ts.map +1 -1
- package/dist/schemas/workspace-tree.js +3 -0
- package/dist/schemas/workspace-tree.js.map +1 -1
- package/dist/transcript-fold.d.ts +31 -0
- package/dist/transcript-fold.d.ts.map +1 -0
- package/dist/transcript-fold.js +457 -0
- package/dist/transcript-fold.js.map +1 -0
- package/dist/workspace-state.d.ts +20 -3
- package/dist/workspace-state.d.ts.map +1 -1
- package/dist/workspace-state.js +22 -2
- package/dist/workspace-state.js.map +1 -1
- package/package.json +27 -5
- package/src/agent-catalog.test.ts +1 -1
- package/src/agent-catalog.ts +76 -555
- package/src/agent-run-model.test.ts +31 -15
- package/src/agent-run-model.ts +26 -12
- package/src/agent-runtimes.ts +419 -0
- package/src/approvals-execution.ts +96 -0
- package/src/arrival.ts +160 -0
- package/src/capability-ledger.test.ts +6 -4
- package/src/card-status.ts +93 -0
- package/src/chores/chores.ts +6 -3
- package/src/command-classes.test.ts +25 -0
- package/src/command-classes.ts +47 -5
- package/src/command-run.ts +78 -0
- package/src/contract-lock.test.ts +1 -1
- package/src/contract-lock.ts +2 -2
- package/src/contracts/agents.contract.ts +35 -2
- package/src/contracts/approvals.contract.ts +37 -0
- package/src/contracts/ci.contract.ts +0 -13
- package/src/contracts/git.contract.ts +28 -3
- package/src/contracts/keys.contract.ts +79 -0
- package/src/contracts/prepush.contract.ts +3 -3
- package/src/contracts/safety.contract.ts +48 -0
- package/src/contracts/usage.contract.ts +22 -0
- package/src/conversation-ids.test.ts +31 -1
- package/src/conversation-ids.ts +37 -3
- package/src/credential-material.test.ts +69 -1
- package/src/credential-material.ts +86 -5
- package/src/definition.ts +25 -53
- package/src/events.ts +374 -173
- package/src/history-state.ts +6 -0
- package/src/index.ts +24 -5
- package/src/ingress-protocol.ts +52 -1
- package/src/mentions.test.ts +22 -0
- package/src/mentions.ts +25 -0
- package/src/needs-action.ts +14 -0
- package/src/overlay-lint.test.ts +89 -0
- package/src/overlay-lint.ts +116 -0
- package/src/owner-ticket.test.ts +54 -0
- package/src/owner-ticket.ts +102 -0
- package/src/plan-pools.test.ts +71 -0
- package/src/plan-pools.ts +92 -0
- package/src/provider-specs.test.ts +130 -0
- package/src/provider-specs.ts +352 -0
- package/src/quick-model.ts +9 -5
- package/src/runner-protocol.ts +2 -2
- package/src/runtime-state.ts +6 -6
- package/src/safety-policy.ts +165 -0
- package/src/schemas/agent.ts +62 -17
- package/src/schemas/agents.ts +71 -0
- package/src/schemas/approvals.ts +174 -0
- package/src/schemas/ci.ts +19 -26
- package/src/schemas/computers.ts +91 -15
- package/src/schemas/environment.ts +21 -100
- package/src/schemas/git.ts +121 -6
- package/src/schemas/issues.ts +1 -1
- package/src/schemas/panels.ts +20 -0
- package/src/schemas/plan-limits.ts +58 -11
- package/src/schemas/provider-subscriptions.ts +7 -2
- package/src/schemas/settings.ts +67 -93
- package/src/schemas/system.ts +12 -1
- package/src/schemas/workspace-repos.ts +9 -0
- package/src/schemas/workspace-tree.ts +11 -0
- package/src/transcript-fold.test.ts +493 -0
- package/src/transcript-fold.ts +655 -0
- package/src/workspace-state.test.ts +77 -29
- package/src/workspace-state.ts +99 -31
- package/dist/contracts/drafts.contract.d.ts +0 -57
- package/dist/contracts/drafts.contract.d.ts.map +0 -1
- package/dist/contracts/drafts.contract.js +0 -32
- package/dist/contracts/drafts.contract.js.map +0 -1
- package/dist/definition-action.d.ts +0 -7
- package/dist/definition-action.d.ts.map +0 -1
- package/dist/definition-action.js +0 -3
- package/dist/definition-action.js.map +0 -1
- package/dist/publish-drafts.d.ts +0 -7
- package/dist/publish-drafts.d.ts.map +0 -1
- package/dist/publish-drafts.js +0 -20
- package/dist/publish-drafts.js.map +0 -1
- package/dist/schemas/drafts.d.ts +0 -84
- package/dist/schemas/drafts.d.ts.map +0 -1
- package/dist/schemas/drafts.js +0 -44
- package/dist/schemas/drafts.js.map +0 -1
- package/src/contracts/drafts.contract.ts +0 -35
- package/src/definition-action.ts +0 -8
- package/src/publish-drafts.ts +0 -59
- package/src/schemas/drafts.ts +0 -108
package/src/schemas/agent.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { KEY_PROVIDERS, NATIVE_PROVIDERS } from "../provider-specs.js";
|
|
2
3
|
import { AgentPlacementSchema } from "../runner-protocol.js";
|
|
3
4
|
import { entryId } from "./internal.js";
|
|
4
5
|
// The agent runtimes the daemon can serve, the vocabulary every surface that picks an agent shares (chat
|
|
@@ -8,16 +9,23 @@ import { entryId } from "./internal.js";
|
|
|
8
9
|
// ACP (Agent Client Protocol).
|
|
9
10
|
// Kept as a bare string on the wire (not an enum) so an unknown id is a clean error frame from the agent
|
|
10
11
|
// route, the same bet RepoParamSchema makes, and adding an ACP agent needs no contract change.
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
//
|
|
13
|
+
// NATIVE_PROVIDERS itself is DERIVED from the one row-per-provider table (provider-specs.ts) and imported
|
|
14
|
+
// here rather than written out again, so the wire vocabulary cannot name a provider the product does not
|
|
15
|
+
// describe, or miss one it does.
|
|
13
16
|
export const AgentProviderSchema = z.string().min(1);
|
|
14
17
|
export type AgentProvider = z.infer<typeof AgentProviderSchema>;
|
|
15
18
|
// The provider naming a catalog in the one route every native provider shares (providers.contract.ts). An ENUM
|
|
16
19
|
// rather than the bare-string schema above, and deliberately so: the open vocabulary exists because an ACP agent
|
|
17
20
|
// or an endpoint can be added without a contract change, but neither has a daemon-held catalog, this route's
|
|
18
|
-
// subjects are exactly the
|
|
21
|
+
// subjects are exactly the ones the daemon keeps one for. Closing it here is what makes an unknown id a 400 from
|
|
19
22
|
// the contract instead of a registry lookup that reads back `undefined` and serves an empty list.
|
|
20
23
|
export const NativeProviderParamSchema = z.object({ provider: z.enum(NATIVE_PROVIDERS) });
|
|
24
|
+
// The provider naming an account on the routes that connect one by pasting a key (keys.contract.ts). Closed the
|
|
25
|
+
// same way and for the same reason as the catalog param above, narrowed to the providers whose credential this
|
|
26
|
+
// daemon actually stores as a key: pasting one at a provider that authenticates some other way is a 400 from
|
|
27
|
+
// the contract rather than a handler discovering there is no store to write to.
|
|
28
|
+
export const KeyProviderParamSchema = z.object({ provider: z.enum(KEY_PROVIDERS) });
|
|
21
29
|
// The harness (agentic loop) a turn runs on, orthogonal to the provider. See AgentTurnSchema.harness.
|
|
22
30
|
export const AgentHarnessSchema = z.enum(["native", "claude-code"]);
|
|
23
31
|
export type AgentHarness = z.infer<typeof AgentHarnessSchema>;
|
|
@@ -275,7 +283,7 @@ export const AgentTurnSchema = z
|
|
|
275
283
|
* opposite defaults, the chat wants the provider's own catalog default, an unattended run wants the
|
|
276
284
|
* tier its owner chose for work that spends money while they are not watching.
|
|
277
285
|
*
|
|
278
|
-
* The daemon fills `agent`/`model
|
|
286
|
+
* The daemon fills `agent`/`model` and the pinned entry's own knobs from agentRunModels for any turn that says
|
|
279
287
|
* this and names none of them (startConversationTurn), walking that list until one can actually be
|
|
280
288
|
* started. Naming one still wins: every surface-started run now carries a caret that overrides the list
|
|
281
289
|
* for that run alone, and Acceptance picks per run because it fans a session out per story. Either way
|
|
@@ -384,7 +392,14 @@ export type AgentTurn = z.infer<typeof AgentTurnSchema>;
|
|
|
384
392
|
*
|
|
385
393
|
* Both halves or neither, because a model id is only meaningful to the provider that vends it: half a pick
|
|
386
394
|
* would send a Codex model id to Claude. Routes that accept this pass it through verbatim; a model this build
|
|
387
|
-
* has never heard of is a supported pick, since the picker offers a custom-id escape hatch.
|
|
395
|
+
* has never heard of is a supported pick, since the picker offers a custom-id escape hatch.
|
|
396
|
+
*
|
|
397
|
+
* AND THE TIER IT RUNS AT, because naming a model is only half of what the standing setting says. A pinned
|
|
398
|
+
* entry carries its own effort (AgentRunPinSchema), and the daemon applies the pin's knobs ONLY to a turn that
|
|
399
|
+
* named no model (turn-resume.ts): so a caret that could re-point the model but not the tier moved every
|
|
400
|
+
* override onto the provider's own default effort, and the one moment somebody reaches for the caret is the
|
|
401
|
+
* failure that just beat the standing order. Optional, and absent means absent, the turn goes out without an
|
|
402
|
+
* effort and the model's own answers. */
|
|
388
403
|
export const AgentRunPickSchema = z
|
|
389
404
|
.object({
|
|
390
405
|
agent: z.string().min(1).describe("Which provider."),
|
|
@@ -392,31 +407,61 @@ export const AgentRunPickSchema = z
|
|
|
392
407
|
.string()
|
|
393
408
|
.min(1)
|
|
394
409
|
.describe("Which of its models. Both or neither, because a model name only means anything to the provider that serves it."),
|
|
410
|
+
effort: z
|
|
411
|
+
.string()
|
|
412
|
+
.optional()
|
|
413
|
+
.describe("How hard that model should think, where it offers a choice. Leave it out to take the model's own default."),
|
|
395
414
|
})
|
|
396
415
|
.optional();
|
|
397
416
|
export type AgentRunPick = z.infer<typeof AgentRunPickSchema>;
|
|
417
|
+
/* A MODEL PINNED FOR EVERY SURFACE-STARTED RUN, one entry of settings.agentRunModels: the standing version of
|
|
418
|
+
* the pick above, and not merely which model but HOW it is to be run.
|
|
419
|
+
*
|
|
420
|
+
* THE KNOBS RIDE THE ENTRY RATHER THAN THE LIST, which is the whole reason this is an object where the setting
|
|
421
|
+
* used to hold a `${provider}:${model}` string. The reasoning effort was a single field beside the list, so one
|
|
422
|
+
* tier answered for every model in it — and the entries of that list are deliberately NOT interchangeable: it
|
|
423
|
+
* is a frontier pin with the cheap account underneath that catches it when the first is spent. A tier scale is
|
|
424
|
+
* a property of the MODEL as well ('max' is off Kimi's scale entirely, and off Claude's own the moment thinking
|
|
425
|
+
* is switched off), so a shared effort was either off-scale for half the list or the lowest common rung for all
|
|
426
|
+
* of it. Each entry now carries what the composer's picker configures for the turn in front of you.
|
|
427
|
+
*
|
|
428
|
+
* EVERY FIELD BUT THE PAIR IS OPTIONAL, AND ABSENT MEANS ABSENT: the turn goes out without the field and the
|
|
429
|
+
* provider's own default answers, exactly as an unconfigured pin always did. Nothing here invents a "low".
|
|
430
|
+
*
|
|
431
|
+
* NO TIER HOLD, and its absence is the rule rather than an omission: automatic tier selection gates on
|
|
432
|
+
* `unattended` (prompt-complexity.ts), so a surface-started run is never downgraded in the first place and a
|
|
433
|
+
* veto over it would be a control whose state can make no difference to anything.
|
|
434
|
+
*
|
|
435
|
+
* The pair is BOTH HALVES for the reason the pick above is: a model id is only meaningful to the provider that
|
|
436
|
+
* vends it, so half a pin would send a Codex id to Claude. Taken verbatim, never validated against a catalog:
|
|
437
|
+
* the picker offers a custom-id escape hatch, so a model this build has never heard of is a supported pin. */
|
|
438
|
+
export const AgentRunPinSchema = z.object({
|
|
439
|
+
provider: AgentProviderSchema.describe("Which provider serves the run."),
|
|
440
|
+
model: z.string().min(1).describe("Which of its models. Both halves, because a model name only means anything to the provider that serves it."),
|
|
441
|
+
effort: z
|
|
442
|
+
.string()
|
|
443
|
+
.optional()
|
|
444
|
+
.describe("How hard this model should think, where it offers a choice. Leave it out to take the model's own default."),
|
|
445
|
+
thinking: z.boolean().optional().describe("Whether this model reasons before it answers, where that is a choice it offers."),
|
|
446
|
+
fast: z.boolean().optional().describe("Ask for this model's work at a higher rate for a higher price. A request rather than a promise."),
|
|
447
|
+
harness: AgentHarnessSchema.optional().describe("Which agentic loop runs it. Leave it out to use the provider's own."),
|
|
448
|
+
});
|
|
449
|
+
export type AgentRunPin = z.infer<typeof AgentRunPinSchema>;
|
|
398
450
|
// POST /agent's ack: the daemon-minted id of the detached turn run it started. The turn executes daemon-side
|
|
399
451
|
// regardless of any client connection; every window, the initiator included, renders it via /agent/attach.
|
|
400
452
|
export const StartedTurnSchema = z.object({
|
|
401
453
|
run: z.string().describe("The id of the run that just started. Hand it back when you attach, so the stream resumes rather than replaying."),
|
|
402
454
|
});
|
|
403
455
|
export type StartedTurn = z.infer<typeof StartedTurnSchema>;
|
|
404
|
-
// Attach to a conversation's turn run (live, or finished within the retention window).
|
|
405
|
-
//
|
|
406
|
-
//
|
|
456
|
+
// Attach to a conversation's turn run (live, or finished within the retention window). The head carries the
|
|
457
|
+
// run's rows whole, so there is no cursor to resume from: a client that reconnects takes the rows again and
|
|
458
|
+
// applies what follows. `run` names the run the client was watching, so the head's own id tells it whether a
|
|
459
|
+
// newer turn has started meanwhile.
|
|
407
460
|
export const AttachTurnSchema = z.object({
|
|
408
461
|
conversationId: ConversationIdSchema.describe("Which conversation to watch."),
|
|
409
462
|
run: z
|
|
410
463
|
.string()
|
|
411
464
|
.optional()
|
|
412
|
-
.describe("The run you were watching. If a newer turn has started since, the
|
|
413
|
-
after: z
|
|
414
|
-
.number()
|
|
415
|
-
.int()
|
|
416
|
-
.min(0)
|
|
417
|
-
.optional()
|
|
418
|
-
.describe(
|
|
419
|
-
"The last frame you already have. Everything after it replays, then the stream goes live. Leave it out to start from the beginning.",
|
|
420
|
-
),
|
|
465
|
+
.describe("The run you were watching. If a newer turn has started since, the head names that one instead, and its rows are that turn's."),
|
|
421
466
|
});
|
|
422
467
|
export type AttachTurn = z.infer<typeof AttachTurnSchema>;
|
package/src/schemas/agents.ts
CHANGED
|
@@ -204,6 +204,52 @@ export const AgentSummarySchema = z.object({
|
|
|
204
204
|
.describe(
|
|
205
205
|
"Why the last turn failed, in the words it died on. Absent unless it did, and cleared the moment it runs again. Carried here because the word error on its own is not an answer, least of all for a run nobody was watching.",
|
|
206
206
|
),
|
|
207
|
+
/* WHICH KIND OF FAILURE IT WAS, the error frame's own code (AgentEvent's `error`), beside the sentence it
|
|
208
|
+
* came with. The sentence says what happened to a person; this says it to the board, which has to DRAW the
|
|
209
|
+
* difference and could not.
|
|
210
|
+
*
|
|
211
|
+
* The chat has always had it, and the gap between the two surfaces is the whole reason this exists. A chat
|
|
212
|
+
* reads `rate_limit` and renders a muted notice with a countdown and a press; the board read `status:
|
|
213
|
+
* "error"` and rendered a red crash line with "View error" on it, because the code never reached the
|
|
214
|
+
* summary. So one spent allowance looked exactly like a harness that died mid-run, on the surface where
|
|
215
|
+
* most people meet it, and the state the product knows most about (it knows when it ends) was the one
|
|
216
|
+
* drawn with the least. */
|
|
217
|
+
failureCode: z
|
|
218
|
+
.string()
|
|
219
|
+
.optional()
|
|
220
|
+
.describe(
|
|
221
|
+
"Which kind of failure it was, as the turn's own error frame coded it. Absent for a failure nothing could classify, which reads as the plain red line it is.",
|
|
222
|
+
),
|
|
223
|
+
/* WHEN THE SPENT WINDOW REOPENS (epoch SECONDS), for a card whose last turn a usage limit refused. The one
|
|
224
|
+
* fact this failure has and no other failure here does, and the reason it is not a failure at all so much
|
|
225
|
+
* as a wait: nothing is broken, nobody has anything to fix, and the thing that changes the outcome is a
|
|
226
|
+
* clock. A card that cannot say the hour has to spend its line saying "Error" instead, which is how an
|
|
227
|
+
* 18-hour-old refusal went on reporting a wall that had reopened before breakfast.
|
|
228
|
+
*
|
|
229
|
+
* Absent means the instant is genuinely unknown, which for Grok (no published quota) and Cursor (not routed
|
|
230
|
+
* through the translator) is the honest answer and stays one. Never invent one: a countdown to a guess is
|
|
231
|
+
* worse than no countdown, because the reader plans around it. */
|
|
232
|
+
limitResetsAt: z.number().optional().describe("When the spent allowance reopens, in epoch seconds. Absent when the provider publishes no instant."),
|
|
233
|
+
/* THE DAEMON IS STILL HOLDING THAT EXACT TURN, so the way on is one press that RE-RUNS it rather than a new
|
|
234
|
+
* message saying "carry on" (turn-resume.ts's pendingLimit has the whole argument, and the transcript full
|
|
235
|
+
* of the word "Continue" that made it). On the summary because the board is where somebody with four
|
|
236
|
+
* stranded agents is standing, and until now the press existed only inside each chat. */
|
|
237
|
+
limitHeld: z.boolean().optional().describe("Whether the refused turn is held whole, so sending again re-runs it instead of appending to it."),
|
|
238
|
+
/* A FIRE IS ALREADY BOOKED FOR THIS ONE: the conversation is armed (`resumeAfterLimit`), the reset instant
|
|
239
|
+
* is known, and the daemon's pass will send the held turn again when the window opens without anybody
|
|
240
|
+
* pressing anything.
|
|
241
|
+
*
|
|
242
|
+
* IT IS THE ONE THING THAT MOVES A STRANDED CARD OUT OF THE ATTENTION LANE, and the only reason it needs to
|
|
243
|
+
* be on the wire at all. "Does this session need me?" is the question that lane answers, and for a spent
|
|
244
|
+
* allowance the honest answer is yes: the window reopening does not send the turn, a person does. Unless
|
|
245
|
+
* this is set, in which case a machine does, and demanding a press for work already booked is the same
|
|
246
|
+
* false alarm as demanding one for a turn that is running.
|
|
247
|
+
*
|
|
248
|
+
* A BOOLEAN THE DAEMON ALREADY DECIDED rather than a posture the client re-folds. The effective posture is
|
|
249
|
+
* two levels deep (this conversation's override, else the sandbox setting), and the lane machine is a leaf
|
|
250
|
+
* with no store to ask: threading a settings read through every caller of `laneOf` would put the answer in
|
|
251
|
+
* five places and let them disagree. The daemon resolves it once, where the failure happened. */
|
|
252
|
+
limitScheduled: z.boolean().optional().describe("Whether the held turn is already booked to go again at the reset, so nobody has to press anything."),
|
|
207
253
|
provider: AgentProviderSchema.describe("Which model provider it runs on."),
|
|
208
254
|
harness: AgentHarnessSchema.describe("Which agentic loop it runs on."),
|
|
209
255
|
// Which machine its turns execute on: a paired runner's id, absent for this sandbox (runners/). Latched
|
|
@@ -265,6 +311,19 @@ export const AgentSummarySchema = z.object({
|
|
|
265
311
|
* never expressed an opinion follows the sandbox wherever it is pointed next. Written by
|
|
266
312
|
* `agents.resumeAfterOutage`; every surface shows the EFFECTIVE value (this ?? the setting). */
|
|
267
313
|
resumeAfterOutage: z.boolean().optional(),
|
|
314
|
+
/* The same two-level shape again, for the blocker that is not a failure: "when a usage limit refused my
|
|
315
|
+
* turn, send it again the moment the allowance comes back".
|
|
316
|
+
*
|
|
317
|
+
* IT IS THE ONE RESUME WITH A KNOWN HOUR, which is what makes it worth automating and what makes it
|
|
318
|
+
* different from its neighbour. An outage resume guesses (a backoff, a bounded number of attempts, no idea
|
|
319
|
+
* when the provider returns); this one waits for an instant the provider published and fires once, at it.
|
|
320
|
+
*
|
|
321
|
+
* OFF unless somebody says otherwise, and that default is load-bearing rather than cautious. Every other
|
|
322
|
+
* blocker here clears at no cost to the user, while this one clears into a window they may have been
|
|
323
|
+
* saving: spending it the second it reopens is not a decision to make on anybody's behalf. What arming it
|
|
324
|
+
* buys is the case nothing else can reach, a turn that hit the wall at 2am on a board nobody is watching,
|
|
325
|
+
* where the alternative is a card that waited eight hours for a press that was always going to come. */
|
|
326
|
+
resumeAfterLimit: z.boolean().optional(),
|
|
268
327
|
// A collaborator asked for this agent's work to be landed (agents.requestLand), collaborators may drive
|
|
269
328
|
// agents but not merge into the main tree, so the ask rides the summary where every maintainer's board
|
|
270
329
|
// sees it. Cleared by the land or discard that answers it. Absent ⇒ nobody is waiting.
|
|
@@ -681,6 +740,18 @@ export const AgentResumeAfterOutageSchema = z.object({
|
|
|
681
740
|
.nullable()
|
|
682
741
|
.describe("Whether it retries by itself when the model provider was what failed. Null clears the override back to the sandbox-wide setting."),
|
|
683
742
|
});
|
|
743
|
+
// resumeAfterLimit's input, the same override in the same three states as the outage one above, for the
|
|
744
|
+
// blocker that comes back on a clock. Written by the card's own offer at the moment a limit strands a turn,
|
|
745
|
+
// which is where somebody looking at a stranded card actually is; the settings toggle writes the default.
|
|
746
|
+
export const AgentResumeAfterLimitSchema = z.object({
|
|
747
|
+
id: z.string().min(1).describe("Which conversation."),
|
|
748
|
+
resumeAfterLimit: z
|
|
749
|
+
.boolean()
|
|
750
|
+
.nullable()
|
|
751
|
+
.describe(
|
|
752
|
+
"Whether the turn a spent allowance refused is sent again by itself once the window reopens. Null clears the override back to the sandbox-wide setting.",
|
|
753
|
+
),
|
|
754
|
+
});
|
|
684
755
|
export const AgentFileDiffQuerySchema = z.object({
|
|
685
756
|
id: z.string().min(1).describe("Which conversation."),
|
|
686
757
|
repo: z.string().min(1).describe("Which repository."),
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// approvals: things the agent prepared and may not do until the owner says yes (.intentic/config/approvals/<id>.json)
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { entryId } from "./internal.js";
|
|
4
|
+
|
|
5
|
+
/* ONE QUEUE FOR EVERYTHING THAT WAITS ON A YES, and the test for what belongs in it: the agent prepared an exact
|
|
6
|
+
* thing, the owner's click releases it, a machine then carries out precisely that thing, and the outcome is
|
|
7
|
+
* written back. A post is the first such thing and was the whole of this file (it was `drafts`); a hotel
|
|
8
|
+
* booking, a payment, a message sent under the owner's name are the same shape with a different payload, and
|
|
9
|
+
* each of them arriving as its own inbox is how a product grows five tiles that all say "approve".
|
|
10
|
+
*
|
|
11
|
+
* So the record is an ENVELOPE plus a KIND. The envelope is what every approval shares and what the queue, the
|
|
12
|
+
* badge and the daemon act on: who it acts as, when it is due, where it stands, what happened. The kind is what
|
|
13
|
+
* the row draws and the daemon dispatches on, a discriminated union so a new kind is one variant here, one
|
|
14
|
+
* body component in the extension and one executor in the daemon, and nothing else moves.
|
|
15
|
+
*
|
|
16
|
+
* What does NOT belong here, and why the line is drawn where it is: an inbox of FACTS (the issues queue, where
|
|
17
|
+
* a crash arrived and the owner's verbs are resolve / ignore / investigate) has no prepared thing to release,
|
|
18
|
+
* and a hold a RUNNING turn is blocked on (a permission card, a spend offer) lives in the conversation, because
|
|
19
|
+
* a queue is the wrong latency for a click somebody is spinning on.
|
|
20
|
+
*
|
|
21
|
+
* One JSON file per approval. The AGENT creates them with its normal file tools, it can't call daemon routes,
|
|
22
|
+
* the same split as the environment proposal, while the daemon edits/deletes them on the owner's behalf, so
|
|
23
|
+
* the two writers never share a file. The id IS the filename (entryId charset ⇒ path-safe); the body never
|
|
24
|
+
* carries it. */
|
|
25
|
+
|
|
26
|
+
export const ApprovalKindSchema = z.enum(["post", "action"]);
|
|
27
|
+
export type ApprovalKind = z.infer<typeof ApprovalKindSchema>;
|
|
28
|
+
|
|
29
|
+
/* proposed (agent) → approved (owner) → running (executor, set BEFORE acting so a dead turn can't do it twice)
|
|
30
|
+
* → done | failed. Reject = delete the file; retry = re-approve a failed one. The names are deliberately not a
|
|
31
|
+
* post's ("posting", "posted"): they are read by every kind, and a booking is not "posted". */
|
|
32
|
+
export const ApprovalStatusSchema = z.enum(["proposed", "approved", "running", "done", "failed"]);
|
|
33
|
+
export type ApprovalStatus = z.infer<typeof ApprovalStatusSchema>;
|
|
34
|
+
|
|
35
|
+
/* THE ENVELOPE, spread into every variant below (zod's discriminated union wants flat objects, not an extended
|
|
36
|
+
* base), which is also why a variant's own fields sit beside these rather than under a `payload` key: the file
|
|
37
|
+
* an agent writes stays one level deep, and "which fields are mine" is answered by the variant's schema. */
|
|
38
|
+
const envelope = {
|
|
39
|
+
/* WHOSE NAME THIS ACTS UNDER, a PersonaSchema id, handed to the executing turn as AgentTurnSchema.actsAs.
|
|
40
|
+
* Required in practice for every post outside DIRECT_PUBLISH_PLATFORMS, and the reason is the whole shape
|
|
41
|
+
* of turnPersona: acting through a browser needs a logged-in account, and an UNATTENDED turn that names no
|
|
42
|
+
* persona is denied every account there is. Without this field the executor could only wake such a turn,
|
|
43
|
+
* one structurally unable to reach the login the post needs, which read from inside the turn as "this
|
|
44
|
+
* account is not connected" and cost two approved posts before anyone traced it back here.
|
|
45
|
+
*
|
|
46
|
+
* A PERSONA RATHER THAN AN ACCOUNT ID, because that is the vocabulary the rest of the system already speaks:
|
|
47
|
+
* `actsAs` is the only pin turnPersona honours, and a card carries the workspace scope the turn also needs to
|
|
48
|
+
* write this file's own status back. Naming the account directly would invent a second way to say the same
|
|
49
|
+
* thing, and the two would disagree the first time a card's accounts changed.
|
|
50
|
+
*
|
|
51
|
+
* The daemon never guesses it. One site can be connected several times over, five Reddit logins here, and
|
|
52
|
+
* picking for the owner means picking wrong in public, with no undo. A post that needs a turn and names
|
|
53
|
+
* nobody is failed with that sentence instead of sent. An ACTION that names nobody runs with no accounts,
|
|
54
|
+
* which is a legitimate choice for work that needs none. */
|
|
55
|
+
actsAs: entryId
|
|
56
|
+
.optional()
|
|
57
|
+
.describe(
|
|
58
|
+
"Whose name it acts under. Needed for anything that requires being logged in, because an unwatched turn naming nobody is allowed no account at all. Never guessed: one site can be connected five times over, and picking for you means picking wrong in public with no undo.",
|
|
59
|
+
),
|
|
60
|
+
// Suggested time (epoch ms, the at/nextRun convention). Optional, the agent may propose without a date and
|
|
61
|
+
// the owner sets one at approval; an approved item with no date is dated one hold ahead by the daemon.
|
|
62
|
+
scheduledAt: z
|
|
63
|
+
.number()
|
|
64
|
+
.optional()
|
|
65
|
+
.describe(
|
|
66
|
+
"When it should happen, in milliseconds. An agent may propose without one and you set it when approving; an approved item with no time goes after a short countdown you can still stop.",
|
|
67
|
+
),
|
|
68
|
+
// Agent-written files only need the kind's own fields; status defaults, the rest are optional, so a
|
|
69
|
+
// well-formed proposal never lands in `invalid` just for omitting bookkeeping fields.
|
|
70
|
+
status: ApprovalStatusSchema.default("proposed").describe(
|
|
71
|
+
"Where it is: proposed by the agent, approved by you, being carried out, done, or failed. Rejecting is deleting it; retrying is approving a failed one again.",
|
|
72
|
+
),
|
|
73
|
+
createdAt: z.number().optional().describe("When it was written, in milliseconds."),
|
|
74
|
+
// When execution STARTED, stamped with status "running". The executor needs it to tell a run that is under
|
|
75
|
+
// way from one whose turn died mid-flight, and those two are indistinguishable from the due time: a post
|
|
76
|
+
// scheduled for last week is not a post that has been sending since last week.
|
|
77
|
+
startedAt: z
|
|
78
|
+
.number()
|
|
79
|
+
.optional()
|
|
80
|
+
.describe(
|
|
81
|
+
"When it started being carried out, in milliseconds. Needed to tell a run that is under way from one whose turn died mid-flight, which the scheduled time cannot.",
|
|
82
|
+
),
|
|
83
|
+
finishedAt: z.number().optional().describe("When it was done, in milliseconds."),
|
|
84
|
+
// What came back, when something did: a post's own address, a booking's confirmation. The one thing a done
|
|
85
|
+
// row can offer that reading the proposal cannot: the result itself, to go and look at. A URL is drawn as
|
|
86
|
+
// a link; anything else as the sentence it is.
|
|
87
|
+
result: z
|
|
88
|
+
.string()
|
|
89
|
+
.optional()
|
|
90
|
+
.describe(
|
|
91
|
+
"What came back, when something did: the post's own address, a confirmation number. The one thing a finished item can offer that reading it cannot.",
|
|
92
|
+
),
|
|
93
|
+
// Why it failed; set with status "failed". Written for the owner to read in the queue, so it is a sentence
|
|
94
|
+
// rather than a code.
|
|
95
|
+
error: z.string().optional().describe("Why it failed, written as a sentence for a person to read rather than as a code."),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/* A POST, the first kind: words that go out in public under the owner's name and cannot be recalled. */
|
|
99
|
+
export const PostApprovalSchema = z.object({
|
|
100
|
+
kind: z.literal("post").describe("A post to publish somewhere."),
|
|
101
|
+
// Which skill posts it: "x" | "reddit" | "youtube" | "discord" | …, a bare string so new platforms need
|
|
102
|
+
// no contract change; an unknown platform simply fails at posting time.
|
|
103
|
+
platform: z
|
|
104
|
+
.string()
|
|
105
|
+
.min(1)
|
|
106
|
+
.describe("Where it should go. A plain name, so a new site needs no change here; an unknown one simply fails when it tries to post."),
|
|
107
|
+
content: z.string().min(1).describe("The post itself."),
|
|
108
|
+
// Reddit posts / YouTube uploads need one.
|
|
109
|
+
title: z.string().optional().describe("A title, where the site wants one."),
|
|
110
|
+
/* Where on the platform: subreddit / Discord channel id / community. OR the URL of the thing this post
|
|
111
|
+
* replies to. A URL target means the post is a reply, and on reddit the difference between a thread's
|
|
112
|
+
* address and one comment's permalink is the difference between talking to the room and answering the
|
|
113
|
+
* person: the publisher opens exactly this and replies where it lands. */
|
|
114
|
+
target: z
|
|
115
|
+
.string()
|
|
116
|
+
.optional()
|
|
117
|
+
.describe(
|
|
118
|
+
"Where on the site: a community, a channel. Or the address of the thing this replies to, in which case it is a reply, and on some sites the difference between a thread's address and one comment's is the difference between talking to the room and answering the person.",
|
|
119
|
+
),
|
|
120
|
+
// Workspace-relative attachment paths, e.g. ".intentic/config/approvals/media/chart.png".
|
|
121
|
+
media: z.array(z.string()).optional().describe("Anything to attach, as workspace paths."),
|
|
122
|
+
...envelope,
|
|
123
|
+
});
|
|
124
|
+
export type PostApproval = z.infer<typeof PostApprovalSchema>;
|
|
125
|
+
|
|
126
|
+
/* AN ACTION, the general kind: anything else the agent is about to do that it should not do unasked. A
|
|
127
|
+
* booking, a purchase, a message to a person, a deletion that cannot be undone. The agent writes what it will
|
|
128
|
+
* do in words the owner reads (`summary`, `details`), and what it will tell ITSELF to do once released
|
|
129
|
+
* (`instructions`), because the turn that carries it out is a fresh one, hours later, with none of the
|
|
130
|
+
* conversation that led here. Executed by an agent turn, always: there is no typed door for "whatever it is". */
|
|
131
|
+
export const ActionApprovalSchema = z.object({
|
|
132
|
+
kind: z.literal("action").describe("Something the agent will do once you say so."),
|
|
133
|
+
summary: z.string().min(1).max(200).describe("What will happen, in one line: the row's headline and the confirm dialog's item."),
|
|
134
|
+
// Markdown. The specifics a yes is being asked for: the hotel and the dates, the amount and the account,
|
|
135
|
+
// the exact message and its recipient. Everything the owner has to see to be able to say no.
|
|
136
|
+
details: z.string().optional().describe("The specifics, as Markdown: everything you would want to see before saying yes."),
|
|
137
|
+
// What the executing turn is told. Written by the agent for its later self, so it names files, ids and
|
|
138
|
+
// steps rather than saying "do what we discussed".
|
|
139
|
+
instructions: z
|
|
140
|
+
.string()
|
|
141
|
+
.min(1)
|
|
142
|
+
.describe(
|
|
143
|
+
"What to do once approved, written for the fresh turn that will do it: names, ids and steps, since it has none of this conversation.",
|
|
144
|
+
),
|
|
145
|
+
...envelope,
|
|
146
|
+
});
|
|
147
|
+
export type ActionApproval = z.infer<typeof ActionApprovalSchema>;
|
|
148
|
+
|
|
149
|
+
// The on-disk file body, whichever kind it is.
|
|
150
|
+
export const ApprovalSchema = z.discriminatedUnion("kind", [PostApprovalSchema, ActionApprovalSchema]);
|
|
151
|
+
export type Approval = z.infer<typeof ApprovalSchema>;
|
|
152
|
+
|
|
153
|
+
// The list row / upsert input: the file body plus its filename id.
|
|
154
|
+
const withId = { id: entryId.describe("The approval's id.") };
|
|
155
|
+
export const PostApprovalSummarySchema = PostApprovalSchema.extend(withId);
|
|
156
|
+
export type PostApprovalSummary = z.infer<typeof PostApprovalSummarySchema>;
|
|
157
|
+
export const ActionApprovalSummarySchema = ActionApprovalSchema.extend(withId);
|
|
158
|
+
export type ActionApprovalSummary = z.infer<typeof ActionApprovalSummarySchema>;
|
|
159
|
+
export const ApprovalSummarySchema = z.discriminatedUnion("kind", [PostApprovalSummarySchema, ActionApprovalSummarySchema]);
|
|
160
|
+
export type ApprovalSummary = z.infer<typeof ApprovalSummarySchema>;
|
|
161
|
+
|
|
162
|
+
// `invalid` = filenames that failed to parse. Agent-written files are a trust boundary, without this a typo'd
|
|
163
|
+
// approval (or one of a kind this daemon does not know) would silently never run.
|
|
164
|
+
export const ApprovalsListSchema = z.object({
|
|
165
|
+
approvals: z.array(ApprovalSummarySchema).describe("The queue."),
|
|
166
|
+
invalid: z
|
|
167
|
+
.array(z.string())
|
|
168
|
+
.describe(
|
|
169
|
+
"Files that could not be read at all, or name a kind this daemon does not know. Listed rather than skipped, because an agent writes these files directly and a malformed one would otherwise never run and never say why.",
|
|
170
|
+
),
|
|
171
|
+
});
|
|
172
|
+
export type ApprovalsList = z.infer<typeof ApprovalsListSchema>;
|
|
173
|
+
// entryId, not a bare string: the id becomes a filename under .intentic/config/approvals/.
|
|
174
|
+
export const ApprovalIdParamSchema = z.object({ id: entryId.describe("Which approval.") });
|
package/src/schemas/ci.ts
CHANGED
|
@@ -124,22 +124,8 @@ export const CiRunsResponseSchema = z.object({
|
|
|
124
124
|
repos: z.array(CiRepoSchema).describe("Which workspace repositories are wired to a forge, and how each one's notifications are set up."),
|
|
125
125
|
// Newest first, across all mapped repos.
|
|
126
126
|
runs: z.array(PipelineRunSchema).describe("Runs across all of them, newest first."),
|
|
127
|
-
// When the owner last opened the pipelines view. Rides the runs response so the rail can decide what is
|
|
128
|
-
// NEW without a second call, a breakage older than this has already been seen and must not badge again.
|
|
129
|
-
// Absent ⇒ never opened, so everything counts as unseen.
|
|
130
|
-
seenAt: z
|
|
131
|
-
.number()
|
|
132
|
-
.optional()
|
|
133
|
-
.describe(
|
|
134
|
-
"When this was last looked at, in milliseconds, so a badge can tell new breakages from ones already read without a second call. Absent means never, so everything counts as new.",
|
|
135
|
-
),
|
|
136
127
|
});
|
|
137
128
|
export type CiRunsResponse = z.infer<typeof CiRunsResponseSchema>;
|
|
138
|
-
// Stamping the view as read hands back the timestamp it wrote, so the client updates without a refetch.
|
|
139
|
-
export const CiSeenResponseSchema = z.object({
|
|
140
|
-
seenAt: z.number().describe("The timestamp that was written, handed back so a caller can update without asking again."),
|
|
141
|
-
});
|
|
142
|
-
export type CiSeenResponse = z.infer<typeof CiSeenResponseSchema>;
|
|
143
129
|
// rerun/cancel/fix address a run by repo + vendor id; the daemon re-resolves repo → project + token per call,
|
|
144
130
|
// so a stale card can't act on a project the workspace no longer maps to.
|
|
145
131
|
export const CiRunParamSchema = z.object({
|
|
@@ -181,21 +167,28 @@ export type CiFixResponse = z.infer<typeof CiFixResponseSchema>;
|
|
|
181
167
|
* dialog that started it, and is gone. Nothing survives a daemon restart because nothing needs to: the next
|
|
182
168
|
* push asks again. */
|
|
183
169
|
|
|
184
|
-
/*
|
|
170
|
+
/* A COMMAND RUN ON A CLICK, in a visible terminal, with a verdict and a quotable tail: the ONE shape for
|
|
171
|
+
* everything the daemon runs because the owner pressed a button and then has to be told how it went. The
|
|
172
|
+
* pre-push check is one (above); the push itself is another (PushRunSchema, schemas/git.ts), because a push
|
|
173
|
+
* runs the repository's own pre-push hook, which is a suite in disguise. One shape rather than one per
|
|
174
|
+
* moment, so a field the browser learns to read for the check (the terminal to open, the tail to quote, the
|
|
175
|
+
* kill to distinguish from the timeout) is read for the push by the same code, and cannot drift.
|
|
176
|
+
*
|
|
177
|
+
* Where a run is.
|
|
185
178
|
*
|
|
186
179
|
* idle , nothing has run in this daemon's life, or the last run was cleared.
|
|
187
|
-
* running , the
|
|
188
|
-
* passed , exited 0. The push goes.
|
|
189
|
-
* failed , exited non-zero, or was killed by
|
|
190
|
-
* error , the
|
|
191
|
-
*
|
|
192
|
-
*
|
|
180
|
+
* running , the command is live. Its output is the terminal's (`session`), not this object's.
|
|
181
|
+
* passed , exited 0. The push goes (or went).
|
|
182
|
+
* failed , exited non-zero, or was killed by its ceiling (`timedOut`). The state a fix answers.
|
|
183
|
+
* error , the command could not run at all: it was not spawnable. NOT a fix-able failure, because there
|
|
184
|
+
* is nothing wrong with the code, the command is misconfigured, and saying "tests failed" would
|
|
185
|
+
* send an agent hunting a bug that isn't there.
|
|
193
186
|
* cancelled, the user stopped the run.
|
|
194
187
|
*/
|
|
195
|
-
export const
|
|
196
|
-
export type
|
|
197
|
-
export const
|
|
198
|
-
status:
|
|
188
|
+
export const CommandRunStatusSchema = z.enum(["idle", "running", "passed", "failed", "error", "cancelled"]);
|
|
189
|
+
export type CommandRunStatus = z.infer<typeof CommandRunStatusSchema>;
|
|
190
|
+
export const CommandRunSchema = z.object({
|
|
191
|
+
status: CommandRunStatusSchema.describe(
|
|
199
192
|
"Where the run is. Failed and error are deliberately different: failed means the code is wrong, error means the command could not be run at all, and calling the second one a test failure would send an agent hunting a bug that is not there.",
|
|
200
193
|
),
|
|
201
194
|
// The command this run executed, echoed rather than read back from settings: a result read after the
|
|
@@ -232,4 +225,4 @@ export const PrepushRunSchema = z.object({
|
|
|
232
225
|
"The end of what it printed, as plain text with the colour codes and redrawn progress lines resolved away. The end rather than the beginning, because a suite's verdict is at the end. Empty while it runs, and for one that was killed.",
|
|
233
226
|
),
|
|
234
227
|
});
|
|
235
|
-
export type
|
|
228
|
+
export type CommandRun = z.infer<typeof CommandRunSchema>;
|