@astrosheep/keiyaku 4.0.0 → 4.0.2
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 +133 -8
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +13 -5
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -32
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +134 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +262 -46
- package/build/src/akuma/abort.d.ts +2 -0
- package/build/src/akuma/abort.js +50 -0
- package/build/src/akuma/akuma.d.ts +50 -33
- package/build/src/akuma/akuma.js +175 -127
- package/build/src/akuma/archetype.d.ts +14 -5
- package/build/src/akuma/archetype.js +85 -39
- package/build/src/akuma/body.d.ts +3 -5
- package/build/src/akuma/body.js +490 -183
- package/build/src/akuma/coordinate.d.ts +9 -0
- package/build/src/akuma/coordinate.js +22 -0
- package/build/src/akuma/heart/facts.d.ts +88 -45
- package/build/src/akuma/heart/facts.js +19 -8
- package/build/src/akuma/heart/index.d.ts +64 -55
- package/build/src/akuma/heart/index.js +172 -252
- package/build/src/akuma/heart/rows.d.ts +38 -83
- package/build/src/akuma/heart/rows.js +117 -155
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +61 -22
- package/build/src/akuma/heart/soul.d.ts +8 -0
- package/build/src/akuma/heart/soul.js +136 -0
- package/build/src/akuma/heart/storage.d.ts +47 -0
- package/build/src/akuma/heart/storage.js +224 -0
- package/build/src/akuma/heart/tells.d.ts +12 -0
- package/build/src/akuma/heart/tells.js +79 -0
- package/build/src/akuma/heart/timeline.d.ts +15 -0
- package/build/src/akuma/heart/timeline.js +86 -0
- package/build/src/akuma/identity.d.ts +2 -2
- package/build/src/akuma/identity.js +9 -9
- package/build/src/akuma/index.d.ts +10 -3
- package/build/src/akuma/index.js +7 -1
- package/build/src/akuma/projection.d.ts +176 -0
- package/build/src/akuma/projection.js +256 -0
- package/build/src/akuma/provider-recipe.d.ts +24 -0
- package/build/src/akuma/provider-recipe.js +100 -0
- package/build/src/akuma/provider.d.ts +67 -13
- package/build/src/akuma/provider.js +172 -105
- package/build/src/akuma/providers/acp/core.d.ts +19 -0
- package/build/src/akuma/providers/acp/core.js +159 -0
- package/build/src/akuma/providers/acp/events.d.ts +20 -0
- package/build/src/akuma/providers/acp/events.js +73 -0
- package/build/src/akuma/providers/acp/index.d.ts +12 -0
- package/build/src/akuma/providers/acp/index.js +94 -0
- package/build/src/akuma/providers/{claude.d.ts → claude/events.d.ts} +9 -41
- package/build/src/akuma/providers/claude/events.js +238 -0
- package/build/src/akuma/providers/claude/index.d.ts +47 -0
- package/build/src/akuma/providers/claude/index.js +279 -0
- package/build/src/akuma/providers/claude/input.d.ts +13 -0
- package/build/src/akuma/providers/claude/input.js +109 -0
- package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
- package/build/src/akuma/providers/codex-app-server/events.js +15 -12
- package/build/src/akuma/providers/codex-app-server/index.d.ts +15 -13
- package/build/src/akuma/providers/codex-app-server/index.js +77 -33
- package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
- package/build/src/akuma/providers/grok-build/index.js +70 -0
- package/build/src/akuma/providers/index.d.ts +5 -3
- package/build/src/akuma/providers/index.js +35 -56
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +54 -0
- package/build/src/akuma/providers/opencode-sdk/events.js +235 -0
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +33 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +308 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +26 -0
- package/build/src/akuma/providers/opencode-sdk/session.js +63 -0
- package/build/src/akuma/providers/pi/events.d.ts +33 -0
- package/build/src/akuma/providers/pi/events.js +166 -0
- package/build/src/akuma/providers/pi/index.d.ts +11 -0
- package/build/src/akuma/providers/pi/index.js +191 -0
- package/build/src/akuma/publication.d.ts +3 -3
- package/build/src/akuma/publication.js +28 -40
- package/build/src/akuma/requests.d.ts +9 -6
- package/build/src/akuma/requests.js +95 -65
- package/build/src/alias/index.d.ts +4 -3
- package/build/src/alias/index.js +12 -13
- package/build/src/body/decode.js +7 -1
- package/build/src/body/region.d.ts +2 -0
- package/build/src/body/region.js +77 -7
- package/build/src/body/render.js +2 -1
- package/build/src/body/shape.js +7 -1
- package/build/src/body/verification.js +19 -4
- package/build/src/cli/accepted.d.ts +18 -12
- package/build/src/cli/accepted.js +73 -34
- package/build/src/cli/actor.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +44 -19
- package/build/src/cli/commands/akuma-invoke.js +101 -52
- package/build/src/cli/commands/akuma.d.ts +27 -9
- package/build/src/cli/commands/akuma.js +151 -80
- package/build/src/cli/commands/contract.d.ts +155 -0
- package/build/src/cli/commands/contract.js +20 -0
- package/build/src/cli/commands/install.js +2 -0
- package/build/src/cli/commands/task-invoke.d.ts +19 -4
- package/build/src/cli/commands/task-invoke.js +65 -17
- package/build/src/cli/commands/task-query.d.ts +5 -0
- package/build/src/cli/commands/task-query.js +247 -0
- package/build/src/cli/commands/task.d.ts +3 -1
- package/build/src/cli/commands/task.js +52 -14
- package/build/src/cli/coordinates.d.ts +18 -0
- package/build/src/cli/coordinates.js +120 -0
- package/build/src/cli/draft.d.ts +8 -0
- package/build/src/cli/draft.js +96 -0
- package/build/src/cli/invoke.d.ts +9 -3
- package/build/src/cli/invoke.js +287 -108
- package/build/src/cli/main.js +54 -7
- package/build/src/cli/parse.d.ts +21 -117
- package/build/src/cli/parse.js +79 -84
- package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
- package/build/src/cli/render/akuma-tool-command.js +144 -0
- package/build/src/cli/render/akuma-tool.d.ts +4 -2
- package/build/src/cli/render/akuma-tool.js +35 -5
- package/build/src/cli/render/akuma.d.ts +3 -1
- package/build/src/cli/render/akuma.js +247 -212
- package/build/src/cli/render/audit.d.ts +3 -0
- package/build/src/cli/render/audit.js +104 -0
- package/build/src/cli/render/catalog.d.ts +2 -0
- package/build/src/cli/render/catalog.js +16 -0
- package/build/src/cli/render/contract.d.ts +3 -3
- package/build/src/cli/render/contract.js +200 -54
- package/build/src/cli/render/kanshi.js +272 -129
- package/build/src/cli/render/receipt.d.ts +19 -0
- package/build/src/cli/render/receipt.js +106 -0
- package/build/src/cli/render/refusal.d.ts +16 -2
- package/build/src/cli/render/refusal.js +88 -3
- package/build/src/cli/render/region.d.ts +2 -0
- package/build/src/cli/render/region.js +17 -0
- package/build/src/cli/render/task.d.ts +2 -1
- package/build/src/cli/render/task.js +223 -60
- package/build/src/cli/render/terminal.d.ts +20 -0
- package/build/src/cli/render/terminal.js +121 -0
- package/build/src/cli/render/text.js +11 -3
- package/build/src/cli/result.d.ts +126 -19
- package/build/src/cli/usage.d.ts +1 -0
- package/build/src/cli/usage.js +3 -0
- package/build/src/contract-worktree.d.ts +44 -0
- package/build/src/contract-worktree.js +251 -0
- package/build/src/coordination/durable-file.d.ts +5 -1
- package/build/src/coordination/durable-file.js +57 -10
- package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
- package/build/src/coordination/sqlite-transaction-lock.js +22 -5
- package/build/src/core/facts/codec.js +23 -4
- package/build/src/core/facts/eligibility.d.ts +1 -10
- package/build/src/core/facts/eligibility.js +0 -49
- package/build/src/core/facts/fold.js +1 -6
- package/build/src/core/facts/gate.d.ts +1 -0
- package/build/src/core/facts/gate.js +1 -0
- package/build/src/core/facts/observation.d.ts +3 -0
- package/build/src/core/facts/observation.js +12 -0
- package/build/src/core/facts/types.d.ts +10 -3
- package/build/src/core/subject.js +2 -2
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +3 -18
- package/build/src/core/verbs/bind.js +2 -16
- package/build/src/core/verbs/deliver.d.ts +1 -1
- package/build/src/core/verbs/deliver.js +14 -4
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +7 -9
- package/build/src/dispatch/index.d.ts +5 -3
- package/build/src/dispatch/index.js +30 -21
- package/build/src/duration.d.ts +10 -0
- package/build/src/duration.js +22 -0
- package/build/src/git/admission.d.ts +2 -2
- package/build/src/git/admission.js +33 -23
- package/build/src/git/hooks.d.ts +15 -0
- package/build/src/git/hooks.js +70 -18
- package/build/src/git/identity.d.ts +5 -1
- package/build/src/git/identity.js +23 -4
- package/build/src/git/integration.d.ts +48 -0
- package/build/src/git/integration.js +250 -0
- package/build/src/git/observe.d.ts +29 -15
- package/build/src/git/observe.js +185 -76
- package/build/src/git/read-observation.d.ts +41 -0
- package/build/src/git/read-observation.js +361 -0
- package/build/src/git/reconcile.d.ts +17 -5
- package/build/src/git/reconcile.js +305 -109
- package/build/src/git/repository.d.ts +41 -18
- package/build/src/git/repository.js +220 -114
- package/build/src/git/scratch.d.ts +17 -0
- package/build/src/git/scratch.js +73 -0
- package/build/src/git/target-placement.d.ts +92 -0
- package/build/src/git/target-placement.js +375 -0
- package/build/src/git/tender.d.ts +49 -0
- package/build/src/git/tender.js +63 -0
- package/build/src/git/terminal-seal.d.ts +24 -0
- package/build/src/git/terminal-seal.js +89 -0
- package/build/src/git/tree.d.ts +2 -2
- package/build/src/git/tree.js +4 -0
- package/build/src/git/workspace.d.ts +53 -0
- package/build/src/git/workspace.js +139 -0
- package/build/src/identity/selector.d.ts +6 -0
- package/build/src/identity/selector.js +19 -0
- package/build/src/index.d.ts +4 -2
- package/build/src/index.js +2 -1
- package/build/src/kanshi/index.d.ts +2 -2
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +7 -3
- package/build/src/kanshi/read.js +245 -45
- package/build/src/kanshi/report.d.ts +81 -6
- package/build/src/kanshi/select.d.ts +5 -0
- package/build/src/kanshi/select.js +33 -1
- package/build/src/library/address.d.ts +57 -0
- package/build/src/library/address.js +165 -0
- package/build/src/library/akuma-creation.d.ts +16 -7
- package/build/src/library/akuma-creation.js +96 -22
- package/build/src/library/audit.d.ts +18 -0
- package/build/src/library/audit.js +44 -0
- package/build/src/library/bind.d.ts +21 -0
- package/build/src/library/bind.js +56 -0
- package/build/src/library/catalog.d.ts +58 -0
- package/build/src/library/catalog.js +69 -0
- package/build/src/library/configuration.d.ts +6 -15
- package/build/src/library/configuration.js +14 -17
- package/build/src/library/contract.d.ts +23 -49
- package/build/src/library/contract.js +171 -185
- package/build/src/library/delivery.d.ts +24 -0
- package/build/src/library/delivery.js +21 -0
- package/build/src/library/fleet.d.ts +65 -0
- package/build/src/library/fleet.js +153 -0
- package/build/src/library/input.d.ts +3 -0
- package/build/src/library/input.js +19 -0
- package/build/src/library/keiyaku.d.ts +18 -3
- package/build/src/library/keiyaku.js +12 -1
- package/build/src/library/mutation.d.ts +39 -0
- package/build/src/library/mutation.js +37 -0
- package/build/src/library/reconcile.d.ts +29 -0
- package/build/src/library/reconcile.js +179 -0
- package/build/src/library/refusal.d.ts +21 -0
- package/build/src/library/refusal.js +29 -0
- package/build/src/library/region.d.ts +14 -1
- package/build/src/library/region.js +18 -4
- package/build/src/library/repo.d.ts +4 -13
- package/build/src/library/repo.js +14 -24
- package/build/src/protocol/attempt.d.ts +16 -3
- package/build/src/protocol/attempt.js +41 -10
- package/build/src/protocol/bind.d.ts +9 -2
- package/build/src/protocol/bind.js +48 -40
- package/build/src/protocol/intent.d.ts +57 -20
- package/build/src/protocol/intent.js +55 -79
- package/build/src/protocol/operations.d.ts +152 -43
- package/build/src/protocol/operations.js +482 -166
- package/build/src/protocol/outcome.d.ts +14 -3
- package/build/src/protocol/outcome.js +11 -3
- package/build/src/protocol/placement.d.ts +41 -0
- package/build/src/protocol/placement.js +147 -0
- package/build/src/protocol/read/documents.d.ts +2 -2
- package/build/src/protocol/read/documents.js +4 -4
- package/build/src/protocol/read/status.d.ts +18 -5
- package/build/src/protocol/read/status.js +73 -13
- package/build/src/protocol/run.d.ts +49 -7
- package/build/src/protocol/run.js +53 -25
- package/build/src/runtime/proc/line-rpc.d.ts +4 -8
- package/build/src/runtime/proc/line-rpc.js +22 -28
- package/build/src/runtime/proc/run.d.ts +23 -21
- package/build/src/runtime/proc/run.js +123 -89
- package/build/src/runtime/proc/stdio.d.ts +18 -0
- package/build/src/runtime/proc/stdio.js +58 -0
- package/build/src/settings.d.ts +7 -1
- package/build/src/settings.js +32 -17
- package/build/src/settlement/fence.d.ts +5 -0
- package/build/src/settlement/fence.js +14 -0
- package/build/src/settlement/holder.d.ts +35 -4
- package/build/src/settlement/holder.js +127 -28
- package/build/src/settlement/settle.d.ts +9 -1
- package/build/src/settlement/settle.js +74 -37
- package/build/src/task/board.d.ts +23 -5
- package/build/src/task/board.js +17 -10
- package/build/src/task/compose.d.ts +2 -2
- package/build/src/task/compose.js +18 -10
- package/build/src/task/context.d.ts +3 -3
- package/build/src/task/context.js +15 -20
- package/build/src/task/document.d.ts +2 -1
- package/build/src/task/document.js +15 -5
- package/build/src/task/index.d.ts +27 -15
- package/build/src/task/index.js +57 -35
- package/build/src/task/operations.d.ts +38 -13
- package/build/src/task/operations.js +80 -46
- package/build/src/task/query.d.ts +67 -0
- package/build/src/task/query.js +279 -0
- package/build/src/task/store.d.ts +5 -7
- package/build/src/task/store.js +43 -28
- package/build/src/verification/declaration.d.ts +1 -0
- package/build/src/verification/execution.d.ts +51 -0
- package/build/src/verification/execution.js +108 -0
- package/build/src/workspace-place.d.ts +41 -0
- package/build/src/workspace-place.js +386 -0
- package/build/src/world.d.ts +24 -0
- package/build/src/world.js +136 -0
- package/package.json +8 -4
- package/build/src/akuma/activity.d.ts +0 -66
- package/build/src/akuma/activity.js +0 -139
- package/build/src/akuma/providers/claude.js +0 -305
- package/build/src/context-root.d.ts +0 -4
- package/build/src/context-root.js +0 -15
- package/build/src/git/delivery.d.ts +0 -20
- package/build/src/git/delivery.js +0 -109
- package/build/src/git/verification.d.ts +0 -14
- package/build/src/git/verification.js +0 -56
- package/build/src/protocol/read/audit.d.ts +0 -25
- package/build/src/protocol/read/audit.js +0 -39
- package/build/src/verification/producer.d.ts +0 -23
- package/build/src/verification/producer.js +0 -54
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { decodeActivityRow, decodeCallRow, decodeTurnRow, } from "./rows.js";
|
|
2
|
+
import { decodeTellAtSequence, pendingTellProtectionSql, pendingTellSequencesSql } from "./tells.js";
|
|
3
|
+
export function pruneActivityFacts(database, limit) {
|
|
4
|
+
const count = database.prepare("SELECT COUNT(*) AS count FROM timeline").get();
|
|
5
|
+
if (count.count <= limit + 500)
|
|
6
|
+
return;
|
|
7
|
+
const cutoff = database.prepare(`SELECT sequence FROM timeline ORDER BY sequence DESC LIMIT 1 OFFSET ?`)
|
|
8
|
+
.get(limit - 1);
|
|
9
|
+
if (cutoff === undefined)
|
|
10
|
+
return;
|
|
11
|
+
database.prepare(`WITH protected_turns(sequence) AS (
|
|
12
|
+
SELECT sequence FROM turns WHERE end_sequence IS NULL
|
|
13
|
+
UNION SELECT turn_sequence FROM calls WHERE sequence >= ?
|
|
14
|
+
UNION SELECT turn_sequence FROM activity WHERE sequence >= ?
|
|
15
|
+
UNION SELECT sequence FROM turns WHERE end_sequence >= ?
|
|
16
|
+
UNION ${pendingTellProtectionSql}
|
|
17
|
+
), protected(sequence) AS (
|
|
18
|
+
SELECT sequence FROM protected_turns
|
|
19
|
+
UNION SELECT sequence FROM calls WHERE turn_sequence IN (SELECT sequence FROM protected_turns)
|
|
20
|
+
UNION SELECT end_sequence FROM turns WHERE sequence IN (SELECT sequence FROM protected_turns) AND end_sequence IS NOT NULL
|
|
21
|
+
UNION ${pendingTellSequencesSql}
|
|
22
|
+
)
|
|
23
|
+
DELETE FROM timeline WHERE sequence < ? AND sequence NOT IN protected`)
|
|
24
|
+
.run(cutoff.sequence, cutoff.sequence, cutoff.sequence, cutoff.sequence);
|
|
25
|
+
}
|
|
26
|
+
function turn(database, sequence) {
|
|
27
|
+
const row = database.prepare(`SELECT sequence, body_sequence, started_at, end_sequence, outcome,
|
|
28
|
+
history_id, session_json, answer, diagnostic, completed_at FROM turns WHERE sequence = ?`)
|
|
29
|
+
.get(sequence);
|
|
30
|
+
if (row === undefined)
|
|
31
|
+
throw new Error(`Akuma timeline references missing Turn ${sequence}`);
|
|
32
|
+
return decodeTurnRow(row);
|
|
33
|
+
}
|
|
34
|
+
function turnStart(database, sequence) {
|
|
35
|
+
const row = database.prepare("SELECT sequence, body_sequence, started_at FROM turns WHERE sequence = ?")
|
|
36
|
+
.get(sequence);
|
|
37
|
+
if (row === undefined)
|
|
38
|
+
throw new Error(`Akuma timeline references missing Turn ${sequence}`);
|
|
39
|
+
return { kind: "turn-start", sequence: row.sequence, bodySequence: row.body_sequence, startedAt: row.started_at };
|
|
40
|
+
}
|
|
41
|
+
function decodeTimelineRow(database, row) {
|
|
42
|
+
if (row.kind === "turn-start")
|
|
43
|
+
return turnStart(database, row.sequence);
|
|
44
|
+
if (row.kind === "turn-end") {
|
|
45
|
+
const source = database.prepare("SELECT sequence FROM turns WHERE end_sequence = ?").get(row.sequence);
|
|
46
|
+
const fact = source === undefined ? undefined : turn(database, source.sequence).end;
|
|
47
|
+
if (fact === undefined)
|
|
48
|
+
throw new Error(`Akuma timeline references missing Turn end ${row.sequence}`);
|
|
49
|
+
return fact;
|
|
50
|
+
}
|
|
51
|
+
if (row.kind === "call") {
|
|
52
|
+
const value = database.prepare("SELECT sequence, turn_sequence, body, at FROM calls WHERE sequence = ?")
|
|
53
|
+
.get(row.sequence);
|
|
54
|
+
if (value === undefined)
|
|
55
|
+
throw new Error(`Akuma timeline references missing call ${row.sequence}`);
|
|
56
|
+
return decodeCallRow(value);
|
|
57
|
+
}
|
|
58
|
+
if (row.kind === "activity") {
|
|
59
|
+
const value = database.prepare("SELECT sequence, turn_sequence, event_json, at FROM activity WHERE sequence = ?")
|
|
60
|
+
.get(row.sequence);
|
|
61
|
+
if (value === undefined)
|
|
62
|
+
throw new Error(`Akuma timeline references missing activity ${row.sequence}`);
|
|
63
|
+
return decodeActivityRow(value);
|
|
64
|
+
}
|
|
65
|
+
return decodeTellAtSequence(database, row.sequence);
|
|
66
|
+
}
|
|
67
|
+
export function activityFactSlice(database, input) {
|
|
68
|
+
const bounds = database.prepare("SELECT MIN(sequence) AS lowest, MAX(sequence) AS highest FROM timeline")
|
|
69
|
+
.get();
|
|
70
|
+
let rows;
|
|
71
|
+
if (input.before !== undefined) {
|
|
72
|
+
rows = database.prepare(`SELECT * FROM (
|
|
73
|
+
SELECT sequence, kind FROM timeline WHERE sequence < ? ORDER BY sequence DESC LIMIT ?
|
|
74
|
+
) ORDER BY sequence`).all(input.before, input.limit);
|
|
75
|
+
}
|
|
76
|
+
else if (input.since !== undefined) {
|
|
77
|
+
rows = database.prepare(`SELECT sequence, kind FROM timeline WHERE sequence > ? ORDER BY sequence LIMIT ?`)
|
|
78
|
+
.all(input.since, input.limit);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
rows = database.prepare(`SELECT * FROM (
|
|
82
|
+
SELECT sequence, kind FROM timeline ORDER BY sequence DESC LIMIT ?
|
|
83
|
+
) ORDER BY sequence`).all(input.limit);
|
|
84
|
+
}
|
|
85
|
+
return { rows: rows.map((row) => decodeTimelineRow(database, row)), lowestRetained: bounds.lowest, highest: bounds.highest };
|
|
86
|
+
}
|
|
@@ -35,12 +35,12 @@ export declare function akuIdFromDirectoryName(name: string): Readonly<{
|
|
|
35
35
|
archetype: string;
|
|
36
36
|
suffix: string;
|
|
37
37
|
}>;
|
|
38
|
-
export declare function ensureAkumaRunRoot(worldRoot: string): string
|
|
38
|
+
export declare function ensureAkumaRunRoot(worldRoot: string): Promise<string>;
|
|
39
39
|
export declare function allocateAkumaDirectory(input: Readonly<{
|
|
40
40
|
worldRoot: string;
|
|
41
41
|
archetype: string;
|
|
42
42
|
draw?: () => string;
|
|
43
|
-
}>): AllocatedAkuma
|
|
43
|
+
}>): Promise<AllocatedAkuma>;
|
|
44
44
|
export declare function pathsForAkuId(worldRoot: string, id: AkuId): AkumaPaths;
|
|
45
45
|
export declare function worldRootForAkumaPaths(paths: AkumaPaths): string;
|
|
46
46
|
export {};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { identityCoordinate, identitySegments } from "../identity/coordinates.js";
|
|
5
5
|
import { normalizeIdentityStem } from "../identity/normalize.js";
|
|
6
6
|
const HEX8 = /^[0-9a-f]{8}$/u;
|
|
7
7
|
export function archetypeName(value) {
|
|
8
8
|
if (value.length === 0 || normalizeIdentityStem({ source: value }) !== value) {
|
|
9
|
-
throw new TypeError("Akuma
|
|
9
|
+
throw new TypeError("Akuma name must be one normalized human identity segment");
|
|
10
10
|
}
|
|
11
11
|
return value;
|
|
12
12
|
}
|
|
@@ -24,7 +24,7 @@ export function akuId(input) {
|
|
|
24
24
|
export function parseAkuId(value) {
|
|
25
25
|
const segments = identitySegments({ family: "aku", value });
|
|
26
26
|
if (segments.length !== 2)
|
|
27
|
-
throw new TypeError("Akuma identity must be aku/<
|
|
27
|
+
throw new TypeError("Akuma identity must be aku/<akuma>/<hex8>");
|
|
28
28
|
const archetype = archetypeName(segments[0]);
|
|
29
29
|
const suffix = suffixSegment(segments[1]);
|
|
30
30
|
return { id: akuId({ archetype, suffix }), archetype, suffix };
|
|
@@ -48,11 +48,11 @@ export function akuIdFromDirectoryName(name) {
|
|
|
48
48
|
const suffix = name.slice(-8);
|
|
49
49
|
return { id: akuId({ archetype, suffix }), archetype, suffix };
|
|
50
50
|
}
|
|
51
|
-
export function ensureAkumaRunRoot(worldRoot) {
|
|
51
|
+
export async function ensureAkumaRunRoot(worldRoot) {
|
|
52
52
|
const runRoot = akumaRunRoot(worldRoot);
|
|
53
|
-
|
|
53
|
+
await mkdir(runRoot, { recursive: true });
|
|
54
54
|
try {
|
|
55
|
-
|
|
55
|
+
await writeFile(join(runRoot, ".gitignore"), "*\n", { flag: "wx" });
|
|
56
56
|
}
|
|
57
57
|
catch (error) {
|
|
58
58
|
if (error.code !== "EEXIST")
|
|
@@ -60,14 +60,14 @@ export function ensureAkumaRunRoot(worldRoot) {
|
|
|
60
60
|
}
|
|
61
61
|
return runRoot;
|
|
62
62
|
}
|
|
63
|
-
export function allocateAkumaDirectory(input) {
|
|
63
|
+
export async function allocateAkumaDirectory(input) {
|
|
64
64
|
const archetype = archetypeName(input.archetype);
|
|
65
|
-
const runRoot = ensureAkumaRunRoot(input.worldRoot);
|
|
65
|
+
const runRoot = await ensureAkumaRunRoot(input.worldRoot);
|
|
66
66
|
for (;;) {
|
|
67
67
|
const suffix = suffixSegment(input.draw?.() ?? randomBytes(4).toString("hex"));
|
|
68
68
|
const paths = akumaPaths({ runRoot, archetype, suffix });
|
|
69
69
|
try {
|
|
70
|
-
|
|
70
|
+
await mkdir(paths.directory);
|
|
71
71
|
return { id: akuId({ archetype, suffix }), archetype, suffix, paths };
|
|
72
72
|
}
|
|
73
73
|
catch (error) {
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
import { type AkuId } from "./identity.js";
|
|
2
|
+
import type { WorldRoot } from "../world.js";
|
|
1
3
|
export { Akuma, AkumaHandle, AkumaNotBornError } from "./akuma.js";
|
|
2
|
-
export {
|
|
4
|
+
export type { WorldRoot } from "../world.js";
|
|
5
|
+
export declare function probeBornAkuma(worldPath: WorldRoot, id: AkuId): Promise<boolean>;
|
|
6
|
+
export { AkumaArchetypeError, listArchetypeDefinitions, listArchetypes } from "./archetype.js";
|
|
7
|
+
export type { ArchetypeCatalogRow } from "./archetype.js";
|
|
3
8
|
export { AkumaBodyRequestError } from "./requests.js";
|
|
4
|
-
export type { AkumaList, AkumaListRow, AkumaStatus, ActivityHistory, ActivityRow, ActivitySnapshot, ForkReceipt, InterruptReceipt,
|
|
9
|
+
export type { AkumaList, AkumaListInput, AkumaListRow, AkumaStatus, ActivityHistory, ActivityRow, ActivitySnapshot, ActivitySnapshotEntry, ForkReceipt, InterruptReceipt, TellResult, UnbornAkumaListRow, } from "./akuma.js";
|
|
10
|
+
export type { ActiveToolRow, ClosedTurn, ClosedTurnRow, CompletedToolRow, HistoryCursor, HistoryPage, IdleSnapshotRow, OpenSnapshotRow, OpenTurn, OpenTurnRow, OutcomeRow, RetainedWindow, Snapshot, SnapshotRow, TellRow, TurnLedger, TurnOutcome, TurnStartRow, UnsettledToolRow, } from "./akuma.js";
|
|
5
11
|
export type { AgentEvent, ToolCall, ToolEvent, ToolResult } from "./provider.js";
|
|
6
12
|
export type { AkuId } from "./identity.js";
|
|
7
|
-
export type { Confinement, KillEvidence,
|
|
13
|
+
export type { Confinement, KillEvidence, ResumeCoordinate, TurnFact, } from "./heart/index.js";
|
|
14
|
+
export type { ProviderOptions, ReadonlyRestraint } from "./provider-recipe.js";
|
package/build/src/akuma/index.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { readSoul } from "./heart/index.js";
|
|
2
|
+
import { pathsForAkuId } from "./identity.js";
|
|
1
3
|
export { Akuma, AkumaHandle, AkumaNotBornError } from "./akuma.js";
|
|
2
|
-
export
|
|
4
|
+
export async function probeBornAkuma(worldPath, id) {
|
|
5
|
+
const soul = await readSoul(pathsForAkuId(worldPath, id));
|
|
6
|
+
return soul !== null;
|
|
7
|
+
}
|
|
8
|
+
export { AkumaArchetypeError, listArchetypeDefinitions, listArchetypes } from "./archetype.js";
|
|
3
9
|
export { AkumaBodyRequestError } from "./requests.js";
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { type ToolCall, type ToolResult } from "./provider.js";
|
|
2
|
+
import type { TellDelivery, TellFact, TimelineFact, TurnEndFact } from "./heart/index.js";
|
|
3
|
+
export type TurnOutcome = TurnEndFact["outcome"];
|
|
4
|
+
export type TurnStartRow = Readonly<{
|
|
5
|
+
kind: "turn";
|
|
6
|
+
sequence: number;
|
|
7
|
+
turnSequence: number;
|
|
8
|
+
bodySequence: number;
|
|
9
|
+
at: string;
|
|
10
|
+
}>;
|
|
11
|
+
type CallRow = Readonly<{
|
|
12
|
+
kind: "call";
|
|
13
|
+
sequence: number;
|
|
14
|
+
turnSequence: number;
|
|
15
|
+
at: string;
|
|
16
|
+
text: string;
|
|
17
|
+
}>;
|
|
18
|
+
type SaidRow = Readonly<{
|
|
19
|
+
kind: "said";
|
|
20
|
+
sequence: number;
|
|
21
|
+
turnSequence: number;
|
|
22
|
+
at: string;
|
|
23
|
+
text: string;
|
|
24
|
+
truncated?: true;
|
|
25
|
+
}>;
|
|
26
|
+
type ThoughtRow = Readonly<{
|
|
27
|
+
kind: "thought";
|
|
28
|
+
sequence: number;
|
|
29
|
+
turnSequence: number;
|
|
30
|
+
at: string;
|
|
31
|
+
text: string;
|
|
32
|
+
truncated?: true;
|
|
33
|
+
}>;
|
|
34
|
+
type NoteRow = Readonly<{
|
|
35
|
+
kind: "note";
|
|
36
|
+
sequence: number;
|
|
37
|
+
turnSequence: number;
|
|
38
|
+
at: string;
|
|
39
|
+
text: string;
|
|
40
|
+
truncated?: true;
|
|
41
|
+
}>;
|
|
42
|
+
type TurnNarrationRow = CallRow | SaidRow | ThoughtRow | NoteRow;
|
|
43
|
+
export type TellRow = Readonly<{
|
|
44
|
+
kind: "tell";
|
|
45
|
+
sequence: number;
|
|
46
|
+
at: string;
|
|
47
|
+
tellId: string;
|
|
48
|
+
text: string;
|
|
49
|
+
state: TellFact["state"];
|
|
50
|
+
deliveries: readonly TellDelivery[];
|
|
51
|
+
}>;
|
|
52
|
+
export type OutcomeRow = Readonly<{
|
|
53
|
+
kind: "outcome";
|
|
54
|
+
sequence: number;
|
|
55
|
+
turnSequence: number;
|
|
56
|
+
at: string;
|
|
57
|
+
outcome: TurnOutcome;
|
|
58
|
+
}>;
|
|
59
|
+
export type ActiveToolRow = Readonly<{
|
|
60
|
+
kind: "tool";
|
|
61
|
+
sequence: number;
|
|
62
|
+
turnSequence: number;
|
|
63
|
+
at: string;
|
|
64
|
+
name: string;
|
|
65
|
+
call: ToolCall;
|
|
66
|
+
state: "active";
|
|
67
|
+
truncated?: true;
|
|
68
|
+
}>;
|
|
69
|
+
export type CompletedToolRow = Readonly<{
|
|
70
|
+
kind: "tool";
|
|
71
|
+
sequence: number;
|
|
72
|
+
turnSequence: number;
|
|
73
|
+
at: string;
|
|
74
|
+
completedAt?: string;
|
|
75
|
+
durationMs?: number;
|
|
76
|
+
name: string;
|
|
77
|
+
call: ToolCall;
|
|
78
|
+
state: ToolResult;
|
|
79
|
+
truncated?: true;
|
|
80
|
+
}>;
|
|
81
|
+
export type UnsettledToolRow = Readonly<{
|
|
82
|
+
kind: "tool";
|
|
83
|
+
sequence: number;
|
|
84
|
+
turnSequence: number;
|
|
85
|
+
at: string;
|
|
86
|
+
name: string;
|
|
87
|
+
call: ToolCall;
|
|
88
|
+
state: "unsettled";
|
|
89
|
+
truncated?: true;
|
|
90
|
+
}>;
|
|
91
|
+
export type OpenTurnRow = TurnNarrationRow | ActiveToolRow | CompletedToolRow;
|
|
92
|
+
export type ClosedTurnRow = TurnNarrationRow | UnsettledToolRow | CompletedToolRow;
|
|
93
|
+
export type OpenTurn = Readonly<{
|
|
94
|
+
kind: "open";
|
|
95
|
+
turn: TurnStartRow;
|
|
96
|
+
rows: readonly OpenTurnRow[];
|
|
97
|
+
}>;
|
|
98
|
+
export type ClosedTurn = Readonly<{
|
|
99
|
+
kind: "closed";
|
|
100
|
+
turn: TurnStartRow;
|
|
101
|
+
rows: readonly ClosedTurnRow[];
|
|
102
|
+
outcome: OutcomeRow;
|
|
103
|
+
}>;
|
|
104
|
+
export type ProjectedTurn = OpenTurn | ClosedTurn;
|
|
105
|
+
export type ActivityRow = TurnStartRow | OpenTurnRow | ClosedTurnRow | TellRow | OutcomeRow;
|
|
106
|
+
type SnapshotFactRow = TurnNarrationRow | TellRow;
|
|
107
|
+
export type OpenSnapshotRow = SnapshotFactRow | ActiveToolRow | CompletedToolRow;
|
|
108
|
+
export type IdleSnapshotRow = SnapshotFactRow | CompletedToolRow;
|
|
109
|
+
export type SnapshotRow = OpenSnapshotRow | IdleSnapshotRow;
|
|
110
|
+
export type ActivitySnapshotEntry<Row extends SnapshotRow = SnapshotRow> = Readonly<{
|
|
111
|
+
kind: "row";
|
|
112
|
+
row: Row;
|
|
113
|
+
}> | Readonly<{
|
|
114
|
+
kind: "gap";
|
|
115
|
+
count: number;
|
|
116
|
+
}>;
|
|
117
|
+
export type Snapshot = Readonly<{
|
|
118
|
+
kind: "unborn";
|
|
119
|
+
entries: readonly [];
|
|
120
|
+
omitted: 0;
|
|
121
|
+
}> | Readonly<{
|
|
122
|
+
kind: "open";
|
|
123
|
+
turn: TurnStartRow;
|
|
124
|
+
entries: readonly ActivitySnapshotEntry<OpenSnapshotRow>[];
|
|
125
|
+
omitted: number;
|
|
126
|
+
}> | Readonly<{
|
|
127
|
+
kind: "idle";
|
|
128
|
+
outcome?: OutcomeRow;
|
|
129
|
+
entries: readonly ActivitySnapshotEntry<IdleSnapshotRow>[];
|
|
130
|
+
omitted: number;
|
|
131
|
+
}>;
|
|
132
|
+
export type ActivitySnapshot = Snapshot;
|
|
133
|
+
export type ActivityHistory = Readonly<{
|
|
134
|
+
rows: readonly ActivityRow[];
|
|
135
|
+
omitted: number;
|
|
136
|
+
hasEarlier: boolean;
|
|
137
|
+
hasLater: boolean;
|
|
138
|
+
historyLost: boolean;
|
|
139
|
+
lowestRetained: number | null;
|
|
140
|
+
highest: number | null;
|
|
141
|
+
}>;
|
|
142
|
+
export type HistoryPage = ActivityHistory;
|
|
143
|
+
export type HistoryCursor = Readonly<{
|
|
144
|
+
before?: number;
|
|
145
|
+
since?: number;
|
|
146
|
+
limit: number;
|
|
147
|
+
}>;
|
|
148
|
+
export type RetainedWindow = Readonly<{
|
|
149
|
+
lowestRetained: number | null;
|
|
150
|
+
highest: number | null;
|
|
151
|
+
}>;
|
|
152
|
+
export type TurnLedger = Readonly<{
|
|
153
|
+
rows: readonly ActivityRow[];
|
|
154
|
+
turns: readonly ProjectedTurn[];
|
|
155
|
+
retained: RetainedWindow;
|
|
156
|
+
openTurn?: OpenTurn;
|
|
157
|
+
latestOutcome?: OutcomeRow;
|
|
158
|
+
}>;
|
|
159
|
+
/** Fold the retained fact timeline into Turn-owned rows without inventing provider facts. */
|
|
160
|
+
export declare function projectTurns(facts: readonly TimelineFact[], retained?: RetainedWindow): TurnLedger;
|
|
161
|
+
/** Split one nonnegative ordinary allowance into newest tail first, then pre-tail voice. */
|
|
162
|
+
export declare function ordinarySnapshotBudget(ordinaryBudget: number): Readonly<{
|
|
163
|
+
tail: number;
|
|
164
|
+
voice: number;
|
|
165
|
+
}>;
|
|
166
|
+
/** Count selected ordinary rows; active tools and pending tells stay outside this total. */
|
|
167
|
+
export declare function ordinarySelectedCount(snapshot: ActivitySnapshot): number;
|
|
168
|
+
/** Select one current Turn, one latest outcome, or no focus; pending tells stay actionable. */
|
|
169
|
+
export declare function selectSnapshot(ledger: TurnLedger, budget?: Readonly<{
|
|
170
|
+
tail: number;
|
|
171
|
+
voice?: number;
|
|
172
|
+
}>): ActivitySnapshot;
|
|
173
|
+
/** Apply the one snapshot policy used by every public observation consumer. */
|
|
174
|
+
export declare function selectActivitySnapshot(facts: readonly TimelineFact[]): ActivitySnapshot;
|
|
175
|
+
export declare function selectHistory(ledger: TurnLedger, cursor: HistoryCursor): HistoryPage;
|
|
176
|
+
export {};
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { decodeAgentEvent } from "./provider.js";
|
|
2
|
+
const DEFAULT_TAIL = 3;
|
|
3
|
+
const DEFAULT_VOICE = 3;
|
|
4
|
+
function duration(startedAt, completedAt) {
|
|
5
|
+
const start = Date.parse(startedAt);
|
|
6
|
+
const end = Date.parse(completedAt);
|
|
7
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || end < start)
|
|
8
|
+
return undefined;
|
|
9
|
+
return end - start;
|
|
10
|
+
}
|
|
11
|
+
function toolKey(turnSequence, id) {
|
|
12
|
+
return `${turnSequence}:${id}`;
|
|
13
|
+
}
|
|
14
|
+
function narrationRow(fact, event) {
|
|
15
|
+
if (event.type === "assistant") {
|
|
16
|
+
return { kind: "said", sequence: fact.sequence, turnSequence: fact.turnSequence, at: fact.at, text: event.text,
|
|
17
|
+
...(event.truncated === true ? { truncated: true } : {}) };
|
|
18
|
+
}
|
|
19
|
+
if (event.type === "thought" || event.type === "note") {
|
|
20
|
+
return { kind: event.type, sequence: fact.sequence, turnSequence: fact.turnSequence, at: fact.at, text: event.text,
|
|
21
|
+
...(event.truncated === true ? { truncated: true } : {}) };
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
function projectToolEvent(rows, running, fact, event, phase) {
|
|
26
|
+
const key = toolKey(fact.turnSequence, event.id);
|
|
27
|
+
if (event.phase === "started") {
|
|
28
|
+
running.set(key, rows.length);
|
|
29
|
+
rows.push({
|
|
30
|
+
kind: "tool",
|
|
31
|
+
sequence: fact.sequence,
|
|
32
|
+
turnSequence: fact.turnSequence,
|
|
33
|
+
at: fact.at,
|
|
34
|
+
name: event.name,
|
|
35
|
+
call: event.call,
|
|
36
|
+
state: phase === "open" ? "active" : "unsettled",
|
|
37
|
+
...(event.truncated === true ? { truncated: true } : {}),
|
|
38
|
+
});
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const index = running.get(key);
|
|
42
|
+
const started = index === undefined ? undefined : rows[index];
|
|
43
|
+
if (started?.kind !== "tool") {
|
|
44
|
+
rows.push({ kind: "tool", sequence: fact.sequence, turnSequence: fact.turnSequence, at: fact.at, name: event.name, call: event.call, state: event.result, ...(event.truncated === true ? { truncated: true } : {}) });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const durationMs = duration(started.at, fact.at);
|
|
48
|
+
rows[index] = {
|
|
49
|
+
kind: "tool",
|
|
50
|
+
sequence: started.sequence,
|
|
51
|
+
turnSequence: fact.turnSequence,
|
|
52
|
+
at: started.at,
|
|
53
|
+
completedAt: fact.at,
|
|
54
|
+
...(durationMs === undefined ? {} : { durationMs }),
|
|
55
|
+
name: event.name,
|
|
56
|
+
call: event.call,
|
|
57
|
+
state: event.result,
|
|
58
|
+
...(started.truncated === true || event.truncated === true ? { truncated: true } : {}),
|
|
59
|
+
};
|
|
60
|
+
running.delete(key);
|
|
61
|
+
}
|
|
62
|
+
function projectActivityEvent(state, fact) {
|
|
63
|
+
const event = decodeAgentEvent(fact.event);
|
|
64
|
+
const narration = narrationRow(fact, event);
|
|
65
|
+
if (narration !== null) {
|
|
66
|
+
const turn = state.turnsBySequence.get(fact.turnSequence);
|
|
67
|
+
if (turn === undefined)
|
|
68
|
+
state.orphanRows.push(narration);
|
|
69
|
+
else
|
|
70
|
+
turn.rows.push(narration);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (event.type !== "tool")
|
|
74
|
+
return;
|
|
75
|
+
const turn = state.turnsBySequence.get(fact.turnSequence);
|
|
76
|
+
if (turn === undefined)
|
|
77
|
+
projectToolEvent(state.orphanRows, state.orphanRunning, fact, event, "closed");
|
|
78
|
+
else
|
|
79
|
+
projectToolEvent(turn.rows, turn.running, fact, event, turn.phase);
|
|
80
|
+
}
|
|
81
|
+
function demoteActive(row) {
|
|
82
|
+
if (row.kind !== "tool" || row.state !== "active")
|
|
83
|
+
return row;
|
|
84
|
+
return { ...row, state: "unsettled" };
|
|
85
|
+
}
|
|
86
|
+
function foldOutcomeVoice(rows, outcome) {
|
|
87
|
+
if (outcome?.outcome.kind !== "answered")
|
|
88
|
+
return rows;
|
|
89
|
+
const finalVoice = rows.findLast((row) => row.kind === "said");
|
|
90
|
+
return finalVoice?.text === outcome.outcome.answer && finalVoice.truncated !== true
|
|
91
|
+
? rows.filter((row) => row !== finalVoice)
|
|
92
|
+
: rows;
|
|
93
|
+
}
|
|
94
|
+
function finishTurn(turn) {
|
|
95
|
+
const rows = foldOutcomeVoice(turn.rows, turn.outcome);
|
|
96
|
+
if (turn.phase === "closed" && turn.outcome !== undefined) {
|
|
97
|
+
return { kind: "closed", turn: turn.turn, rows: rows.map(demoteActive), outcome: turn.outcome };
|
|
98
|
+
}
|
|
99
|
+
if (rows.some((row) => row.kind === "tool" && row.state === "unsettled")) {
|
|
100
|
+
throw new Error(`open Turn ${turn.turn.turnSequence} contains an unsettled tool`);
|
|
101
|
+
}
|
|
102
|
+
return { kind: "open", turn: turn.turn, rows: rows };
|
|
103
|
+
}
|
|
104
|
+
/** Fold the retained fact timeline into Turn-owned rows without inventing provider facts. */
|
|
105
|
+
export function projectTurns(facts, retained = {
|
|
106
|
+
lowestRetained: facts[0]?.sequence ?? null,
|
|
107
|
+
highest: facts.at(-1)?.sequence ?? null,
|
|
108
|
+
}) {
|
|
109
|
+
const state = {
|
|
110
|
+
turns: [],
|
|
111
|
+
turnsBySequence: new Map(),
|
|
112
|
+
tells: [],
|
|
113
|
+
orphanRows: [],
|
|
114
|
+
orphanOutcomes: [],
|
|
115
|
+
orphanRunning: new Map(),
|
|
116
|
+
};
|
|
117
|
+
for (const fact of facts) {
|
|
118
|
+
if (fact.kind === "turn-start") {
|
|
119
|
+
const turn = { kind: "turn", sequence: fact.sequence, turnSequence: fact.sequence, bodySequence: fact.bodySequence, at: fact.startedAt };
|
|
120
|
+
const projected = { phase: "open", turn, rows: [], running: new Map() };
|
|
121
|
+
state.turns.push(projected);
|
|
122
|
+
state.turnsBySequence.set(turn.turnSequence, projected);
|
|
123
|
+
}
|
|
124
|
+
else if (fact.kind === "turn-end") {
|
|
125
|
+
const outcome = { kind: "outcome", sequence: fact.sequence, turnSequence: fact.turnSequence, at: fact.completedAt, outcome: fact.outcome };
|
|
126
|
+
const turn = state.turnsBySequence.get(fact.turnSequence);
|
|
127
|
+
if (turn === undefined)
|
|
128
|
+
state.orphanOutcomes.push(outcome);
|
|
129
|
+
else {
|
|
130
|
+
turn.phase = "closed";
|
|
131
|
+
turn.rows = turn.rows.map(demoteActive);
|
|
132
|
+
turn.outcome = outcome;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else if (fact.kind === "call") {
|
|
136
|
+
const row = { kind: "call", sequence: fact.sequence, turnSequence: fact.turnSequence, at: fact.at, text: fact.body };
|
|
137
|
+
const turn = state.turnsBySequence.get(fact.turnSequence);
|
|
138
|
+
if (turn === undefined)
|
|
139
|
+
state.orphanRows.push(row);
|
|
140
|
+
else
|
|
141
|
+
turn.rows.push(row);
|
|
142
|
+
}
|
|
143
|
+
else if (fact.kind === "tell") {
|
|
144
|
+
state.tells.push({ kind: "tell", sequence: fact.sequence, at: fact.recordedAt, tellId: fact.id, text: fact.body, state: fact.state, deliveries: fact.deliveries });
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
projectActivityEvent(state, fact);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const turns = state.turns.map(finishTurn);
|
|
151
|
+
const rows = [
|
|
152
|
+
...turns.flatMap((turn) => [turn.turn, ...turn.rows, ...(turn.kind === "closed" ? [turn.outcome] : [])]),
|
|
153
|
+
...state.tells,
|
|
154
|
+
...state.orphanRows,
|
|
155
|
+
...state.orphanOutcomes,
|
|
156
|
+
].sort((left, right) => left.sequence - right.sequence);
|
|
157
|
+
const frontier = turns.at(-1);
|
|
158
|
+
const openTurn = frontier?.kind === "open" ? frontier : undefined;
|
|
159
|
+
const latestOutcome = rows.findLast((row) => row.kind === "outcome");
|
|
160
|
+
return { rows, turns, retained, ...(openTurn === undefined ? {} : { openTurn }), ...(latestOutcome === undefined ? {} : { latestOutcome }) };
|
|
161
|
+
}
|
|
162
|
+
function entries(rows) {
|
|
163
|
+
return rows.map((row) => ({ kind: "row", row }));
|
|
164
|
+
}
|
|
165
|
+
function openEntries(ledger, window, selected) {
|
|
166
|
+
const windowRows = new Set(window);
|
|
167
|
+
const result = [];
|
|
168
|
+
let hidden = 0;
|
|
169
|
+
const flushGap = () => {
|
|
170
|
+
if (hidden === 0)
|
|
171
|
+
return;
|
|
172
|
+
result.push({ kind: "gap", count: hidden });
|
|
173
|
+
hidden = 0;
|
|
174
|
+
};
|
|
175
|
+
for (const row of ledger.rows) {
|
|
176
|
+
if (windowRows.has(row) && !selected.has(row)) {
|
|
177
|
+
hidden += 1;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (!selected.has(row))
|
|
181
|
+
continue;
|
|
182
|
+
flushGap();
|
|
183
|
+
if (row.kind !== "turn" && row.kind !== "outcome" && !(row.kind === "tool" && row.state === "unsettled")) {
|
|
184
|
+
result.push({ kind: "row", row });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
flushGap();
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
/** Split one nonnegative ordinary allowance into newest tail first, then pre-tail voice. */
|
|
191
|
+
export function ordinarySnapshotBudget(ordinaryBudget) {
|
|
192
|
+
const tail = Math.min(DEFAULT_TAIL, Math.max(0, ordinaryBudget));
|
|
193
|
+
return { tail, voice: Math.min(DEFAULT_VOICE, Math.max(0, ordinaryBudget) - tail) };
|
|
194
|
+
}
|
|
195
|
+
/** Count selected ordinary rows; active tools and pending tells stay outside this total. */
|
|
196
|
+
export function ordinarySelectedCount(snapshot) {
|
|
197
|
+
return snapshot.entries.reduce((count, entry) => {
|
|
198
|
+
if (entry.kind !== "row")
|
|
199
|
+
return count;
|
|
200
|
+
if (entry.row.kind === "tool" && entry.row.state === "active")
|
|
201
|
+
return count;
|
|
202
|
+
if (entry.row.kind === "tell" && entry.row.state === "pending")
|
|
203
|
+
return count;
|
|
204
|
+
return count + 1;
|
|
205
|
+
}, 0);
|
|
206
|
+
}
|
|
207
|
+
/** Select one current Turn, one latest outcome, or no focus; pending tells stay actionable. */
|
|
208
|
+
export function selectSnapshot(ledger, budget = { tail: DEFAULT_TAIL, voice: DEFAULT_VOICE }) {
|
|
209
|
+
if (ledger.turns.length === 0 && !ledger.rows.some((row) => row.kind === "tell"))
|
|
210
|
+
return { kind: "unborn", entries: [], omitted: 0 };
|
|
211
|
+
const pending = ledger.rows.filter((row) => row.kind === "tell" && row.state === "pending");
|
|
212
|
+
if (ledger.openTurn !== undefined) {
|
|
213
|
+
const window = ledger.openTurn.rows;
|
|
214
|
+
const active = window.filter((row) => row.kind === "tool" && row.state === "active");
|
|
215
|
+
const ordinary = window.filter((row) => !(row.kind === "tool" && row.state === "active"));
|
|
216
|
+
const tailCount = Math.max(0, budget.tail);
|
|
217
|
+
const tail = tailCount === 0 ? [] : ordinary.slice(-tailCount);
|
|
218
|
+
const tailSet = new Set(tail);
|
|
219
|
+
const voiceCount = Math.max(0, budget.voice ?? DEFAULT_VOICE);
|
|
220
|
+
const voiceCandidates = ordinary
|
|
221
|
+
.filter((row) => !tailSet.has(row) && (row.kind === "said" || row.kind === "thought"));
|
|
222
|
+
const voice = voiceCount === 0 ? [] : voiceCandidates.slice(-voiceCount);
|
|
223
|
+
const selected = new Set([...tail, ...voice, ...active, ...pending]);
|
|
224
|
+
const omitted = window.filter((row) => !selected.has(row)).length;
|
|
225
|
+
return { kind: "open", turn: ledger.openTurn.turn, entries: openEntries(ledger, window, selected), omitted };
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
kind: "idle",
|
|
229
|
+
...(ledger.latestOutcome === undefined ? {} : { outcome: ledger.latestOutcome }),
|
|
230
|
+
entries: entries(pending),
|
|
231
|
+
omitted: 0,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/** Apply the one snapshot policy used by every public observation consumer. */
|
|
235
|
+
export function selectActivitySnapshot(facts) {
|
|
236
|
+
return selectSnapshot(projectTurns(facts));
|
|
237
|
+
}
|
|
238
|
+
export function selectHistory(ledger, cursor) {
|
|
239
|
+
const eligible = ledger.rows.filter((row) => cursor.before !== undefined
|
|
240
|
+
? row.sequence < cursor.before
|
|
241
|
+
: cursor.since !== undefined ? row.sequence > cursor.since : true);
|
|
242
|
+
const rows = cursor.since !== undefined ? eligible.slice(0, cursor.limit) : eligible.slice(-cursor.limit);
|
|
243
|
+
const omitted = Math.max(0, eligible.length - rows.length);
|
|
244
|
+
const historyLost = cursor.since !== undefined
|
|
245
|
+
? (ledger.rows[0] !== undefined && ledger.rows[0].sequence > cursor.since + 1)
|
|
246
|
+
: (ledger.retained.lowestRetained !== null && ledger.retained.lowestRetained > 1 && omitted === 0);
|
|
247
|
+
return {
|
|
248
|
+
rows,
|
|
249
|
+
omitted,
|
|
250
|
+
hasEarlier: cursor.since === undefined && eligible.length > rows.length,
|
|
251
|
+
hasLater: cursor.since !== undefined && eligible.length > rows.length,
|
|
252
|
+
historyLost,
|
|
253
|
+
lowestRetained: ledger.retained.lowestRetained,
|
|
254
|
+
highest: ledger.retained.highest,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type ProviderOptions = Readonly<{
|
|
2
|
+
model?: string;
|
|
3
|
+
effort?: string;
|
|
4
|
+
readonly?: true;
|
|
5
|
+
network?: "disabled" | "enabled";
|
|
6
|
+
systemPrompt?: string;
|
|
7
|
+
}>;
|
|
8
|
+
export type ReadonlyRestraint = Readonly<{
|
|
9
|
+
enforcement: "native";
|
|
10
|
+
diagnostic?: never;
|
|
11
|
+
} | {
|
|
12
|
+
enforcement: "none";
|
|
13
|
+
diagnostic: string;
|
|
14
|
+
}>;
|
|
15
|
+
export type ProviderExecution = Readonly<{
|
|
16
|
+
name: string;
|
|
17
|
+
kind: "acp" | "claude-agent-sdk" | "codex-app-server" | "grok-build" | "opencode-sdk" | "pi";
|
|
18
|
+
executable?: string;
|
|
19
|
+
config?: Readonly<Record<string, unknown>>;
|
|
20
|
+
env?: Readonly<Record<string, string>>;
|
|
21
|
+
}>;
|
|
22
|
+
export declare function decodeProviderOptions(value: unknown): ProviderOptions;
|
|
23
|
+
export declare function decodeReadonlyRestraint(value: unknown): ReadonlyRestraint;
|
|
24
|
+
export declare function decodeProviderRecipe(input: unknown): ProviderExecution;
|