@parlor/agent-host 0.2.0 → 0.3.0
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/dist/acp.d.ts +21 -0
- package/dist/acp.d.ts.map +1 -1
- package/dist/acp.js +138 -12
- package/dist/acp.js.map +1 -1
- package/dist/agent-options.d.ts +17 -0
- package/dist/agent-options.d.ts.map +1 -0
- package/dist/agent-options.js +73 -0
- package/dist/agent-options.js.map +1 -0
- package/dist/agent-tools.d.ts +30 -0
- package/dist/agent-tools.d.ts.map +1 -0
- package/dist/agent-tools.js +71 -0
- package/dist/agent-tools.js.map +1 -0
- package/dist/control.d.ts +15 -0
- package/dist/control.d.ts.map +1 -1
- package/dist/control.js.map +1 -1
- package/dist/daemon.d.ts +10 -2
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +149 -14
- package/dist/daemon.js.map +1 -1
- package/dist/fold.d.ts.map +1 -1
- package/dist/fold.js +2 -0
- package/dist/fold.js.map +1 -1
- package/dist/grants.d.ts +9 -0
- package/dist/grants.d.ts.map +1 -1
- package/dist/grants.js.map +1 -1
- package/dist/learned.d.ts +23 -0
- package/dist/learned.d.ts.map +1 -0
- package/dist/learned.js +36 -0
- package/dist/learned.js.map +1 -0
- package/dist/main.js +105 -9
- package/dist/main.js.map +1 -1
- package/dist/mcp-proxy.d.ts +26 -3
- package/dist/mcp-proxy.d.ts.map +1 -1
- package/dist/mcp-proxy.js +180 -9
- package/dist/mcp-proxy.js.map +1 -1
- package/dist/pairing.d.ts +2 -0
- package/dist/pairing.d.ts.map +1 -1
- package/dist/pairing.js +25 -3
- package/dist/pairing.js.map +1 -1
- package/dist/paths.d.ts +2 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +1 -0
- package/dist/paths.js.map +1 -1
- package/dist/policy.d.ts +12 -2
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +13 -3
- package/dist/policy.js.map +1 -1
- package/dist/prompter.d.ts +5 -0
- package/dist/prompter.d.ts.map +1 -1
- package/dist/prompter.js +15 -0
- package/dist/prompter.js.map +1 -1
- package/dist/spec-kit.d.ts +2 -1
- package/dist/spec-kit.d.ts.map +1 -1
- package/dist/spec-kit.js +6 -1
- package/dist/spec-kit.js.map +1 -1
- package/dist/testing/fake-agent.d.ts +12 -0
- package/dist/testing/fake-agent.d.ts.map +1 -1
- package/dist/testing/fake-agent.js +11 -1
- package/dist/testing/fake-agent.js.map +1 -1
- package/dist/turn.d.ts +7 -1
- package/dist/turn.d.ts.map +1 -1
- package/dist/turn.js +16 -3
- package/dist/turn.js.map +1 -1
- package/package.json +9 -9
package/dist/acp.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type SessionConfigOption } from "@agentclientprotocol/sdk";
|
|
2
|
+
import type { AgentOption, AgentUsage } from "@parlor/chat";
|
|
1
3
|
import type { AgentProfile } from "./agents.js";
|
|
2
4
|
/**
|
|
3
5
|
* The only file that knows ACP. The v1 adapter speaks ndjson over stdio through
|
|
@@ -41,6 +43,12 @@ export interface OpenSessionInput {
|
|
|
41
43
|
/** A remote turn never runs in a bypass mode. */
|
|
42
44
|
readonly pinAskMode: boolean;
|
|
43
45
|
readonly strictAsk?: boolean | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* With `pinAskMode`, the agent's own safety review where it has one (Claude's `auto`,
|
|
48
|
+
* Codex's `agent`), asking only for what that review flags. Once the agent leaves it, the
|
|
49
|
+
* session stays in a mode that asks before every action.
|
|
50
|
+
*/
|
|
51
|
+
readonly autoMode?: boolean | undefined;
|
|
44
52
|
}
|
|
45
53
|
export interface StdioMcpServer {
|
|
46
54
|
readonly name: string;
|
|
@@ -58,6 +66,10 @@ export interface AgentSession {
|
|
|
58
66
|
prompt(blocks: readonly PromptBlock[], handlers: TurnHandlers): Promise<StopReason>;
|
|
59
67
|
cancel(): Promise<void>;
|
|
60
68
|
close(): Promise<void>;
|
|
69
|
+
/** What a prompt may choose for this session now, with the value it runs with. */
|
|
70
|
+
readonly options: readonly AgentOption[];
|
|
71
|
+
/** Sets one of `options` to one of its values. */
|
|
72
|
+
setOption(id: string, value: string): Promise<void>;
|
|
61
73
|
}
|
|
62
74
|
export type PromptBlock = {
|
|
63
75
|
readonly kind: "text";
|
|
@@ -100,6 +112,12 @@ export type AgentUpdate = {
|
|
|
100
112
|
} | {
|
|
101
113
|
readonly kind: "mode";
|
|
102
114
|
readonly modeId: string;
|
|
115
|
+
} | {
|
|
116
|
+
readonly kind: "options";
|
|
117
|
+
readonly options: readonly AgentOption[];
|
|
118
|
+
} | {
|
|
119
|
+
readonly kind: "usage";
|
|
120
|
+
readonly usage: AgentUsage;
|
|
103
121
|
};
|
|
104
122
|
export type AskEffect = "allow_once" | "allow_always" | "reject_once" | "reject_always";
|
|
105
123
|
export type AgentAsk = {
|
|
@@ -151,6 +169,7 @@ export interface AcpAgentHandlers {
|
|
|
151
169
|
newSession(input: OpenSessionInput): Promise<{
|
|
152
170
|
readonly id: string;
|
|
153
171
|
readonly modes?: AgentModes | undefined;
|
|
172
|
+
readonly options?: readonly AgentOption[] | undefined;
|
|
154
173
|
}>;
|
|
155
174
|
prompt(sessionId: string, blocks: readonly PromptBlock[], peer: {
|
|
156
175
|
update(update: AgentUpdate): Promise<void>;
|
|
@@ -158,6 +177,8 @@ export interface AcpAgentHandlers {
|
|
|
158
177
|
readonly cancelled: AbortSignal;
|
|
159
178
|
}): Promise<StopReason>;
|
|
160
179
|
}
|
|
180
|
+
/** The agent's select options a prompt may choose, its groups flattened. */
|
|
181
|
+
export declare function agentOptionsOf(configOptions: readonly SessionConfigOption[] | null | undefined): AgentOption[];
|
|
161
182
|
/** ACP v1 over stdio. */
|
|
162
183
|
export declare function acpLauncher(): AgentLauncher;
|
|
163
184
|
/** Serves `handlers` as an ACP agent on `io`, until the other side hangs up. */
|
package/dist/acp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acp.d.ts","sourceRoot":"","sources":["../src/acp.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"acp.d.ts","sourceRoot":"","sources":["../src/acp.ts"],"names":[],"mappings":"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"}
|
package/dist/acp.js
CHANGED
|
@@ -2,6 +2,7 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { Readable, Writable } from "node:stream";
|
|
3
3
|
import { agent as acpAgent, client as acpClient, methods, ndJsonStream, PROTOCOL_VERSION, RequestError, } from "@agentclientprotocol/sdk";
|
|
4
4
|
import { commandOf, launchEnvironment } from "./adapter-launch.js";
|
|
5
|
+
import { agentUsageOf } from "./agent-options.js";
|
|
5
6
|
import { logEvent } from "./log.js";
|
|
6
7
|
/** `openSession` would not run the session; `leftOpen` when the agent still holds it. */
|
|
7
8
|
export class SessionRefused extends Error {
|
|
@@ -17,6 +18,7 @@ const KILL_GRACE_MS = 2_000;
|
|
|
17
18
|
const MAX_DETAIL_CHARS = 4_000;
|
|
18
19
|
const AUTH_REQUIRED = -32000;
|
|
19
20
|
const MCP_PREFIX = "mcp__";
|
|
21
|
+
const AUTO_MODES_BY_PREFERENCE = ["auto", "agent"];
|
|
20
22
|
const ASK_MODES_BY_PREFERENCE = ["default", "workspace-write", "read-only"];
|
|
21
23
|
const STRICT_ASK_MODES_BY_PREFERENCE = ["default", "read-only", "workspace-write"];
|
|
22
24
|
const isFields = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -118,6 +120,12 @@ function updateOf(update) {
|
|
|
118
120
|
};
|
|
119
121
|
case "current_mode_update":
|
|
120
122
|
return { kind: "mode", modeId: update.currentModeId };
|
|
123
|
+
case "config_option_update":
|
|
124
|
+
return { kind: "options", options: agentOptionsOf(update.configOptions) };
|
|
125
|
+
case "usage_update": {
|
|
126
|
+
const usage = agentUsageOf(update._meta, Date.now());
|
|
127
|
+
return usage && { kind: "usage", usage };
|
|
128
|
+
}
|
|
121
129
|
default:
|
|
122
130
|
return undefined;
|
|
123
131
|
}
|
|
@@ -164,8 +172,71 @@ function sessionUpdateOf(update) {
|
|
|
164
172
|
};
|
|
165
173
|
case "mode":
|
|
166
174
|
return { sessionUpdate: "current_mode_update", currentModeId: update.modeId };
|
|
175
|
+
case "options":
|
|
176
|
+
return {
|
|
177
|
+
sessionUpdate: "config_option_update",
|
|
178
|
+
configOptions: update.options.map(configOptionOf),
|
|
179
|
+
};
|
|
180
|
+
case "usage":
|
|
181
|
+
return {
|
|
182
|
+
sessionUpdate: "usage_update",
|
|
183
|
+
used: 0,
|
|
184
|
+
size: 0,
|
|
185
|
+
_meta: {
|
|
186
|
+
"_claude/rateLimit": {
|
|
187
|
+
unifiedWindows: Object.fromEntries(update.usage.windows.map((window) => [
|
|
188
|
+
window.id,
|
|
189
|
+
{
|
|
190
|
+
utilization: window.used,
|
|
191
|
+
...(window.resetsAt === undefined
|
|
192
|
+
? {}
|
|
193
|
+
: { resetsAt: window.resetsAt / 1000 }),
|
|
194
|
+
},
|
|
195
|
+
])),
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
};
|
|
167
199
|
}
|
|
168
200
|
}
|
|
201
|
+
/** The permission mode is the computer's to pin; `model_config` tunes a model, not a choice. */
|
|
202
|
+
const HIDDEN_CATEGORIES = new Set(["mode", "model_config"]);
|
|
203
|
+
/** The agent's select options a prompt may choose, its groups flattened. */
|
|
204
|
+
export function agentOptionsOf(configOptions) {
|
|
205
|
+
return (configOptions ?? []).flatMap((option) => {
|
|
206
|
+
if (option.type !== "select")
|
|
207
|
+
return [];
|
|
208
|
+
if (option.category && HIDDEN_CATEGORIES.has(option.category))
|
|
209
|
+
return [];
|
|
210
|
+
const values = option.options.flatMap((entry) => "options" in entry ? entry.options : [entry]);
|
|
211
|
+
return [
|
|
212
|
+
{
|
|
213
|
+
id: option.id,
|
|
214
|
+
name: option.name,
|
|
215
|
+
...(option.category ? { category: option.category } : {}),
|
|
216
|
+
current: option.currentValue,
|
|
217
|
+
values: values.map((value) => ({
|
|
218
|
+
id: value.value,
|
|
219
|
+
name: value.name,
|
|
220
|
+
...(value.description ? { description: value.description } : {}),
|
|
221
|
+
})),
|
|
222
|
+
},
|
|
223
|
+
];
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
function configOptionOf(option) {
|
|
227
|
+
return {
|
|
228
|
+
id: option.id,
|
|
229
|
+
name: option.name,
|
|
230
|
+
...(option.category ? { category: option.category } : {}),
|
|
231
|
+
type: "select",
|
|
232
|
+
currentValue: option.current,
|
|
233
|
+
options: option.values.map((value) => ({
|
|
234
|
+
value: value.id,
|
|
235
|
+
name: value.name,
|
|
236
|
+
...(value.description ? { description: value.description } : {}),
|
|
237
|
+
})),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
169
240
|
const claudeToolName = (mcp) => ({
|
|
170
241
|
claudeCode: { toolName: `${MCP_PREFIX}${mcp.server}__${mcp.tool}` },
|
|
171
242
|
});
|
|
@@ -290,6 +361,10 @@ function askingModeOf(modes, strict) {
|
|
|
290
361
|
return modes.currentModeId;
|
|
291
362
|
return ASK_MODES_BY_PREFERENCE.find((mode) => available.has(mode));
|
|
292
363
|
}
|
|
364
|
+
function autoModeOf(modes) {
|
|
365
|
+
const available = new Set(modes.availableModes.map((mode) => mode.id));
|
|
366
|
+
return AUTO_MODES_BY_PREFERENCE.find((mode) => available.has(mode));
|
|
367
|
+
}
|
|
293
368
|
function sessionModesOf(modes) {
|
|
294
369
|
return modes
|
|
295
370
|
? {
|
|
@@ -363,13 +438,20 @@ export function acpLauncher() {
|
|
|
363
438
|
const known = state.calls.get(mapped.toolCallId);
|
|
364
439
|
state.calls.set(mapped.toolCallId, { ...known, title: mapped.title });
|
|
365
440
|
}
|
|
441
|
+
else if (mapped.kind === "options") {
|
|
442
|
+
state.options = mapped.options;
|
|
443
|
+
}
|
|
366
444
|
if (mapped.kind === "mode" && state.pinned && mapped.modeId !== state.pinned) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
445
|
+
state.pinned = state.fallback ?? state.pinned;
|
|
446
|
+
state.fallback = undefined;
|
|
447
|
+
if (mapped.modeId !== state.pinned) {
|
|
448
|
+
void context
|
|
449
|
+
.request(methods.agent.session.setMode, {
|
|
450
|
+
sessionId: notification.sessionId,
|
|
451
|
+
modeId: state.pinned,
|
|
452
|
+
})
|
|
453
|
+
.catch(() => undefined);
|
|
454
|
+
}
|
|
373
455
|
}
|
|
374
456
|
state.handlers?.update(mapped);
|
|
375
457
|
};
|
|
@@ -436,7 +518,12 @@ export function acpLauncher() {
|
|
|
436
518
|
cwd: input.cwd,
|
|
437
519
|
mcpServers,
|
|
438
520
|
});
|
|
439
|
-
return {
|
|
521
|
+
return {
|
|
522
|
+
id: input.resume,
|
|
523
|
+
modes: resumed.modes,
|
|
524
|
+
configOptions: resumed.configOptions,
|
|
525
|
+
resumed: true,
|
|
526
|
+
};
|
|
440
527
|
}
|
|
441
528
|
catch { }
|
|
442
529
|
}
|
|
@@ -444,7 +531,12 @@ export function acpLauncher() {
|
|
|
444
531
|
cwd: input.cwd,
|
|
445
532
|
mcpServers,
|
|
446
533
|
});
|
|
447
|
-
return {
|
|
534
|
+
return {
|
|
535
|
+
id: created.sessionId,
|
|
536
|
+
modes: created.modes,
|
|
537
|
+
configOptions: created.configOptions,
|
|
538
|
+
resumed: false,
|
|
539
|
+
};
|
|
448
540
|
};
|
|
449
541
|
return {
|
|
450
542
|
capabilities,
|
|
@@ -466,13 +558,21 @@ export function acpLauncher() {
|
|
|
466
558
|
return context.request(methods.agent.session.close, { sessionId }).then(() => true, () => false);
|
|
467
559
|
};
|
|
468
560
|
const modes = input.pinAskMode ? opened.modes : undefined;
|
|
469
|
-
const
|
|
561
|
+
const asking = modes
|
|
470
562
|
? askingModeOf(modes, input.strictAsk === true)
|
|
471
563
|
: undefined;
|
|
564
|
+
const auto = modes && input.autoMode ? autoModeOf(modes) : undefined;
|
|
565
|
+
const pinned = asking === undefined ? undefined : (auto ?? asking);
|
|
472
566
|
if (modes && pinned === undefined) {
|
|
473
567
|
throw new SessionRefused(`${profile.name} offers no mode that asks before it acts, so it cannot take a turn from an app.`, !(await close()));
|
|
474
568
|
}
|
|
475
|
-
const state = {
|
|
569
|
+
const state = {
|
|
570
|
+
handlers: undefined,
|
|
571
|
+
calls: new Map(),
|
|
572
|
+
pinned,
|
|
573
|
+
fallback: pinned === asking ? undefined : asking,
|
|
574
|
+
options: agentOptionsOf(opened.configOptions),
|
|
575
|
+
};
|
|
476
576
|
sessions.set(sessionId, state);
|
|
477
577
|
if (pinned !== undefined && pinned !== modes?.currentModeId) {
|
|
478
578
|
try {
|
|
@@ -488,6 +588,17 @@ export function acpLauncher() {
|
|
|
488
588
|
const session = {
|
|
489
589
|
id: sessionId,
|
|
490
590
|
resumed: opened.resumed,
|
|
591
|
+
get options() {
|
|
592
|
+
return state.options;
|
|
593
|
+
},
|
|
594
|
+
setOption: async (id, value) => {
|
|
595
|
+
const response = await context.request(methods.agent.session.setConfigOption, {
|
|
596
|
+
sessionId,
|
|
597
|
+
configId: id,
|
|
598
|
+
value,
|
|
599
|
+
});
|
|
600
|
+
state.options = agentOptionsOf(response.configOptions);
|
|
601
|
+
},
|
|
491
602
|
prompt: async (blocks, handlers) => {
|
|
492
603
|
if (state.handlers)
|
|
493
604
|
throw new Error("This session is already answering a prompt.");
|
|
@@ -521,6 +632,7 @@ export function acpLauncher() {
|
|
|
521
632
|
export function serveAcpAgent(handlers, io) {
|
|
522
633
|
const running = new Map();
|
|
523
634
|
const aliases = new Map();
|
|
635
|
+
const configs = new Map();
|
|
524
636
|
const idOf = (sessionId) => aliases.get(sessionId) ?? sessionId;
|
|
525
637
|
const app = acpAgent({ name: "parlor-fake-agent" })
|
|
526
638
|
.onRequest(methods.agent.initialize, () => ({
|
|
@@ -536,13 +648,20 @@ export function serveAcpAgent(handlers, io) {
|
|
|
536
648
|
authMethods: [],
|
|
537
649
|
}))
|
|
538
650
|
.onRequest(methods.agent.session.new, async ({ params }) => {
|
|
539
|
-
const { id, modes } = await handlers.newSession({
|
|
651
|
+
const { id, modes, options } = await handlers.newSession({
|
|
540
652
|
cwd: params.cwd,
|
|
541
653
|
mcpServers: stdioServersOf(params.mcpServers),
|
|
542
654
|
pinAskMode: false,
|
|
543
655
|
});
|
|
544
656
|
const state = sessionModesOf(modes);
|
|
545
|
-
|
|
657
|
+
const configOptions = options?.map(configOptionOf);
|
|
658
|
+
if (configOptions)
|
|
659
|
+
configs.set(id, configOptions);
|
|
660
|
+
return {
|
|
661
|
+
sessionId: id,
|
|
662
|
+
...(state ? { modes: state } : {}),
|
|
663
|
+
...(configOptions ? { configOptions } : {}),
|
|
664
|
+
};
|
|
546
665
|
})
|
|
547
666
|
.onRequest(methods.agent.session.resume, async ({ params }) => {
|
|
548
667
|
if (!handlers.capabilities.resume) {
|
|
@@ -557,6 +676,13 @@ export function serveAcpAgent(handlers, io) {
|
|
|
557
676
|
return {};
|
|
558
677
|
})
|
|
559
678
|
.onRequest(methods.agent.session.setMode, () => ({}))
|
|
679
|
+
.onRequest(methods.agent.session.setConfigOption, ({ params }) => {
|
|
680
|
+
const options = (configs.get(idOf(params.sessionId)) ?? []).map((option) => option.id === params.configId && option.type === "select"
|
|
681
|
+
? { ...option, currentValue: String(params.value) }
|
|
682
|
+
: option);
|
|
683
|
+
configs.set(idOf(params.sessionId), options);
|
|
684
|
+
return { configOptions: options };
|
|
685
|
+
})
|
|
560
686
|
.onRequest(methods.agent.session.close, () => {
|
|
561
687
|
if (!handlers.capabilities.close) {
|
|
562
688
|
throw RequestError.methodNotFound(methods.agent.session.close);
|