@astrosheep/keiyaku 4.6.7 → 4.6.8

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.
Files changed (165) hide show
  1. package/README.md +6 -2
  2. package/build/plugins/pi/keiyaku.ts +0 -5
  3. package/build/src/akuma/akuma-call.d.ts +2 -0
  4. package/build/src/akuma/akuma-call.js +8 -2
  5. package/build/src/akuma/akuma-instance.d.ts +12 -1
  6. package/build/src/akuma/akuma-instance.js +27 -7
  7. package/build/src/akuma/akuma-observe.js +2 -0
  8. package/build/src/akuma/akuma-owner.d.ts +3 -0
  9. package/build/src/akuma/akuma-owner.js +4 -0
  10. package/build/src/akuma/akuma.d.ts +35 -5
  11. package/build/src/akuma/akuma.js +8 -10
  12. package/build/src/akuma/archetype.d.ts +7 -15
  13. package/build/src/akuma/archetype.js +36 -35
  14. package/build/src/akuma/body.d.ts +5 -3
  15. package/build/src/akuma/body.js +29 -7
  16. package/build/src/akuma/call-request.d.ts +18 -10
  17. package/build/src/akuma/call-request.js +10 -3
  18. package/build/src/akuma/caller.d.ts +39 -0
  19. package/build/src/akuma/caller.js +36 -0
  20. package/build/src/akuma/dispatch-association.d.ts +0 -1
  21. package/build/src/akuma/dispatch-association.js +0 -3
  22. package/build/src/akuma/heart/facts.d.ts +16 -12
  23. package/build/src/akuma/heart/facts.js +8 -0
  24. package/build/src/akuma/heart/index.d.ts +2 -7
  25. package/build/src/akuma/heart/index.js +3 -17
  26. package/build/src/akuma/heart/rows.d.ts +3 -3
  27. package/build/src/akuma/heart/soul.d.ts +1 -1
  28. package/build/src/akuma/heart/soul.js +5 -24
  29. package/build/src/akuma/heart/storage.d.ts +5 -0
  30. package/build/src/akuma/heart/storage.js +7 -3
  31. package/build/src/akuma/identity.d.ts +0 -1
  32. package/build/src/akuma/identity.js +2 -5
  33. package/build/src/akuma/index.d.ts +5 -2
  34. package/build/src/akuma/index.js +1 -0
  35. package/build/src/akuma/nuke.js +6 -28
  36. package/build/src/akuma/projection.d.ts +0 -11
  37. package/build/src/akuma/provider-recipe.d.ts +7 -6
  38. package/build/src/akuma/provider-recipe.js +1 -1
  39. package/build/src/akuma/provider.d.ts +6 -10
  40. package/build/src/akuma/provider.js +6 -7
  41. package/build/src/akuma/providers/acp/events.js +5 -18
  42. package/build/src/akuma/providers/acp/index.js +2 -3
  43. package/build/src/akuma/providers/claude/events.js +35 -60
  44. package/build/src/akuma/providers/claude/index.d.ts +2 -2
  45. package/build/src/akuma/providers/claude/index.js +2 -3
  46. package/build/src/akuma/providers/codex-app-server/index.js +2 -2
  47. package/build/src/akuma/providers/decode.d.ts +25 -0
  48. package/build/src/akuma/providers/decode.js +44 -0
  49. package/build/src/akuma/providers/execution-environment.d.ts +2 -1
  50. package/build/src/akuma/providers/execution-environment.js +3 -0
  51. package/build/src/akuma/providers/grok-build/index.js +6 -22
  52. package/build/src/akuma/providers/index.js +2 -0
  53. package/build/src/akuma/providers/lifecycle.d.ts +9 -0
  54. package/build/src/akuma/providers/lifecycle.js +10 -0
  55. package/build/src/akuma/providers/opencode-sdk/events.js +1 -14
  56. package/build/src/akuma/providers/opencode-sdk/index.js +10 -17
  57. package/build/src/akuma/providers/opencode-sdk/session.js +1 -3
  58. package/build/src/akuma/providers/paseo/events.d.ts +25 -0
  59. package/build/src/akuma/providers/paseo/events.js +157 -0
  60. package/build/src/akuma/providers/paseo/index.d.ts +9 -0
  61. package/build/src/akuma/providers/paseo/index.js +353 -0
  62. package/build/src/akuma/providers/pi/events.js +5 -15
  63. package/build/src/akuma/publication.d.ts +2 -0
  64. package/build/src/akuma/publication.js +5 -0
  65. package/build/src/akuma/request-lifecycle.d.ts +3 -0
  66. package/build/src/akuma/request-lifecycle.js +25 -4
  67. package/build/src/akuma/requests.d.ts +3 -1
  68. package/build/src/akuma/requests.js +32 -0
  69. package/build/src/akuma/selection-observation.d.ts +72 -2
  70. package/build/src/akuma/selection-observation.js +0 -6
  71. package/build/src/akuma/turn-drive.js +2 -5
  72. package/build/src/cli/akuma-caller.d.ts +3 -0
  73. package/build/src/cli/akuma-caller.js +21 -0
  74. package/build/src/cli/commands/akuma-grammar.js +7 -12
  75. package/build/src/cli/commands/akuma.js +12 -4
  76. package/build/src/cli/commands/contract-grammar.d.ts +2 -1
  77. package/build/src/cli/commands/contract-grammar.js +13 -15
  78. package/build/src/cli/commands/contract-help.d.ts +2 -1
  79. package/build/src/cli/commands/contract-help.js +31 -1
  80. package/build/src/cli/commands/contract.js +24 -53
  81. package/build/src/cli/commands/task.js +18 -35
  82. package/build/src/cli/parse.d.ts +2 -2
  83. package/build/src/cli/render/catalog.d.ts +2 -5
  84. package/build/src/cli/render/contract-history.js +3 -6
  85. package/build/src/cli/render/contract.js +15 -50
  86. package/build/src/cli/render/receipt.js +3 -10
  87. package/build/src/cli/render/task.d.ts +4 -6
  88. package/build/src/cli/render/task.js +9 -26
  89. package/build/src/cli/runtime.d.ts +1 -1
  90. package/build/src/cli/runtime.js +11 -17
  91. package/build/src/cli/selectors.d.ts +3 -6
  92. package/build/src/cli/selectors.js +22 -53
  93. package/build/src/dispatch/index.d.ts +3 -3
  94. package/build/src/dispatch/index.js +1 -2
  95. package/build/src/git/observe.d.ts +6 -2
  96. package/build/src/git/observe.js +6 -2
  97. package/build/src/index.d.ts +6 -6
  98. package/build/src/index.js +2 -2
  99. package/build/src/kanshi/index.d.ts +1 -1
  100. package/build/src/kanshi/read.js +21 -6
  101. package/build/src/library/address.js +2 -4
  102. package/build/src/library/akuma-creation.d.ts +5 -1
  103. package/build/src/library/akuma-creation.js +27 -47
  104. package/build/src/library/akumas.d.ts +5 -4
  105. package/build/src/library/akumas.js +13 -9
  106. package/build/src/library/bind.d.ts +14 -14
  107. package/build/src/library/bind.js +11 -7
  108. package/build/src/library/contract-address.d.ts +9 -0
  109. package/build/src/library/contract-address.js +71 -0
  110. package/build/src/library/contract-composition.d.ts +4 -7
  111. package/build/src/library/contract-composition.js +6 -18
  112. package/build/src/library/contract-creation.d.ts +3 -5
  113. package/build/src/library/contract-creation.js +19 -17
  114. package/build/src/library/contract-execution.js +18 -23
  115. package/build/src/library/contract-outcomes.d.ts +2 -14
  116. package/build/src/library/contract-outcomes.js +2 -13
  117. package/build/src/library/contract-types.d.ts +36 -2
  118. package/build/src/library/delivery.d.ts +0 -2
  119. package/build/src/library/delivery.js +2 -5
  120. package/build/src/library/keiyaku.d.ts +0 -5
  121. package/build/src/library/keiyaku.js +6 -12
  122. package/build/src/library/outcome.d.ts +500 -499
  123. package/build/src/library/outcome.js +10 -0
  124. package/build/src/library/reconcile.js +8 -16
  125. package/build/src/library/refusal.d.ts +2 -2
  126. package/build/src/library/repo.d.ts +3 -2
  127. package/build/src/library/repo.js +10 -5
  128. package/build/src/library/selection.d.ts +4 -4
  129. package/build/src/library/selection.js +12 -12
  130. package/build/src/plugin/akuma-signals.d.ts +2 -0
  131. package/build/src/plugin/akuma-signals.js +4 -0
  132. package/build/src/plugin/public.d.ts +27 -2
  133. package/build/src/plugin/runtime.js +2 -2
  134. package/build/src/protocol/amend.js +3 -2
  135. package/build/src/protocol/attempt.js +3 -8
  136. package/build/src/protocol/bind.d.ts +2 -2
  137. package/build/src/protocol/bind.js +1 -1
  138. package/build/src/protocol/deliver.js +3 -3
  139. package/build/src/protocol/operations.d.ts +1 -3
  140. package/build/src/protocol/operations.js +0 -8
  141. package/build/src/protocol/outcome.d.ts +1 -2
  142. package/build/src/protocol/outcome.js +1 -13
  143. package/build/src/protocol/placement.js +3 -10
  144. package/build/src/protocol/read/status.js +31 -70
  145. package/build/src/protocol/reintegrate.js +3 -10
  146. package/build/src/protocol/review.js +3 -3
  147. package/build/src/protocol/run.d.ts +5 -1
  148. package/build/src/protocol/run.js +3 -3
  149. package/build/src/runtime/proc/windows-launch.exe +0 -0
  150. package/package.json +8 -4
  151. package/plugins/pi/keiyaku.ts +57 -0
  152. package/skills/keiyaku/SKILL.md +44 -0
  153. package/skills/keiyaku-akuma/SKILL.md +130 -0
  154. package/skills/keiyaku-akuma/references/automation.md +269 -0
  155. package/skills/keiyaku-babysit/SKILL.md +65 -0
  156. package/skills/keiyaku-bind/SKILL.md +216 -0
  157. package/skills/keiyaku-bind/agents/openai.yaml +4 -0
  158. package/skills/keiyaku-task/SKILL.md +104 -0
  159. package/skills/keiyaku-workflow/SKILL.md +129 -0
  160. package/build/src/cli/commands/amend.d.ts +0 -12
  161. package/build/src/cli/commands/amend.js +0 -10
  162. package/build/src/cli/commands/bind.d.ts +0 -11
  163. package/build/src/cli/commands/bind.js +0 -23
  164. package/build/src/dispatch/association.d.ts +0 -1
  165. package/build/src/dispatch/association.js +0 -1
@@ -1,10 +1,11 @@
1
1
  import { lstat, readdir, rm, rmdir } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
3
  import { nukeAliases } from "../alias/index.js";
4
+ import { knownAkuma } from "./akuma.js";
4
5
  import { settleAkumaKill } from "./akuma-owner.js";
5
6
  import { acquireLeash } from "./control.js";
6
7
  import { classifyHeartSchema, readHeart } from "./heart/index.js";
7
- import { akuIdFromDirectoryName, akumaPaths, akumaRunRoot } from "./identity.js";
8
+ import { akumaRunRoot } from "./identity.js";
8
9
  export class AkumaResetStopError extends Error {
9
10
  constructor(message) {
10
11
  super(message);
@@ -105,6 +106,7 @@ async function removeKnownRequestChannel(path) {
105
106
  async function removeAkumaEntry(entry) {
106
107
  await removeKnownRequestChannel(entry.paths.requests);
107
108
  for (const path of [
109
+ join(entry.paths.directory, "request-entry.json"),
108
110
  entry.paths.log,
109
111
  `${entry.paths.heart}-wal`,
110
112
  `${entry.paths.heart}-shm`,
@@ -136,34 +138,10 @@ async function removeEmptyAkumaRunRoot(world) {
136
138
  await removeEmptyDirectory(dirname(runRoot));
137
139
  }
138
140
  async function nukeAkumaEntries(world) {
139
- const runRoot = akumaRunRoot(world);
140
- let names;
141
- try {
142
- names = (await readdir(runRoot, { withFileTypes: true }))
143
- .filter((entry) => entry.isDirectory())
144
- .map((entry) => entry.name)
145
- .sort();
146
- }
147
- catch (error) {
148
- if (error.code === "ENOENT")
149
- names = [];
150
- else
151
- throw error;
152
- }
153
141
  const entries = [];
154
- for (const name of names) {
155
- let physical;
156
- try {
157
- physical = akuIdFromDirectoryName(name);
158
- }
159
- catch {
160
- // The run root can contain bytes not produced by Keiyaku. Preserve them.
161
- continue;
162
- }
163
- const paths = akumaPaths({ runRoot, archetype: physical.archetype, suffix: physical.suffix });
164
- if (!(await hasAkumaCustody(paths)))
165
- continue;
166
- entries.push({ id: physical.id, paths });
142
+ for (const entry of (await knownAkuma(world)).rows) {
143
+ if (await hasAkumaCustody(entry.paths))
144
+ entries.push(entry);
167
145
  }
168
146
  return entries;
169
147
  }
@@ -56,15 +56,6 @@ export declare const tellRowSchema: z.ZodObject<{
56
56
  receipt?: "unavailable" | "required" | undefined;
57
57
  }>>>>;
58
58
  }, z.core.$strict>;
59
- declare const outcomeSchema: z.ZodUnion<readonly [z.ZodObject<{
60
- kind: z.ZodLiteral<"answered">;
61
- historyId: z.ZodString;
62
- answer: z.ZodString;
63
- }, z.core.$strict>, z.ZodObject<{
64
- kind: z.ZodLiteral<"failed">;
65
- historyId: z.ZodString;
66
- diagnostic: z.ZodString;
67
- }, z.core.$strict>]>;
68
59
  declare const outcomeRowSchema: z.ZodObject<{
69
60
  kind: z.ZodLiteral<"outcome">;
70
61
  sequence: z.ZodNumber;
@@ -920,7 +911,6 @@ export declare const activitySnapshotSchema: z.ZodUnion<readonly [z.ZodObject<{
920
911
  }, z.core.$strict>]>>>;
921
912
  omitted: z.ZodNumber;
922
913
  }, z.core.$strict>]>;
923
- export type TurnOutcome = z.infer<typeof outcomeSchema>;
924
914
  export type TurnStartRow = z.infer<typeof turnRowSchema>;
925
915
  type CallRow = z.infer<typeof callRowSchema>;
926
916
  type SaidRow = z.infer<ReturnType<typeof textRowSchema>>;
@@ -952,7 +942,6 @@ export type IdleSnapshotRow = z.infer<typeof idleSnapshotRowSchema>;
952
942
  export type SnapshotRow = OpenSnapshotRow | IdleSnapshotRow;
953
943
  export type ActivitySnapshotEntry<Row extends SnapshotRow = SnapshotRow> = z.infer<ReturnType<typeof snapshotEntrySchema<z.ZodType<Row>>>>;
954
944
  export type ReportedFileChange = z.infer<typeof reportedFileChangeSchema>;
955
- export type Snapshot = z.infer<typeof activitySnapshotSchema>;
956
945
  export type ActivitySnapshot = z.infer<typeof activitySnapshotSchema>;
957
946
  export type ActivityHistory = Readonly<{
958
947
  rows: readonly ActivityRow[];
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  declare const systemPromptModeSchema: z.ZodEnum<{
3
- append: "append";
4
3
  replace: "replace";
4
+ append: "append";
5
5
  }>;
6
6
  export type SystemPromptMode = z.infer<typeof systemPromptModeSchema>;
7
7
  export declare const providerOptionsSchema: z.ZodPipe<z.ZodObject<{
@@ -13,11 +13,11 @@ export declare const providerOptionsSchema: z.ZodPipe<z.ZodObject<{
13
13
  }>>;
14
14
  systemPrompt: z.ZodOptional<z.ZodString>;
15
15
  systemPromptMode: z.ZodOptional<z.ZodEnum<{
16
- append: "append";
17
16
  replace: "replace";
17
+ append: "append";
18
18
  }>>;
19
19
  }, z.core.$strip>, z.ZodTransform<Readonly<{
20
- systemPromptMode?: "append" | "replace";
20
+ systemPromptMode?: "replace" | "append";
21
21
  systemPrompt?: string;
22
22
  network?: "disabled" | "enabled";
23
23
  effort?: string;
@@ -27,7 +27,7 @@ export declare const providerOptionsSchema: z.ZodPipe<z.ZodObject<{
27
27
  effort?: string | undefined;
28
28
  network?: "disabled" | "enabled" | undefined;
29
29
  systemPrompt?: string | undefined;
30
- systemPromptMode?: "append" | "replace" | undefined;
30
+ systemPromptMode?: "replace" | "append" | undefined;
31
31
  }>>;
32
32
  export type ProviderOptions = z.infer<typeof providerOptionsSchema>;
33
33
  export declare const providerRecipeSchema: z.ZodPipe<z.ZodObject<{
@@ -38,6 +38,7 @@ export declare const providerRecipeSchema: z.ZodPipe<z.ZodObject<{
38
38
  "codex-app-server": "codex-app-server";
39
39
  "grok-build": "grok-build";
40
40
  "opencode-sdk": "opencode-sdk";
41
+ paseo: "paseo";
41
42
  pi: "pi";
42
43
  }>;
43
44
  executable: z.ZodOptional<z.ZodString>;
@@ -48,10 +49,10 @@ export declare const providerRecipeSchema: z.ZodPipe<z.ZodObject<{
48
49
  config?: Readonly<Record<string, unknown>>;
49
50
  executable?: string;
50
51
  name: string;
51
- kind: "acp" | "claude-agent-sdk" | "codex-app-server" | "grok-build" | "opencode-sdk" | "pi";
52
+ kind: "acp" | "claude-agent-sdk" | "codex-app-server" | "grok-build" | "opencode-sdk" | "paseo" | "pi";
52
53
  }>, {
53
54
  name: string;
54
- kind: "acp" | "claude-agent-sdk" | "codex-app-server" | "grok-build" | "opencode-sdk" | "pi";
55
+ kind: "acp" | "claude-agent-sdk" | "codex-app-server" | "grok-build" | "opencode-sdk" | "paseo" | "pi";
55
56
  executable?: string | undefined;
56
57
  config?: Record<string, unknown> | undefined;
57
58
  env?: Record<string, string> | undefined;
@@ -35,7 +35,7 @@ function snapshot(value) {
35
35
  export const providerRecipeSchema = z
36
36
  .object({
37
37
  name: z.string().refine((value) => value.trim() !== "", "provider execution name must be a nonblank string"),
38
- kind: z.enum(["acp", "claude-agent-sdk", "codex-app-server", "grok-build", "opencode-sdk", "pi"], {
38
+ kind: z.enum(["acp", "claude-agent-sdk", "codex-app-server", "grok-build", "opencode-sdk", "paseo", "pi"], {
39
39
  error: "provider execution has unknown kind",
40
40
  }),
41
41
  executable: z
@@ -1,13 +1,10 @@
1
1
  import { type ResumeCoordinate } from "./coordinate.js";
2
2
  import type { ProviderOptions } from "./provider-recipe.js";
3
3
  export type { ResumeCoordinate } from "./coordinate.js";
4
- export { decodeResumeCoordinate, encodeResumeCoordinate } from "./coordinate.js";
5
- export { AKUMA_REQUESTS_ENV } from "./providers/execution-environment.js";
6
- export declare const AGENT_EVENT_TEXT_LIMIT = 16384;
7
- export declare const AGENT_THOUGHT_TEXT_LIMIT = 4000;
4
+ export { AKUMA_REQUESTS_ENV, AKUMA_REQUESTS_ENTRY_ENV } from "./providers/execution-environment.js";
8
5
  export declare const AGENT_EVENT_QUEUE_LIMIT = 256;
9
- export { agentEventSchema, decodeAgentEvent } from "./heart/activity-schema.js";
10
- export type { AgentEvent, SearchScope, ToolCall, ToolEvent, ToolInput, ToolResult } from "./heart/activity-schema.js";
6
+ export { decodeAgentEvent } from "./heart/activity-schema.js";
7
+ export type { AgentEvent, SearchScope, ToolCall, ToolResult } from "./heart/activity-schema.js";
11
8
  import type { AgentEvent, ToolCall, ToolInput } from "./heart/activity-schema.js";
12
9
  export declare function encodeAgentEvent(event: AgentEvent): AgentEvent;
13
10
  /**
@@ -19,8 +16,6 @@ export declare function boundedToolInput(input: unknown): ToolInput | undefined;
19
16
  export declare function otherToolCall(display: string, input?: unknown): Extract<ToolCall, {
20
17
  kind: "other";
21
18
  }>;
22
- export declare function boundedEventText(value: string): string;
23
- export declare function boundedThoughtText(value: string): string;
24
19
  export declare function noteEvent(note: string): Extract<AgentEvent, {
25
20
  type: "note";
26
21
  }>;
@@ -45,7 +40,7 @@ export type TurnResult = Readonly<{
45
40
  kind: "failed";
46
41
  diagnostic: string;
47
42
  }>;
48
- export type ProviderFence = string;
43
+ type ProviderFence = string;
49
44
  export type TellReceipt = Readonly<{
50
45
  evidence: "exact";
51
46
  tellId: string;
@@ -87,7 +82,7 @@ export type ProviderAttempt<Result> = Readonly<{
87
82
  abort(): Promise<void>;
88
83
  forceDispose(): Promise<void>;
89
84
  }>;
90
- export type AttemptResource = Readonly<{
85
+ type AttemptResource = Readonly<{
91
86
  /** Resolves only when this physical resource has retired. */
92
87
  closed: Promise<void>;
93
88
  abort?(): Promise<void>;
@@ -115,6 +110,7 @@ export type DriveInput = Readonly<{
115
110
  signal: AbortSignal;
116
111
  requests: Readonly<{
117
112
  dir: string;
113
+ entry?: string;
118
114
  }>;
119
115
  schemaJson?: string;
120
116
  }>;
@@ -1,9 +1,8 @@
1
- export { decodeResumeCoordinate, encodeResumeCoordinate } from "./coordinate.js";
2
- export { AKUMA_REQUESTS_ENV } from "./providers/execution-environment.js";
3
- export const AGENT_EVENT_TEXT_LIMIT = 16_384;
4
- export const AGENT_THOUGHT_TEXT_LIMIT = 4_000;
1
+ export { AKUMA_REQUESTS_ENV, AKUMA_REQUESTS_ENTRY_ENV } from "./providers/execution-environment.js";
2
+ const AGENT_EVENT_TEXT_LIMIT = 16_384;
3
+ const AGENT_THOUGHT_TEXT_LIMIT = 4_000;
5
4
  export const AGENT_EVENT_QUEUE_LIMIT = 256;
6
- export { agentEventSchema, decodeAgentEvent } from "./heart/activity-schema.js";
5
+ export { decodeAgentEvent } from "./heart/activity-schema.js";
7
6
  function boundedToolCall(call) {
8
7
  switch (call.kind) {
9
8
  case "run":
@@ -156,10 +155,10 @@ function boundedToolInputJson(value) {
156
155
  }
157
156
  return { value: prefix, truncated: true };
158
157
  }
159
- export function boundedEventText(value) {
158
+ function boundedEventText(value) {
160
159
  return value.slice(0, AGENT_EVENT_TEXT_LIMIT);
161
160
  }
162
- export function boundedThoughtText(value) {
161
+ function boundedThoughtText(value) {
163
162
  return value.slice(0, AGENT_THOUGHT_TEXT_LIMIT);
164
163
  }
165
164
  export function noteEvent(note) {
@@ -1,4 +1,5 @@
1
1
  import { noteEvent, otherToolCall, unknownEvent } from "../../provider.js";
2
+ import { nonblank, object, positiveLine } from "../decode.js";
2
3
  export const EMPTY_ACP_EVENT_STATE = Object.freeze({
3
4
  answer: "",
4
5
  assistantMessageId: null,
@@ -27,20 +28,6 @@ function appendBlock(state, type, text, messageId) {
27
28
  },
28
29
  };
29
30
  }
30
- function nonblank(value) {
31
- return typeof value === "string" && value.trim().length > 0 ? value : undefined;
32
- }
33
- function object(value) {
34
- return value !== null && typeof value === "object" && !Array.isArray(value)
35
- ? value
36
- : undefined;
37
- }
38
- function positiveLine(value) {
39
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 1 ? value : undefined;
40
- }
41
- function otherCall(name, input) {
42
- return otherToolCall(name, input);
43
- }
44
31
  function locationFact(locations) {
45
32
  if (locations === null || locations === undefined)
46
33
  return {};
@@ -57,7 +44,7 @@ function standardCall(update, name) {
57
44
  const location = locationFact(update.locations);
58
45
  if (update.kind === "read") {
59
46
  return location.path === undefined
60
- ? otherCall(name, update.rawInput)
47
+ ? otherToolCall(name, update.rawInput)
61
48
  : {
62
49
  kind: "read",
63
50
  path: location.path,
@@ -67,12 +54,12 @@ function standardCall(update, name) {
67
54
  const input = object(update.rawInput);
68
55
  if (update.kind === "execute") {
69
56
  const command = nonblank(input?.command);
70
- return command === undefined ? otherCall(name, update.rawInput) : { kind: "run", command };
57
+ return command === undefined ? otherToolCall(name, update.rawInput) : { kind: "run", command };
71
58
  }
72
59
  if (update.kind === "search") {
73
60
  const query = nonblank(input?.query);
74
61
  if (query === undefined)
75
- return otherCall(name, update.rawInput);
62
+ return otherToolCall(name, update.rawInput);
76
63
  const path = nonblank(input?.path);
77
64
  const glob = nonblank(input?.glob);
78
65
  const scope = input?.scope;
@@ -85,7 +72,7 @@ function standardCall(update, name) {
85
72
  ...(glob === undefined ? {} : { glob }),
86
73
  };
87
74
  }
88
- return otherCall(name, update.rawInput);
75
+ return otherToolCall(name, update.rawInput);
89
76
  }
90
77
  function strongest(previous, next) {
91
78
  if (previous === undefined || previous.kind === "other")
@@ -1,4 +1,4 @@
1
- import { createProviderAttempt } from "../../provider.js";
1
+ import { providerLifecycle } from "../lifecycle.js";
2
2
  import { decodeAcpConfig } from "./config.js";
3
3
  import { startAcpSession } from "./core.js";
4
4
  export { decodeAcpConfig } from "./config.js";
@@ -63,7 +63,6 @@ export function createAcpProvider(execution, dependencies = {}) {
63
63
  };
64
64
  return {
65
65
  admitOptions: (options) => optionAdmission(options, config),
66
- start: (input) => createProviderAttempt(input.signal, async (custody) => await drive({ ...input, signal: custody.signal }, custody)),
67
- resume: (input) => createProviderAttempt(input.signal, async (custody) => await drive({ ...input, signal: custody.signal }, custody)),
66
+ ...providerLifecycle(drive),
68
67
  };
69
68
  }
@@ -1,4 +1,5 @@
1
1
  import { noteEvent, otherToolCall, unknownEvent } from "../../provider.js";
2
+ import { finiteNumber, object, positiveLine, searchToolCall, trimmed } from "../decode.js";
2
3
  export const CLAUDE_MESSAGE_DISPOSITIONS = {
3
4
  assistant: "assistant",
4
5
  auth_status: "auth",
@@ -42,20 +43,6 @@ export const CLAUDE_SYSTEM_DISPOSITIONS = {
42
43
  thinking_tokens: "drop",
43
44
  worker_shutting_down: "note",
44
45
  };
45
- function object(value) {
46
- return value !== null && typeof value === "object" && !Array.isArray(value)
47
- ? value
48
- : undefined;
49
- }
50
- function nonblank(value) {
51
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
52
- }
53
- function number(value) {
54
- return typeof value === "number" && Number.isFinite(value) ? value : undefined;
55
- }
56
- function positiveLine(value) {
57
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 1 ? value : undefined;
58
- }
59
46
  function readRange(value) {
60
47
  const offset = positiveLine(value.offset);
61
48
  const limit = positiveLine(value.limit);
@@ -64,21 +51,10 @@ function readRange(value) {
64
51
  ...(limit === undefined ? {} : { limit }),
65
52
  };
66
53
  }
67
- function contentSearch(value, query) {
68
- const path = nonblank(value.path);
69
- const glob = nonblank(value.glob);
70
- return {
71
- kind: "search",
72
- query,
73
- scope: "content",
74
- ...(path === undefined ? {} : { path }),
75
- ...(glob === undefined ? {} : { glob }),
76
- };
77
- }
78
54
  const CLAUDE_SYSTEM_NOTES = {
79
55
  api_retry: (message) => {
80
- const attempt = number(message.attempt);
81
- const maximum = number(message.max_retries);
56
+ const attempt = finiteNumber(message.attempt);
57
+ const maximum = finiteNumber(message.max_retries);
82
58
  return attempt === undefined || maximum === undefined
83
59
  ? "Retrying request"
84
60
  : `Retrying request ${attempt}/${maximum}`;
@@ -90,24 +66,24 @@ const CLAUDE_SYSTEM_NOTES = {
90
66
  const failed = Array.isArray(message.failed) ? message.failed.length : 0;
91
67
  return failed === 0 ? `Persisted ${files} files` : `Persisted ${files} files; ${failed} failed`;
92
68
  },
93
- informational: (message) => nonblank(message.content) ?? "Informational notice",
94
- mirror_error: (message) => `Transcript mirror warning: ${nonblank(message.error) ?? nonblank(message.message) ?? "unknown error"}`,
69
+ informational: (message) => trimmed(message.content) ?? "Informational notice",
70
+ mirror_error: (message) => `Transcript mirror warning: ${trimmed(message.error) ?? trimmed(message.message) ?? "unknown error"}`,
95
71
  model_refusal_fallback: () => "Model refusal; using fallback",
96
72
  model_refusal_no_fallback: () => "Model refusal; no fallback available",
97
- notification: (message) => nonblank(message.message) ?? nonblank(message.content) ?? "Notification",
98
- permission_denied: (message) => `Permission refused${nonblank(message.message) === undefined ? "" : `: ${nonblank(message.message)}`}`,
99
- plugin_install: (message) => `Plugin install ${nonblank(message.status) ?? "updated"}${nonblank(message.name) === undefined ? "" : `: ${nonblank(message.name)}`}`,
100
- status: (message) => `Status: ${nonblank(message.status) ?? "idle"}${nonblank(message.error) === undefined ? "" : ` (${nonblank(message.error)})`}`,
101
- task_notification: (message) => `Task ${nonblank(message.task_id) ?? "unknown"} ${nonblank(message.status) ?? "updated"}`,
102
- task_progress: (message) => nonblank(message.description) ?? `Task ${nonblank(message.task_id) ?? "unknown"} progressed`,
103
- task_started: (message) => nonblank(message.description) ?? `Task ${nonblank(message.task_id) ?? "unknown"} started`,
104
- task_updated: (message) => `Task ${nonblank(message.task_id) ?? "unknown"} updated`,
105
- worker_shutting_down: (message) => `Worker stopping: ${nonblank(message.reason) ?? "unknown reason"}`,
73
+ notification: (message) => trimmed(message.message) ?? trimmed(message.content) ?? "Notification",
74
+ permission_denied: (message) => `Permission refused${trimmed(message.message) === undefined ? "" : `: ${trimmed(message.message)}`}`,
75
+ plugin_install: (message) => `Plugin install ${trimmed(message.status) ?? "updated"}${trimmed(message.name) === undefined ? "" : `: ${trimmed(message.name)}`}`,
76
+ status: (message) => `Status: ${trimmed(message.status) ?? "idle"}${trimmed(message.error) === undefined ? "" : ` (${trimmed(message.error)})`}`,
77
+ task_notification: (message) => `Task ${trimmed(message.task_id) ?? "unknown"} ${trimmed(message.status) ?? "updated"}`,
78
+ task_progress: (message) => trimmed(message.description) ?? `Task ${trimmed(message.task_id) ?? "unknown"} progressed`,
79
+ task_started: (message) => trimmed(message.description) ?? `Task ${trimmed(message.task_id) ?? "unknown"} started`,
80
+ task_updated: (message) => `Task ${trimmed(message.task_id) ?? "unknown"} updated`,
81
+ worker_shutting_down: (message) => `Worker stopping: ${trimmed(message.reason) ?? "unknown reason"}`,
106
82
  };
107
83
  function runCall(name, value, input) {
108
84
  if (name !== "Bash")
109
85
  return undefined;
110
- const command = nonblank(value.command);
86
+ const command = trimmed(value.command);
111
87
  return command === undefined ? otherToolCall(name, input) : { kind: "run", command };
112
88
  }
113
89
  function readCall(name, path, value) {
@@ -115,19 +91,18 @@ function readCall(name, path, value) {
115
91
  }
116
92
  function searchCall(name, value) {
117
93
  if (name === "Grep") {
118
- const query = nonblank(value.pattern) ?? nonblank(value.query);
119
- return query === undefined ? undefined : contentSearch(value, query);
120
- }
121
- if (name === "Glob") {
122
- const query = nonblank(value.pattern);
123
- const globPath = nonblank(value.path);
94
+ const query = trimmed(value.pattern) ?? trimmed(value.query);
124
95
  return query === undefined
125
96
  ? undefined
126
- : { kind: "search", query, scope: "files", ...(globPath === undefined ? {} : { path: globPath }) };
97
+ : searchToolCall(query, "content", { path: trimmed(value.path), glob: trimmed(value.glob) });
98
+ }
99
+ if (name === "Glob") {
100
+ const query = trimmed(value.pattern);
101
+ return query === undefined ? undefined : searchToolCall(query, "files", { path: trimmed(value.path) });
127
102
  }
128
103
  if (name === "WebSearch") {
129
- const query = nonblank(value.query);
130
- return query === undefined ? undefined : { kind: "search", query, scope: "web" };
104
+ const query = trimmed(value.query);
105
+ return query === undefined ? undefined : searchToolCall(query, "web");
131
106
  }
132
107
  return undefined;
133
108
  }
@@ -143,8 +118,8 @@ function fileChangeCall(name, path) {
143
118
  }
144
119
  function startedPath(name, value) {
145
120
  if (name === "NotebookEdit")
146
- return nonblank(value.notebook_path);
147
- return nonblank(value.file_path) ?? (name === "Read" ? nonblank(value.path) : undefined);
121
+ return trimmed(value.notebook_path);
122
+ return trimmed(value.file_path) ?? (name === "Read" ? trimmed(value.path) : undefined);
148
123
  }
149
124
  function nonnegativeInt(value) {
150
125
  return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : undefined;
@@ -163,7 +138,7 @@ function writeResult(result) {
163
138
  const value = object(result);
164
139
  if (value === undefined || (value.type !== "create" && value.type !== "update"))
165
140
  return undefined;
166
- const path = nonblank(value.filePath);
141
+ const path = trimmed(value.filePath);
167
142
  if (path === undefined)
168
143
  return undefined;
169
144
  const op = value.type === "create" ? "add" : "update";
@@ -173,14 +148,14 @@ function editResult(result) {
173
148
  const value = object(result);
174
149
  if (value === undefined || value.type === "create" || value.type === "update")
175
150
  return undefined;
176
- const path = nonblank(value.filePath);
151
+ const path = trimmed(value.filePath);
177
152
  if (path === undefined)
178
153
  return undefined;
179
154
  const status = object(value.gitDiff)?.status;
180
155
  return fileChange(status === "added" ? "add" : "update", path, value.gitDiff);
181
156
  }
182
157
  function notebookResult(result) {
183
- const path = nonblank(object(result)?.notebook_path);
158
+ const path = trimmed(object(result)?.notebook_path);
184
159
  return path === undefined ? undefined : { kind: "fileChange", changes: [{ op: "update", path }] };
185
160
  }
186
161
  function structuredFileChange(name, result) {
@@ -232,7 +207,7 @@ function toolResultEvents(message, events, state) {
232
207
  const value = object(block);
233
208
  if (value?.type !== "tool_result")
234
209
  continue;
235
- const id = nonblank(value.tool_use_id);
210
+ const id = trimmed(value.tool_use_id);
236
211
  if (id === undefined)
237
212
  continue;
238
213
  const observed = state.tools.get(id);
@@ -252,15 +227,15 @@ function toolResultEvents(message, events, state) {
252
227
  }
253
228
  }
254
229
  function hookResponseNote(value) {
255
- const outcome = nonblank(value.outcome);
230
+ const outcome = trimmed(value.outcome);
256
231
  if (outcome !== "error" && outcome !== "cancelled")
257
232
  return undefined;
258
- const hook = nonblank(value.hook_name) ?? "unknown";
259
- const exitCode = number(value.exit_code);
233
+ const hook = trimmed(value.hook_name) ?? "unknown";
234
+ const exitCode = finiteNumber(value.exit_code);
260
235
  return `Hook ${hook} ${outcome}${exitCode === undefined ? "" : ` (exit ${exitCode})`}`;
261
236
  }
262
237
  function emitSystemMessage(value, events) {
263
- const subtype = nonblank(value?.subtype) ?? "unknown";
238
+ const subtype = trimmed(value?.subtype) ?? "unknown";
264
239
  if (!Object.hasOwn(CLAUDE_SYSTEM_DISPOSITIONS, subtype)) {
265
240
  events.emit(unknownEvent(subtype));
266
241
  return;
@@ -281,7 +256,7 @@ function emitSystemMessage(value, events) {
281
256
  }
282
257
  export function emitClaudeMessage(message, events, state) {
283
258
  const value = object(message) ?? {};
284
- const kind = nonblank(value.type) ?? "unknown";
259
+ const kind = trimmed(value.type) ?? "unknown";
285
260
  if (!Object.hasOwn(CLAUDE_MESSAGE_DISPOSITIONS, kind))
286
261
  return events.emit(unknownEvent(kind));
287
262
  const disposition = CLAUDE_MESSAGE_DISPOSITIONS[kind];
@@ -292,7 +267,7 @@ export function emitClaudeMessage(message, events, state) {
292
267
  toolResultEvents(message, events, state);
293
268
  }
294
269
  else if (disposition === "auth") {
295
- const error = nonblank(value.error);
270
+ const error = trimmed(value.error);
296
271
  if (error !== undefined)
297
272
  events.emit(noteEvent(`Authentication warning: ${error}`));
298
273
  }
@@ -2,13 +2,12 @@ import type { Options, Query, SDKUserMessage } from "@anthropic-ai/claude-agent-
2
2
  import { type ProviderAdapter, type Session } from "../../provider.js";
3
3
  import type { ProviderOptions } from "../../provider-recipe.js";
4
4
  import type { ResumeCoordinate } from "../../provider.js";
5
- export { CLAUDE_MESSAGE_DISPOSITIONS, CLAUDE_SYSTEM_DISPOSITIONS } from "./events.js";
6
5
  type ClaudeExecution = Readonly<{
7
6
  executable?: string;
8
7
  config?: Readonly<Record<string, unknown>>;
9
8
  env?: Readonly<Record<string, string>>;
10
9
  }>;
11
- export type ClaudeSdk = Readonly<{
10
+ type ClaudeSdk = Readonly<{
12
11
  query(input: Readonly<{
13
12
  prompt: string | AsyncIterable<SDKUserMessage>;
14
13
  options?: Options;
@@ -42,3 +41,4 @@ export declare const claudeProvider: Readonly<{
42
41
  }>;
43
42
  }>): import("../../provider.js").ProviderAttempt<Session>;
44
43
  }>;
44
+ export {};
@@ -2,9 +2,9 @@ import { randomUUID } from "node:crypto";
2
2
  import { abortable } from "../../abort.js";
3
3
  import { AgentEventChannel, createProviderAttempt, } from "../../provider.js";
4
4
  import { akumaExecutionEnvironment } from "../execution-environment.js";
5
+ import { providerLifecycle } from "../lifecycle.js";
5
6
  import { emitClaudeMessage } from "./events.js";
6
7
  import { claudeUserMessage, createClaudeInput, isClaudeTurnEnded } from "./input.js";
7
- export { CLAUDE_MESSAGE_DISPOSITIONS, CLAUDE_SYSTEM_DISPOSITIONS } from "./events.js";
8
8
  class ReceiptChannel {
9
9
  queued = [];
10
10
  waiters = [];
@@ -364,8 +364,7 @@ export function createClaudeProvider(loadOrExecution = async () => (await import
364
364
  return {
365
365
  admitOptions: admitClaudeOptions,
366
366
  fork: (input) => createProviderAttempt(new AbortController().signal, async () => await forkClaude(load, selectedExecution, input)),
367
- start: (input) => createProviderAttempt(input.signal, async (custody) => await driveClaude(load, selectedExecution, { ...input, signal: custody.signal }, custody)),
368
- resume: (input) => createProviderAttempt(input.signal, async (custody) => await driveClaude(load, selectedExecution, { ...input, signal: custody.signal }, custody)),
367
+ ...providerLifecycle((input, custody) => driveClaude(load, selectedExecution, input, custody)),
369
368
  };
370
369
  }
371
370
  export const claudeProvider = createClaudeProvider(async () => (await import("@anthropic-ai/claude-agent-sdk")));
@@ -1,6 +1,7 @@
1
1
  import { LineRpcProcess } from "../../../runtime/proc/line-rpc.js";
2
2
  import { AgentEventChannel, createProviderAttempt, } from "../../provider.js";
3
3
  import { akumaExecutionEnvironment } from "../execution-environment.js";
4
+ import { providerLifecycle } from "../lifecycle.js";
4
5
  import { codexNotificationResult, codexObject, codexText } from "./events.js";
5
6
  export { CODEX_ITEM_DISPOSITIONS, CODEX_NOTIFICATION_DISPOSITIONS } from "./events.js";
6
7
  function diagnostic(error) {
@@ -214,7 +215,6 @@ export function createCodexAppServerProvider(input = "codex") {
214
215
  };
215
216
  },
216
217
  fork: (input) => createProviderAttempt(new AbortController().signal, async (custody) => await forkCodex(execution, input, custody)),
217
- start: (input) => createProviderAttempt(input.signal, async (custody) => await startCodex(execution, { ...input, signal: custody.signal }, custody)),
218
- resume: (input) => createProviderAttempt(input.signal, async (custody) => await startCodex(execution, { ...input, signal: custody.signal }, custody)),
218
+ ...providerLifecycle((input, custody) => startCodex(execution, input, custody)),
219
219
  };
220
220
  }
@@ -0,0 +1,25 @@
1
+ import type { SearchScope, ToolCall } from "../provider.js";
2
+ /**
3
+ * Native payload decoders shared by provider event adaptation. Every adapter
4
+ * reads the same untrusted native shapes; these are the only places that decide
5
+ * what a present value means, so each keeps one exact predicate and return.
6
+ */
7
+ export declare function isRecord(value: unknown): value is Readonly<Record<string, unknown>>;
8
+ export declare function object(value: unknown): Readonly<Record<string, unknown>> | undefined;
9
+ /** A string with non-blank trim, returned as supplied. */
10
+ export declare function nonblank(value: unknown): string | undefined;
11
+ /** A string with non-blank trim, returned trimmed. */
12
+ export declare function trimmed(value: unknown): string | undefined;
13
+ /** A nonempty string, returned as supplied; internal whitespace stays content. */
14
+ export declare function text(value: unknown): string | undefined;
15
+ /** A one-based line number. */
16
+ export declare function positiveLine(value: unknown): number | undefined;
17
+ export declare function nonnegativeCount(value: unknown): number | undefined;
18
+ export declare function finiteNumber(value: unknown): number | undefined;
19
+ /** One neutral search call carrying only the bounds the native input supplied. */
20
+ export declare function searchToolCall(query: string, scope: SearchScope | undefined, bounds?: Readonly<{
21
+ path?: string | undefined;
22
+ glob?: string | undefined;
23
+ }>): Extract<ToolCall, {
24
+ kind: "search";
25
+ }>;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Native payload decoders shared by provider event adaptation. Every adapter
3
+ * reads the same untrusted native shapes; these are the only places that decide
4
+ * what a present value means, so each keeps one exact predicate and return.
5
+ */
6
+ export function isRecord(value) {
7
+ return value !== null && typeof value === "object" && !Array.isArray(value);
8
+ }
9
+ export function object(value) {
10
+ return isRecord(value) ? value : undefined;
11
+ }
12
+ /** A string with non-blank trim, returned as supplied. */
13
+ export function nonblank(value) {
14
+ return typeof value === "string" && value.trim().length > 0 ? value : undefined;
15
+ }
16
+ /** A string with non-blank trim, returned trimmed. */
17
+ export function trimmed(value) {
18
+ const text = nonblank(value);
19
+ return text === undefined ? undefined : text.trim();
20
+ }
21
+ /** A nonempty string, returned as supplied; internal whitespace stays content. */
22
+ export function text(value) {
23
+ return typeof value === "string" && value.length > 0 ? value : undefined;
24
+ }
25
+ /** A one-based line number. */
26
+ export function positiveLine(value) {
27
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 1 ? value : undefined;
28
+ }
29
+ export function nonnegativeCount(value) {
30
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
31
+ }
32
+ export function finiteNumber(value) {
33
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
34
+ }
35
+ /** One neutral search call carrying only the bounds the native input supplied. */
36
+ export function searchToolCall(query, scope, bounds = {}) {
37
+ return {
38
+ kind: "search",
39
+ query,
40
+ ...(scope === undefined ? {} : { scope }),
41
+ ...(bounds.path === undefined ? {} : { path: bounds.path }),
42
+ ...(bounds.glob === undefined ? {} : { glob: bounds.glob }),
43
+ };
44
+ }
@@ -1,5 +1,6 @@
1
1
  export declare const AKUMA_REQUESTS_ENV = "AKUMA_REQUESTS";
2
- declare const PARENT_HARNESS_IDENTITY_KEYS: readonly ["CLAUDE_CODE_SESSION_ID", "CLAUDE_CODE_CHILD_SESSION", "CLAUDECODE", "CODEX_THREAD_ID", "OPENCODE_SESSION_ID", "PI_SESSION_ID", "PI_SESSION_FILE", "PASEO_AGENT_ID", "SQUARE_PARTICIPANT_NAME"];
2
+ export declare const AKUMA_REQUESTS_ENTRY_ENV = "AKUMA_REQUESTS_ENTRY";
3
+ declare const PARENT_HARNESS_IDENTITY_KEYS: readonly ["CLAUDE_CODE_SESSION_ID", "CLAUDE_CODE_CHILD_SESSION", "CLAUDECODE", "CODEX_THREAD_ID", "OPENCODE_SESSION_ID", "PI_SESSION_ID", "PI_SESSION_FILE", "PASEO_AGENT_ID", "SQUARE_PARTICIPANT_NAME", "KEIYAKU_EXTERNAL_CALLER"];
3
4
  type Environment = Readonly<Record<string, string | undefined>>;
4
5
  /** Construct the environment for one isolated Akuma execution or native child. */
5
6
  export declare function akumaExecutionEnvironment(inherited: Environment, overrides?: Environment, requests?: string, nativeIdentity?: readonly (typeof PARENT_HARNESS_IDENTITY_KEYS)[number][]): Record<string, string>;