@astrosheep/keiyaku 4.6.8 → 4.6.9
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 +40 -14
- package/build/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/build/plugins/claude/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/claude/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/claude/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/claude/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/claude/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/claude/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/claude/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/codex/.codex-plugin/plugin.json +1 -1
- package/build/plugins/codex/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/codex/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/opencode/index.js +1 -1
- package/build/plugins/opencode/skills/keiyaku/SKILL.md +5 -6
- package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/plugins/opencode/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/skills/keiyaku/SKILL.md +5 -6
- package/build/skills/keiyaku-akuma/SKILL.md +1 -1
- package/build/skills/keiyaku-akuma/references/automation.md +8 -8
- package/build/skills/keiyaku-babysit/SKILL.md +1 -1
- package/build/skills/keiyaku-bind/SKILL.md +9 -9
- package/build/skills/keiyaku-debt/SKILL.md +91 -0
- package/build/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/src/akuma/akuma-instance.d.ts +2 -0
- package/build/src/akuma/akuma-instance.js +10 -0
- package/build/src/akuma/akuma-observe.d.ts +33 -8
- package/build/src/akuma/akuma-observe.js +88 -64
- package/build/src/akuma/akuma-owner.d.ts +11 -2
- package/build/src/akuma/akuma-owner.js +45 -35
- package/build/src/akuma/akuma-selection-execution.js +9 -1
- package/build/src/akuma/akuma-stream.d.ts +22 -0
- package/build/src/akuma/akuma-stream.js +116 -0
- package/build/src/akuma/akuma-wait.d.ts +1 -40
- package/build/src/akuma/akuma-wait.js +23 -84
- package/build/src/akuma/akuma.d.ts +17 -11
- package/build/src/akuma/akuma.js +2 -0
- package/build/src/akuma/allowed.d.ts +7 -12
- package/build/src/akuma/allowed.js +13 -4
- package/build/src/akuma/body-supervisor.d.ts +5 -5
- package/build/src/akuma/body-supervisor.js +22 -20
- package/build/src/akuma/body.js +28 -1
- package/build/src/akuma/call-request.d.ts +12 -22
- package/build/src/akuma/heart/activity-schema.d.ts +12 -0
- package/build/src/akuma/heart/activity-schema.js +6 -0
- package/build/src/akuma/heart/index.d.ts +59 -2
- package/build/src/akuma/heart/index.js +87 -8
- package/build/src/akuma/heart/rows.js +5 -3
- package/build/src/akuma/heart/soul.d.ts +9 -0
- package/build/src/akuma/heart/soul.js +29 -0
- package/build/src/akuma/heart/storage.d.ts +15 -0
- package/build/src/akuma/heart/storage.js +55 -0
- package/build/src/akuma/heart/timeline.d.ts +7 -0
- package/build/src/akuma/heart/timeline.js +10 -0
- package/build/src/akuma/index.d.ts +1 -0
- package/build/src/akuma/projection.d.ts +25 -0
- package/build/src/akuma/projection.js +24 -7
- package/build/src/akuma/provider-recipe.d.ts +11 -0
- package/build/src/akuma/provider-recipe.js +23 -0
- package/build/src/akuma/provider.d.ts +25 -0
- package/build/src/akuma/provider.js +99 -7
- package/build/src/akuma/providers/acp/events.js +25 -2
- package/build/src/akuma/providers/claude/events.js +76 -10
- package/build/src/akuma/providers/claude/index.js +2 -5
- package/build/src/akuma/providers/codex-app-server/events.js +17 -2
- package/build/src/akuma/providers/codex-app-server/index.js +15 -9
- package/build/src/akuma/providers/decode.d.ts +8 -0
- package/build/src/akuma/providers/decode.js +21 -0
- package/build/src/akuma/providers/grok-build/index.js +10 -26
- package/build/src/akuma/providers/opencode-sdk/event-stream.d.ts +3 -3
- package/build/src/akuma/providers/opencode-sdk/event-stream.js +2 -25
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +7 -43
- package/build/src/akuma/providers/opencode-sdk/events.js +147 -284
- package/build/src/akuma/providers/opencode-sdk/index.js +267 -421
- package/build/src/akuma/providers/opencode-sdk/native-http.d.ts +9 -0
- package/build/src/akuma/providers/opencode-sdk/native-http.js +69 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +42 -36
- package/build/src/akuma/providers/opencode-sdk/session.js +75 -82
- package/build/src/akuma/providers/paseo/events.d.ts +8 -0
- package/build/src/akuma/providers/paseo/events.js +58 -11
- package/build/src/akuma/providers/paseo/index.js +11 -7
- package/build/src/akuma/providers/pi/events.d.ts +2 -0
- package/build/src/akuma/providers/pi/events.js +32 -24
- package/build/src/akuma/providers/pi/index.js +21 -35
- package/build/src/akuma/request-lifecycle.d.ts +1 -2
- package/build/src/akuma/request-lifecycle.js +2 -8
- package/build/src/akuma/request-rendezvous.js +38 -55
- package/build/src/akuma/request-serve.d.ts +1 -1
- package/build/src/akuma/request-serve.js +77 -113
- package/build/src/akuma/selection-observation.d.ts +57 -51
- package/build/src/akuma/selection-observation.js +3 -3
- package/build/src/akuma/turn-drive.d.ts +3 -0
- package/build/src/akuma/turn-drive.js +26 -5
- package/build/src/akuma-body.js +12 -22
- package/build/src/cli/akuma-caller.js +10 -0
- package/build/src/cli/commands/akuma-grammar.js +3 -4
- package/build/src/cli/commands/akuma.js +13 -51
- package/build/src/cli/commands/contract-grammar.d.ts +7 -6
- package/build/src/cli/commands/contract-grammar.js +27 -32
- package/build/src/cli/commands/contract-help.d.ts +16 -7
- package/build/src/cli/commands/contract-help.js +20 -11
- package/build/src/cli/commands/contract.js +11 -11
- package/build/src/cli/commands/debt-grammar.d.ts +19 -0
- package/build/src/cli/commands/debt-grammar.js +323 -0
- package/build/src/cli/commands/debt-query.d.ts +5 -0
- package/build/src/cli/commands/{task-query.js → debt-query.js} +9 -9
- package/build/src/cli/commands/{task.d.ts → debt.d.ts} +2 -2
- package/build/src/cli/commands/{task.js → debt.js} +83 -143
- package/build/src/cli/coordinates.d.ts +1 -1
- package/build/src/cli/coordinates.js +1 -1
- package/build/src/cli/parse.d.ts +4 -4
- package/build/src/cli/parse.js +17 -16
- package/build/src/cli/render/akuma-activity.d.ts +11 -83
- package/build/src/cli/render/akuma-activity.js +20 -382
- package/build/src/cli/render/catalog.d.ts +2 -2
- package/build/src/cli/render/catalog.js +5 -5
- package/build/src/cli/render/contract.js +2 -2
- package/build/src/cli/render/debt.d.ts +28 -0
- package/build/src/cli/render/{task.js → debt.js} +51 -112
- package/build/src/cli/render/kanshi.js +28 -28
- package/build/src/cli/render/marks.d.ts +5 -5
- package/build/src/cli/render/marks.js +4 -10
- package/build/src/cli/render/nuke.js +1 -1
- package/build/src/cli/runtime.js +3 -3
- package/build/src/cli/scan.d.ts +1 -1
- package/build/src/cli/usage.d.ts +1 -1
- package/build/src/cli/usage.js +4 -4
- package/build/src/contract-worktree.js +3 -3
- package/build/src/debt/board.d.ts +160 -0
- package/build/src/{task → debt}/board.js +89 -89
- package/build/src/debt/catalog.d.ts +11 -0
- package/build/src/debt/catalog.js +59 -0
- package/build/src/{task → debt}/context.d.ts +1 -1
- package/build/src/{task → debt}/context.js +1 -1
- package/build/src/{task → debt}/created-observation.d.ts +6 -10
- package/build/src/{task → debt}/created-observation.js +7 -7
- package/build/src/debt/document.d.ts +37 -0
- package/build/src/{task → debt}/document.js +37 -37
- package/build/src/debt/identity.d.ts +21 -0
- package/build/src/{task → debt}/identity.js +35 -35
- package/build/src/debt/index.d.ts +111 -0
- package/build/src/debt/index.js +203 -0
- package/build/src/{task → debt}/input.d.ts +8 -8
- package/build/src/{task → debt}/input.js +21 -21
- package/build/src/debt/lifecycle-operations.d.ts +6 -0
- package/build/src/{task → debt}/lifecycle-operations.js +27 -31
- package/build/src/debt/mutation-result.d.ts +981 -0
- package/build/src/debt/mutation-result.js +109 -0
- package/build/src/debt/mutation.d.ts +424 -0
- package/build/src/debt/mutation.js +223 -0
- package/build/src/debt/operation-types.d.ts +71 -0
- package/build/src/debt/operations.d.ts +28 -0
- package/build/src/{task → debt}/operations.js +59 -60
- package/build/src/debt/query.d.ts +76 -0
- package/build/src/{task → debt}/query.js +55 -55
- package/build/src/{task → debt}/store.d.ts +13 -13
- package/build/src/{task → debt}/store.js +58 -49
- package/build/src/debt/view.d.ts +4 -0
- package/build/src/debt/view.js +7 -0
- package/build/src/identity/coordinates.d.ts +1 -1
- package/build/src/index.d.ts +13 -13
- package/build/src/index.js +9 -9
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +33 -33
- package/build/src/kanshi/report.d.ts +7 -7
- package/build/src/kanshi/select.js +4 -4
- package/build/src/library/akumas.d.ts +2 -3
- package/build/src/library/bind.d.ts +3 -3
- package/build/src/library/bind.js +5 -5
- package/build/src/library/contract-creation.js +5 -5
- package/build/src/library/contract-execution.js +4 -4
- package/build/src/library/contract-types.d.ts +2 -2
- package/build/src/library/input.d.ts +2 -2
- package/build/src/library/input.js +5 -5
- package/build/src/library/invocation.js +2 -2
- package/build/src/library/nuke.js +3 -3
- package/build/src/library/outcome.d.ts +126 -126
- package/build/src/library/outcome.js +3 -3
- package/build/src/library/selection.d.ts +1 -4
- package/build/src/library/selection.js +11 -62
- package/build/src/plugin/public.d.ts +5 -0
- package/build/src/plugin/runtime.js +3 -1
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/build/src/settlement/fence.d.ts +3 -3
- package/build/src/settlement/fence.js +4 -4
- package/build/src/settlement/holder.d.ts +16 -16
- package/build/src/settlement/holder.js +69 -63
- package/build/src/settlement/settle.d.ts +5 -5
- package/build/src/settlement/settle.js +53 -53
- package/package.json +12 -6
- package/plugins/paseo/plugin/index.server.ts +17 -0
- package/plugins/paseo/plugin/paseo-plugin.json +4 -0
- package/plugins/paseo/plugin/server/attach.ts +52 -0
- package/plugins/paseo/plugin/server/keiyaku.ts +44 -0
- package/plugins/paseo/plugin/server/message.ts +60 -0
- package/plugins/paseo/plugin/server/mirror.ts +193 -0
- package/plugins/paseo/plugin/server/model.ts +14 -0
- package/plugins/paseo/plugin/server/provider.ts +276 -0
- package/plugins/paseo/plugin/server/sdk-worker.ts +237 -0
- package/plugins/paseo/plugin/server/sdk.ts +289 -0
- package/plugins/paseo/plugin/server/stop.ts +26 -0
- package/plugins/paseo/plugin/server/transport.ts +35 -0
- package/plugins/paseo/plugin/shared/attach-rpc.ts +10 -0
- package/plugins/paseo/plugin/shared/refresh-rpc.ts +6 -0
- package/plugins/paseo/plugin/tsconfig.json +6 -0
- package/skills/keiyaku/SKILL.md +5 -6
- package/skills/keiyaku-akuma/SKILL.md +1 -1
- package/skills/keiyaku-akuma/references/automation.md +8 -8
- package/skills/keiyaku-babysit/SKILL.md +1 -1
- package/skills/keiyaku-bind/SKILL.md +9 -9
- package/skills/keiyaku-debt/SKILL.md +91 -0
- package/skills/keiyaku-workflow/SKILL.md +2 -2
- package/build/plugins/claude/skills/keiyaku-task/SKILL.md +0 -104
- package/build/plugins/codex/skills/keiyaku-task/SKILL.md +0 -104
- package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +0 -104
- package/build/skills/keiyaku-task/SKILL.md +0 -104
- package/build/src/cli/commands/task-grammar.d.ts +0 -19
- package/build/src/cli/commands/task-grammar.js +0 -384
- package/build/src/cli/commands/task-query.d.ts +0 -5
- package/build/src/cli/render/task.d.ts +0 -39
- package/build/src/task/board.d.ts +0 -168
- package/build/src/task/catalog.d.ts +0 -11
- package/build/src/task/catalog.js +0 -59
- package/build/src/task/compose-language.d.ts +0 -57
- package/build/src/task/compose-language.js +0 -364
- package/build/src/task/compose-parser.d.ts +0 -32
- package/build/src/task/compose-parser.js +0 -180
- package/build/src/task/compose.d.ts +0 -16
- package/build/src/task/compose.js +0 -189
- package/build/src/task/document.d.ts +0 -39
- package/build/src/task/identity.d.ts +0 -21
- package/build/src/task/index.d.ts +0 -138
- package/build/src/task/index.js +0 -269
- package/build/src/task/lifecycle-operations.d.ts +0 -6
- package/build/src/task/mutation-result.d.ts +0 -1726
- package/build/src/task/mutation-result.js +0 -198
- package/build/src/task/mutation.d.ts +0 -590
- package/build/src/task/mutation.js +0 -262
- package/build/src/task/operation-types.d.ts +0 -71
- package/build/src/task/operations.d.ts +0 -28
- package/build/src/task/query.d.ts +0 -76
- package/build/src/task/view.d.ts +0 -4
- package/build/src/task/view.js +0 -7
- package/skills/keiyaku-task/SKILL.md +0 -104
- /package/build/src/{task → debt}/operation-types.js +0 -0
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { contractIdSchema } from "../git/identity.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
3
|
+
import { debtIdSchema } from "../debt/identity.js";
|
|
4
4
|
import { observeContractsForAdmissionAt } from "../git/observe.js";
|
|
5
5
|
import { appendPrivateStateSeatClose, withPrivateStatePublicationSeat, } from "../git/private-state-seat.js";
|
|
6
6
|
import { GitPlumbingError } from "../git/process.js";
|
|
7
7
|
import { SqliteTransactionLockError } from "../coordination/sqlite-transaction-lock.js";
|
|
8
8
|
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { settleDebt } from "../debt/operations.js";
|
|
10
|
+
import { publishDebtHolderRelease, readDebtHolderProjectionFromDecision, debtHolderObservationSelection, } from "./holder.js";
|
|
11
|
+
import { acquireDebtSettlementFence } from "./fence.js";
|
|
12
12
|
import { World } from "../world.js";
|
|
13
13
|
export const settlementActionSchema = z
|
|
14
|
-
.object({ kind: z.literal("
|
|
14
|
+
.object({ kind: z.literal("debt"), debtId: debtIdSchema, action: z.literal("done") })
|
|
15
15
|
.strict();
|
|
16
16
|
export const settlementLagSchema = z
|
|
17
17
|
.object({
|
|
18
18
|
kind: z.literal("settlement-failed"),
|
|
19
|
-
surface: z.enum(["
|
|
19
|
+
surface: z.enum(["debt-holder", "debt"]),
|
|
20
20
|
contractId: contractIdSchema,
|
|
21
|
-
|
|
21
|
+
debtId: debtIdSchema.optional(),
|
|
22
22
|
path: z
|
|
23
23
|
.string()
|
|
24
24
|
.refine((value) => value.trim() !== "")
|
|
@@ -36,10 +36,10 @@ function operational(error) {
|
|
|
36
36
|
function diagnostic(error) {
|
|
37
37
|
return error instanceof Error ? error.message : String(error);
|
|
38
38
|
}
|
|
39
|
-
function
|
|
39
|
+
function debtFailure(result) {
|
|
40
40
|
return result.kind === "retry"
|
|
41
|
-
? `
|
|
42
|
-
: `
|
|
41
|
+
? `Debt settlement requires retry: ${result.reason}`
|
|
42
|
+
: `Debt settlement refused: ${JSON.stringify(result.refusal)}`;
|
|
43
43
|
}
|
|
44
44
|
function recordLag(input, lag) {
|
|
45
45
|
input.lags.push(lag);
|
|
@@ -53,11 +53,11 @@ async function observeApplicableHolder(input) {
|
|
|
53
53
|
const { repository, channel, candidate } = input;
|
|
54
54
|
let observation;
|
|
55
55
|
try {
|
|
56
|
-
observation = await observeContractsForAdmissionAt(repository, channel, [candidate.id],
|
|
56
|
+
observation = await observeContractsForAdmissionAt(repository, channel, [candidate.id], debtHolderObservationSelection());
|
|
57
57
|
const state = observation.journals.get(candidate.id)?.state ?? null;
|
|
58
58
|
if (state === null || state.terminal?.kind !== "claimed")
|
|
59
59
|
return null;
|
|
60
|
-
const holder = (await
|
|
60
|
+
const holder = (await readDebtHolderProjectionFromDecision(channel, observation)).get(candidate.id) ?? null;
|
|
61
61
|
return holder?.disposition === "held" ? holder : null;
|
|
62
62
|
}
|
|
63
63
|
catch (error) {
|
|
@@ -65,15 +65,15 @@ async function observeApplicableHolder(input) {
|
|
|
65
65
|
throw error;
|
|
66
66
|
recordLag(input, {
|
|
67
67
|
kind: "settlement-failed",
|
|
68
|
-
surface: "
|
|
68
|
+
surface: "debt-holder",
|
|
69
69
|
contractId: candidate.id,
|
|
70
70
|
diagnostic: diagnostic(error),
|
|
71
71
|
});
|
|
72
72
|
return null;
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
-
async function
|
|
76
|
-
const { repository, candidate,
|
|
75
|
+
async function completeHeldDebt(input) {
|
|
76
|
+
const { repository, candidate, debtId } = input;
|
|
77
77
|
let world;
|
|
78
78
|
try {
|
|
79
79
|
world = await World.at(repository.primaryWorktree);
|
|
@@ -83,38 +83,38 @@ async function completeHeldTask(input) {
|
|
|
83
83
|
throw error;
|
|
84
84
|
recordLag(input, {
|
|
85
85
|
kind: "settlement-failed",
|
|
86
|
-
surface: "
|
|
86
|
+
surface: "debt",
|
|
87
87
|
contractId: candidate.id,
|
|
88
|
-
|
|
88
|
+
debtId,
|
|
89
89
|
diagnostic: diagnostic(error),
|
|
90
90
|
});
|
|
91
91
|
return false;
|
|
92
92
|
}
|
|
93
93
|
let result;
|
|
94
94
|
try {
|
|
95
|
-
result = await
|
|
95
|
+
result = await settleDebt(world, debtId);
|
|
96
96
|
}
|
|
97
97
|
catch (error) {
|
|
98
98
|
if (!operational(error))
|
|
99
99
|
throw error;
|
|
100
100
|
recordLag(input, {
|
|
101
101
|
kind: "settlement-failed",
|
|
102
|
-
surface: "
|
|
102
|
+
surface: "debt",
|
|
103
103
|
contractId: candidate.id,
|
|
104
|
-
|
|
104
|
+
debtId,
|
|
105
105
|
diagnostic: diagnostic(error),
|
|
106
106
|
});
|
|
107
107
|
return false;
|
|
108
108
|
}
|
|
109
109
|
if (result.kind === "changed")
|
|
110
|
-
recordAction(input, { kind: "
|
|
110
|
+
recordAction(input, { kind: "debt", debtId, action: "done" });
|
|
111
111
|
if (result.kind === "changed" && result.cleanup !== undefined) {
|
|
112
112
|
for (const detail of result.cleanup.diagnostics) {
|
|
113
113
|
recordLag(input, {
|
|
114
114
|
kind: "settlement-failed",
|
|
115
|
-
surface: "
|
|
115
|
+
surface: "debt",
|
|
116
116
|
contractId: candidate.id,
|
|
117
|
-
|
|
117
|
+
debtId,
|
|
118
118
|
diagnostic: detail,
|
|
119
119
|
});
|
|
120
120
|
}
|
|
@@ -123,32 +123,32 @@ async function completeHeldTask(input) {
|
|
|
123
123
|
return true;
|
|
124
124
|
recordLag(input, {
|
|
125
125
|
kind: "settlement-failed",
|
|
126
|
-
surface: "
|
|
126
|
+
surface: "debt",
|
|
127
127
|
contractId: candidate.id,
|
|
128
|
-
|
|
129
|
-
diagnostic:
|
|
128
|
+
debtId,
|
|
129
|
+
diagnostic: debtFailure(result),
|
|
130
130
|
});
|
|
131
131
|
return false;
|
|
132
132
|
}
|
|
133
|
-
async function
|
|
134
|
-
const { repository, channel, candidate, seatClose,
|
|
133
|
+
async function releaseHeldDebtHolder(input) {
|
|
134
|
+
const { repository, channel, candidate, seatClose, debtId } = input;
|
|
135
135
|
try {
|
|
136
136
|
const outcome = await withPrivateStatePublicationSeat(repository, async (seat) => {
|
|
137
|
-
const observation = await observeContractsForAdmissionAt(repository, channel, [candidate.id],
|
|
137
|
+
const observation = await observeContractsForAdmissionAt(repository, channel, [candidate.id], debtHolderObservationSelection());
|
|
138
138
|
const state = observation.journals.get(candidate.id)?.state ?? null;
|
|
139
139
|
if (state === null || state.terminal?.kind !== "claimed")
|
|
140
140
|
return "inert";
|
|
141
|
-
const holder = (await
|
|
142
|
-
if (holder === null || holder.disposition !== "held" || holder.
|
|
141
|
+
const holder = (await readDebtHolderProjectionFromDecision(channel, observation)).get(candidate.id) ?? null;
|
|
142
|
+
if (holder === null || holder.disposition !== "held" || holder.debtId !== debtId)
|
|
143
143
|
return "inert";
|
|
144
|
-
const publication = await
|
|
144
|
+
const publication = await publishDebtHolderRelease(repository, channel, observation, candidate.id, seat);
|
|
145
145
|
if (publication.kind === "non-published") {
|
|
146
146
|
recordLag(input, {
|
|
147
147
|
kind: "settlement-failed",
|
|
148
|
-
surface: "
|
|
148
|
+
surface: "debt-holder",
|
|
149
149
|
contractId: candidate.id,
|
|
150
|
-
|
|
151
|
-
diagnostic: `
|
|
150
|
+
debtId,
|
|
151
|
+
diagnostic: `Debt holder release requires retry: ${publication.diagnostic}`,
|
|
152
152
|
});
|
|
153
153
|
return "held";
|
|
154
154
|
}
|
|
@@ -165,51 +165,51 @@ async function releaseHeldTaskHolder(input) {
|
|
|
165
165
|
throw error;
|
|
166
166
|
recordLag(input, {
|
|
167
167
|
kind: "settlement-failed",
|
|
168
|
-
surface: "
|
|
168
|
+
surface: "debt-holder",
|
|
169
169
|
contractId: candidate.id,
|
|
170
|
-
|
|
170
|
+
debtId,
|
|
171
171
|
diagnostic: diagnostic(error),
|
|
172
172
|
});
|
|
173
173
|
return "held";
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
-
async function
|
|
176
|
+
async function settleDebts(input) {
|
|
177
177
|
const { repository, channel, candidate, lags, seatClose } = input;
|
|
178
178
|
const hint = await observeApplicableHolder(input);
|
|
179
179
|
if (hint === null)
|
|
180
180
|
return false;
|
|
181
|
-
const
|
|
181
|
+
const debtId = hint.debtId;
|
|
182
182
|
let fence;
|
|
183
183
|
try {
|
|
184
|
-
fence = await
|
|
184
|
+
fence = await acquireDebtSettlementFence(repository, debtId);
|
|
185
185
|
}
|
|
186
186
|
catch (error) {
|
|
187
187
|
if (!operational(error))
|
|
188
188
|
throw error;
|
|
189
189
|
recordLag(input, {
|
|
190
190
|
kind: "settlement-failed",
|
|
191
|
-
surface: "
|
|
191
|
+
surface: "debt",
|
|
192
192
|
contractId: candidate.id,
|
|
193
|
-
|
|
193
|
+
debtId,
|
|
194
194
|
diagnostic: diagnostic(error),
|
|
195
195
|
});
|
|
196
196
|
return true;
|
|
197
197
|
}
|
|
198
198
|
let failure;
|
|
199
|
-
let
|
|
199
|
+
let debtSettled = false;
|
|
200
200
|
let holderDisposition = null;
|
|
201
201
|
try {
|
|
202
202
|
const holder = await observeApplicableHolder(input);
|
|
203
|
-
if (holder === null || holder.
|
|
203
|
+
if (holder === null || holder.debtId !== debtId)
|
|
204
204
|
return false;
|
|
205
|
-
|
|
206
|
-
if (!
|
|
205
|
+
debtSettled = await completeHeldDebt({ ...input, debtId });
|
|
206
|
+
if (!debtSettled)
|
|
207
207
|
return true;
|
|
208
|
-
holderDisposition = await
|
|
208
|
+
holderDisposition = await releaseHeldDebtHolder({
|
|
209
209
|
repository,
|
|
210
210
|
channel,
|
|
211
211
|
candidate,
|
|
212
|
-
|
|
212
|
+
debtId,
|
|
213
213
|
lags,
|
|
214
214
|
seatClose,
|
|
215
215
|
...(input.progress === undefined ? {} : { progress: input.progress }),
|
|
@@ -229,15 +229,15 @@ async function settleTasks(input) {
|
|
|
229
229
|
if (failure === undefined)
|
|
230
230
|
throw error;
|
|
231
231
|
}
|
|
232
|
-
else if (!
|
|
232
|
+
else if (!debtSettled && failure === undefined)
|
|
233
233
|
throw error;
|
|
234
234
|
// Post-release fence teardown is custodial residue, not an owed holder publication.
|
|
235
235
|
if (holderDisposition !== "released") {
|
|
236
236
|
recordLag(input, {
|
|
237
237
|
kind: "settlement-failed",
|
|
238
|
-
surface: "
|
|
238
|
+
surface: "debt-holder",
|
|
239
239
|
contractId: candidate.id,
|
|
240
|
-
|
|
240
|
+
debtId,
|
|
241
241
|
diagnostic: diagnostic(error),
|
|
242
242
|
});
|
|
243
243
|
}
|
|
@@ -258,7 +258,7 @@ async function settleObserved(input) {
|
|
|
258
258
|
const candidate = input.state;
|
|
259
259
|
if (candidate.terminal?.kind === "claimed") {
|
|
260
260
|
try {
|
|
261
|
-
await
|
|
261
|
+
await settleDebts({
|
|
262
262
|
repository: input.repository,
|
|
263
263
|
channel: input.channel,
|
|
264
264
|
candidate,
|
|
@@ -273,7 +273,7 @@ async function settleObserved(input) {
|
|
|
273
273
|
throw error;
|
|
274
274
|
recordLag({ candidate, lags, ...(input.progress === undefined ? {} : { progress: input.progress }) }, {
|
|
275
275
|
kind: "settlement-failed",
|
|
276
|
-
surface: "
|
|
276
|
+
surface: "debt",
|
|
277
277
|
contractId: candidate.id,
|
|
278
278
|
diagnostic: diagnostic(error),
|
|
279
279
|
});
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrosheep/keiyaku",
|
|
3
|
-
"version": "4.6.
|
|
3
|
+
"version": "4.6.9",
|
|
4
4
|
"workspaces": [
|
|
5
|
-
"plugins/square"
|
|
5
|
+
"plugins/square",
|
|
6
|
+
"plugins/paseo/forwarder"
|
|
6
7
|
],
|
|
7
8
|
"files": [
|
|
8
9
|
"build",
|
|
9
10
|
"plugins/pi",
|
|
11
|
+
"plugins/paseo/plugin",
|
|
10
12
|
"skills"
|
|
11
13
|
],
|
|
12
14
|
"main": "./build/src/index.js",
|
|
@@ -31,7 +33,7 @@
|
|
|
31
33
|
},
|
|
32
34
|
"scripts": {
|
|
33
35
|
"release": "npm run test:release && npm version patch && npm publish",
|
|
34
|
-
"build": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('build', { recursive: true, force: true })\" && tsc -p tsconfig.json && npm run build --workspace @astrosheep/keiyaku-plugin-square && node scripts/copy-plugins.js && node scripts/build-windows-launcher.js && node --input-type=module -e \"import { chmodSync } from 'node:fs'; chmodSync('build/src/cli/index.js', 0o755)\"",
|
|
36
|
+
"build": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('build', { recursive: true, force: true })\" && tsc -p tsconfig.json && npm run build --workspace @astrosheep/keiyaku-plugin-square && npm run build --workspace @astrosheep/keiyaku-plugin-paseo && node scripts/copy-plugins.js && node scripts/build-windows-launcher.js && node --input-type=module -e \"import { chmodSync } from 'node:fs'; chmodSync('build/src/cli/index.js', 0o755)\"",
|
|
35
37
|
"prepack": "node scripts/verify-package.js",
|
|
36
38
|
"postpack": "node scripts/verify-package.js",
|
|
37
39
|
"harness:version": "node scripts/update-harness-version.js",
|
|
@@ -63,8 +65,10 @@
|
|
|
63
65
|
},
|
|
64
66
|
"devDependencies": {
|
|
65
67
|
"@earendil-works/pi-coding-agent": "^1.0.0",
|
|
68
|
+
"@getpaseo/plugin": "0.11.2",
|
|
66
69
|
"@types/cross-spawn": "^6.0.6",
|
|
67
70
|
"@types/node": "^25.0.0",
|
|
71
|
+
"@types/ws": "^8.18.2",
|
|
68
72
|
"@typescript-eslint/parser": "^8.66.0",
|
|
69
73
|
"eslint": "^9.39.5",
|
|
70
74
|
"knip": "^6.31.0",
|
|
@@ -75,13 +79,15 @@
|
|
|
75
79
|
"dependencies": {
|
|
76
80
|
"@agentclientprotocol/sdk": "^1.3.0",
|
|
77
81
|
"@anthropic-ai/claude-agent-sdk": "^0.3.226",
|
|
78
|
-
"@astrosheep/keiyaku-plugin-
|
|
79
|
-
"@astrosheep/square": "
|
|
82
|
+
"@astrosheep/keiyaku-plugin-paseo": "0.1.0",
|
|
83
|
+
"@astrosheep/keiyaku-plugin-square": "0.1.9",
|
|
84
|
+
"@astrosheep/square": "^0.3.79",
|
|
80
85
|
"@getpaseo/client": "0.11.2",
|
|
81
86
|
"@getpaseo/protocol": "0.11.2",
|
|
82
|
-
"@opencode
|
|
87
|
+
"@opencode/client": "2.0.20",
|
|
83
88
|
"cross-spawn": "^7.0.6",
|
|
84
89
|
"diff": "^8.0.4",
|
|
90
|
+
"undici": "8.10.2",
|
|
85
91
|
"yaml": "^2.9.0",
|
|
86
92
|
"zod": "^4.5.2"
|
|
87
93
|
},
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PluginServerContext } from "@getpaseo/plugin/server";
|
|
2
|
+
import { createProvider } from "./server/provider.js";
|
|
3
|
+
import { createSdkTransport } from "./server/sdk.js";
|
|
4
|
+
import { attach } from "./server/attach.js";
|
|
5
|
+
import { attachRpc } from "./shared/attach-rpc.js";
|
|
6
|
+
import { refreshRpc } from "./shared/refresh-rpc.js";
|
|
7
|
+
|
|
8
|
+
export default function contribute(server: PluginServerContext) {
|
|
9
|
+
const transport = createSdkTransport();
|
|
10
|
+
const mirror = createProvider(transport);
|
|
11
|
+
server.registerProvider(mirror.provider);
|
|
12
|
+
server.handle(refreshRpc, (input) => mirror.refresh(input));
|
|
13
|
+
server.handle(attachRpc, (input, context) => attach(input, context, mirror.sync));
|
|
14
|
+
return async () => {
|
|
15
|
+
try { await mirror.close(); } finally { await transport.close(); }
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { realpath } from "node:fs/promises";
|
|
2
|
+
import type { PluginHandlerContext } from "@getpaseo/plugin/server";
|
|
3
|
+
import type { z } from "zod";
|
|
4
|
+
import type { attachRpc } from "../shared/attach-rpc.js";
|
|
5
|
+
|
|
6
|
+
function skip(reason: string) {
|
|
7
|
+
console.warn(`Keiyaku mirror not attached: ${reason}`);
|
|
8
|
+
return { attached: false };
|
|
9
|
+
}
|
|
10
|
+
export async function attach(input: z.output<typeof attachRpc.input>, { paseo }: PluginHandlerContext,
|
|
11
|
+
sync: (input: { world: string; akuId: string }) => Promise<void>) {
|
|
12
|
+
const caller = input.caller;
|
|
13
|
+
if (caller?.kind !== "external") return skip("caller is not an external host");
|
|
14
|
+
const native = ["codex", "pi", "claude"].includes(caller.integration);
|
|
15
|
+
let parentId = caller.id;
|
|
16
|
+
const matches = (agent: { persistence?: { provider: string; sessionId: string } | null }) =>
|
|
17
|
+
agent.persistence?.provider === caller.integration && agent.persistence.sessionId === caller.id;
|
|
18
|
+
if (native) {
|
|
19
|
+
const candidates: string[] = [];
|
|
20
|
+
let cursor: string | undefined;
|
|
21
|
+
do {
|
|
22
|
+
const filter = { includeArchived: true };
|
|
23
|
+
const page = await paseo.agents.list({ filter, page: { limit: 200, ...(cursor ? { cursor } : {}) } });
|
|
24
|
+
for (const { agent } of page.entries) if (matches(agent)) candidates.push(agent.id);
|
|
25
|
+
if (candidates.length > 1) return skip(`ambiguous ${caller.integration} session ${caller.id}: multiple parents`);
|
|
26
|
+
if (!page.pageInfo.hasMore) break;
|
|
27
|
+
const next = page.pageInfo.nextCursor;
|
|
28
|
+
if (!next || next === cursor) return skip("incomplete parent directory pagination");
|
|
29
|
+
cursor = next;
|
|
30
|
+
} while (cursor);
|
|
31
|
+
if (!candidates[0]) return skip(`no parent for ${caller.integration} session ${caller.id}`);
|
|
32
|
+
parentId = candidates[0];
|
|
33
|
+
} else if (caller.integration !== "paseo") {
|
|
34
|
+
return skip(`unsupported caller integration ${caller.integration}`);
|
|
35
|
+
}
|
|
36
|
+
const parent = await paseo.agents.ref(parentId).refresh();
|
|
37
|
+
if (!parent) return skip(`parent ${parentId} does not exist`);
|
|
38
|
+
if (parent.agent.archivedAt) return skip(`parent ${parentId} is archived`);
|
|
39
|
+
if (native && !matches(parent.agent)) return skip(`parent ${parentId} changed native identity`);
|
|
40
|
+
const world = await realpath(input.world);
|
|
41
|
+
// Keep the creation fingerprint immutable: aliases belong to the forwarder's
|
|
42
|
+
// rename path, not this idempotent request (including retries after rename).
|
|
43
|
+
await paseo.agents.create({ parent: parentId, cwd: parent.agent.cwd, title: input.akuId,
|
|
44
|
+
config: { provider: "keiyaku/mirror", options: { world, akuId: input.akuId } },
|
|
45
|
+
idempotencyKey: `keiyaku:${world}:${input.akuId}`,
|
|
46
|
+
});
|
|
47
|
+
// Creation returns only after the host has registered and subscribed to the session.
|
|
48
|
+
// Opening's ready event is too early to restore running presentation there.
|
|
49
|
+
try { await sync({ world, akuId: input.akuId }); }
|
|
50
|
+
catch (error) { console.warn(`Keiyaku mirror attached, but synchronization failed: ${error instanceof Error ? error.message : String(error)}`); }
|
|
51
|
+
return { attached: true };
|
|
52
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const identityKeys = [
|
|
4
|
+
"CLAUDE_CODE_SESSION_ID", "CLAUDE_CODE_CHILD_SESSION", "CLAUDECODE", "CODEX_THREAD_ID",
|
|
5
|
+
"OPENCODE_SESSION_ID", "PI_SESSION_ID", "PI_SESSION_FILE", "PASEO_AGENT_ID",
|
|
6
|
+
"SQUARE_PARTICIPANT_NAME", "AKUMA_REQUESTS", "KEIYAKU_ACTOR_ID", "KEIYAKU_EXTERNAL_CALLER",
|
|
7
|
+
] as const;
|
|
8
|
+
const count = z.number().int().nonnegative();
|
|
9
|
+
const base = z.object({ sequence: count, at: z.string() });
|
|
10
|
+
const turnFields = { turnSequence: count };
|
|
11
|
+
const input = z.object({ json: z.string(), truncated: z.boolean() });
|
|
12
|
+
const call = z.discriminatedUnion("kind", [
|
|
13
|
+
z.object({ kind: z.literal("run"), command: z.string() }),
|
|
14
|
+
z.object({ kind: z.literal("read"), path: z.string(), offset: count.optional(), limit: count.optional() }),
|
|
15
|
+
z.object({ kind: z.literal("search"), query: z.string(), scope: z.enum(["content", "files", "web"]).optional(),
|
|
16
|
+
path: z.string().optional(), glob: z.string().optional() }),
|
|
17
|
+
z.object({ kind: z.literal("fileChange"), changes: z.array(z.object({
|
|
18
|
+
op: z.enum(["add", "update", "delete", "unspecified"]), path: z.string(),
|
|
19
|
+
diffstat: z.object({ added: count, removed: count }).optional(), patch: z.string().optional(),
|
|
20
|
+
})) }),
|
|
21
|
+
z.object({ kind: z.literal("other"), display: z.string(), input: input.optional() }),
|
|
22
|
+
]);
|
|
23
|
+
const row = z.union([
|
|
24
|
+
base.extend({ kind: z.literal("turn"), ...turnFields, bodySequence: count.optional() }),
|
|
25
|
+
base.extend({ kind: z.literal("tell"), tellId: z.string(), text: z.string(), state: z.enum(["pending", "told"]),
|
|
26
|
+
deliveries: z.array(z.object({ deliveredAt: z.string(), route: z.enum(["launch", "live"]),
|
|
27
|
+
turnSequence: count, receipt: z.enum(["unavailable", "required"]).optional() })).optional() }),
|
|
28
|
+
base.extend({ kind: z.literal("outcome"), ...turnFields, outcome: z.discriminatedUnion("kind", [
|
|
29
|
+
z.object({ kind: z.literal("answered"), historyId: z.string().optional(), answer: z.string(),
|
|
30
|
+
foldedSaidSequence: count.optional() }),
|
|
31
|
+
z.object({ kind: z.literal("failed"), historyId: z.string().optional(), diagnostic: z.string() }),
|
|
32
|
+
]) }),
|
|
33
|
+
base.extend({ kind: z.literal("tool"), ...turnFields, name: z.string(), toolId: z.string().optional(), call,
|
|
34
|
+
state: z.union([z.enum(["active", "unsettled"]), z.object({ status: z.enum(["ok", "error"]),
|
|
35
|
+
message: z.string().optional(), exitCode: z.number().int().optional(), output: z.string().optional() })]),
|
|
36
|
+
durationMs: z.number().nonnegative().optional(), truncated: z.literal(true).optional() }),
|
|
37
|
+
base.extend({ kind: z.enum(["said", "thought", "note", "call"]), ...turnFields, text: z.string(),
|
|
38
|
+
truncated: z.literal(true).optional() }),
|
|
39
|
+
]);
|
|
40
|
+
export const historySchema = z.object({ rows: z.array(row), omitted: count,
|
|
41
|
+
hasEarlier: z.boolean(), hasLater: z.boolean(), historyLost: z.boolean(),
|
|
42
|
+
lowestRetained: count.nullable(), highest: count.nullable() });
|
|
43
|
+
export type Row = z.infer<typeof row>;
|
|
44
|
+
export type History = z.infer<typeof historySchema>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ProviderEvent, ProviderPrompt } from "@getpaseo/plugin/server/provider";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
const sequence = z.number().int().nonnegative();
|
|
5
|
+
export const tellReceiptSchema = z.object({
|
|
6
|
+
akuma: z.string(),
|
|
7
|
+
tell: z.object({
|
|
8
|
+
admission: z.object({ fact: z.literal("recorded"), tellId: z.string().min(1) }),
|
|
9
|
+
row: z.object({ kind: z.literal("tell"), sequence, at: z.string(), tellId: z.string().min(1), text: z.string(),
|
|
10
|
+
state: z.enum(["pending", "told"]), deliveries: z.array(z.object({
|
|
11
|
+
route: z.enum(["live", "launch"]), turnSequence: sequence, deliveredAt: z.string(),
|
|
12
|
+
receipt: z.enum(["unavailable", "required"]).optional(),
|
|
13
|
+
})).optional() }),
|
|
14
|
+
wake: z.discriminatedUnion("kind", [
|
|
15
|
+
z.object({ kind: z.literal("told") }), z.object({ kind: z.literal("held") }),
|
|
16
|
+
z.object({ kind: z.literal("pursuing"), bodySequence: sequence }),
|
|
17
|
+
z.object({ kind: z.literal("failed"), diagnostic: z.string() }),
|
|
18
|
+
]),
|
|
19
|
+
}),
|
|
20
|
+
});
|
|
21
|
+
/** One durable Tell admission and the wake it observed, however that wake settled. */
|
|
22
|
+
export type TellAdmission = z.infer<typeof tellReceiptSchema>["tell"];
|
|
23
|
+
export type AdmittedMessage = TellAdmission["row"];
|
|
24
|
+
/** Submit one plain-text Tell and return its admission receipt. */
|
|
25
|
+
export type Tell = (world: string, akuId: string, signal: AbortSignal, text: string) => Promise<TellAdmission>;
|
|
26
|
+
type PromptResult = Extract<ProviderEvent, { type: "session.prompt_result" }>["result"];
|
|
27
|
+
|
|
28
|
+
export function messageText(prompt: ProviderPrompt): string {
|
|
29
|
+
// Paseo requests stale permission cleanup on ordinary steering. This mirror
|
|
30
|
+
// owns no permission requests, so there is nothing to clear.
|
|
31
|
+
if (prompt.outputSchema !== undefined) {
|
|
32
|
+
throw new Error("Keiyaku messages do not support output schemas");
|
|
33
|
+
}
|
|
34
|
+
if (prompt.input.type !== "message") {
|
|
35
|
+
throw new Error("Keiyaku messages support plain text only, not commands");
|
|
36
|
+
}
|
|
37
|
+
const parts: string[] = [];
|
|
38
|
+
for (const part of prompt.input.content) {
|
|
39
|
+
if (part.type !== "text" || "mimeType" in part) throw new Error("Keiyaku messages support plain text only, not attachments");
|
|
40
|
+
parts.push(part.text);
|
|
41
|
+
}
|
|
42
|
+
const text = parts.join("\n");
|
|
43
|
+
if (!text.trim()) throw new Error("Keiyaku messages require nonblank text");
|
|
44
|
+
return text;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Map one admitted Tell to its Paseo presentation. Paseo steering acknowledges
|
|
49
|
+
* durable input acceptance, never native delivery: the observed Turn is a host
|
|
50
|
+
* presentation correlation, never a Heart binding.
|
|
51
|
+
*/
|
|
52
|
+
export function tellPresentation(admitted: TellAdmission, steerTurnId?: string): { row: AdmittedMessage; result: PromptResult } {
|
|
53
|
+
const { row, wake } = admitted;
|
|
54
|
+
if (wake.kind === "failed") console.warn(`Keiyaku Tell ${row.tellId} recorded; wake failed: ${wake.diagnostic}`);
|
|
55
|
+
if (steerTurnId !== undefined) return { row, result: { type: "steer", turnId: steerTurnId } };
|
|
56
|
+
const delivery = row.deliveries?.at(-1);
|
|
57
|
+
if (delivery) return { row, result: { type: "turn", turnId: `turn/${delivery.turnSequence}` } };
|
|
58
|
+
// The host may complete its send command; no Akuma outcome is manufactured.
|
|
59
|
+
return { row, result: { type: "completed" } };
|
|
60
|
+
}
|