@intentic/sandbox-contract 1.308.2 → 1.310.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/contracts/agent.contract.d.ts +98 -4
- package/dist/contracts/agent.contract.d.ts.map +1 -1
- package/dist/contracts/agent.contract.js +40 -10
- package/dist/contracts/agent.contract.js.map +1 -1
- package/dist/contracts/agents.contract.d.ts +285 -0
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/approvals.contract.d.ts +34 -0
- package/dist/contracts/approvals.contract.d.ts.map +1 -1
- package/dist/contracts/approvals.contract.js +30 -1
- package/dist/contracts/approvals.contract.js.map +1 -1
- package/dist/contracts/device.contract.d.ts +1 -0
- package/dist/contracts/device.contract.d.ts.map +1 -1
- package/dist/contracts/extensions.contract.d.ts +390 -0
- package/dist/contracts/extensions.contract.d.ts.map +1 -1
- package/dist/contracts/extensions.contract.js +11 -1
- package/dist/contracts/extensions.contract.js.map +1 -1
- package/dist/contracts/runner.contract.d.ts +117 -107
- package/dist/contracts/runner.contract.d.ts.map +1 -1
- package/dist/contracts/sessions.contract.d.ts +1 -0
- package/dist/contracts/sessions.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.d.ts +57 -15
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.d.ts +210 -0
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.js +35 -1
- package/dist/contracts/system.contract.js.map +1 -1
- package/dist/events/agent-events.d.ts +9 -2
- package/dist/events/agent-events.d.ts.map +1 -1
- package/dist/events/agent-events.js +5 -1
- package/dist/events/agent-events.js.map +1 -1
- package/dist/events/resume.d.ts +1 -0
- package/dist/events/resume.d.ts.map +1 -1
- package/dist/events/resume.js +2 -0
- package/dist/events/resume.js.map +1 -1
- package/dist/events/system-events.d.ts +40 -0
- package/dist/events/system-events.d.ts.map +1 -1
- package/dist/events/transcript.d.ts +14 -0
- package/dist/events/transcript.d.ts.map +1 -1
- package/dist/events/transcript.js +7 -1
- package/dist/events/transcript.js.map +1 -1
- package/dist/index.d.ts +1114 -84
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/models/model-label.d.ts +2 -0
- package/dist/models/model-label.d.ts.map +1 -0
- package/dist/models/model-label.js +20 -0
- package/dist/models/model-label.js.map +1 -0
- package/dist/models/model-pins.d.ts +0 -1
- package/dist/models/model-pins.d.ts.map +1 -1
- package/dist/models/model-pins.js +0 -2
- package/dist/models/model-pins.js.map +1 -1
- package/dist/policy/command-classes.d.ts.map +1 -1
- package/dist/policy/command-classes.js +88 -7
- package/dist/policy/command-classes.js.map +1 -1
- package/dist/policy/reserved-servers.d.ts +7 -0
- package/dist/policy/reserved-servers.d.ts.map +1 -0
- package/dist/policy/reserved-servers.js +21 -0
- package/dist/policy/reserved-servers.js.map +1 -0
- package/dist/policy/turned-away.d.ts.map +1 -1
- package/dist/policy/turned-away.js.map +1 -1
- package/dist/protocol/ingress-protocol.d.ts +2 -0
- package/dist/protocol/ingress-protocol.d.ts.map +1 -1
- package/dist/protocol/ingress-protocol.js +4 -1
- package/dist/protocol/ingress-protocol.js.map +1 -1
- package/dist/protocol/peer-mcp-server.d.ts +7 -0
- package/dist/protocol/peer-mcp-server.d.ts.map +1 -1
- package/dist/protocol/peer-mcp-server.js +6 -1
- package/dist/protocol/peer-mcp-server.js.map +1 -1
- package/dist/protocol/tunnel-heartbeat.d.ts +19 -0
- package/dist/protocol/tunnel-heartbeat.d.ts.map +1 -0
- package/dist/protocol/tunnel-heartbeat.js +41 -0
- package/dist/protocol/tunnel-heartbeat.js.map +1 -0
- package/dist/protocol/upgrade-relay.d.ts +4 -0
- package/dist/protocol/upgrade-relay.d.ts.map +1 -0
- package/dist/protocol/upgrade-relay.js +25 -0
- package/dist/protocol/upgrade-relay.js.map +1 -0
- package/dist/schemas/agent.d.ts +59 -0
- package/dist/schemas/agent.d.ts.map +1 -1
- package/dist/schemas/agent.js +45 -2
- package/dist/schemas/agent.js.map +1 -1
- package/dist/schemas/agents.d.ts +60 -0
- package/dist/schemas/agents.d.ts.map +1 -1
- package/dist/schemas/agents.js +6 -1
- package/dist/schemas/agents.js.map +1 -1
- package/dist/schemas/approvals.d.ts +67 -0
- package/dist/schemas/approvals.d.ts.map +1 -1
- package/dist/schemas/approvals.js +43 -0
- package/dist/schemas/approvals.js.map +1 -1
- package/dist/schemas/automations.d.ts +20 -0
- package/dist/schemas/automations.d.ts.map +1 -1
- package/dist/schemas/ci.d.ts.map +1 -1
- package/dist/schemas/ci.js.map +1 -1
- package/dist/schemas/devices.d.ts +2 -0
- package/dist/schemas/devices.d.ts.map +1 -1
- package/dist/schemas/devices.js +1 -0
- package/dist/schemas/devices.js.map +1 -1
- package/dist/schemas/extension-updates.d.ts +850 -77
- package/dist/schemas/extension-updates.d.ts.map +1 -1
- package/dist/schemas/extension-updates.js +23 -0
- package/dist/schemas/extension-updates.js.map +1 -1
- package/dist/schemas/history.d.ts +1 -0
- package/dist/schemas/history.d.ts.map +1 -1
- package/dist/schemas/history.js +4 -0
- package/dist/schemas/history.js.map +1 -1
- package/dist/schemas/metrics.d.ts +257 -0
- package/dist/schemas/metrics.d.ts.map +1 -1
- package/dist/schemas/metrics.js +73 -3
- package/dist/schemas/metrics.js.map +1 -1
- package/dist/schemas/providers/plan-limits.d.ts +42 -1
- package/dist/schemas/providers/plan-limits.d.ts.map +1 -1
- package/dist/schemas/providers/plan-limits.js +48 -1
- package/dist/schemas/providers/plan-limits.js.map +1 -1
- package/dist/schemas/providers/usage.d.ts +2 -0
- package/dist/schemas/providers/usage.d.ts.map +1 -1
- package/dist/schemas/providers/usage.js +2 -0
- package/dist/schemas/providers/usage.js.map +1 -1
- package/dist/schemas/settings.d.ts +61 -29
- package/dist/schemas/settings.d.ts.map +1 -1
- package/dist/schemas/settings.js +36 -11
- package/dist/schemas/settings.js.map +1 -1
- package/dist/schemas/turn-break.d.ts +5 -0
- package/dist/schemas/turn-break.d.ts.map +1 -1
- package/dist/schemas/turn-break.js +4 -0
- package/dist/schemas/turn-break.js.map +1 -1
- package/dist/state/definition.d.ts +16 -20
- package/dist/state/definition.d.ts.map +1 -1
- package/dist/state/history-state.d.ts.map +1 -1
- package/dist/state/history-state.js +3 -0
- package/dist/state/history-state.js.map +1 -1
- package/dist/state/workspace-state.d.ts +0 -7
- package/dist/state/workspace-state.d.ts.map +1 -1
- package/dist/state/workspace-state.js +0 -8
- package/dist/state/workspace-state.js.map +1 -1
- package/dist/text/transcript-fold.d.ts +1 -1
- package/dist/text/transcript-fold.d.ts.map +1 -1
- package/dist/text/transcript-fold.js +19 -9
- package/dist/text/transcript-fold.js.map +1 -1
- package/package.json +27 -5
- package/src/chores/chores.test.ts +0 -1
- package/src/chores/digest.test.ts +0 -1
- package/src/chores/probes.test.ts +0 -1
- package/src/chores/stack.test.ts +0 -1
- package/src/chores/verdict.test.ts +0 -1
- package/src/contracts/agent.contract.ts +62 -15
- package/src/contracts/approvals.contract.ts +35 -1
- package/src/contracts/extensions.contract.ts +14 -0
- package/src/contracts/system.contract.ts +42 -1
- package/src/events/agent-events.ts +10 -2
- package/src/events/agent-words.test.ts +0 -1
- package/src/events/resume.test.ts +8 -1
- package/src/events/resume.ts +4 -0
- package/src/events/transcript.ts +13 -2
- package/src/events/watch-wake.test.ts +0 -1
- package/src/ids/conversation-ids.test.ts +1 -2
- package/src/ids/hostnames.test.ts +0 -1
- package/src/ids/share-paths.test.ts +0 -1
- package/src/ids/tunnel-ids.test.ts +0 -1
- package/src/index.ts +2 -3
- package/src/models/agent-catalog.test.ts +0 -1
- package/src/models/capability-ledger.test.ts +0 -1
- package/src/models/model-label.test.ts +23 -0
- package/src/models/model-label.ts +29 -0
- package/src/models/model-offer.test.ts +0 -1
- package/src/models/model-order.test.ts +0 -1
- package/src/models/model-pins.test.ts +0 -1
- package/src/models/model-pins.ts +0 -6
- package/src/models/model-roles.test.ts +0 -1
- package/src/models/plan-pools.test.ts +0 -1
- package/src/models/provider-specs.test.ts +0 -1
- package/src/policy/batch-runs.test.ts +0 -1
- package/src/policy/command-classes.test.ts +99 -2
- package/src/policy/command-classes.ts +143 -11
- package/src/policy/credential-material.test.ts +0 -1
- package/src/policy/fence-paths.test.ts +0 -1
- package/src/policy/overlay-lint.test.ts +0 -1
- package/src/policy/owner-ticket.test.ts +0 -1
- package/src/policy/persona-home.test.ts +0 -1
- package/src/policy/reserved-servers.test.ts +50 -0
- package/src/policy/reserved-servers.ts +48 -0
- package/src/policy/safety-policy.test.ts +0 -1
- package/src/policy/search-globs.test.ts +0 -1
- package/src/policy/turned-away.ts +2 -1
- package/src/protocol/container-requirements.test.ts +0 -1
- package/src/protocol/ingress-contract.test.ts +0 -1
- package/src/protocol/ingress-protocol.test.ts +78 -2
- package/src/protocol/ingress-protocol.ts +8 -1
- package/src/protocol/peer-dial.test.ts +1 -2
- package/src/protocol/peer-mcp-server.test.ts +10 -4
- package/src/protocol/peer-mcp-server.ts +14 -1
- package/src/protocol/routes.test.ts +6 -3
- package/src/protocol/tunnel-heartbeat.test.ts +75 -0
- package/src/protocol/tunnel-heartbeat.ts +67 -0
- package/src/protocol/upgrade-relay.ts +28 -0
- package/src/schemas/agent.test.ts +0 -1
- package/src/schemas/agent.ts +77 -5
- package/src/schemas/agents.ts +11 -1
- package/src/schemas/approvals.ts +67 -0
- package/src/schemas/areas.test.ts +1 -2
- package/src/schemas/ci.ts +3 -9
- package/src/schemas/context-trim.test.ts +2 -3
- package/src/schemas/dev-rebuild-log.test.ts +0 -1
- package/src/schemas/devices.ts +2 -0
- package/src/schemas/extension-updates.ts +30 -0
- package/src/schemas/git/git.test.ts +0 -1
- package/src/schemas/history.ts +8 -1
- package/src/schemas/metrics.ts +121 -4
- package/src/schemas/providers/plan-limits.ts +67 -2
- package/src/schemas/providers/usage.ts +3 -0
- package/src/schemas/settings.test.ts +41 -7
- package/src/schemas/settings.ts +64 -44
- package/src/schemas/turn-break.ts +8 -0
- package/src/schemas/version-seam.test.ts +0 -1
- package/src/state/contract-lock.test.ts +0 -1
- package/src/state/fix-attempt-plan.test.ts +0 -1
- package/src/state/fix-stance.test.ts +0 -1
- package/src/state/history-state.ts +6 -0
- package/src/state/landed-commit.test.ts +0 -1
- package/src/state/runtime-state.test.ts +0 -1
- package/src/state/versions.test.ts +0 -1
- package/src/state/workspace-state.test.ts +2 -5
- package/src/state/workspace-state.ts +0 -14
- package/src/text/archives.test.ts +0 -1
- package/src/text/documents.test.ts +0 -1
- package/src/text/embed.test.ts +2 -3
- package/src/text/emoji.test.ts +0 -1
- package/src/text/mentions.test.ts +0 -1
- package/src/text/path-refs.test.ts +0 -1
- package/src/text/title.test.ts +0 -1
- package/src/text/transcript-fold.test.ts +35 -8
- package/src/text/transcript-fold.ts +32 -19
- package/src/text/whisper.test.ts +0 -1
- package/src/text/workflow-faults.test.ts +0 -1
- package/src/time/zone.test.ts +0 -1
- package/dist/contracts/prepush.contract.d.ts +0 -32
- package/dist/contracts/prepush.contract.d.ts.map +0 -1
- package/dist/contracts/prepush.contract.js +0 -41
- package/dist/contracts/prepush.contract.js.map +0 -1
- package/src/contracts/prepush.contract.ts +0 -58
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { STATE_DIR } from "@intentic/constants";
|
|
2
2
|
import type { FileContribution } from "@intentic/extension-manifest";
|
|
3
|
-
import { describe, it, expect } from "bun:test";
|
|
4
3
|
import {
|
|
5
4
|
BACKED_UP_STATE_PATHS,
|
|
6
5
|
isLockedWorkspacePath,
|
|
@@ -60,8 +59,8 @@ describe(`staleQueryKeys`, () => {
|
|
|
60
59
|
});
|
|
61
60
|
|
|
62
61
|
it(`ignores a store's own temp file while it is mid-swap`, () => {
|
|
63
|
-
//
|
|
64
|
-
expect(staleQueryKeys([`.intentic/.settings.json.42.tmp`], [])).toEqual([]);
|
|
62
|
+
// writeTextFile's atomic-rename temp name: `.<name>.<pid>.<n>.tmp` beside the target.
|
|
63
|
+
expect(staleQueryKeys([`.intentic/.settings.json.42.7.tmp`], [])).toEqual([]);
|
|
65
64
|
expect(staleQueryKeys([`.intentic/config/settings.json`], [])).toEqual([`settings`, `manifests`]);
|
|
66
65
|
});
|
|
67
66
|
|
|
@@ -346,8 +345,6 @@ describe(`VERSIONED_STATE_PATHS`, () => {
|
|
|
346
345
|
// Which commands count as heavy, and how many may run at once; a shared-box decision worth a `git log`
|
|
347
346
|
// line.
|
|
348
347
|
`${STATE_DIR}/config/heavy-commands.json`,
|
|
349
|
-
// The exclude list carves entries out by name; an unlisted directory is invisible to git and to land.
|
|
350
|
-
`${STATE_DIR}/config/hooks/`,
|
|
351
348
|
`${STATE_DIR}/config/loop-designs.json`,
|
|
352
349
|
`${STATE_DIR}/config/personas.json`,
|
|
353
350
|
// A persona's prompt and reachable skills: the text that decides how it behaves, same reason as its card.
|
|
@@ -120,20 +120,6 @@ const STATE_FILES = [
|
|
|
120
120
|
// Bash command. `carry`: a property of the workspace, not the machine. `versioned`: raising the limit is a decision
|
|
121
121
|
// worth a diff.
|
|
122
122
|
{ path: ".intentic/config/heavy-commands.json", invalidates: ["settings"], portability: "carry", versioned: true },
|
|
123
|
-
// Scripts the rule table runs, one per reader (settings.json points at them per event, e.g. `file.edited`).
|
|
124
|
-
// `versioned`: this is code that runs against every file an agent writes, more consequential than the rule naming
|
|
125
|
-
// it. `carry`: authored text, no credential. Invalidates nothing: the settings screen renders the rules from
|
|
126
|
-
// settings.json, not these scripts.
|
|
127
|
-
{
|
|
128
|
-
path: ".intentic/config/hooks/",
|
|
129
|
-
invalidates: [],
|
|
130
|
-
why: "The settings screen renders the rules that name these scripts, out of settings.json; nothing in the browser reads the scripts themselves.",
|
|
131
|
-
portability: "carry",
|
|
132
|
-
versioned: true,
|
|
133
|
-
// The daemon only runs these scripts by path; it never builds them, so there's no `statePath` call for the
|
|
134
|
-
// coverage guard to find.
|
|
135
|
-
outsideWriter: "the owner or an agent, authoring them; the daemon only ever RUNS one, by the path a rule's command names",
|
|
136
|
-
},
|
|
137
123
|
// Last-fired stamps for the rule table. `derived`: records what happened on this machine, not carried.
|
|
138
124
|
{
|
|
139
125
|
path: ".intentic/local/rule-firings.json",
|
package/src/text/embed.test.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { webcrypto } from "node:crypto";
|
|
2
|
-
import { test, expect, beforeAll, mock } from "bun:test";
|
|
3
2
|
import { stubGlobal, unstubAllGlobals } from "@intentic/testing/bun";
|
|
4
3
|
import { EmbedError, embedFailure, embedUrl, fetchEmbedJson, solveProofOfWork } from "./embed.js";
|
|
5
4
|
|
|
@@ -40,12 +39,12 @@ test("a refusal carries the server's own sentence and status, and a bodyless one
|
|
|
40
39
|
test("a JSON fetch answers the body or throws the refusal", async () => {
|
|
41
40
|
stubGlobal(
|
|
42
41
|
"fetch",
|
|
43
|
-
|
|
42
|
+
jest.fn(async () => new Response(JSON.stringify({ ok: true }), { status: 200 })),
|
|
44
43
|
);
|
|
45
44
|
expect(await fetchEmbedJson<{ ok: boolean }>("https://x/y")).toEqual({ ok: true });
|
|
46
45
|
stubGlobal(
|
|
47
46
|
"fetch",
|
|
48
|
-
|
|
47
|
+
jest.fn(async () => new Response(JSON.stringify({ error: "rate limited" }), { status: 429 })),
|
|
49
48
|
);
|
|
50
49
|
await expect(fetchEmbedJson("https://x/y")).rejects.toMatchObject({ message: "rate limited", status: 429 });
|
|
51
50
|
unstubAllGlobals();
|
package/src/text/emoji.test.ts
CHANGED
package/src/text/title.test.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { STATE_DIR } from "@intentic/constants";
|
|
2
|
-
import { describe, it, expect } from "bun:test";
|
|
3
2
|
import type { AgentEvent } from "../events/agent-events.js";
|
|
4
3
|
import type { TranscriptPatch, TranscriptRow } from "../events/transcript.js";
|
|
5
4
|
import { watchWakePrompt } from "../events/watch-wake.js";
|
|
@@ -186,7 +185,8 @@ describe("foldTurn", () => {
|
|
|
186
185
|
code: "provider-outage",
|
|
187
186
|
message: "Anthropic is down.",
|
|
188
187
|
autoResume: "scheduled",
|
|
189
|
-
outage: { retryAt: 1
|
|
188
|
+
outage: { retryAt: 1 },
|
|
189
|
+
retries: { made: 1, max: 6 },
|
|
190
190
|
},
|
|
191
191
|
];
|
|
192
192
|
// The row states what happened and nothing more: what happens next, and the one control that changes it, are
|
|
@@ -200,6 +200,33 @@ describe("foldTurn", () => {
|
|
|
200
200
|
});
|
|
201
201
|
});
|
|
202
202
|
|
|
203
|
+
// The count lives in the record, so a reader scrolling back sees how many times a stuck turn was sent again.
|
|
204
|
+
it("says on a stopped turn's row which automatic try comes next, or that the ladder stood down", () => {
|
|
205
|
+
const timedOut = "Google turn timed out waiting for OpenCode.";
|
|
206
|
+
const booked: AgentEvent[] = [{ kind: "error", message: timedOut, autoResume: "scheduled", nextAt: 1, retries: { made: 1, max: 3 } }];
|
|
207
|
+
expect(foldOf("hi", booked).at(-1)).toEqual({ role: "notice", text: `${timedOut} Retrying by itself: attempt 2 of 3.` });
|
|
208
|
+
const spent: AgentEvent[] = [{ kind: "error", message: timedOut, autoResume: "available", retries: { made: 3, max: 3 } }];
|
|
209
|
+
expect(foldOf("hi", spent).at(-1)).toEqual({
|
|
210
|
+
role: "notice",
|
|
211
|
+
text: `${timedOut} Retried 3 of 3 times by itself; nothing more is sent automatically.`,
|
|
212
|
+
});
|
|
213
|
+
// An outage nobody armed says so, instead of promising the breaker's retry.
|
|
214
|
+
const unarmed: AgentEvent[] = [
|
|
215
|
+
{
|
|
216
|
+
kind: "error",
|
|
217
|
+
code: "provider-outage",
|
|
218
|
+
message: "Anthropic is down.",
|
|
219
|
+
autoResume: "available",
|
|
220
|
+
outage: { retryAt: 1 },
|
|
221
|
+
retries: { made: 0, max: 6 },
|
|
222
|
+
},
|
|
223
|
+
];
|
|
224
|
+
expect(foldOf("hi", unarmed).at(-1)).toEqual({
|
|
225
|
+
role: "notice",
|
|
226
|
+
text: "Anthropic is down. Nothing is retrying it, so the turn is waiting here.",
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
203
230
|
it("writes the turn's own events down as notices", () => {
|
|
204
231
|
const events: AgentEvent[] = [
|
|
205
232
|
{ kind: "worktree", branch: "agent/x", base: "abc1234", sync: { commits: 2, blocked: [] } },
|
|
@@ -213,7 +240,7 @@ describe("foldTurn", () => {
|
|
|
213
240
|
{ role: "notice", text: "Context compacted to free up space." },
|
|
214
241
|
{
|
|
215
242
|
role: "notice",
|
|
216
|
-
text: "Changes landed in your workspace: review them in the Changes panel. Installing 1
|
|
243
|
+
text: "Changes landed in your workspace: review them in the Changes panel. Installing 1 dependency it added or changed; the project's checks run when that finishes, and the outcome lands in Activity.",
|
|
217
244
|
noticeAction: "depsInstall",
|
|
218
245
|
},
|
|
219
246
|
]);
|
|
@@ -495,8 +522,8 @@ describe("patches", () => {
|
|
|
495
522
|
});
|
|
496
523
|
});
|
|
497
524
|
|
|
498
|
-
// A refusal that ran nothing offers the message back
|
|
499
|
-
// that started itself, where there is no composer and no typed message.
|
|
525
|
+
// A refusal that ran nothing offers the message back for another press — true where somebody typed one, false for a
|
|
526
|
+
// run that started itself, where there is no composer and no typed message.
|
|
500
527
|
describe(`a refusal that ran nothing`, () => {
|
|
501
528
|
const REFUSED = { kind: `error`, code: `context-window-too-small`, message: `This model accepts 16,384 tokens.` } as const satisfies AgentEvent;
|
|
502
529
|
|
|
@@ -551,9 +578,9 @@ describe(`a refusal that ran nothing`, () => {
|
|
|
551
578
|
expect(foldOf(`land it`, [REFUSED]).at(-1)?.noticeAction).toBeUndefined();
|
|
552
579
|
});
|
|
553
580
|
|
|
554
|
-
// The bug this retraction exists for: the
|
|
555
|
-
// here is the SAME message a second time, and a third, once per press against a gate that keeps refusing.
|
|
556
|
-
it(`takes the message back out, leaving the
|
|
581
|
+
// The bug this retraction exists for: the conversation's queue keeps the words for another press, so a bubble left
|
|
582
|
+
// standing here is the SAME message a second time, and a third, once per press against a gate that keeps refusing.
|
|
583
|
+
it(`takes the message back out, leaving the queue's copy as the only one`, () => {
|
|
557
584
|
const fold = new TranscriptFold(openingOf(`land it`));
|
|
558
585
|
const patches = fold.apply(REFUSED);
|
|
559
586
|
|
|
@@ -62,10 +62,11 @@ const dependencyLine = (deps: { missing: number; started: string[]; deferred: bo
|
|
|
62
62
|
if (deps === undefined || deps.missing === 0) {
|
|
63
63
|
return ``;
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
// `missing` counts versions the turn bumped as well as names it added, so the sentence names both.
|
|
66
|
+
const what = `${deps.missing} ${deps.missing === 1 ? `dependency` : `dependencies`} it added or changed`;
|
|
66
67
|
return deps.deferred
|
|
67
|
-
? ` ${what} are queued: installation starts after this turn and any other active agents finish, appears in Work terminals, then its checks and outcome land in Activity.`
|
|
68
|
-
: ` Installing ${what}
|
|
68
|
+
? ` ${what} ${deps.missing === 1 ? `is` : `are`} queued: installation starts after this turn and any other active agents finish, appears in Work terminals, then its checks and outcome land in Activity.`
|
|
69
|
+
: ` Installing ${what}; the project's checks run when that finishes, and the outcome lands in Activity.`;
|
|
69
70
|
};
|
|
70
71
|
|
|
71
72
|
// One line reporting the daemon's rebase of this agent's branch onto the current workspace; `blocked` names repos it
|
|
@@ -106,10 +107,10 @@ const landedRow = (event: Extract<AgentEvent, { kind: "landed" }>): TranscriptRo
|
|
|
106
107
|
};
|
|
107
108
|
};
|
|
108
109
|
|
|
109
|
-
// The clause after a refusal that ran nothing. A turn somebody typed is held in
|
|
110
|
-
// that started itself — an automation, a loop, a watch wake — has no typed message and nobody watching,
|
|
111
|
-
// resend there names a composer the reader is not looking at. Neither version promises a retry: whether
|
|
112
|
-
// the scheduler's decision, not this row's to state.
|
|
110
|
+
// The clause after a refusal that ran nothing. A turn somebody typed is held in its conversation's queue for another
|
|
111
|
+
// press; a turn that started itself — an automation, a loop, a watch wake — has no typed message and nobody watching,
|
|
112
|
+
// so promising a resend there names a composer the reader is not looking at. Neither version promises a retry: whether
|
|
113
|
+
// one comes is the scheduler's decision, not this row's to state.
|
|
113
114
|
const undelivered = (unattended: boolean): string =>
|
|
114
115
|
unattended
|
|
115
116
|
? `Nothing ran, and nothing is held: this run started on its own, so there is no message waiting to be sent again.`
|
|
@@ -152,9 +153,7 @@ const errorRow = (event: Extract<AgentEvent, { kind: "error" }>): TranscriptRow
|
|
|
152
153
|
const { message, code } = event;
|
|
153
154
|
switch (code) {
|
|
154
155
|
case "provider-outage":
|
|
155
|
-
return event
|
|
156
|
-
? { role: "notice", text: `${message} Nothing is retrying it, so the turn is waiting here.` }
|
|
157
|
-
: { role: "notice", text: `${message} Retrying by itself: attempt ${event.outage.attempt} of ${event.outage.maxAttempts}.` };
|
|
156
|
+
return { role: "notice", text: `${message} ${retryClause(event) ?? `Nothing is retrying it, so the turn is waiting here.`}` };
|
|
158
157
|
case "claude-token-refused":
|
|
159
158
|
return event.autoResume === "scheduled"
|
|
160
159
|
? {
|
|
@@ -169,18 +168,31 @@ const errorRow = (event: Extract<AgentEvent, { kind: "error" }>): TranscriptRow
|
|
|
169
168
|
break;
|
|
170
169
|
}
|
|
171
170
|
if (!turnedAwayCode(code)) {
|
|
172
|
-
|
|
171
|
+
const clause = retryClause(event);
|
|
172
|
+
return { role: "notice", text: clause === undefined ? message : `${message} ${clause}` };
|
|
173
173
|
}
|
|
174
174
|
return heldRow(event);
|
|
175
175
|
};
|
|
176
176
|
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
// What a laddered wall's automatic re-runs are doing, said on the failure's own row so the count stays in the record.
|
|
178
|
+
const retryClause = (event: Extract<AgentEvent, { kind: "error" }>): string | undefined => {
|
|
179
|
+
const { retries } = event;
|
|
180
|
+
if (retries === undefined) {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
if (event.autoResume === "scheduled") {
|
|
184
|
+
return `Retrying by itself: attempt ${retries.made + 1} of ${retries.max}.`;
|
|
185
|
+
}
|
|
186
|
+
return retries.made >= retries.max ? `Retried ${retries.made} of ${retries.max} times by itself; nothing more is sent automatically.` : undefined;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// The turn's opening user row: text, timestamp, attachments, the message's id, and whatever the daemon later stamps onto
|
|
190
|
+
// it (checkpoint, notes).
|
|
191
|
+
export const userRow = (text: string, sentAt: number, attachments: readonly string[], messageId?: string): TranscriptRow => {
|
|
180
192
|
// Drops an attachment already inline as an @-mention, unless it's a generated upload path (its own thumbnail).
|
|
181
193
|
const inline = new Set(mentionedPathTokens(text));
|
|
182
194
|
const chips = attachments.filter((path) => !inline.has(path) || path.includes(`/records/artifacts/attachments/`));
|
|
183
|
-
return { role: "user", text, sentAt, ...(chips.length > 0 ? { attachments: chips } : {}) };
|
|
195
|
+
return { role: "user", text, sentAt, ...(chips.length > 0 ? { attachments: chips } : {}), ...(messageId === undefined ? {} : { messageId }) };
|
|
184
196
|
};
|
|
185
197
|
|
|
186
198
|
export class TranscriptFold {
|
|
@@ -196,7 +208,7 @@ export class TranscriptFold {
|
|
|
196
208
|
private readonly parked = new Map<string, number>();
|
|
197
209
|
// The turn's opening user row, where the checkpoint and daemon notes land; cleared once `retract` takes it back.
|
|
198
210
|
private opener: number | undefined;
|
|
199
|
-
// Set by `retract`: this turn was refused before it ran, and its message went back to the
|
|
211
|
+
// Set by `retract`: this turn was refused before it ran, and its message went back to the conversation's queue.
|
|
200
212
|
private unrun = false;
|
|
201
213
|
|
|
202
214
|
constructor(
|
|
@@ -426,6 +438,7 @@ export class TranscriptFold {
|
|
|
426
438
|
text: event.text,
|
|
427
439
|
sentAt: event.sentAt,
|
|
428
440
|
...(event.attachments === undefined ? {} : { attachments: [...event.attachments] }),
|
|
441
|
+
...(event.messageId === undefined ? {} : { messageId: event.messageId }),
|
|
429
442
|
});
|
|
430
443
|
// Anchors pair by position with the checkpoints only a person's steer reserves.
|
|
431
444
|
if (event.voice === undefined) {
|
|
@@ -461,9 +474,9 @@ export class TranscriptFold {
|
|
|
461
474
|
);
|
|
462
475
|
}
|
|
463
476
|
|
|
464
|
-
// Attended refusals only: the
|
|
465
|
-
// once per press. Splicing is safe because nothing ran — no open bubble, no parked card, no steer above
|
|
466
|
-
// the sandbox kept (`held`) keeps its message and is recorded: no
|
|
477
|
+
// Attended refusals only: the conversation's queue holds those words for another press, so a bubble left standing
|
|
478
|
+
// repeats them once per press. Splicing is safe because nothing ran — no open bubble, no parked card, no steer above
|
|
479
|
+
// it. A turn the sandbox kept (`held`) keeps its message and is recorded: no queue holds a copy of it.
|
|
467
480
|
private retract(event: Extract<AgentEvent, { kind: "error" }>): TranscriptPatch[] {
|
|
468
481
|
if (!this.turnedAway(event) || event.held !== undefined) {
|
|
469
482
|
return [];
|
package/src/text/whisper.test.ts
CHANGED
package/src/time/zone.test.ts
CHANGED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
export declare const PrepushRunSchema: z.ZodPrefault<z.ZodObject<{
|
|
3
|
-
repos: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
4
|
-
}, z.core.$strip>>;
|
|
5
|
-
export declare const prepushContract: {
|
|
6
|
-
state: import("@orpc/contract").ContractProcedureBuilderWithOutput<import("@orpc/contract").Schema<unknown, unknown>, z.ZodObject<{
|
|
7
|
-
status: z.ZodEnum<{
|
|
8
|
-
cancelled: "cancelled";
|
|
9
|
-
error: "error";
|
|
10
|
-
failed: "failed";
|
|
11
|
-
idle: "idle";
|
|
12
|
-
passed: "passed";
|
|
13
|
-
running: "running";
|
|
14
|
-
}>;
|
|
15
|
-
command: z.ZodString;
|
|
16
|
-
startedAt: z.ZodOptional<z.ZodNumber>;
|
|
17
|
-
finishedAt: z.ZodOptional<z.ZodNumber>;
|
|
18
|
-
exitCode: z.ZodOptional<z.ZodNumber>;
|
|
19
|
-
timedOut: z.ZodOptional<z.ZodBoolean>;
|
|
20
|
-
session: z.ZodOptional<z.ZodString>;
|
|
21
|
-
output: z.ZodString;
|
|
22
|
-
}, z.core.$strip>, Record<never, never>, import("../protocol/route-meta.js").RouteMeta & Record<never, never>>;
|
|
23
|
-
run: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodPrefault<z.ZodObject<{
|
|
24
|
-
repos: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
25
|
-
}, z.core.$strip>>, z.ZodObject<{
|
|
26
|
-
ok: z.ZodLiteral<true>;
|
|
27
|
-
}, z.core.$strip>, Record<never, never>, import("../protocol/route-meta.js").RouteMeta & Record<never, never>>;
|
|
28
|
-
cancel: import("@orpc/contract").ContractProcedureBuilderWithOutput<import("@orpc/contract").Schema<unknown, unknown>, z.ZodObject<{
|
|
29
|
-
ok: z.ZodLiteral<true>;
|
|
30
|
-
}, z.core.$strip>, Record<never, never>, import("../protocol/route-meta.js").RouteMeta & Record<never, never>>;
|
|
31
|
-
};
|
|
32
|
-
//# sourceMappingURL=prepush.contract.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prepush.contract.d.ts","sourceRoot":"","sources":["../../src/contracts/prepush.contract.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,gBAAgB;;kBAQZ,CAAC;AAWlB,eAAO,MAAM,eAAe;IACxB,KAAK;;;;;;;;;;;;;;;;;IASL,GAAG;;;;;IAUH,MAAM;;;CAQT,CAAC"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { procedure } from "../protocol/route-meta.js";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { CommandRunSchema } from "../schemas/ci.js";
|
|
4
|
-
import { OkSchema } from "../schemas/shared.js";
|
|
5
|
-
export const PrepushRunSchema = z
|
|
6
|
-
.object({
|
|
7
|
-
repos: z
|
|
8
|
-
.array(z.string().min(1))
|
|
9
|
-
.max(100)
|
|
10
|
-
.default([])
|
|
11
|
-
.describe("The repositories going out, by workspace id. Empty runs only what stands for every push, whichever repository it is."),
|
|
12
|
-
})
|
|
13
|
-
.prefault({});
|
|
14
|
-
export const prepushContract = {
|
|
15
|
-
state: procedure
|
|
16
|
-
.route({
|
|
17
|
-
method: "GET",
|
|
18
|
-
path: "/prepush/state",
|
|
19
|
-
summary: "How the pre-push check is going",
|
|
20
|
-
description: "The verdict, or the progress so far. Nothing is addressed by id here, because there is one working tree and so exactly one check.",
|
|
21
|
-
})
|
|
22
|
-
.output(CommandRunSchema),
|
|
23
|
-
run: procedure
|
|
24
|
-
.route({
|
|
25
|
-
method: "POST",
|
|
26
|
-
path: "/prepush/run",
|
|
27
|
-
summary: "Run the checks before pushing",
|
|
28
|
-
description: "Starts the suite the workspace runs before anything leaves the machine, and answers immediately. A suite takes minutes, and a request held open that long dies at the first proxy. It runs in a real terminal, so watch it there and poll for the verdict. Name the repositories going out, and each one's own checks run in its own directory.",
|
|
29
|
-
})
|
|
30
|
-
.input(PrepushRunSchema)
|
|
31
|
-
.output(OkSchema),
|
|
32
|
-
cancel: procedure
|
|
33
|
-
.route({
|
|
34
|
-
method: "POST",
|
|
35
|
-
path: "/prepush/cancel",
|
|
36
|
-
summary: "Stop the pre-push check",
|
|
37
|
-
description: "Kills the run. It settles as cancelled and the push it was gating does not go.",
|
|
38
|
-
})
|
|
39
|
-
.output(OkSchema),
|
|
40
|
-
};
|
|
41
|
-
//# sourceMappingURL=prepush.contract.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prepush.contract.js","sourceRoot":"","sources":["../../src/contracts/prepush.contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAOhD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC;KAC5B,MAAM,CAAC;IACJ,KAAK,EAAE,CAAC;SACH,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACxB,GAAG,CAAC,GAAG,CAAC;SACR,OAAO,CAAC,EAAE,CAAC;SACX,QAAQ,CAAC,sHAAsH,CAAC;CACxI,CAAC;KACD,QAAQ,CAAC,EAAE,CAAC,CAAC;AAWlB,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,KAAK,EAAE,SAAS;SACX,KAAK,CAAC;QACH,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,iCAAiC;QAC1C,WAAW,EACP,mIAAmI;KAC1I,CAAC;SACD,MAAM,CAAC,gBAAgB,CAAC;IAC7B,GAAG,EAAE,SAAS;SACT,KAAK,CAAC;QACH,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,+BAA+B;QACxC,WAAW,EACP,iVAAiV;KACxV,CAAC;SACD,KAAK,CAAC,gBAAgB,CAAC;SACvB,MAAM,CAAC,QAAQ,CAAC;IACrB,MAAM,EAAE,SAAS;SACZ,KAAK,CAAC;QACH,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,yBAAyB;QAClC,WAAW,EAAE,gFAAgF;KAChG,CAAC;SACD,MAAM,CAAC,QAAQ,CAAC;CACxB,CAAC"}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { procedure } from "../protocol/route-meta.js";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { CommandRunSchema } from "../schemas/ci.js";
|
|
4
|
-
import { OkSchema } from "../schemas/shared.js";
|
|
5
|
-
|
|
6
|
-
// Which repositories are about to be pushed. The check is one run over one working tree, but what stands in it is not
|
|
7
|
-
// the same for every push: a repository's own checks (repo-checks.ts) run only when that repository is going out, and a
|
|
8
|
-
// rule the owner aimed at one repository does the same.
|
|
9
|
-
// `prefault`, so a caller that sends no body at all still starts the check: a browser tab open since before this input
|
|
10
|
-
// existed is the ordinary case, and refusing its push over a missing field would be the worst possible way to say so.
|
|
11
|
-
export const PrepushRunSchema = z
|
|
12
|
-
.object({
|
|
13
|
-
repos: z
|
|
14
|
-
.array(z.string().min(1))
|
|
15
|
-
.max(100)
|
|
16
|
-
.default([])
|
|
17
|
-
.describe("The repositories going out, by workspace id. Empty runs only what stands for every push, whichever repository it is."),
|
|
18
|
-
})
|
|
19
|
-
.prefault({});
|
|
20
|
-
|
|
21
|
-
// The pre-push check, the command the workspace runs when the user pushes, before anything leaves the machine
|
|
22
|
-
// (see CommandRunSchema for where this sits and why). Three verbs about ONE run: the check answers about the
|
|
23
|
-
// main working tree, of which there is exactly one, so nothing here is addressed by id.
|
|
24
|
-
//
|
|
25
|
-
// `run` starts the check and returns immediately, a suite takes minutes, and an oRPC call held open for one
|
|
26
|
-
// would die on the first proxy timeout with the work still going. The dialog that started it polls `state` for
|
|
27
|
-
// the verdict, and opens the terminals panel on the `session` the first answer names: the suite runs in a real
|
|
28
|
-
// tmux window, so watching it is the terminal's job. `cancel` kills that window; the run settles as `cancelled`
|
|
29
|
-
// and the push it was gating does not go.
|
|
30
|
-
export const prepushContract = {
|
|
31
|
-
state: procedure
|
|
32
|
-
.route({
|
|
33
|
-
method: "GET",
|
|
34
|
-
path: "/prepush/state",
|
|
35
|
-
summary: "How the pre-push check is going",
|
|
36
|
-
description:
|
|
37
|
-
"The verdict, or the progress so far. Nothing is addressed by id here, because there is one working tree and so exactly one check.",
|
|
38
|
-
})
|
|
39
|
-
.output(CommandRunSchema),
|
|
40
|
-
run: procedure
|
|
41
|
-
.route({
|
|
42
|
-
method: "POST",
|
|
43
|
-
path: "/prepush/run",
|
|
44
|
-
summary: "Run the checks before pushing",
|
|
45
|
-
description:
|
|
46
|
-
"Starts the suite the workspace runs before anything leaves the machine, and answers immediately. A suite takes minutes, and a request held open that long dies at the first proxy. It runs in a real terminal, so watch it there and poll for the verdict. Name the repositories going out, and each one's own checks run in its own directory.",
|
|
47
|
-
})
|
|
48
|
-
.input(PrepushRunSchema)
|
|
49
|
-
.output(OkSchema),
|
|
50
|
-
cancel: procedure
|
|
51
|
-
.route({
|
|
52
|
-
method: "POST",
|
|
53
|
-
path: "/prepush/cancel",
|
|
54
|
-
summary: "Stop the pre-push check",
|
|
55
|
-
description: "Kills the run. It settles as cancelled and the push it was gating does not go.",
|
|
56
|
-
})
|
|
57
|
-
.output(OkSchema),
|
|
58
|
-
};
|