@justin06lee/yagami 0.4.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/LICENSE +21 -0
- package/README.md +217 -0
- package/dist/chunk-ASS6MJ7C.js +1821 -0
- package/dist/chunk-ASS6MJ7C.js.map +1 -0
- package/dist/chunk-M5UHR273.js +317 -0
- package/dist/chunk-M5UHR273.js.map +1 -0
- package/dist/cli.js +307 -0
- package/dist/cli.js.map +1 -0
- package/dist/engine-pmCK3S7z.d.ts +381 -0
- package/dist/index.d.ts +328 -0
- package/dist/index.js +259 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +85 -0
- package/dist/server.js +36 -0
- package/dist/server.js.map +1 -0
- package/package.json +78 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { A as ApiError, P as Provider, a as ProviderCapabilities, T as TurnRequest, b as TurnEvent, E as EngineModel } from './engine-pmCK3S7z.js';
|
|
2
|
+
export { c as ApiErrorType, C as CodexProvider, d as CodexProviderOptions, e as CodexSandboxMode, f as CompleteResult, g as ContentBlock, h as ContentBlockParam, D as DetectedProvider, i as EngineOptions, L as LoadedProviders, M as MessageParam, j as MessagesRequest, k as MessagesResponse, l as ModelRef, m as PROVIDER_PRESETS, n as ProviderConfigEntry, o as ProviderKind, p as ProviderPreset, S as SessionCache, q as SessionCacheOptions, r as SseEvent, s as StreamOptions, t as StreamResultInfo, u as StreamStart, v as SystemParam, U as Usage, Y as YagamiEngine, w as createProvider, x as detectProviders, y as loadProviders, z as parseModelRef, B as presetFor, F as qualifiedModel } from './engine-pmCK3S7z.js';
|
|
3
|
+
import { Options, SDKUserMessage, Query, SettingSource, PermissionUpdate, CanUseTool, PermissionResult, SDKMessage } from '@anthropic-ai/claude-agent-sdk';
|
|
4
|
+
export { Options as AgentOptions, CanUseTool, PermissionMode, Query, SDKMessage, SDKUserMessage } from '@anthropic-ai/claude-agent-sdk';
|
|
5
|
+
import { ClientSideConnection, InitializeResponse, SessionNotification, RequestPermissionRequest, RequestPermissionResponse } from '@agentclientprotocol/sdk';
|
|
6
|
+
|
|
7
|
+
interface ClaudeSessionOptions {
|
|
8
|
+
/** Path to the `claude` binary. Auto-resolved when omitted. */
|
|
9
|
+
claudePath?: string;
|
|
10
|
+
/** Agent SDK options; merged over yagami's defaults. */
|
|
11
|
+
options?: Options;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Full agentic Claude Code session (tools, permissions, plan mode — the
|
|
15
|
+
* works), backed by the user's installed, signed-in CLI. This is the
|
|
16
|
+
* embeddable "what T3 Code does" primitive for building UIs on top of
|
|
17
|
+
* Claude Code: unlike the Messages-API engine, nothing is restricted here.
|
|
18
|
+
*
|
|
19
|
+
* Defaults to the `claude_code` system prompt preset so behavior matches the
|
|
20
|
+
* interactive CLI; pass `options.systemPrompt` to override.
|
|
21
|
+
*/
|
|
22
|
+
declare function claudeCodeSession(prompt: string | AsyncIterable<SDKUserMessage>, sessionOptions?: ClaudeSessionOptions): Query;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* How closely an embedded session should mirror the interactive `claude`
|
|
26
|
+
* terminal. This resolves the single most common surprise in library mode:
|
|
27
|
+
* the Agent SDK loads none of your settings by default.
|
|
28
|
+
*
|
|
29
|
+
* - `"terminal"` — behave like your CLI: load user + project + local
|
|
30
|
+
* settings, so CLAUDE.md, skills, hooks, and .mcp.json all apply.
|
|
31
|
+
* - `"isolated"` — load nothing (the raw SDK default); the app supplies
|
|
32
|
+
* everything explicitly. Best when the session must be reproducible or
|
|
33
|
+
* must not pick up the developer's personal config.
|
|
34
|
+
* - `"project"` — load project + local settings but not the user's global
|
|
35
|
+
* ones: shared repo config without personal CLAUDE.md/skills.
|
|
36
|
+
*/
|
|
37
|
+
type Parity = "terminal" | "project" | "isolated";
|
|
38
|
+
/** The `settingSources` a parity level maps to. */
|
|
39
|
+
declare function settingSourcesFor(parity: Parity): SettingSource[];
|
|
40
|
+
|
|
41
|
+
/** A tool-use request handed to the host for a decision. */
|
|
42
|
+
interface PermissionRequest {
|
|
43
|
+
toolName: string;
|
|
44
|
+
input: Record<string, unknown>;
|
|
45
|
+
signal: AbortSignal;
|
|
46
|
+
/**
|
|
47
|
+
* Suggested permission updates the host can echo back to stop being asked
|
|
48
|
+
* again this session (e.g. behind an "always allow" button).
|
|
49
|
+
*/
|
|
50
|
+
suggestions?: PermissionUpdate[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The host's answer. `allow` optionally rewrites the tool input and/or
|
|
54
|
+
* persists permission updates for the rest of the session; `deny` carries a
|
|
55
|
+
* message the model sees and can optionally interrupt the turn.
|
|
56
|
+
*/
|
|
57
|
+
type PermissionDecision = {
|
|
58
|
+
behavior: "allow";
|
|
59
|
+
updatedInput?: Record<string, unknown>;
|
|
60
|
+
updatedPermissions?: PermissionUpdate[];
|
|
61
|
+
} | {
|
|
62
|
+
behavior: "deny";
|
|
63
|
+
message?: string;
|
|
64
|
+
interrupt?: boolean;
|
|
65
|
+
};
|
|
66
|
+
/** What the app implements: show UI, return a decision. */
|
|
67
|
+
type PermissionHandler = (req: PermissionRequest) => PermissionDecision | Promise<PermissionDecision>;
|
|
68
|
+
interface PermissionAdapterOptions {
|
|
69
|
+
/**
|
|
70
|
+
* Decision used when no handler is set, a handler throws, or the request is
|
|
71
|
+
* aborted. Defaults to denying — the safe choice for an unattended host.
|
|
72
|
+
*/
|
|
73
|
+
fallback?: "allow" | "deny";
|
|
74
|
+
/** Tool names to auto-allow without ever calling the handler. */
|
|
75
|
+
autoAllow?: Iterable<string>;
|
|
76
|
+
/** Tool names to auto-deny without ever calling the handler. */
|
|
77
|
+
autoDeny?: Iterable<string>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Turns a host-supplied {@link PermissionHandler} into the Agent SDK's
|
|
81
|
+
* {@link CanUseTool} callback, owning the state machine so the app only has
|
|
82
|
+
* to answer one question: allow or deny this tool call?
|
|
83
|
+
*
|
|
84
|
+
* The policy (what to auto-approve) stays with the app — yagami never bakes
|
|
85
|
+
* in a permissive default. Without a handler, everything falls back (deny by
|
|
86
|
+
* default), so a session is safe before the UI is wired up.
|
|
87
|
+
*/
|
|
88
|
+
declare class PermissionAdapter {
|
|
89
|
+
private handler;
|
|
90
|
+
private readonly fallback;
|
|
91
|
+
private readonly autoAllow;
|
|
92
|
+
private readonly autoDeny;
|
|
93
|
+
constructor(options?: PermissionAdapterOptions);
|
|
94
|
+
/** Install (or replace) the host decision callback. */
|
|
95
|
+
setHandler(handler: PermissionHandler | undefined): void;
|
|
96
|
+
allowTool(toolName: string): void;
|
|
97
|
+
denyTool(toolName: string): void;
|
|
98
|
+
private fallbackResult;
|
|
99
|
+
/**
|
|
100
|
+
* The callback to hand to `claudeCodeSession`/the Agent SDK. Typed to
|
|
101
|
+
* always resolve (never null), and assignable to the SDK's CanUseTool.
|
|
102
|
+
*/
|
|
103
|
+
readonly canUseTool: (...args: Parameters<CanUseTool>) => Promise<PermissionResult>;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
interface AgentSessionOptions {
|
|
107
|
+
/** Path to the `claude` binary. Auto-resolved when omitted. */
|
|
108
|
+
claudePath?: string;
|
|
109
|
+
/** Project directory the agent works in. */
|
|
110
|
+
cwd?: string;
|
|
111
|
+
/** How closely to mirror the interactive terminal (default "terminal"). */
|
|
112
|
+
parity?: Parity;
|
|
113
|
+
/** Model id/alias; the CLI default when omitted. */
|
|
114
|
+
model?: string;
|
|
115
|
+
/** Host permission callback (see {@link PermissionAdapter}). */
|
|
116
|
+
onPermission?: PermissionHandler;
|
|
117
|
+
/** Options for the permission adapter (fallback, auto-allow/deny). */
|
|
118
|
+
permission?: PermissionAdapterOptions;
|
|
119
|
+
/** Reported to the CLI as the client application (e.g. your app name). */
|
|
120
|
+
appName?: string;
|
|
121
|
+
/** Extra Agent SDK options, merged last (wins over the above). */
|
|
122
|
+
options?: Options;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* A long-lived, agentic Claude Code session for building a UI on top of the
|
|
126
|
+
* CLI — the ruri use case. It keeps one warm process across turns (so only
|
|
127
|
+
* the first turn pays cold-start), threads permission decisions to a host
|
|
128
|
+
* callback, mirrors your terminal settings by default, and exposes the
|
|
129
|
+
* lifecycle the interactive CLI gives you for free: send, interrupt, resume,
|
|
130
|
+
* change model/permission mode, close.
|
|
131
|
+
*
|
|
132
|
+
* Everything the model produces is an {@link SDKMessage} you render yourself.
|
|
133
|
+
*/
|
|
134
|
+
declare class AgentSession implements AsyncIterable<SDKMessage> {
|
|
135
|
+
readonly permissions: PermissionAdapter;
|
|
136
|
+
private readonly claudePath;
|
|
137
|
+
private readonly appName;
|
|
138
|
+
private readonly baseOptions;
|
|
139
|
+
private readonly input;
|
|
140
|
+
private query;
|
|
141
|
+
private started;
|
|
142
|
+
private closed;
|
|
143
|
+
private currentSessionId;
|
|
144
|
+
constructor(options?: AgentSessionOptions);
|
|
145
|
+
/** Set (or clear) the host permission callback after construction. */
|
|
146
|
+
setPermissionHandler(handler: PermissionHandler | undefined): void;
|
|
147
|
+
/** The live Claude Code session id, once the first turn has started. */
|
|
148
|
+
get sessionId(): string | undefined;
|
|
149
|
+
/** Queue a user turn. The process starts on the first send and stays warm. */
|
|
150
|
+
send(text: string, options?: {
|
|
151
|
+
images?: Array<{
|
|
152
|
+
data: string;
|
|
153
|
+
mediaType?: string;
|
|
154
|
+
}>;
|
|
155
|
+
}): void;
|
|
156
|
+
private ensureStarted;
|
|
157
|
+
/** Iterate every SDK message the agent produces across all turns. */
|
|
158
|
+
[Symbol.asyncIterator](): AsyncIterator<SDKMessage>;
|
|
159
|
+
/** Interrupt the in-flight turn (the CLI's Esc/Ctrl-C). */
|
|
160
|
+
interrupt(): Promise<void>;
|
|
161
|
+
/** Switch models mid-session (the CLI's /model). */
|
|
162
|
+
setModel(model: string): Promise<void>;
|
|
163
|
+
/** Switch permission mode mid-session (default/acceptEdits/plan/bypassPermissions). */
|
|
164
|
+
setPermissionMode(mode: "default" | "acceptEdits" | "plan" | "bypassPermissions"): Promise<void>;
|
|
165
|
+
/** Models the CLI reports as available (for a picker). */
|
|
166
|
+
supportedModels(): Promise<Array<{
|
|
167
|
+
value: string;
|
|
168
|
+
displayName: string;
|
|
169
|
+
}>>;
|
|
170
|
+
/** End the session and tear down the process. */
|
|
171
|
+
close(): void;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Convenience: start an {@link AgentSession} and immediately send one turn.
|
|
175
|
+
* Returns the session so callers can iterate it, interrupt, or send more.
|
|
176
|
+
*/
|
|
177
|
+
declare function startAgentSession(prompt: string, options?: AgentSessionOptions): AgentSession;
|
|
178
|
+
|
|
179
|
+
/** Base class for typed yagami failures — every subclass carries a stable `code`. */
|
|
180
|
+
declare class YagamiError extends Error {
|
|
181
|
+
readonly code: string;
|
|
182
|
+
constructor(message: string, code: string);
|
|
183
|
+
}
|
|
184
|
+
/** The provider's CLI could not be found on this machine. */
|
|
185
|
+
declare class ProviderNotInstalledError extends YagamiError {
|
|
186
|
+
readonly provider: string;
|
|
187
|
+
readonly installHint: string;
|
|
188
|
+
constructor(provider: string, installHint: string, detail?: string);
|
|
189
|
+
}
|
|
190
|
+
/** The provider's CLI is installed but not logged in (or its login expired). */
|
|
191
|
+
declare class AuthRequiredError extends YagamiError {
|
|
192
|
+
readonly provider: string;
|
|
193
|
+
readonly loginCommand: string;
|
|
194
|
+
constructor(provider: string, loginCommand: string, detail?: string);
|
|
195
|
+
}
|
|
196
|
+
/** The provider ran but failed — process crash, protocol error, engine error. */
|
|
197
|
+
declare class ProviderError extends YagamiError {
|
|
198
|
+
readonly provider: string;
|
|
199
|
+
constructor(provider: string, message: string);
|
|
200
|
+
}
|
|
201
|
+
/** Result of comparing an SDK build against the CLI binary it drives. */
|
|
202
|
+
interface VersionSkew {
|
|
203
|
+
sdkVersion: string;
|
|
204
|
+
binaryVersion: string;
|
|
205
|
+
inSync: boolean;
|
|
206
|
+
note: string;
|
|
207
|
+
}
|
|
208
|
+
/** Map any failure onto the Anthropic-shaped HTTP error the API returns. */
|
|
209
|
+
declare function toApiError(err: unknown): ApiError;
|
|
210
|
+
|
|
211
|
+
interface ClaudeProviderOptions {
|
|
212
|
+
/** Path to the `claude` binary. Auto-resolved when omitted. */
|
|
213
|
+
path?: string;
|
|
214
|
+
/** Optional CLAUDE_CONFIG_DIR override for the spawned CLI. */
|
|
215
|
+
configDir?: string;
|
|
216
|
+
/** Working directory for completion turns (inert — tools are disabled). */
|
|
217
|
+
workDir?: string;
|
|
218
|
+
/** Reported to the CLI as the client application. */
|
|
219
|
+
appName?: string;
|
|
220
|
+
}
|
|
221
|
+
/** Claude Code through the Agent SDK, pointed at the user's signed-in binary. */
|
|
222
|
+
declare class ClaudeProvider implements Provider {
|
|
223
|
+
readonly id = "claude";
|
|
224
|
+
readonly label = "Claude Code";
|
|
225
|
+
readonly executable: string;
|
|
226
|
+
readonly loginCommand = "claude (then /login)";
|
|
227
|
+
readonly capabilities: ProviderCapabilities;
|
|
228
|
+
private readonly configDir;
|
|
229
|
+
private readonly workDir;
|
|
230
|
+
private readonly appName;
|
|
231
|
+
constructor(options?: ClaudeProviderOptions);
|
|
232
|
+
/** Hardened options shared by every completion turn and probe. */
|
|
233
|
+
private baseOptions;
|
|
234
|
+
run(req: TurnRequest): AsyncGenerator<TurnEvent, void, undefined>;
|
|
235
|
+
/** Ask the CLI which models it supports via a short-lived control session. */
|
|
236
|
+
listModels(): Promise<EngineModel[]>;
|
|
237
|
+
version(): Promise<string | undefined>;
|
|
238
|
+
/**
|
|
239
|
+
* Compare the bundled Agent SDK build against the installed CLI. Their
|
|
240
|
+
* last version components track the same build number when in sync.
|
|
241
|
+
*/
|
|
242
|
+
versionSkew(): Promise<VersionSkew | undefined>;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
interface AcpHandlers {
|
|
246
|
+
onUpdate?: (n: SessionNotification) => void;
|
|
247
|
+
onPermission?: (p: RequestPermissionRequest) => Promise<RequestPermissionResponse>;
|
|
248
|
+
}
|
|
249
|
+
/** A live ACP agent process plus its negotiated connection. */
|
|
250
|
+
interface AcpConnection {
|
|
251
|
+
agent: ClientSideConnection;
|
|
252
|
+
init: InitializeResponse;
|
|
253
|
+
setHandlers(handlers: AcpHandlers): void;
|
|
254
|
+
close(): void;
|
|
255
|
+
}
|
|
256
|
+
interface AcpProviderOptions {
|
|
257
|
+
id: string;
|
|
258
|
+
label: string;
|
|
259
|
+
/** Executable name or path, resolved like any other CLI. */
|
|
260
|
+
command: string;
|
|
261
|
+
args?: string[];
|
|
262
|
+
/** Explicit executable path override (wins over `command`). */
|
|
263
|
+
path?: string;
|
|
264
|
+
env?: Record<string, string>;
|
|
265
|
+
workDir?: string;
|
|
266
|
+
appName?: string;
|
|
267
|
+
/** Id of the session config option that selects the model (default "model"). */
|
|
268
|
+
modelConfigId?: string;
|
|
269
|
+
loginCommand?: string;
|
|
270
|
+
installHint?: string;
|
|
271
|
+
/** Test seam: replaces process spawning. */
|
|
272
|
+
connect?: (cwd: string) => Promise<AcpConnection>;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Any agent speaking the Agent Client Protocol over stdio — OpenCode,
|
|
276
|
+
* Gemini CLI, Copilot, Cursor, Qwen Code, Kimi, Goose, and anything in the
|
|
277
|
+
* ACP registry. One adapter, many harnesses.
|
|
278
|
+
*/
|
|
279
|
+
declare class AcpProvider implements Provider {
|
|
280
|
+
readonly id: string;
|
|
281
|
+
readonly label: string;
|
|
282
|
+
readonly executable: string;
|
|
283
|
+
readonly loginCommand: string;
|
|
284
|
+
readonly capabilities: ProviderCapabilities;
|
|
285
|
+
private readonly args;
|
|
286
|
+
private readonly env;
|
|
287
|
+
private readonly workDir;
|
|
288
|
+
private readonly appName;
|
|
289
|
+
private readonly modelConfigId;
|
|
290
|
+
private readonly connectImpl;
|
|
291
|
+
constructor(options: AcpProviderOptions);
|
|
292
|
+
private spawnConnection;
|
|
293
|
+
private classify;
|
|
294
|
+
run(req: TurnRequest): AsyncGenerator<TurnEvent, void, undefined>;
|
|
295
|
+
private selectModel;
|
|
296
|
+
listModels(): Promise<EngineModel[]>;
|
|
297
|
+
/**
|
|
298
|
+
* The agent's self-reported name/version from the ACP handshake. When the
|
|
299
|
+
* handshake fails (wrong binary, version too old for ACP), falls back to
|
|
300
|
+
* `--version` and says so, because that is exactly what `doctor` needs.
|
|
301
|
+
*/
|
|
302
|
+
version(): Promise<string | undefined>;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
interface FindExecutableOptions {
|
|
306
|
+
/** Explicit path from config/CLI flags; wins when set, errors when wrong. */
|
|
307
|
+
explicit?: string;
|
|
308
|
+
/** Extra absolute candidates to try after PATH. */
|
|
309
|
+
extraPaths?: string[];
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Locate a CLI binary: explicit path first, then PATH, then the usual
|
|
313
|
+
* install directories. Returns undefined when nothing is found.
|
|
314
|
+
*/
|
|
315
|
+
declare function findExecutable(name: string, options?: FindExecutableOptions): string | undefined;
|
|
316
|
+
/** Like findExecutable, but throws a typed, actionable error when missing. */
|
|
317
|
+
declare function resolveExecutable(providerId: string, name: string, installHint: string, options?: FindExecutableOptions): string;
|
|
318
|
+
/**
|
|
319
|
+
* Locate the user's installed (and signed-in) Claude Code CLI. The resolved
|
|
320
|
+
* path is handed to the Agent SDK via `pathToClaudeCodeExecutable`, so the
|
|
321
|
+
* spawned engine is the same binary — and the same login — the user gets in
|
|
322
|
+
* their terminal.
|
|
323
|
+
*/
|
|
324
|
+
declare function resolveClaudeExecutable(explicit?: string): string;
|
|
325
|
+
|
|
326
|
+
declare const VERSION = "0.4.1";
|
|
327
|
+
|
|
328
|
+
export { type AcpConnection, AcpProvider, type AcpProviderOptions, AgentSession, type AgentSessionOptions, ApiError, AuthRequiredError, ClaudeProvider, type ClaudeProviderOptions, type ClaudeSessionOptions, EngineModel, type Parity, PermissionAdapter, type PermissionAdapterOptions, type PermissionDecision, type PermissionHandler, type PermissionRequest, Provider, ProviderCapabilities, ProviderError, ProviderNotInstalledError, TurnEvent, TurnRequest, VERSION, type VersionSkew, YagamiError, claudeCodeSession, findExecutable, resolveClaudeExecutable, resolveExecutable, settingSourcesFor, startAgentSession, toApiError };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AcpProvider,
|
|
3
|
+
ApiError,
|
|
4
|
+
AsyncQueue,
|
|
5
|
+
AuthRequiredError,
|
|
6
|
+
ClaudeProvider,
|
|
7
|
+
CodexProvider,
|
|
8
|
+
PROVIDER_PRESETS,
|
|
9
|
+
ProviderError,
|
|
10
|
+
ProviderNotInstalledError,
|
|
11
|
+
SessionCache,
|
|
12
|
+
VERSION,
|
|
13
|
+
YagamiEngine,
|
|
14
|
+
YagamiError,
|
|
15
|
+
classifyProviderFailure,
|
|
16
|
+
createProvider,
|
|
17
|
+
detectProviders,
|
|
18
|
+
findExecutable,
|
|
19
|
+
loadProviders,
|
|
20
|
+
parseModelRef,
|
|
21
|
+
presetFor,
|
|
22
|
+
qualifiedModel,
|
|
23
|
+
resolveClaudeExecutable,
|
|
24
|
+
resolveExecutable,
|
|
25
|
+
toApiError
|
|
26
|
+
} from "./chunk-ASS6MJ7C.js";
|
|
27
|
+
|
|
28
|
+
// src/core/session.ts
|
|
29
|
+
import {
|
|
30
|
+
query
|
|
31
|
+
} from "@anthropic-ai/claude-agent-sdk";
|
|
32
|
+
function claudeCodeSession(prompt, sessionOptions = {}) {
|
|
33
|
+
const claudePath = resolveClaudeExecutable(
|
|
34
|
+
sessionOptions.claudePath ?? sessionOptions.options?.pathToClaudeCodeExecutable
|
|
35
|
+
);
|
|
36
|
+
return query({
|
|
37
|
+
prompt,
|
|
38
|
+
options: {
|
|
39
|
+
systemPrompt: { type: "preset", preset: "claude_code" },
|
|
40
|
+
...sessionOptions.options,
|
|
41
|
+
pathToClaudeCodeExecutable: claudePath
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/core/agentSession.ts
|
|
47
|
+
import {
|
|
48
|
+
query as query2
|
|
49
|
+
} from "@anthropic-ai/claude-agent-sdk";
|
|
50
|
+
|
|
51
|
+
// src/core/parity.ts
|
|
52
|
+
var SETTING_SOURCES = {
|
|
53
|
+
terminal: ["user", "project", "local"],
|
|
54
|
+
project: ["project", "local"],
|
|
55
|
+
isolated: []
|
|
56
|
+
};
|
|
57
|
+
function settingSourcesFor(parity) {
|
|
58
|
+
return [...SETTING_SOURCES[parity]];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/core/permission.ts
|
|
62
|
+
var PermissionAdapter = class {
|
|
63
|
+
handler;
|
|
64
|
+
fallback;
|
|
65
|
+
autoAllow;
|
|
66
|
+
autoDeny;
|
|
67
|
+
constructor(options = {}) {
|
|
68
|
+
this.fallback = options.fallback ?? "deny";
|
|
69
|
+
this.autoAllow = new Set(options.autoAllow ?? []);
|
|
70
|
+
this.autoDeny = new Set(options.autoDeny ?? []);
|
|
71
|
+
}
|
|
72
|
+
/** Install (or replace) the host decision callback. */
|
|
73
|
+
setHandler(handler) {
|
|
74
|
+
this.handler = handler;
|
|
75
|
+
}
|
|
76
|
+
allowTool(toolName) {
|
|
77
|
+
this.autoDeny.delete(toolName);
|
|
78
|
+
this.autoAllow.add(toolName);
|
|
79
|
+
}
|
|
80
|
+
denyTool(toolName) {
|
|
81
|
+
this.autoAllow.delete(toolName);
|
|
82
|
+
this.autoDeny.add(toolName);
|
|
83
|
+
}
|
|
84
|
+
fallbackResult(reason) {
|
|
85
|
+
return this.fallback === "allow" ? { behavior: "allow", updatedInput: {} } : { behavior: "deny", message: reason };
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The callback to hand to `claudeCodeSession`/the Agent SDK. Typed to
|
|
89
|
+
* always resolve (never null), and assignable to the SDK's CanUseTool.
|
|
90
|
+
*/
|
|
91
|
+
canUseTool = async (toolName, input, options) => {
|
|
92
|
+
if (this.autoDeny.has(toolName)) {
|
|
93
|
+
return { behavior: "deny", message: `tool "${toolName}" is disabled for this session` };
|
|
94
|
+
}
|
|
95
|
+
if (this.autoAllow.has(toolName)) {
|
|
96
|
+
return { behavior: "allow", updatedInput: input };
|
|
97
|
+
}
|
|
98
|
+
if (!this.handler) return this.fallbackResult(`no permission handler is set; denying "${toolName}"`);
|
|
99
|
+
if (options.signal.aborted) return this.fallbackResult("request aborted");
|
|
100
|
+
let decision;
|
|
101
|
+
try {
|
|
102
|
+
decision = await this.handler({
|
|
103
|
+
toolName,
|
|
104
|
+
input,
|
|
105
|
+
signal: options.signal,
|
|
106
|
+
...options.suggestions ? { suggestions: options.suggestions } : {}
|
|
107
|
+
});
|
|
108
|
+
} catch (err) {
|
|
109
|
+
return this.fallbackResult(`permission handler threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
110
|
+
}
|
|
111
|
+
if (decision.behavior === "allow") {
|
|
112
|
+
return {
|
|
113
|
+
behavior: "allow",
|
|
114
|
+
updatedInput: decision.updatedInput ?? input,
|
|
115
|
+
...decision.updatedPermissions ? { updatedPermissions: decision.updatedPermissions } : {}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
behavior: "deny",
|
|
120
|
+
message: decision.message ?? `tool "${toolName}" denied by host`,
|
|
121
|
+
...decision.interrupt ? { interrupt: true } : {}
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// src/core/agentSession.ts
|
|
127
|
+
var AgentSession = class {
|
|
128
|
+
permissions;
|
|
129
|
+
claudePath;
|
|
130
|
+
appName;
|
|
131
|
+
baseOptions;
|
|
132
|
+
input = new AsyncQueue();
|
|
133
|
+
query;
|
|
134
|
+
started = false;
|
|
135
|
+
closed = false;
|
|
136
|
+
currentSessionId;
|
|
137
|
+
constructor(options = {}) {
|
|
138
|
+
this.claudePath = resolveClaudeExecutable(options.claudePath ?? options.options?.pathToClaudeCodeExecutable);
|
|
139
|
+
this.appName = options.appName ?? "yagami";
|
|
140
|
+
this.permissions = new PermissionAdapter(options.permission ?? {});
|
|
141
|
+
if (options.onPermission) this.permissions.setHandler(options.onPermission);
|
|
142
|
+
this.baseOptions = {
|
|
143
|
+
systemPrompt: { type: "preset", preset: "claude_code" },
|
|
144
|
+
settingSources: settingSourcesFor(options.parity ?? "terminal"),
|
|
145
|
+
includePartialMessages: true,
|
|
146
|
+
...options.cwd ? { cwd: options.cwd } : {},
|
|
147
|
+
...options.model ? { model: options.model } : {},
|
|
148
|
+
...options.options,
|
|
149
|
+
canUseTool: options.options?.canUseTool ?? this.permissions.canUseTool,
|
|
150
|
+
pathToClaudeCodeExecutable: this.claudePath,
|
|
151
|
+
env: {
|
|
152
|
+
...process.env,
|
|
153
|
+
CLAUDE_AGENT_SDK_CLIENT_APP: `${this.appName}/${VERSION}`,
|
|
154
|
+
...options.options?.env
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/** Set (or clear) the host permission callback after construction. */
|
|
159
|
+
setPermissionHandler(handler) {
|
|
160
|
+
this.permissions.setHandler(handler);
|
|
161
|
+
}
|
|
162
|
+
/** The live Claude Code session id, once the first turn has started. */
|
|
163
|
+
get sessionId() {
|
|
164
|
+
return this.currentSessionId;
|
|
165
|
+
}
|
|
166
|
+
/** Queue a user turn. The process starts on the first send and stays warm. */
|
|
167
|
+
send(text, options = {}) {
|
|
168
|
+
if (this.closed) throw new Error("session is closed");
|
|
169
|
+
const content = options.images && options.images.length > 0 ? [
|
|
170
|
+
...options.images.map((img) => ({ type: "image", source: { type: "base64", media_type: img.mediaType ?? "image/png", data: img.data } })),
|
|
171
|
+
{ type: "text", text }
|
|
172
|
+
] : text;
|
|
173
|
+
this.input.push({
|
|
174
|
+
type: "user",
|
|
175
|
+
message: { role: "user", content },
|
|
176
|
+
parent_tool_use_id: null,
|
|
177
|
+
session_id: this.currentSessionId ?? ""
|
|
178
|
+
});
|
|
179
|
+
this.ensureStarted();
|
|
180
|
+
}
|
|
181
|
+
ensureStarted() {
|
|
182
|
+
if (this.started) return;
|
|
183
|
+
this.started = true;
|
|
184
|
+
this.query = query2({ prompt: this.input, options: this.baseOptions });
|
|
185
|
+
}
|
|
186
|
+
/** Iterate every SDK message the agent produces across all turns. */
|
|
187
|
+
async *[Symbol.asyncIterator]() {
|
|
188
|
+
this.ensureStarted();
|
|
189
|
+
try {
|
|
190
|
+
for await (const msg of this.query) {
|
|
191
|
+
if (msg.type === "system" && msg.subtype === "init") this.currentSessionId = msg.session_id;
|
|
192
|
+
else if (msg.type === "result") this.currentSessionId = msg.session_id;
|
|
193
|
+
yield msg;
|
|
194
|
+
}
|
|
195
|
+
} catch (err) {
|
|
196
|
+
throw classifyProviderFailure("claude", "claude (then /login)", err);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/** Interrupt the in-flight turn (the CLI's Esc/Ctrl-C). */
|
|
200
|
+
async interrupt() {
|
|
201
|
+
await this.query?.interrupt();
|
|
202
|
+
}
|
|
203
|
+
/** Switch models mid-session (the CLI's /model). */
|
|
204
|
+
async setModel(model) {
|
|
205
|
+
await this.query?.setModel(model);
|
|
206
|
+
}
|
|
207
|
+
/** Switch permission mode mid-session (default/acceptEdits/plan/bypassPermissions). */
|
|
208
|
+
async setPermissionMode(mode) {
|
|
209
|
+
await this.query?.setPermissionMode(mode);
|
|
210
|
+
}
|
|
211
|
+
/** Models the CLI reports as available (for a picker). */
|
|
212
|
+
async supportedModels() {
|
|
213
|
+
this.ensureStarted();
|
|
214
|
+
const models = await this.query.supportedModels();
|
|
215
|
+
return models.map((m) => ({ value: m.value, displayName: m.displayName }));
|
|
216
|
+
}
|
|
217
|
+
/** End the session and tear down the process. */
|
|
218
|
+
close() {
|
|
219
|
+
if (this.closed) return;
|
|
220
|
+
this.closed = true;
|
|
221
|
+
this.input.end();
|
|
222
|
+
this.query?.close();
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
function startAgentSession(prompt, options = {}) {
|
|
226
|
+
const session = new AgentSession(options);
|
|
227
|
+
session.send(prompt);
|
|
228
|
+
return session;
|
|
229
|
+
}
|
|
230
|
+
export {
|
|
231
|
+
AcpProvider,
|
|
232
|
+
AgentSession,
|
|
233
|
+
ApiError,
|
|
234
|
+
AuthRequiredError,
|
|
235
|
+
ClaudeProvider,
|
|
236
|
+
CodexProvider,
|
|
237
|
+
PROVIDER_PRESETS,
|
|
238
|
+
PermissionAdapter,
|
|
239
|
+
ProviderError,
|
|
240
|
+
ProviderNotInstalledError,
|
|
241
|
+
SessionCache,
|
|
242
|
+
VERSION,
|
|
243
|
+
YagamiEngine,
|
|
244
|
+
YagamiError,
|
|
245
|
+
claudeCodeSession,
|
|
246
|
+
createProvider,
|
|
247
|
+
detectProviders,
|
|
248
|
+
findExecutable,
|
|
249
|
+
loadProviders,
|
|
250
|
+
parseModelRef,
|
|
251
|
+
presetFor,
|
|
252
|
+
qualifiedModel,
|
|
253
|
+
resolveClaudeExecutable,
|
|
254
|
+
resolveExecutable,
|
|
255
|
+
settingSourcesFor,
|
|
256
|
+
startAgentSession,
|
|
257
|
+
toApiError
|
|
258
|
+
};
|
|
259
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/session.ts","../src/core/agentSession.ts","../src/core/parity.ts","../src/core/permission.ts"],"sourcesContent":["import {\n query,\n type Options,\n type Query,\n type SDKUserMessage,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport { resolveClaudeExecutable } from \"./executable.js\";\n\nexport interface ClaudeSessionOptions {\n /** Path to the `claude` binary. Auto-resolved when omitted. */\n claudePath?: string;\n /** Agent SDK options; merged over yagami's defaults. */\n options?: Options;\n}\n\n/**\n * Full agentic Claude Code session (tools, permissions, plan mode — the\n * works), backed by the user's installed, signed-in CLI. This is the\n * embeddable \"what T3 Code does\" primitive for building UIs on top of\n * Claude Code: unlike the Messages-API engine, nothing is restricted here.\n *\n * Defaults to the `claude_code` system prompt preset so behavior matches the\n * interactive CLI; pass `options.systemPrompt` to override.\n */\nexport function claudeCodeSession(\n prompt: string | AsyncIterable<SDKUserMessage>,\n sessionOptions: ClaudeSessionOptions = {},\n): Query {\n const claudePath = resolveClaudeExecutable(\n sessionOptions.claudePath ?? sessionOptions.options?.pathToClaudeCodeExecutable,\n );\n return query({\n prompt,\n options: {\n systemPrompt: { type: \"preset\", preset: \"claude_code\" },\n ...sessionOptions.options,\n pathToClaudeCodeExecutable: claudePath,\n },\n });\n}\n\nexport type {\n Options as AgentOptions,\n Query,\n SDKMessage,\n SDKUserMessage,\n PermissionMode,\n CanUseTool,\n} from \"@anthropic-ai/claude-agent-sdk\";\n","import {\n query,\n type Options,\n type Query,\n type SDKMessage,\n type SDKUserMessage,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport { resolveClaudeExecutable } from \"./executable.js\";\nimport { classifyProviderFailure } from \"./errors.js\";\nimport { settingSourcesFor, type Parity } from \"./parity.js\";\nimport { PermissionAdapter, type PermissionHandler, type PermissionAdapterOptions } from \"./permission.js\";\nimport { AsyncQueue } from \"./providers/queue.js\";\nimport { VERSION } from \"../version.js\";\n\nexport interface AgentSessionOptions {\n /** Path to the `claude` binary. Auto-resolved when omitted. */\n claudePath?: string;\n /** Project directory the agent works in. */\n cwd?: string;\n /** How closely to mirror the interactive terminal (default \"terminal\"). */\n parity?: Parity;\n /** Model id/alias; the CLI default when omitted. */\n model?: string;\n /** Host permission callback (see {@link PermissionAdapter}). */\n onPermission?: PermissionHandler;\n /** Options for the permission adapter (fallback, auto-allow/deny). */\n permission?: PermissionAdapterOptions;\n /** Reported to the CLI as the client application (e.g. your app name). */\n appName?: string;\n /** Extra Agent SDK options, merged last (wins over the above). */\n options?: Options;\n}\n\n/**\n * A long-lived, agentic Claude Code session for building a UI on top of the\n * CLI — the ruri use case. It keeps one warm process across turns (so only\n * the first turn pays cold-start), threads permission decisions to a host\n * callback, mirrors your terminal settings by default, and exposes the\n * lifecycle the interactive CLI gives you for free: send, interrupt, resume,\n * change model/permission mode, close.\n *\n * Everything the model produces is an {@link SDKMessage} you render yourself.\n */\nexport class AgentSession implements AsyncIterable<SDKMessage> {\n readonly permissions: PermissionAdapter;\n private readonly claudePath: string;\n private readonly appName: string;\n private readonly baseOptions: Options;\n private readonly input = new AsyncQueue<SDKUserMessage>();\n private query: Query | undefined;\n private started = false;\n private closed = false;\n private currentSessionId: string | undefined;\n\n constructor(options: AgentSessionOptions = {}) {\n this.claudePath = resolveClaudeExecutable(options.claudePath ?? options.options?.pathToClaudeCodeExecutable);\n this.appName = options.appName ?? \"yagami\";\n this.permissions = new PermissionAdapter(options.permission ?? {});\n if (options.onPermission) this.permissions.setHandler(options.onPermission);\n this.baseOptions = {\n systemPrompt: { type: \"preset\", preset: \"claude_code\" },\n settingSources: settingSourcesFor(options.parity ?? \"terminal\"),\n includePartialMessages: true,\n ...(options.cwd ? { cwd: options.cwd } : {}),\n ...(options.model ? { model: options.model } : {}),\n ...options.options,\n canUseTool: options.options?.canUseTool ?? this.permissions.canUseTool,\n pathToClaudeCodeExecutable: this.claudePath,\n env: {\n ...process.env,\n CLAUDE_AGENT_SDK_CLIENT_APP: `${this.appName}/${VERSION}`,\n ...options.options?.env,\n },\n };\n }\n\n /** Set (or clear) the host permission callback after construction. */\n setPermissionHandler(handler: PermissionHandler | undefined): void {\n this.permissions.setHandler(handler);\n }\n\n /** The live Claude Code session id, once the first turn has started. */\n get sessionId(): string | undefined {\n return this.currentSessionId;\n }\n\n /** Queue a user turn. The process starts on the first send and stays warm. */\n send(text: string, options: { images?: Array<{ data: string; mediaType?: string }> } = {}): void {\n if (this.closed) throw new Error(\"session is closed\");\n const content =\n options.images && options.images.length > 0\n ? [\n ...options.images.map((img) => ({ type: \"image\" as const, source: { type: \"base64\" as const, media_type: img.mediaType ?? \"image/png\", data: img.data } })),\n { type: \"text\" as const, text },\n ]\n : text;\n this.input.push({\n type: \"user\",\n message: { role: \"user\", content } as SDKUserMessage[\"message\"],\n parent_tool_use_id: null,\n session_id: this.currentSessionId ?? \"\",\n } as SDKUserMessage);\n this.ensureStarted();\n }\n\n private ensureStarted(): void {\n if (this.started) return;\n this.started = true;\n this.query = query({ prompt: this.input, options: this.baseOptions });\n }\n\n /** Iterate every SDK message the agent produces across all turns. */\n async *[Symbol.asyncIterator](): AsyncIterator<SDKMessage> {\n this.ensureStarted();\n try {\n for await (const msg of this.query!) {\n if (msg.type === \"system\" && msg.subtype === \"init\") this.currentSessionId = msg.session_id;\n else if (msg.type === \"result\") this.currentSessionId = msg.session_id;\n yield msg;\n }\n } catch (err) {\n throw classifyProviderFailure(\"claude\", \"claude (then /login)\", err);\n }\n }\n\n /** Interrupt the in-flight turn (the CLI's Esc/Ctrl-C). */\n async interrupt(): Promise<void> {\n await this.query?.interrupt();\n }\n\n /** Switch models mid-session (the CLI's /model). */\n async setModel(model: string): Promise<void> {\n await this.query?.setModel(model);\n }\n\n /** Switch permission mode mid-session (default/acceptEdits/plan/bypassPermissions). */\n async setPermissionMode(mode: \"default\" | \"acceptEdits\" | \"plan\" | \"bypassPermissions\"): Promise<void> {\n await this.query?.setPermissionMode(mode);\n }\n\n /** Models the CLI reports as available (for a picker). */\n async supportedModels(): Promise<Array<{ value: string; displayName: string }>> {\n this.ensureStarted();\n const models = await this.query!.supportedModels();\n return models.map((m) => ({ value: m.value, displayName: m.displayName }));\n }\n\n /** End the session and tear down the process. */\n close(): void {\n if (this.closed) return;\n this.closed = true;\n this.input.end();\n this.query?.close();\n }\n}\n\n/**\n * Convenience: start an {@link AgentSession} and immediately send one turn.\n * Returns the session so callers can iterate it, interrupt, or send more.\n */\nexport function startAgentSession(prompt: string, options: AgentSessionOptions = {}): AgentSession {\n const session = new AgentSession(options);\n session.send(prompt);\n return session;\n}\n","import type { SettingSource } from \"@anthropic-ai/claude-agent-sdk\";\n\n/**\n * How closely an embedded session should mirror the interactive `claude`\n * terminal. This resolves the single most common surprise in library mode:\n * the Agent SDK loads none of your settings by default.\n *\n * - `\"terminal\"` — behave like your CLI: load user + project + local\n * settings, so CLAUDE.md, skills, hooks, and .mcp.json all apply.\n * - `\"isolated\"` — load nothing (the raw SDK default); the app supplies\n * everything explicitly. Best when the session must be reproducible or\n * must not pick up the developer's personal config.\n * - `\"project\"` — load project + local settings but not the user's global\n * ones: shared repo config without personal CLAUDE.md/skills.\n */\nexport type Parity = \"terminal\" | \"project\" | \"isolated\";\n\nconst SETTING_SOURCES: Record<Parity, SettingSource[]> = {\n terminal: [\"user\", \"project\", \"local\"],\n project: [\"project\", \"local\"],\n isolated: [],\n};\n\n/** The `settingSources` a parity level maps to. */\nexport function settingSourcesFor(parity: Parity): SettingSource[] {\n return [...SETTING_SOURCES[parity]];\n}\n","import type {\n CanUseTool,\n PermissionResult,\n PermissionUpdate,\n} from \"@anthropic-ai/claude-agent-sdk\";\n\n/** A tool-use request handed to the host for a decision. */\nexport interface PermissionRequest {\n toolName: string;\n input: Record<string, unknown>;\n signal: AbortSignal;\n /**\n * Suggested permission updates the host can echo back to stop being asked\n * again this session (e.g. behind an \"always allow\" button).\n */\n suggestions?: PermissionUpdate[];\n}\n\n/**\n * The host's answer. `allow` optionally rewrites the tool input and/or\n * persists permission updates for the rest of the session; `deny` carries a\n * message the model sees and can optionally interrupt the turn.\n */\nexport type PermissionDecision =\n | { behavior: \"allow\"; updatedInput?: Record<string, unknown>; updatedPermissions?: PermissionUpdate[] }\n | { behavior: \"deny\"; message?: string; interrupt?: boolean };\n\n/** What the app implements: show UI, return a decision. */\nexport type PermissionHandler = (req: PermissionRequest) => PermissionDecision | Promise<PermissionDecision>;\n\nexport interface PermissionAdapterOptions {\n /**\n * Decision used when no handler is set, a handler throws, or the request is\n * aborted. Defaults to denying — the safe choice for an unattended host.\n */\n fallback?: \"allow\" | \"deny\";\n /** Tool names to auto-allow without ever calling the handler. */\n autoAllow?: Iterable<string>;\n /** Tool names to auto-deny without ever calling the handler. */\n autoDeny?: Iterable<string>;\n}\n\n/**\n * Turns a host-supplied {@link PermissionHandler} into the Agent SDK's\n * {@link CanUseTool} callback, owning the state machine so the app only has\n * to answer one question: allow or deny this tool call?\n *\n * The policy (what to auto-approve) stays with the app — yagami never bakes\n * in a permissive default. Without a handler, everything falls back (deny by\n * default), so a session is safe before the UI is wired up.\n */\nexport class PermissionAdapter {\n private handler: PermissionHandler | undefined;\n private readonly fallback: \"allow\" | \"deny\";\n private readonly autoAllow: Set<string>;\n private readonly autoDeny: Set<string>;\n\n constructor(options: PermissionAdapterOptions = {}) {\n this.fallback = options.fallback ?? \"deny\";\n this.autoAllow = new Set(options.autoAllow ?? []);\n this.autoDeny = new Set(options.autoDeny ?? []);\n }\n\n /** Install (or replace) the host decision callback. */\n setHandler(handler: PermissionHandler | undefined): void {\n this.handler = handler;\n }\n\n allowTool(toolName: string): void {\n this.autoDeny.delete(toolName);\n this.autoAllow.add(toolName);\n }\n\n denyTool(toolName: string): void {\n this.autoAllow.delete(toolName);\n this.autoDeny.add(toolName);\n }\n\n private fallbackResult(reason: string): PermissionResult {\n return this.fallback === \"allow\"\n ? { behavior: \"allow\", updatedInput: {} }\n : { behavior: \"deny\", message: reason };\n }\n\n /**\n * The callback to hand to `claudeCodeSession`/the Agent SDK. Typed to\n * always resolve (never null), and assignable to the SDK's CanUseTool.\n */\n readonly canUseTool: (\n ...args: Parameters<CanUseTool>\n ) => Promise<PermissionResult> = async (toolName, input, options) => {\n if (this.autoDeny.has(toolName)) {\n return { behavior: \"deny\", message: `tool \"${toolName}\" is disabled for this session` };\n }\n if (this.autoAllow.has(toolName)) {\n return { behavior: \"allow\", updatedInput: input };\n }\n if (!this.handler) return this.fallbackResult(`no permission handler is set; denying \"${toolName}\"`);\n if (options.signal.aborted) return this.fallbackResult(\"request aborted\");\n\n let decision: PermissionDecision;\n try {\n decision = await this.handler({\n toolName,\n input,\n signal: options.signal,\n ...(options.suggestions ? { suggestions: options.suggestions } : {}),\n });\n } catch (err) {\n return this.fallbackResult(`permission handler threw: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n if (decision.behavior === \"allow\") {\n return {\n behavior: \"allow\",\n updatedInput: decision.updatedInput ?? input,\n ...(decision.updatedPermissions ? { updatedPermissions: decision.updatedPermissions } : {}),\n };\n }\n return {\n behavior: \"deny\",\n message: decision.message ?? `tool \"${toolName}\" denied by host`,\n ...(decision.interrupt ? { interrupt: true } : {}),\n };\n };\n}\n"],"mappings":"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","names":["query","query"]}
|