@botiverse/oar 0.0.11 → 0.1.1
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 +2 -2
- package/dist/contracts/model-catalog.d.ts +1 -1
- package/dist/contracts/model-catalog.js +1 -1
- package/dist/contracts/provider-auth.d.ts +2 -2
- package/dist/contracts/provider-auth.js +2 -2
- package/dist/contracts/records.d.ts +214 -0
- package/dist/contracts/records.d.ts.map +1 -0
- package/dist/contracts/records.js +8 -0
- package/dist/contracts/records.js.map +1 -0
- package/dist/contracts/session.d.ts +93 -144
- package/dist/contracts/session.d.ts.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/observe/agent-status.d.ts +32 -18
- package/dist/observe/agent-status.d.ts.map +1 -1
- package/dist/observe/agent-status.js +66 -14
- package/dist/observe/agent-status.js.map +1 -1
- package/dist/observe/aggregate-events.d.ts +7 -6
- package/dist/observe/aggregate-events.d.ts.map +1 -1
- package/dist/observe/aggregate-events.js +38 -28
- package/dist/observe/aggregate-events.js.map +1 -1
- package/dist/observe/index.d.ts +4 -1
- package/dist/observe/index.d.ts.map +1 -1
- package/dist/observe/index.js +3 -1
- package/dist/observe/index.js.map +1 -1
- package/dist/observe/observe-agent.d.ts +4 -4
- package/dist/observe/observe-agent.d.ts.map +1 -1
- package/dist/observe/observe-agent.js +3 -3
- package/dist/observe/observe-agent.js.map +1 -1
- package/dist/observe/stall-observer.d.ts +7 -6
- package/dist/observe/stall-observer.d.ts.map +1 -1
- package/dist/observe/stall-observer.js +6 -5
- package/dist/observe/stall-observer.js.map +1 -1
- package/dist/observe/tool-activity.d.ts +2 -2
- package/dist/observe/tool-activity.d.ts.map +1 -1
- package/dist/observe/tool-activity.js +1 -1
- package/dist/observe/tool-activity.js.map +1 -1
- package/dist/observe/turns.d.ts +37 -0
- package/dist/observe/turns.d.ts.map +1 -0
- package/dist/observe/turns.js +70 -0
- package/dist/observe/turns.js.map +1 -0
- package/dist/observe/usage.d.ts +15 -0
- package/dist/observe/usage.d.ts.map +1 -0
- package/dist/observe/usage.js +94 -0
- package/dist/observe/usage.js.map +1 -0
- package/dist/runtimes/claude/account-usage.js +1 -1
- package/dist/runtimes/claude/context-usage.d.ts +1 -1
- package/dist/runtimes/claude/context-usage.js +1 -1
- package/dist/runtimes/claude/projection.d.ts +40 -27
- package/dist/runtimes/claude/projection.d.ts.map +1 -1
- package/dist/runtimes/claude/projection.js +110 -23
- package/dist/runtimes/claude/projection.js.map +1 -1
- package/dist/runtimes/claude/session.d.ts.map +1 -1
- package/dist/runtimes/claude/session.js +120 -87
- package/dist/runtimes/claude/session.js.map +1 -1
- package/dist/runtimes/codex/app-server-client.d.ts +38 -3
- package/dist/runtimes/codex/app-server-client.d.ts.map +1 -1
- package/dist/runtimes/codex/app-server-client.js +62 -15
- package/dist/runtimes/codex/app-server-client.js.map +1 -1
- package/dist/runtimes/codex/projection.d.ts +12 -12
- package/dist/runtimes/codex/projection.d.ts.map +1 -1
- package/dist/runtimes/codex/projection.js +111 -40
- package/dist/runtimes/codex/projection.js.map +1 -1
- package/dist/runtimes/codex/rpc-control.d.ts +31 -0
- package/dist/runtimes/codex/rpc-control.d.ts.map +1 -0
- package/dist/runtimes/codex/rpc-control.js +51 -0
- package/dist/runtimes/codex/rpc-control.js.map +1 -0
- package/dist/runtimes/codex/session.d.ts.map +1 -1
- package/dist/runtimes/codex/session.js +199 -149
- package/dist/runtimes/codex/session.js.map +1 -1
- package/dist/runtimes/grok/session.d.ts +37 -1
- package/dist/runtimes/grok/session.d.ts.map +1 -1
- package/dist/runtimes/grok/session.js +74 -0
- package/dist/runtimes/grok/session.js.map +1 -1
- package/dist/runtimes/kimi/session.d.ts.map +1 -1
- package/dist/runtimes/kimi/session.js +5 -0
- package/dist/runtimes/kimi/session.js.map +1 -1
- package/dist/runtimes/pi/auth.d.ts.map +1 -1
- package/dist/runtimes/pi/auth.js +6 -1
- package/dist/runtimes/pi/auth.js.map +1 -1
- package/dist/runtimes/pi/catalog.d.ts.map +1 -1
- package/dist/runtimes/pi/catalog.js +6 -1
- package/dist/runtimes/pi/catalog.js.map +1 -1
- package/dist/runtimes/pi/http.d.ts +34 -0
- package/dist/runtimes/pi/http.d.ts.map +1 -0
- package/dist/runtimes/pi/http.js +95 -0
- package/dist/runtimes/pi/http.js.map +1 -0
- package/dist/runtimes/pi/list-models.d.ts.map +1 -1
- package/dist/runtimes/pi/list-models.js +10 -3
- package/dist/runtimes/pi/list-models.js.map +1 -1
- package/dist/runtimes/pi/open.d.ts +32 -0
- package/dist/runtimes/pi/open.d.ts.map +1 -0
- package/dist/runtimes/pi/open.js +106 -0
- package/dist/runtimes/pi/open.js.map +1 -0
- package/dist/runtimes/pi/projection.d.ts +27 -25
- package/dist/runtimes/pi/projection.d.ts.map +1 -1
- package/dist/runtimes/pi/projection.js +86 -50
- package/dist/runtimes/pi/projection.js.map +1 -1
- package/dist/runtimes/pi/session.d.ts +1 -22
- package/dist/runtimes/pi/session.d.ts.map +1 -1
- package/dist/runtimes/pi/session.js +179 -184
- package/dist/runtimes/pi/session.js.map +1 -1
- package/dist/shared/acp/client-app.d.ts +23 -0
- package/dist/shared/acp/client-app.d.ts.map +1 -0
- package/dist/shared/acp/client-app.js +55 -0
- package/dist/shared/acp/client-app.js.map +1 -0
- package/dist/shared/acp/model.d.ts +3 -17
- package/dist/shared/acp/model.d.ts.map +1 -1
- package/dist/shared/acp/model.js +3 -14
- package/dist/shared/acp/model.js.map +1 -1
- package/dist/shared/acp/profile.d.ts +32 -7
- package/dist/shared/acp/profile.d.ts.map +1 -1
- package/dist/shared/acp/profile.js +17 -8
- package/dist/shared/acp/profile.js.map +1 -1
- package/dist/shared/acp/projection.d.ts +16 -8
- package/dist/shared/acp/projection.d.ts.map +1 -1
- package/dist/shared/acp/projection.js +59 -32
- package/dist/shared/acp/projection.js.map +1 -1
- package/dist/shared/acp/records.d.ts +46 -0
- package/dist/shared/acp/records.d.ts.map +1 -0
- package/dist/shared/acp/records.js +125 -0
- package/dist/shared/acp/records.js.map +1 -0
- package/dist/shared/acp/session.d.ts.map +1 -1
- package/dist/shared/acp/session.js +98 -224
- package/dist/shared/acp/session.js.map +1 -1
- package/dist/shared/acp/terminal.d.ts +1 -3
- package/dist/shared/acp/terminal.d.ts.map +1 -1
- package/dist/shared/acp/terminal.js +1 -21
- package/dist/shared/acp/terminal.js.map +1 -1
- package/dist/shared/acp/turns.d.ts +45 -0
- package/dist/shared/acp/turns.d.ts.map +1 -0
- package/dist/shared/acp/turns.js +160 -0
- package/dist/shared/acp/turns.js.map +1 -0
- package/dist/shared/acp/usage-wait.d.ts +6 -6
- package/dist/shared/acp/usage-wait.d.ts.map +1 -1
- package/dist/shared/acp/usage-wait.js +2 -2
- package/dist/shared/acp/usage-wait.js.map +1 -1
- package/dist/shared/failure-class.d.ts +1 -1
- package/dist/shared/failure-class.js +2 -2
- package/dist/shared/failure-class.js.map +1 -1
- package/dist/shared/seal-session.d.ts +5 -3
- package/dist/shared/seal-session.d.ts.map +1 -1
- package/dist/shared/seal-session.js +24 -16
- package/dist/shared/seal-session.js.map +1 -1
- package/dist/shared/session-kernel.d.ts +68 -18
- package/dist/shared/session-kernel.d.ts.map +1 -1
- package/dist/shared/session-kernel.js +82 -42
- package/dist/shared/session-kernel.js.map +1 -1
- package/dist/voyage.d.ts +4 -7
- package/dist/voyage.d.ts.map +1 -1
- package/dist/voyage.js +14 -19
- package/dist/voyage.js.map +1 -1
- package/package.json +4 -3
- package/dist/runtimes/codex/context-usage.d.ts +0 -10
- package/dist/runtimes/codex/context-usage.d.ts.map +0 -1
- package/dist/runtimes/codex/context-usage.js +0 -16
- package/dist/runtimes/codex/context-usage.js.map +0 -1
|
@@ -1,231 +1,226 @@
|
|
|
1
1
|
import { classifyFailure } from "../../shared/failure-class.js";
|
|
2
2
|
import { sealSession } from "../../shared/seal-session.js";
|
|
3
3
|
import { createSessionKernel } from "../../shared/session-kernel.js";
|
|
4
|
-
import { foldPiEvent, initialPiProjection, piAbortRequested, piPrompted,
|
|
5
|
-
import {
|
|
4
|
+
import { foldPiEvent, initialPiProjection, piAbortRequested, piPrompted, } from "./projection.js";
|
|
5
|
+
import { openPiAgentSession, piEffectiveModel } from "./open.js";
|
|
6
|
+
export { piEffectiveModel, piEnvBashTool } from "./open.js";
|
|
6
7
|
/*
|
|
7
|
-
* Bundled pi SDK mapping (in-process, no fork
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* Resume opens the cwd's session file by id and
|
|
11
|
-
* through the ModelRuntime (see resolve.ts).
|
|
12
|
-
* mean another embedded pi cannot safely share
|
|
8
|
+
* Bundled pi SDK mapping (in-process, no fork; settled 2026-08-21, record
|
|
9
|
+
* stream 2026-09-11): every SDK event is one event record; pi's own
|
|
10
|
+
* `agent_settled` is the turn end; steer acceptance means entry into pi's queue;
|
|
11
|
+
* abort is cooperative. Resume opens the cwd's session file by id and
|
|
12
|
+
* options.model resolves through the ModelRuntime (see resolve.ts).
|
|
13
|
+
* Process-global lazy env reads mean another embedded pi cannot safely share
|
|
14
|
+
* this process.
|
|
13
15
|
*/
|
|
14
|
-
/**
|
|
15
|
-
* The bash tool that carries SessionOptions.env into the agent's spawned
|
|
16
|
-
* processes: same builtin bash, plus a spawnHook overlaying the env. pi's
|
|
17
|
-
* defineTool keeps the definition assignable to customTools, where it
|
|
18
|
-
* replaces the builtin by name. Exported for direct unit verification.
|
|
19
|
-
*/
|
|
20
|
-
export async function piEnvBashTool(cwd, overlay) {
|
|
21
|
-
const sdk = await import("@earendil-works/pi-coding-agent");
|
|
22
|
-
return sdk.defineTool(sdk.createBashToolDefinition(cwd, {
|
|
23
|
-
spawnHook: (context) => ({ ...context, env: { ...context.env, ...overlay } }),
|
|
24
|
-
}));
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* pi's `AgentSession.model` (SDK 0.84.2 agent-session.d.ts: "Current model
|
|
28
|
-
* (may be undefined if not yet selected)") is the runtime-owned current
|
|
29
|
-
* model, updated by setModel/model switching; spelled `provider/id` like the
|
|
30
|
-
* list-models projection and pi's own `--model` flag.
|
|
31
|
-
*/
|
|
32
|
-
export function piEffectiveModel(session) {
|
|
33
|
-
const { model } = session;
|
|
34
|
-
return model === undefined ? null : `${model.provider}/${model.id}`;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Opens (or resumes) the pi AgentSession the adapter wraps. Services first
|
|
38
|
-
* (createAgentSessionServices loads the agent dir's extensions and their
|
|
39
|
-
* provider registrations into the ModelRuntime, exactly as `pi` itself does),
|
|
40
|
-
* then the session against an explicit SessionManager so resume and creation
|
|
41
|
-
* share one session directory.
|
|
42
|
-
*/
|
|
43
|
-
async function openPiAgentSession(options) {
|
|
44
|
-
const sdk = await import("@earendil-works/pi-coding-agent");
|
|
45
|
-
// OAR_PI_AGENT_DIR pins pi's global config home (models.json/auth.json/
|
|
46
|
-
// settings/sessions) — same namespaced-env-pin pattern as OAR_CLAUDE_BIN.
|
|
47
|
-
// This is how a host (or the pi-aimock behavior backend) points the
|
|
48
|
-
// in-process model plane somewhere else.
|
|
49
|
-
const agentDir = process.env.OAR_PI_AGENT_DIR ?? sdk.getAgentDir();
|
|
50
|
-
// YOLO by default (repo policy): pi gates tool execution on project trust,
|
|
51
|
-
// which is an approval prompt no embedded host can answer — pre-trust the
|
|
52
|
-
// session cwd the same way pi's own Trust button would (auditable in
|
|
53
|
-
// <agentDir>/trust.json).
|
|
54
|
-
new sdk.ProjectTrustStore(agentDir).set(options.cwd, true);
|
|
55
|
-
const services = await sdk.createAgentSessionServices({
|
|
56
|
-
cwd: options.cwd,
|
|
57
|
-
agentDir,
|
|
58
|
-
// System prompt seams: pi's DefaultResourceLoader natively supports both
|
|
59
|
-
// replace (systemPrompt) and append (appendSystemPrompt).
|
|
60
|
-
resourceLoaderOptions: {
|
|
61
|
-
...(options.systemPrompt === undefined ? {} : { systemPrompt: options.systemPrompt }),
|
|
62
|
-
...(options.appendSystemPrompt === undefined ? {} : { appendSystemPrompt: [options.appendSystemPrompt] }),
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
// pi persists sessions per cwd under <agentDir>/sessions; the same
|
|
66
|
-
// directory is used to create (so a later resume finds the file) and to
|
|
67
|
-
// look a resumed id up.
|
|
68
|
-
const sessionDir = piSessionDir(options.cwd, agentDir);
|
|
69
|
-
const sessionManager = options.resume === undefined
|
|
70
|
-
? sdk.SessionManager.create(options.cwd, sessionDir)
|
|
71
|
-
: sdk.SessionManager.open(await piFindSessionFile(sdk.SessionManager, options.resume, options.cwd, sessionDir), sessionDir);
|
|
72
|
-
// An explicit model wins over the one recorded in a resumed session
|
|
73
|
-
// (sdk.js createAgentSession precedence, same in the services path); the
|
|
74
|
-
// recorded one is restored only when none is given.
|
|
75
|
-
const model = options.model === undefined ? undefined : piResolveModel(services.modelRuntime, options.model);
|
|
76
|
-
// Per-session env on an in-process runtime: the runtime itself has no own
|
|
77
|
-
// process, but the processes the AGENT spawns do — a bash tool built with a
|
|
78
|
-
// spawnHook overlaying the env replaces the builtin by name (custom tools
|
|
79
|
-
// win the SDK's tool registry). Provider config (keys, base URLs) does NOT
|
|
80
|
-
// travel this way for pi; that needs its native modelRuntime/agentDir
|
|
81
|
-
// channel.
|
|
82
|
-
const overlay = options.env;
|
|
83
|
-
const { session } = await sdk.createAgentSessionFromServices({
|
|
84
|
-
services,
|
|
85
|
-
sessionManager,
|
|
86
|
-
...(model === undefined ? {} : { model }),
|
|
87
|
-
...(overlay === undefined ? {} : { customTools: [await piEnvBashTool(options.cwd, overlay)] }),
|
|
88
|
-
});
|
|
89
|
-
// Read back rather than trust the request: Session.model() is the
|
|
90
|
-
// runtime's report, and a resume that kept the old model must not pass.
|
|
91
|
-
const effective = piEffectiveModel(session);
|
|
92
|
-
if (options.model !== undefined && effective !== options.model) {
|
|
93
|
-
session.dispose();
|
|
94
|
-
throw new Error(`pi did not apply model ${options.model}: the session reports ${effective ?? "no model"}`);
|
|
95
|
-
}
|
|
96
|
-
return session;
|
|
97
|
-
}
|
|
98
16
|
export const piSession = async (installation, options) => {
|
|
99
17
|
if (installation.via !== "bundled") {
|
|
100
18
|
throw new Error("The pi session adapter needs the bundled sdk installation");
|
|
101
19
|
}
|
|
102
20
|
const piAgentSession = await openPiAgentSession(options);
|
|
103
21
|
const kernel = createSessionKernel(piAgentSession.sessionId);
|
|
104
|
-
let currentTurn = null;
|
|
105
22
|
let projection = initialPiProjection;
|
|
106
|
-
|
|
107
|
-
//
|
|
23
|
+
// A run is in progress: from an accepted prompt (or a drained queue input,
|
|
24
|
+
// or an adopted agent_start) until pi's own agent_settled. Held in an
|
|
25
|
+
// object so closures always read the live value.
|
|
26
|
+
const gate = { running: false };
|
|
27
|
+
// Identity of the latest launched prompt, so a late rejection of an older
|
|
28
|
+
// one cannot be misread as the current run's.
|
|
29
|
+
let launch = null;
|
|
30
|
+
// The dispose request once issued: dispose is idempotent on it. Liveness
|
|
31
|
+
// itself is the kernel's business (kernel.unreachable() reads the stream).
|
|
32
|
+
let disposeRequest = null;
|
|
33
|
+
// An abort taken over before pi created the run (pi's abort calls are no-ops
|
|
34
|
+
// until then): delivered on agent_start.
|
|
35
|
+
let pendingAbort = false;
|
|
36
|
+
// Adapter-held queue, drained one input per run end. pi's native followUp
|
|
108
37
|
// CONTINUES the active run (more internal turns, one agent_end), which
|
|
109
|
-
// would land the queued input inside the same
|
|
38
|
+
// would land the queued input inside the same turn; the queue contract
|
|
110
39
|
// promises a later turn of its own, so the adapter owns the handoff.
|
|
111
40
|
const held = [];
|
|
112
|
-
|
|
113
|
-
|
|
41
|
+
// pi is authoritative on context fullness: getContextUsage() returns
|
|
42
|
+
// tokens (null right after compaction, before the next response),
|
|
43
|
+
// contextWindow, percent. Read at agent_end so the turn-end record carries
|
|
44
|
+
// it and Session.contextUsage() (a fold) is current at turn end (which
|
|
45
|
+
// is agent_settled, after any threshold compaction; see projection.ts).
|
|
46
|
+
const contextOf = () => {
|
|
47
|
+
const usage = piAgentSession.getContextUsage();
|
|
48
|
+
return usage === undefined
|
|
49
|
+
? null
|
|
50
|
+
: { tokens: usage.tokens, contextWindow: usage.contextWindow, percent: usage.percent };
|
|
51
|
+
};
|
|
52
|
+
// agent_start waiters: a prompt is `accepted` once pi actually starts the
|
|
53
|
+
// run, `rejected` with pi's own message if pi refuses it first.
|
|
54
|
+
const startWaiters = new Set();
|
|
55
|
+
const start = async (input) => {
|
|
56
|
+
gate.running = true;
|
|
57
|
+
projection = piPrompted(projection);
|
|
58
|
+
const token = {};
|
|
59
|
+
launch = token;
|
|
60
|
+
const { promise: started, resolve: onStarted } = Promise.withResolvers();
|
|
61
|
+
startWaiters.add(onStarted);
|
|
62
|
+
const run = piAgentSession.prompt(input);
|
|
63
|
+
const decided = await Promise.race([
|
|
64
|
+
started.then(() => ({ kind: "accepted" })),
|
|
65
|
+
run.then(() => ({ kind: "accepted" }), (error) => ({ kind: "rejected", reason: error instanceof Error ? error.message : "pi prompt failed" })),
|
|
66
|
+
]);
|
|
67
|
+
startWaiters.delete(onStarted);
|
|
68
|
+
if (decided.kind === "rejected") {
|
|
69
|
+
gate.running = false;
|
|
70
|
+
launch = null;
|
|
71
|
+
return decided;
|
|
72
|
+
}
|
|
73
|
+
void (async () => {
|
|
74
|
+
try {
|
|
75
|
+
await run;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
// pi failed the run after starting it and without its own settlement.
|
|
79
|
+
// That failure is pi's own word, recorded as an event carrying pi's
|
|
80
|
+
// message, not a synthesized boundary; it ends the turn only when no
|
|
81
|
+
// agent_settled already did.
|
|
82
|
+
if (launch === token && gate.running) {
|
|
83
|
+
const reason = error instanceof Error ? error.message : "pi prompt failed";
|
|
84
|
+
gate.running = false;
|
|
85
|
+
kernel.event({
|
|
86
|
+
type: "pi/prompt_rejected",
|
|
87
|
+
native: { message: reason },
|
|
88
|
+
views: [{ kind: "turn_ended", outcome: { kind: "failed", reason, failure: classifyFailure(reason) } }],
|
|
89
|
+
});
|
|
90
|
+
drainHeld();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
})();
|
|
94
|
+
return decided;
|
|
95
|
+
};
|
|
96
|
+
function drainHeld() {
|
|
97
|
+
if (disposeRequest !== null || gate.running) {
|
|
114
98
|
return;
|
|
115
99
|
}
|
|
116
100
|
const next = held.shift();
|
|
117
101
|
if (next === undefined) {
|
|
118
102
|
return;
|
|
119
103
|
}
|
|
120
|
-
// The run this starts is adopted as a spontaneous turn by agent_start.
|
|
121
104
|
void (async () => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const reason = error instanceof Error ? error.message : "queued prompt failed";
|
|
129
|
-
kernel.begin()?.settle({ kind: "failed", reason, failure: classifyFailure(reason) });
|
|
105
|
+
const decided = await start(next);
|
|
106
|
+
if (decided.kind === "rejected") {
|
|
107
|
+
// The queue took the input over; pi refusing it is not silent: pi's
|
|
108
|
+
// refusal enters the stream (no turn ever started, so no turn end).
|
|
109
|
+
kernel.event({ type: "pi/prompt_rejected", native: { message: decided.reason, input: next }, views: [] });
|
|
110
|
+
drainHeld();
|
|
130
111
|
}
|
|
131
112
|
})();
|
|
132
|
-
}
|
|
133
|
-
// Drive the pure projection fold
|
|
134
|
-
// fold owns
|
|
135
|
-
// fold (agent_end); prompt-initiated turns settle in prompt() below.
|
|
113
|
+
}
|
|
114
|
+
// Drive the pure projection fold: one SDK event → one event record. The
|
|
115
|
+
// fold owns views and outcome classification; this owns the run gate.
|
|
136
116
|
piAgentSession.subscribe((event) => {
|
|
137
|
-
|
|
117
|
+
if (event.type === "agent_start") {
|
|
118
|
+
gate.running = true;
|
|
119
|
+
for (const waiter of startWaiters) {
|
|
120
|
+
waiter();
|
|
121
|
+
}
|
|
122
|
+
if (pendingAbort) {
|
|
123
|
+
pendingAbort = false;
|
|
124
|
+
piAgentSession.abortRetry();
|
|
125
|
+
piAgentSession.agent.abort();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const extra = event.type === "agent_settled" ? { context: contextOf() } : {};
|
|
129
|
+
const { state: nextProjection, commands } = foldPiEvent(projection, event, extra);
|
|
138
130
|
projection = nextProjection;
|
|
139
131
|
for (const command of commands) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
case "emit":
|
|
145
|
-
currentTurn?.emit(command.body);
|
|
146
|
-
break;
|
|
147
|
-
case "settle":
|
|
148
|
-
currentTurn?.settle(command.outcome);
|
|
149
|
-
currentTurn = null;
|
|
150
|
-
drainHeld();
|
|
151
|
-
break;
|
|
152
|
-
default:
|
|
153
|
-
break;
|
|
132
|
+
kernel.event(command.body);
|
|
133
|
+
if (command.body.views.some((view) => view.kind === "turn_ended")) {
|
|
134
|
+
gate.running = false;
|
|
135
|
+
drainHeld();
|
|
154
136
|
}
|
|
155
137
|
}
|
|
156
138
|
});
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
steer: async (input) => {
|
|
169
|
-
if (turn.settled()) {
|
|
170
|
-
return { kind: "not_steerable", reason: "turn already ended" };
|
|
171
|
-
}
|
|
172
|
-
await piAgentSession.steer(input);
|
|
173
|
-
return { kind: "accepted" };
|
|
174
|
-
},
|
|
175
|
-
});
|
|
139
|
+
const openedModel = piEffectiveModel(piAgentSession);
|
|
140
|
+
if (openedModel !== null) {
|
|
141
|
+
// The SDK's own report of the model in effect at open, captured as the
|
|
142
|
+
// runtime's word (never the request echoed: the mismatch check above
|
|
143
|
+
// already rejected a request pi did not apply).
|
|
144
|
+
kernel.event({
|
|
145
|
+
type: "pi/session_opened",
|
|
146
|
+
native: { sessionId: piAgentSession.sessionId, model: openedModel },
|
|
147
|
+
views: [{ kind: "model", model: openedModel }],
|
|
148
|
+
});
|
|
149
|
+
}
|
|
176
150
|
const session = sealSession({
|
|
177
151
|
id: kernel.sessionId,
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
projection = piPrompted();
|
|
185
|
-
void (async () => {
|
|
186
|
-
try {
|
|
187
|
-
await piAgentSession.prompt(input);
|
|
188
|
-
turn.settle(piSettledOutcome(projection));
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
const reason = error instanceof Error ? error.message : "pi prompt failed";
|
|
192
|
-
turn.settle({ kind: "failed", reason, failure: classifyFailure(reason) });
|
|
152
|
+
capabilities: { steer: true, queue: { durable: false }, attribution: "none" },
|
|
153
|
+
prompt: async (input, promptOptions) => {
|
|
154
|
+
const body = { kind: "prompt", input, ...(promptOptions?.lineage === undefined ? {} : { lineage: promptOptions.lineage }) };
|
|
155
|
+
const result = await kernel.control(body, async () => {
|
|
156
|
+
if (gate.running) {
|
|
157
|
+
return { kind: "rejected", reason: "busy" };
|
|
193
158
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return { kind: "turn", turn: makeTurn(turn) };
|
|
159
|
+
const decided = await start(input);
|
|
160
|
+
return decided;
|
|
161
|
+
});
|
|
162
|
+
return result;
|
|
199
163
|
},
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
164
|
+
steer: async (input) => {
|
|
165
|
+
const result = await kernel.control({ kind: "steer", input }, async () => {
|
|
166
|
+
if (!gate.running) {
|
|
167
|
+
return { kind: "rejected", reason: "not_steerable: no active turn" };
|
|
168
|
+
}
|
|
169
|
+
await piAgentSession.steer(input);
|
|
170
|
+
return { kind: "accepted" };
|
|
171
|
+
});
|
|
172
|
+
return result;
|
|
209
173
|
},
|
|
210
|
-
queue: {
|
|
211
|
-
|
|
212
|
-
add: async (input) => {
|
|
213
|
-
await Promise.resolve();
|
|
174
|
+
queue: async (input) => {
|
|
175
|
+
const result = await kernel.control({ kind: "queue", input }, () => {
|
|
214
176
|
held.push(input);
|
|
215
177
|
drainHeld();
|
|
216
|
-
|
|
178
|
+
return { kind: "accepted" };
|
|
179
|
+
});
|
|
180
|
+
return result;
|
|
181
|
+
},
|
|
182
|
+
abort: async () => {
|
|
183
|
+
const result = await kernel.control({ kind: "abort" }, () => {
|
|
184
|
+
if (!gate.running) {
|
|
185
|
+
return { kind: "rejected", reason: "no active turn" };
|
|
186
|
+
}
|
|
187
|
+
projection = piAbortRequested(projection);
|
|
188
|
+
// Delivery is pi's own AgentSession.abort() minus its idle wait (SDK
|
|
189
|
+
// 0.84.2 agent-session.js: abortRetry(); agent.abort(); await
|
|
190
|
+
// waitForIdle()); both calls are public and synchronous, and both
|
|
191
|
+
// are no-ops until pi has created the run, so before agent_start the
|
|
192
|
+
// intent is held and delivered there. Accepted means taken over; the
|
|
193
|
+
// outcome is pi's own agent_settled on the stream.
|
|
194
|
+
if (piAgentSession.isStreaming) {
|
|
195
|
+
piAgentSession.abortRetry();
|
|
196
|
+
piAgentSession.agent.abort();
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
pendingAbort = true;
|
|
200
|
+
}
|
|
201
|
+
return { kind: "accepted" };
|
|
202
|
+
});
|
|
203
|
+
return result;
|
|
217
204
|
},
|
|
205
|
+
subscribe: (observer, cursor) => kernel.subscribe(observer, cursor),
|
|
206
|
+
records: () => kernel.records(),
|
|
207
|
+
graph: () => kernel.graph(),
|
|
218
208
|
dispose: async () => {
|
|
219
|
-
if (
|
|
209
|
+
if (disposeRequest !== null) {
|
|
220
210
|
return;
|
|
221
211
|
}
|
|
222
|
-
|
|
223
|
-
const
|
|
224
|
-
|
|
212
|
+
held.splice(0);
|
|
213
|
+
const request = kernel.request("toRuntime", { kind: "dispose" });
|
|
214
|
+
disposeRequest = request;
|
|
215
|
+
if (gate.running) {
|
|
216
|
+
// pi's own agent_settled (aborted) ends the turn in the stream.
|
|
217
|
+
projection = piAbortRequested(projection);
|
|
225
218
|
await piAgentSession.abort();
|
|
226
|
-
active.settle({ kind: "aborted" });
|
|
227
219
|
}
|
|
228
220
|
piAgentSession.dispose();
|
|
221
|
+
// pi runs in this process: there is no process exit to observe, so the
|
|
222
|
+
// dispose is answered as taken over rather than with an exit code.
|
|
223
|
+
kernel.respond(request.id, { kind: "accepted" });
|
|
229
224
|
},
|
|
230
225
|
});
|
|
231
226
|
return session;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/runtimes/pi/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/runtimes/pi/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ClientApp, type RequestPermissionRequest, type RequestPermissionResponse, type SessionNotification } from "@agentclientprotocol/sdk";
|
|
2
|
+
import { type JsonRecord } from "../json.js";
|
|
3
|
+
import type { AcpTerminalHost } from "./terminal.js";
|
|
4
|
+
/**
|
|
5
|
+
* What the session records about the runtime→app traffic the SDK routes to
|
|
6
|
+
* this client: every request (permission, terminal) with its id and params,
|
|
7
|
+
* oar's answer to it, every `session/update`, and every vendor extension
|
|
8
|
+
* notification the profile subscribed to. The terminal host stays pure.
|
|
9
|
+
*/
|
|
10
|
+
export interface AcpClientHooks {
|
|
11
|
+
readonly update: (notification: SessionNotification) => void;
|
|
12
|
+
/** A runtime→app request arrived. */
|
|
13
|
+
readonly requested: (id: string, method: string, params: unknown) => void;
|
|
14
|
+
/** oar answered (or failed) a runtime→app request. */
|
|
15
|
+
readonly answered: (id: string, reply: unknown) => void;
|
|
16
|
+
readonly extension: (method: string, params: JsonRecord) => void;
|
|
17
|
+
readonly extensionNotifications: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
/** OAR's YOLO answer to a permission request: the broadest allow on offer, else cancel. */
|
|
20
|
+
export declare function allowPermission(request: RequestPermissionRequest): RequestPermissionResponse;
|
|
21
|
+
/** Compose OAR's typed ACP client handlers directly on the official SDK app. */
|
|
22
|
+
export declare function createAcpClientApp(terminal: AcpTerminalHost, hooks: AcpClientHooks): ClientApp;
|
|
23
|
+
//# sourceMappingURL=client-app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-app.d.ts","sourceRoot":"","sources":["../../../src/shared/acp/client-app.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,SAAS,EAKd,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EAGzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,CAAC,YAAY,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC7D,qCAAqC;IACrC,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1E,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACxD,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACjE,QAAQ,CAAC,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;CACpD;AAED,2FAA2F;AAC3F,wBAAgB,eAAe,CAAC,OAAO,EAAE,wBAAwB,GAAG,yBAAyB,CAM5F;AAcD,gFAAgF;AAChF,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,cAAc,GACpB,SAAS,CAkCX"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* oxlint-disable typescript/promise-function-async -- SDK handlers deliberately return terminal promises directly. */
|
|
2
|
+
import { client as createClient, methods, } from "@agentclientprotocol/sdk";
|
|
3
|
+
import { asRecord } from "../json.js";
|
|
4
|
+
/** OAR's YOLO answer to a permission request: the broadest allow on offer, else cancel. */
|
|
5
|
+
export function allowPermission(request) {
|
|
6
|
+
const selected = request.options.find((option) => option.kind === "allow_always")
|
|
7
|
+
?? request.options.find((option) => option.kind === "allow_once");
|
|
8
|
+
return selected === undefined
|
|
9
|
+
? { outcome: { outcome: "cancelled" } }
|
|
10
|
+
: { outcome: { outcome: "selected", optionId: selected.optionId } };
|
|
11
|
+
}
|
|
12
|
+
let anonymousRequestCounter = 0;
|
|
13
|
+
function requestIdOf(context) {
|
|
14
|
+
if (context.requestId === null) {
|
|
15
|
+
anonymousRequestCounter += 1;
|
|
16
|
+
return `acp-client-${String(anonymousRequestCounter)}`;
|
|
17
|
+
}
|
|
18
|
+
return String(context.requestId);
|
|
19
|
+
}
|
|
20
|
+
const passthrough = (params) => asRecord(params) ?? {};
|
|
21
|
+
/** Compose OAR's typed ACP client handlers directly on the official SDK app. */
|
|
22
|
+
export function createAcpClientApp(terminal, hooks) {
|
|
23
|
+
// Every client request is a toApp request record; the reply (or thrown
|
|
24
|
+
// error) is the answered response.
|
|
25
|
+
const observed = (method, handle) => async (context) => {
|
|
26
|
+
const id = requestIdOf(context);
|
|
27
|
+
hooks.requested(id, method, context.params);
|
|
28
|
+
try {
|
|
29
|
+
const reply = await handle(context.params);
|
|
30
|
+
hooks.answered(id, reply);
|
|
31
|
+
return reply;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
hooks.answered(id, { error: error instanceof Error ? error.message : String(error) });
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
let app = createClient({ name: "oar" })
|
|
39
|
+
.onRequest(methods.client.session.requestPermission, observed(methods.client.session.requestPermission, allowPermission))
|
|
40
|
+
.onRequest(methods.client.terminal.create, observed(methods.client.terminal.create, (params) => terminal.create(params)))
|
|
41
|
+
.onRequest(methods.client.terminal.output, observed(methods.client.terminal.output, (params) => terminal.output(params)))
|
|
42
|
+
.onRequest(methods.client.terminal.waitForExit, observed(methods.client.terminal.waitForExit, (params) => terminal.waitForExit(params)))
|
|
43
|
+
.onRequest(methods.client.terminal.kill, observed(methods.client.terminal.kill, (params) => terminal.kill(params)))
|
|
44
|
+
.onRequest(methods.client.terminal.release, observed(methods.client.terminal.release, (params) => terminal.release(params)))
|
|
45
|
+
.onNotification(methods.client.session.update, ({ params }) => {
|
|
46
|
+
hooks.update(params);
|
|
47
|
+
});
|
|
48
|
+
for (const method of hooks.extensionNotifications) {
|
|
49
|
+
app = app.onNotification(method, passthrough, ({ params }) => {
|
|
50
|
+
hooks.extension(method, params);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return app;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=client-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-app.js","sourceRoot":"","sources":["../../../src/shared/acp/client-app.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type JsonRecord } from "../json.js";
|
|
2
|
-
import type { OpenedAcpSession } from "./profile.js";
|
|
3
2
|
/**
|
|
4
3
|
* The model an ACP agent reports as in effect, read from the agent's own
|
|
5
4
|
* frames rather than from what we asked for. Two spellings exist upstream:
|
|
@@ -15,22 +14,9 @@ import type { OpenedAcpSession } from "./profile.js";
|
|
|
15
14
|
* back to the default silently) and `session/set_model` answers
|
|
16
15
|
* `{_meta: {model}}` with the applied id.
|
|
17
16
|
*
|
|
18
|
-
* Null when the frame carries neither
|
|
19
|
-
*
|
|
17
|
+
* Null when the frame carries neither. Every such frame is an event
|
|
18
|
+
* record with a `model` view, so `Session.model()` is the latest of them;
|
|
19
|
+
* the request parameter is never consulted.
|
|
20
20
|
*/
|
|
21
21
|
export declare function acpReportedModel(frame: JsonRecord | null): string | null;
|
|
22
|
-
/** Last model the agent reported; `null` until it says one. */
|
|
23
|
-
export interface AcpModelReadback {
|
|
24
|
-
readonly current: () => string | null;
|
|
25
|
-
/** Feed any update or response frame; frames without a model change nothing. */
|
|
26
|
-
readonly observe: (frame: JsonRecord | null) => void;
|
|
27
|
-
/**
|
|
28
|
-
* Apply the open handshake in precedence order: the set_model answer
|
|
29
|
-
* (grok's `_meta.model`), then anything pushed while opening (kimi's
|
|
30
|
-
* config_option_update, which arrives before set_model is answered), then
|
|
31
|
-
* the session new/load response. The request parameter is never consulted.
|
|
32
|
-
*/
|
|
33
|
-
readonly opened: (opened: OpenedAcpSession) => void;
|
|
34
|
-
}
|
|
35
|
-
export declare function createAcpModelReadback(): AcpModelReadback;
|
|
36
22
|
//# sourceMappingURL=model.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/shared/acp/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/shared/acp/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAErE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAexE"}
|