@astrosheep/keiyaku 4.6.6 → 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.
- package/README.md +11 -0
- package/build/{integrations/marketplace → plugins}/.agents/plugins/marketplace.json +1 -1
- package/build/plugins/.claude-plugin/marketplace.json +5 -0
- package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/.claude-plugin/plugin.json +1 -1
- package/build/{integrations/marketplace/plugins/keiyaku → plugins/codex}/.codex-plugin/plugin.json +1 -1
- package/build/plugins/codex/skills/keiyaku/SKILL.md +44 -0
- package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +130 -0
- package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +269 -0
- package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +65 -0
- package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +216 -0
- package/build/plugins/codex/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/build/plugins/codex/skills/keiyaku-task/SKILL.md +104 -0
- package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +129 -0
- package/build/plugins/opencode/package.json +6 -0
- package/build/plugins/opencode/skills/keiyaku/SKILL.md +44 -0
- package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +130 -0
- package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +269 -0
- package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +65 -0
- package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +216 -0
- package/build/plugins/opencode/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +104 -0
- package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +129 -0
- package/build/{integrations → plugins}/pi/keiyaku.ts +0 -5
- package/build/skills/keiyaku/SKILL.md +44 -0
- package/build/skills/keiyaku-akuma/SKILL.md +130 -0
- package/build/skills/keiyaku-akuma/references/automation.md +269 -0
- package/build/skills/keiyaku-babysit/SKILL.md +65 -0
- package/build/skills/keiyaku-bind/SKILL.md +216 -0
- package/build/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/build/skills/keiyaku-task/SKILL.md +104 -0
- package/build/skills/keiyaku-workflow/SKILL.md +129 -0
- package/build/src/akuma/akuma-call.d.ts +2 -0
- package/build/src/akuma/akuma-call.js +8 -2
- package/build/src/akuma/akuma-instance.d.ts +12 -1
- package/build/src/akuma/akuma-instance.js +31 -9
- package/build/src/akuma/akuma-observe.d.ts +4 -0
- package/build/src/akuma/akuma-observe.js +14 -0
- package/build/src/akuma/akuma-owner.d.ts +6 -2
- package/build/src/akuma/akuma-owner.js +32 -10
- package/build/src/akuma/akuma-selection-execution.d.ts +3 -1
- package/build/src/akuma/akuma-selection-execution.js +2 -1
- package/build/src/akuma/akuma-wait.d.ts +2 -1
- package/build/src/akuma/akuma-wait.js +4 -1
- package/build/src/akuma/akuma.d.ts +35 -5
- package/build/src/akuma/akuma.js +8 -10
- package/build/src/akuma/archetype.d.ts +7 -15
- package/build/src/akuma/archetype.js +36 -35
- package/build/src/akuma/body.d.ts +6 -3
- package/build/src/akuma/body.js +41 -30
- package/build/src/akuma/call-request.d.ts +18 -10
- package/build/src/akuma/call-request.js +10 -3
- package/build/src/akuma/caller.d.ts +39 -0
- package/build/src/akuma/caller.js +36 -0
- package/build/src/akuma/dispatch-association.d.ts +0 -1
- package/build/src/akuma/dispatch-association.js +0 -3
- package/build/src/akuma/heart/facts.d.ts +16 -12
- package/build/src/akuma/heart/facts.js +8 -0
- package/build/src/akuma/heart/index.d.ts +2 -7
- package/build/src/akuma/heart/index.js +3 -17
- package/build/src/akuma/heart/rows.d.ts +3 -3
- package/build/src/akuma/heart/soul.d.ts +1 -1
- package/build/src/akuma/heart/soul.js +5 -24
- package/build/src/akuma/heart/storage.d.ts +5 -0
- package/build/src/akuma/heart/storage.js +7 -3
- package/build/src/akuma/identity.d.ts +0 -1
- package/build/src/akuma/identity.js +2 -5
- package/build/src/akuma/index.d.ts +5 -2
- package/build/src/akuma/index.js +1 -0
- package/build/src/akuma/nuke.js +6 -28
- package/build/src/akuma/projection.d.ts +0 -11
- package/build/src/akuma/provider-recipe.d.ts +7 -6
- package/build/src/akuma/provider-recipe.js +1 -1
- package/build/src/akuma/provider.d.ts +6 -10
- package/build/src/akuma/provider.js +6 -7
- package/build/src/akuma/providers/acp/events.js +5 -18
- package/build/src/akuma/providers/acp/index.js +2 -3
- package/build/src/akuma/providers/claude/events.js +35 -60
- package/build/src/akuma/providers/claude/index.d.ts +2 -2
- package/build/src/akuma/providers/claude/index.js +2 -3
- package/build/src/akuma/providers/codex-app-server/index.js +2 -2
- package/build/src/akuma/providers/decode.d.ts +25 -0
- package/build/src/akuma/providers/decode.js +44 -0
- package/build/src/akuma/providers/execution-environment.d.ts +2 -1
- package/build/src/akuma/providers/execution-environment.js +3 -0
- package/build/src/akuma/providers/grok-build/index.js +6 -22
- package/build/src/akuma/providers/index.js +2 -0
- package/build/src/akuma/providers/lifecycle.d.ts +9 -0
- package/build/src/akuma/providers/lifecycle.js +10 -0
- package/build/src/akuma/providers/opencode-sdk/events.js +1 -14
- package/build/src/akuma/providers/opencode-sdk/index.js +10 -17
- package/build/src/akuma/providers/opencode-sdk/session.js +1 -3
- package/build/src/akuma/providers/paseo/events.d.ts +25 -0
- package/build/src/akuma/providers/paseo/events.js +157 -0
- package/build/src/akuma/providers/paseo/index.d.ts +9 -0
- package/build/src/akuma/providers/paseo/index.js +353 -0
- package/build/src/akuma/providers/pi/events.js +5 -15
- package/build/src/akuma/publication.d.ts +2 -0
- package/build/src/akuma/publication.js +5 -0
- package/build/src/akuma/request-lifecycle.d.ts +3 -0
- package/build/src/akuma/request-lifecycle.js +25 -4
- package/build/src/akuma/requests.d.ts +3 -1
- package/build/src/akuma/requests.js +32 -0
- package/build/src/akuma/selection-observation.d.ts +72 -2
- package/build/src/akuma/selection-observation.js +0 -6
- package/build/src/akuma/selection-owner-port.d.ts +1 -1
- package/build/src/akuma/selection-owner-port.js +16 -5
- package/build/src/akuma/selection-request.d.ts +2 -0
- package/build/src/akuma/selection-request.js +2 -1
- package/build/src/akuma/turn-drive.js +2 -5
- package/build/src/akuma-body.js +4 -2
- package/build/src/cli/akuma-caller.d.ts +3 -0
- package/build/src/cli/akuma-caller.js +21 -0
- package/build/src/cli/commands/akuma-grammar.js +7 -12
- package/build/src/cli/commands/akuma.js +18 -16
- package/build/src/cli/commands/contract-grammar.d.ts +2 -1
- package/build/src/cli/commands/contract-grammar.js +13 -15
- package/build/src/cli/commands/contract-help.d.ts +2 -1
- package/build/src/cli/commands/contract-help.js +31 -1
- package/build/src/cli/commands/contract.js +24 -53
- package/build/src/cli/commands/install.js +3 -3
- package/build/src/cli/commands/task.js +18 -35
- package/build/src/cli/parse.d.ts +2 -2
- package/build/src/cli/render/catalog.d.ts +2 -5
- package/build/src/cli/render/contract-history.js +3 -6
- package/build/src/cli/render/contract.js +15 -50
- package/build/src/cli/render/receipt.js +3 -10
- package/build/src/cli/render/task.d.ts +4 -6
- package/build/src/cli/render/task.js +9 -26
- package/build/src/cli/runtime.d.ts +1 -1
- package/build/src/cli/runtime.js +11 -17
- package/build/src/cli/selectors.d.ts +3 -6
- package/build/src/cli/selectors.js +22 -53
- package/build/src/dispatch/index.d.ts +3 -3
- package/build/src/dispatch/index.js +1 -2
- package/build/src/git/observe.d.ts +6 -2
- package/build/src/git/observe.js +6 -2
- package/build/src/index.d.ts +6 -6
- package/build/src/index.js +2 -2
- package/build/src/kanshi/index.d.ts +1 -1
- package/build/src/kanshi/read.js +21 -6
- package/build/src/library/address.js +2 -4
- package/build/src/library/akuma-creation.d.ts +5 -1
- package/build/src/library/akuma-creation.js +33 -51
- package/build/src/library/akumas.d.ts +5 -4
- package/build/src/library/akumas.js +13 -9
- package/build/src/library/bind.d.ts +14 -14
- package/build/src/library/bind.js +11 -7
- package/build/src/library/contract-address.d.ts +9 -0
- package/build/src/library/contract-address.js +71 -0
- package/build/src/library/contract-composition.d.ts +4 -7
- package/build/src/library/contract-composition.js +6 -18
- package/build/src/library/contract-creation.d.ts +3 -5
- package/build/src/library/contract-creation.js +19 -17
- package/build/src/library/contract-execution.js +18 -23
- package/build/src/library/contract-outcomes.d.ts +2 -14
- package/build/src/library/contract-outcomes.js +2 -13
- package/build/src/library/contract-types.d.ts +36 -2
- package/build/src/library/delivery.d.ts +0 -2
- package/build/src/library/delivery.js +2 -5
- package/build/src/library/keiyaku.d.ts +0 -5
- package/build/src/library/keiyaku.js +6 -12
- package/build/src/library/outcome.d.ts +500 -499
- package/build/src/library/outcome.js +10 -0
- package/build/src/library/reconcile.js +8 -16
- package/build/src/library/refusal.d.ts +2 -2
- package/build/src/library/repo.d.ts +3 -2
- package/build/src/library/repo.js +10 -5
- package/build/src/library/selection.d.ts +4 -4
- package/build/src/library/selection.js +12 -9
- package/build/src/plugin/akuma-signals.d.ts +12 -11
- package/build/src/plugin/akuma-signals.js +40 -20
- package/build/src/plugin/public.d.ts +32 -2
- package/build/src/plugin/runtime.d.ts +1 -0
- package/build/src/plugin/runtime.js +35 -24
- package/build/src/protocol/amend.js +3 -2
- package/build/src/protocol/attempt.js +3 -8
- package/build/src/protocol/bind.d.ts +2 -2
- package/build/src/protocol/bind.js +1 -1
- package/build/src/protocol/deliver.js +3 -3
- package/build/src/protocol/operations.d.ts +1 -3
- package/build/src/protocol/operations.js +0 -8
- package/build/src/protocol/outcome.d.ts +1 -2
- package/build/src/protocol/outcome.js +1 -13
- package/build/src/protocol/placement.js +3 -10
- package/build/src/protocol/read/status.js +31 -70
- package/build/src/protocol/reintegrate.js +3 -10
- package/build/src/protocol/review.js +3 -3
- package/build/src/protocol/run.d.ts +5 -1
- package/build/src/protocol/run.js +3 -3
- package/build/src/runtime/proc/windows-launch.exe +0 -0
- package/package.json +12 -8
- package/plugins/pi/keiyaku.ts +57 -0
- package/skills/keiyaku/SKILL.md +44 -0
- package/skills/keiyaku-akuma/SKILL.md +130 -0
- package/skills/keiyaku-akuma/references/automation.md +269 -0
- package/skills/keiyaku-babysit/SKILL.md +65 -0
- package/skills/keiyaku-bind/SKILL.md +216 -0
- package/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/skills/keiyaku-task/SKILL.md +104 -0
- package/skills/keiyaku-workflow/SKILL.md +129 -0
- package/build/integrations/marketplace/.claude-plugin/marketplace.json +0 -5
- package/build/integrations/marketplace/plugins/keiyaku/package.json +0 -17
- package/build/src/cli/commands/amend.d.ts +0 -12
- package/build/src/cli/commands/amend.js +0 -10
- package/build/src/cli/commands/bind.d.ts +0 -11
- package/build/src/cli/commands/bind.js +0 -23
- package/build/src/dispatch/association.d.ts +0 -1
- package/build/src/dispatch/association.js +0 -1
- /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku/SKILL.md +0 -0
- /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-akuma/SKILL.md +0 -0
- /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-akuma/references/automation.md +0 -0
- /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-babysit/SKILL.md +0 -0
- /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-bind/SKILL.md +0 -0
- /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-bind/agents/openai.yaml +0 -0
- /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-task/SKILL.md +0 -0
- /package/build/{integrations/marketplace/plugins/keiyaku → plugins/claude}/skills/keiyaku-workflow/SKILL.md +0 -0
- /package/build/{integrations/marketplace/plugins/keiyaku/opencode.js → plugins/opencode/index.js} +0 -0
|
@@ -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
|
-
|
|
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
|
|
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>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export const AKUMA_REQUESTS_ENV = "AKUMA_REQUESTS";
|
|
2
|
+
export const AKUMA_REQUESTS_ENTRY_ENV = "AKUMA_REQUESTS_ENTRY";
|
|
2
3
|
const PARENT_HARNESS_IDENTITY_KEYS = [
|
|
3
4
|
"CLAUDE_CODE_SESSION_ID",
|
|
4
5
|
"CLAUDE_CODE_CHILD_SESSION",
|
|
@@ -9,6 +10,7 @@ const PARENT_HARNESS_IDENTITY_KEYS = [
|
|
|
9
10
|
"PI_SESSION_FILE",
|
|
10
11
|
"PASEO_AGENT_ID",
|
|
11
12
|
"SQUARE_PARTICIPANT_NAME",
|
|
13
|
+
"KEIYAKU_EXTERNAL_CALLER",
|
|
12
14
|
];
|
|
13
15
|
/** Construct the environment for one isolated Akuma execution or native child. */
|
|
14
16
|
export function akumaExecutionEnvironment(inherited, overrides = {}, requests, nativeIdentity = []) {
|
|
@@ -18,6 +20,7 @@ export function akumaExecutionEnvironment(inherited, overrides = {}, requests, n
|
|
|
18
20
|
delete environment[key];
|
|
19
21
|
Object.assign(environment, preserved);
|
|
20
22
|
delete environment[AKUMA_REQUESTS_ENV];
|
|
23
|
+
delete environment[AKUMA_REQUESTS_ENTRY_ENV];
|
|
21
24
|
if (requests !== undefined)
|
|
22
25
|
environment[AKUMA_REQUESTS_ENV] = requests;
|
|
23
26
|
return environment;
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { nonblank, object, searchToolCall } from "../decode.js";
|
|
2
|
+
import { providerLifecycle } from "../lifecycle.js";
|
|
2
3
|
import { startAcpSession, } from "../acp/core.js";
|
|
3
4
|
const INTERJECT_METHOD = "_x.ai/interject";
|
|
4
5
|
const INTERJECTION_METHOD = "_x.ai/session/interjection";
|
|
5
|
-
function nonblank(value) {
|
|
6
|
-
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
7
|
-
}
|
|
8
|
-
function object(value) {
|
|
9
|
-
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
10
|
-
? value
|
|
11
|
-
: undefined;
|
|
12
|
-
}
|
|
13
6
|
function nativeName(update) {
|
|
14
7
|
const wire = update;
|
|
15
8
|
return nonblank(update.name) ?? nonblank(update.title) ?? nonblank(wire.toolName);
|
|
@@ -26,17 +19,9 @@ function contentSearchCall(name, input) {
|
|
|
26
19
|
if (name !== "grep" && name !== "hashline_grep")
|
|
27
20
|
return undefined;
|
|
28
21
|
const query = nonblank(input.pattern);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const glob = nonblank(input.glob);
|
|
33
|
-
return {
|
|
34
|
-
kind: "search",
|
|
35
|
-
query,
|
|
36
|
-
scope: "content",
|
|
37
|
-
...(path === undefined ? {} : { path }),
|
|
38
|
-
...(glob === undefined ? {} : { glob }),
|
|
39
|
-
};
|
|
22
|
+
return query === undefined
|
|
23
|
+
? undefined
|
|
24
|
+
: searchToolCall(query, "content", { path: nonblank(input.path), glob: nonblank(input.glob) });
|
|
40
25
|
}
|
|
41
26
|
function runCall(name, input) {
|
|
42
27
|
if (name !== "run_terminal_cmd")
|
|
@@ -177,7 +162,6 @@ export function createGrokBuildProvider(execution, dependencies = {}) {
|
|
|
177
162
|
};
|
|
178
163
|
return {
|
|
179
164
|
admitOptions: optionAdmission,
|
|
180
|
-
|
|
181
|
-
resume: (input) => createProviderAttempt(input.signal, async (custody) => await drive({ ...input, signal: custody.signal }, custody)),
|
|
165
|
+
...providerLifecycle(drive),
|
|
182
166
|
};
|
|
183
167
|
}
|
|
@@ -14,6 +14,8 @@ async function adapterFor(execution) {
|
|
|
14
14
|
return (await import("./grok-build/index.js")).createGrokBuildProvider(execution);
|
|
15
15
|
if (execution.kind === "opencode-sdk")
|
|
16
16
|
return (await import("./opencode-sdk/index.js")).createOpencodeProvider(execution);
|
|
17
|
+
if (execution.kind === "paseo")
|
|
18
|
+
return (await import("./paseo/index.js")).createPaseoProvider(execution);
|
|
17
19
|
if (execution.kind === "pi")
|
|
18
20
|
return (await import("./pi/index.js")).createPiProvider(execution);
|
|
19
21
|
throw new TypeError(`unknown Akuma provider kind ${execution.kind}`);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type AttemptCustody, type ProviderAdapter, type Session } from "../provider.js";
|
|
2
|
+
type DriveInput = Parameters<ProviderAdapter["start"]>[0] | Parameters<NonNullable<ProviderAdapter["resume"]>>[0];
|
|
3
|
+
/**
|
|
4
|
+
* Start and resume share one custody descriptor: each creates one attempt whose
|
|
5
|
+
* own controller signal reaches the adapter, and the caller's signal stays a
|
|
6
|
+
* cancellation notification.
|
|
7
|
+
*/
|
|
8
|
+
export declare function providerLifecycle(drive: (input: DriveInput, custody: AttemptCustody) => Promise<Session>): Pick<ProviderAdapter, "start" | "resume">;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createProviderAttempt } from "../provider.js";
|
|
2
|
+
/**
|
|
3
|
+
* Start and resume share one custody descriptor: each creates one attempt whose
|
|
4
|
+
* own controller signal reaches the adapter, and the caller's signal stays a
|
|
5
|
+
* cancellation notification.
|
|
6
|
+
*/
|
|
7
|
+
export function providerLifecycle(drive) {
|
|
8
|
+
const attempt = (input) => createProviderAttempt(input.signal, async (custody) => await drive({ ...input, signal: custody.signal }, custody));
|
|
9
|
+
return { start: attempt, resume: attempt };
|
|
10
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { noteEvent, otherToolCall } from "../../provider.js";
|
|
2
|
+
import { nonnegativeCount, object, positiveLine, text } from "../decode.js";
|
|
2
3
|
export const OPENCODE_EVENT_DISPOSITIONS = {
|
|
3
4
|
"server.instance.disposed": "dropped",
|
|
4
5
|
"installation.updated": "dropped",
|
|
@@ -44,25 +45,11 @@ const RUNTIME_DROPPED_EVENT_KINDS = new Set([
|
|
|
44
45
|
"server.heartbeat",
|
|
45
46
|
"message.part.delta",
|
|
46
47
|
]);
|
|
47
|
-
function object(value) {
|
|
48
|
-
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
49
|
-
? value
|
|
50
|
-
: undefined;
|
|
51
|
-
}
|
|
52
|
-
function text(value) {
|
|
53
|
-
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
54
|
-
}
|
|
55
48
|
function diagnostic(value) {
|
|
56
49
|
const data = object(value);
|
|
57
50
|
const nested = object(data?.data);
|
|
58
51
|
return text(nested?.message) ?? text(data?.message) ?? "OpenCode session failed";
|
|
59
52
|
}
|
|
60
|
-
function positiveLine(value) {
|
|
61
|
-
return typeof value === "number" && Number.isSafeInteger(value) && value >= 1 ? value : undefined;
|
|
62
|
-
}
|
|
63
|
-
function nonnegativeCount(value) {
|
|
64
|
-
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
65
|
-
}
|
|
66
53
|
function diffstat(value) {
|
|
67
54
|
if (value === undefined)
|
|
68
55
|
return undefined;
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
import { AgentEventChannel, createProviderAttempt, } from "../../provider.js";
|
|
2
|
+
import { nonblank, object } from "../decode.js";
|
|
3
|
+
import { providerLifecycle } from "../lifecycle.js";
|
|
2
4
|
import { ownEventStream } from "./event-stream.js";
|
|
3
5
|
import { createEventState, mapEvent } from "./events.js";
|
|
4
6
|
import { coordinate, loadOpencode, messageId, OPENCODE_SDK_PROVIDER, parseModel, } from "./session.js";
|
|
5
|
-
function object(value) {
|
|
6
|
-
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
7
|
-
? value
|
|
8
|
-
: undefined;
|
|
9
|
-
}
|
|
10
|
-
function text(value) {
|
|
11
|
-
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
12
|
-
}
|
|
13
7
|
function diagnostic(error) {
|
|
14
8
|
const value = object(error);
|
|
15
9
|
const nested = object(value?.data);
|
|
16
|
-
return
|
|
10
|
+
return nonblank(nested?.message) ?? nonblank(value?.message) ?? String(error);
|
|
17
11
|
}
|
|
18
12
|
function opencodeSessionId(coordinateValue) {
|
|
19
13
|
if (!("sessionId" in coordinateValue) || coordinateValue.sessionId === undefined) {
|
|
@@ -84,9 +78,9 @@ async function readTurnResult(input) {
|
|
|
84
78
|
const user = rows.find((row) => row.info.role === "user" && row.info.id === input.messageID);
|
|
85
79
|
if (user === undefined)
|
|
86
80
|
return { kind: "failed", diagnostic: "OpenCode completed without the admitted user message" };
|
|
87
|
-
const userId =
|
|
81
|
+
const userId = nonblank(user.info.id);
|
|
88
82
|
const assistant = newest(rows.filter((row) => row.info.role === "assistant" && row.info.parentID === userId && row.info.summary !== true));
|
|
89
|
-
const historyId =
|
|
83
|
+
const historyId = nonblank(assistant?.info.id);
|
|
90
84
|
if (input.state.failure !== undefined)
|
|
91
85
|
return { kind: "failed", diagnostic: input.state.failure };
|
|
92
86
|
if (assistant === undefined)
|
|
@@ -108,12 +102,12 @@ async function readTurnResult(input) {
|
|
|
108
102
|
function nativeSessionId(value) {
|
|
109
103
|
const event = object(value);
|
|
110
104
|
const properties = object(event?.properties);
|
|
111
|
-
const direct =
|
|
105
|
+
const direct = nonblank(properties?.sessionID);
|
|
112
106
|
if (direct !== undefined)
|
|
113
107
|
return direct;
|
|
114
108
|
const info = object(properties?.info);
|
|
115
109
|
const part = object(properties?.part);
|
|
116
|
-
return
|
|
110
|
+
return nonblank(info?.sessionID) ?? nonblank(part?.sessionID);
|
|
117
111
|
}
|
|
118
112
|
function scopedProperties(value, sessionId) {
|
|
119
113
|
const properties = object(object(value)?.properties);
|
|
@@ -328,7 +322,7 @@ async function openDriveSession(runtime, input, resumeSessionId, signal) {
|
|
|
328
322
|
: session.get({ path: { id: resumeSessionId }, query: { directory: input.cwd }, throwOnError: true }));
|
|
329
323
|
signal.throwIfAborted();
|
|
330
324
|
const info = object(object(response)?.data) ?? object(response);
|
|
331
|
-
const sessionId =
|
|
325
|
+
const sessionId = nonblank(info?.id) ?? resumeSessionId;
|
|
332
326
|
if (sessionId === undefined)
|
|
333
327
|
throw new Error("OpenCode did not return a session id");
|
|
334
328
|
return { session, sessionId };
|
|
@@ -465,8 +459,7 @@ export function createOpencodeProvider(input = { name: OPENCODE_SDK_PROVIDER, ki
|
|
|
465
459
|
options: Object.freeze({ ...options }),
|
|
466
460
|
};
|
|
467
461
|
},
|
|
468
|
-
|
|
469
|
-
resume: (input) => createProviderAttempt(input.signal, async (custody) => await drive(execution, { ...input, signal: custody.signal }, loader, custody)),
|
|
462
|
+
...providerLifecycle((input, custody) => drive(execution, input, loader, custody)),
|
|
470
463
|
fork: (input) => createProviderAttempt(new AbortController().signal, async (custody) => {
|
|
471
464
|
const sessionId = opencodeSessionId(input.session);
|
|
472
465
|
let close;
|
|
@@ -500,7 +493,7 @@ export function createOpencodeProvider(input = { name: OPENCODE_SDK_PROVIDER, ki
|
|
|
500
493
|
body: { messageID: input.at },
|
|
501
494
|
});
|
|
502
495
|
const info = object(object(result)?.data) ?? object(result);
|
|
503
|
-
const id =
|
|
496
|
+
const id = nonblank(info?.id);
|
|
504
497
|
if (id === undefined || id === sessionId)
|
|
505
498
|
throw new Error("OpenCode fork returned an invalid session id");
|
|
506
499
|
return { session: coordinate(id) };
|
|
@@ -3,6 +3,7 @@ import { randomBytes } from "node:crypto";
|
|
|
3
3
|
import { abortable } from "../../abort.js";
|
|
4
4
|
import { akumaExecutionEnvironment } from "../execution-environment.js";
|
|
5
5
|
import { spawnDetachedProcess } from "../../../runtime/proc/run.js";
|
|
6
|
+
import { isRecord } from "../decode.js";
|
|
6
7
|
export const OPENCODE_SDK_PROVIDER = "opencode-sdk";
|
|
7
8
|
/**
|
|
8
9
|
* Adapt the installed client's generated event endpoint to the adapter's
|
|
@@ -60,9 +61,6 @@ const HEADLESS_PERMISSION_BASE = Object.freeze({
|
|
|
60
61
|
read: "allow",
|
|
61
62
|
question: "deny",
|
|
62
63
|
});
|
|
63
|
-
function isRecord(value) {
|
|
64
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
65
|
-
}
|
|
66
64
|
/**
|
|
67
65
|
* Compose the config handed to a headless opencode server. The permission base
|
|
68
66
|
* layer fills only the classes the caller leaves unspecified: an explicit caller
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AgentStreamEventPayload } from "@getpaseo/protocol/messages";
|
|
2
|
+
import { AgentEventChannel, type TurnResult } from "../../provider.js";
|
|
3
|
+
/** Live fragments belong to a canonical admitted turn, not agent-wide status. */
|
|
4
|
+
export declare class PaseoTurn {
|
|
5
|
+
readonly messageId: string;
|
|
6
|
+
readonly events: AgentEventChannel;
|
|
7
|
+
readonly admission: Promise<string>;
|
|
8
|
+
readonly completion: Promise<TurnResult>;
|
|
9
|
+
private admit;
|
|
10
|
+
private rejectAdmission;
|
|
11
|
+
private finish;
|
|
12
|
+
private rejectCompletion;
|
|
13
|
+
private turnId;
|
|
14
|
+
private readonly messages;
|
|
15
|
+
private readonly messagesById;
|
|
16
|
+
private readonly calls;
|
|
17
|
+
private answer;
|
|
18
|
+
private assistantContiguous;
|
|
19
|
+
settled: boolean;
|
|
20
|
+
terminal: boolean;
|
|
21
|
+
constructor(messageId: string);
|
|
22
|
+
receive(event: AgentStreamEventPayload): void;
|
|
23
|
+
private appendAssistant;
|
|
24
|
+
fail(error: unknown): void;
|
|
25
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { AgentEventChannel, otherToolCall } from "../../provider.js";
|
|
2
|
+
function toolCall(item) {
|
|
3
|
+
const detail = item.detail;
|
|
4
|
+
switch (detail.type) {
|
|
5
|
+
case "shell":
|
|
6
|
+
return { kind: "run", command: detail.command };
|
|
7
|
+
case "read":
|
|
8
|
+
return {
|
|
9
|
+
kind: "read",
|
|
10
|
+
path: detail.filePath,
|
|
11
|
+
...(detail.offset === undefined ? {} : { offset: detail.offset }),
|
|
12
|
+
...(detail.limit === undefined ? {} : { limit: detail.limit }),
|
|
13
|
+
};
|
|
14
|
+
case "edit":
|
|
15
|
+
case "write":
|
|
16
|
+
return { kind: "fileChange", changes: [{ op: "unspecified", path: detail.filePath }] };
|
|
17
|
+
case "search":
|
|
18
|
+
return { kind: "search", query: detail.query, scope: detail.toolName === "web_search" ? "web" : "content" };
|
|
19
|
+
case "unknown":
|
|
20
|
+
return otherToolCall(item.name, detail.input);
|
|
21
|
+
default:
|
|
22
|
+
return otherToolCall(item.name);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function timelineNarration(item, calls) {
|
|
26
|
+
switch (item.type) {
|
|
27
|
+
case "tool_call": {
|
|
28
|
+
const call = calls.get(item.callId) ?? (item.status === "running" ? toolCall(item) : otherToolCall(item.name));
|
|
29
|
+
calls.set(item.callId, call);
|
|
30
|
+
return item.status === "running"
|
|
31
|
+
? { type: "tool", phase: "started", id: item.callId, name: item.name, call }
|
|
32
|
+
: {
|
|
33
|
+
type: "tool",
|
|
34
|
+
phase: "completed",
|
|
35
|
+
id: item.callId,
|
|
36
|
+
name: item.name,
|
|
37
|
+
call,
|
|
38
|
+
result: { status: item.status === "completed" ? "ok" : "error" },
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
case "error":
|
|
42
|
+
case "notification":
|
|
43
|
+
return { type: "note", text: item.message };
|
|
44
|
+
case "compaction":
|
|
45
|
+
return { type: "note", text: `Context compaction ${item.status}` };
|
|
46
|
+
case "reasoning":
|
|
47
|
+
case "user_message":
|
|
48
|
+
case "assistant_message":
|
|
49
|
+
return undefined;
|
|
50
|
+
default:
|
|
51
|
+
return { type: "unknown", kind: item.type };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Live fragments belong to a canonical admitted turn, not agent-wide status. */
|
|
55
|
+
export class PaseoTurn {
|
|
56
|
+
messageId;
|
|
57
|
+
events = new AgentEventChannel();
|
|
58
|
+
admission;
|
|
59
|
+
completion;
|
|
60
|
+
admit;
|
|
61
|
+
rejectAdmission;
|
|
62
|
+
finish;
|
|
63
|
+
rejectCompletion;
|
|
64
|
+
turnId;
|
|
65
|
+
messages = [];
|
|
66
|
+
messagesById = new Map();
|
|
67
|
+
calls = new Map();
|
|
68
|
+
answer = "";
|
|
69
|
+
assistantContiguous = false;
|
|
70
|
+
settled = false;
|
|
71
|
+
terminal = false;
|
|
72
|
+
constructor(messageId) {
|
|
73
|
+
this.messageId = messageId;
|
|
74
|
+
this.admission = new Promise((resolve, reject) => {
|
|
75
|
+
this.admit = resolve;
|
|
76
|
+
this.rejectAdmission = reject;
|
|
77
|
+
});
|
|
78
|
+
this.completion = new Promise((resolve, reject) => {
|
|
79
|
+
this.finish = resolve;
|
|
80
|
+
this.rejectCompletion = reject;
|
|
81
|
+
});
|
|
82
|
+
void this.admission.catch(() => undefined);
|
|
83
|
+
void this.completion.catch(() => undefined);
|
|
84
|
+
}
|
|
85
|
+
receive(event) {
|
|
86
|
+
if (this.settled)
|
|
87
|
+
return;
|
|
88
|
+
if (event.type === "timeline" &&
|
|
89
|
+
event.item.type === "user_message" &&
|
|
90
|
+
event.item.clientMessageId === this.messageId) {
|
|
91
|
+
if (event.turnId === undefined)
|
|
92
|
+
return this.fail(new Error("Paseo native admission omitted turnId"));
|
|
93
|
+
if (this.turnId !== undefined) {
|
|
94
|
+
if (this.turnId !== event.turnId)
|
|
95
|
+
this.fail(new Error("Paseo canonical admission changed native turn"));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
this.turnId = event.turnId;
|
|
99
|
+
this.admit(event.turnId);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (!("turnId" in event) || this.turnId === undefined || event.turnId !== this.turnId)
|
|
103
|
+
return;
|
|
104
|
+
if (event.type === "timeline") {
|
|
105
|
+
if (event.item.type === "assistant_message")
|
|
106
|
+
this.appendAssistant(event.item);
|
|
107
|
+
else {
|
|
108
|
+
this.assistantContiguous = false;
|
|
109
|
+
const narration = timelineNarration(event.item, this.calls);
|
|
110
|
+
if (narration !== undefined)
|
|
111
|
+
this.events.emit(narration);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else if (event.type === "turn_completed") {
|
|
115
|
+
this.settled = true;
|
|
116
|
+
this.finish({
|
|
117
|
+
kind: "answered",
|
|
118
|
+
answer: this.answer,
|
|
119
|
+
historyId: this.turnId,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
else if (event.type === "turn_failed" || event.type === "turn_canceled") {
|
|
123
|
+
this.settled = true;
|
|
124
|
+
this.finish({ kind: "failed", diagnostic: event.type === "turn_failed" ? event.error : event.reason });
|
|
125
|
+
}
|
|
126
|
+
if (this.settled) {
|
|
127
|
+
this.terminal = true;
|
|
128
|
+
for (const message of this.messages)
|
|
129
|
+
this.events.emit({ type: "assistant", text: message.text });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
appendAssistant(item) {
|
|
133
|
+
// Native final text is the last contiguous assistant segment; narration keeps all messages.
|
|
134
|
+
this.answer = this.assistantContiguous ? this.answer + item.text : item.text;
|
|
135
|
+
const previous = item.messageId === undefined
|
|
136
|
+
? this.assistantContiguous
|
|
137
|
+
? this.messages.at(-1)
|
|
138
|
+
: undefined
|
|
139
|
+
: this.messagesById.get(item.messageId);
|
|
140
|
+
this.assistantContiguous = true;
|
|
141
|
+
if (previous !== undefined)
|
|
142
|
+
previous.text += item.text;
|
|
143
|
+
else {
|
|
144
|
+
const message = { ...(item.messageId === undefined ? {} : { id: item.messageId }), text: item.text };
|
|
145
|
+
this.messages.push(message);
|
|
146
|
+
if (item.messageId !== undefined)
|
|
147
|
+
this.messagesById.set(item.messageId, message);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
fail(error) {
|
|
151
|
+
if (this.settled)
|
|
152
|
+
return;
|
|
153
|
+
this.settled = true;
|
|
154
|
+
this.rejectAdmission(error);
|
|
155
|
+
this.rejectCompletion(error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DaemonClient, type DaemonClientConfig } from "@getpaseo/client/internal/daemon-client";
|
|
2
|
+
import { type ProviderAdapter } from "../../provider.js";
|
|
3
|
+
import type { ProviderExecution } from "../../provider-recipe.js";
|
|
4
|
+
type PaseoClient = Pick<DaemonClient, "connect" | "close" | "createAgent" | "fetchAgent" | "setAgentModel" | "listProviderModels" | "setAgentThinkingOption" | "sendMessage" | "cancelAgent" | "subscribeAgentTimeline" | "subscribeConnectionStatus">;
|
|
5
|
+
export type PaseoDependencies = Readonly<{
|
|
6
|
+
createClient?(config: DaemonClientConfig): PaseoClient;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function createPaseoProvider(execution: ProviderExecution, dependencies?: PaseoDependencies): ProviderAdapter;
|
|
9
|
+
export {};
|