@flue/sdk 0.3.11 → 0.4.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.
@@ -1,508 +0,0 @@
1
- import { Model, TSchema } from "@mariozechner/pi-ai";
2
- import { AgentMessage } from "@mariozechner/pi-agent-core";
3
- import * as v from "valibot";
4
-
5
- //#region src/types.d.ts
6
- interface Skill {
7
- name: string;
8
- description: string;
9
- /** Markdown body of SKILL.md (below the frontmatter). */
10
- instructions: string;
11
- }
12
- interface Role {
13
- name: string;
14
- description: string;
15
- /** Markdown body of the role file (below the frontmatter). */
16
- instructions: string;
17
- model?: string;
18
- }
19
- /**
20
- * An executable command that can be passed to prompt(), skill(), or shell().
21
- * Registered into just-bash for the duration of the call.
22
- */
23
- interface Command {
24
- name: string;
25
- execute(args: string[]): Promise<{
26
- stdout: string;
27
- stderr: string;
28
- exitCode: number;
29
- }>;
30
- }
31
- /** @deprecated Use `Command` with `defineCommand()` instead. */
32
- interface CommandDef {
33
- name: string;
34
- env?: Record<string, string>;
35
- }
36
- type ToolParameters = TSchema | Record<string, unknown>;
37
- /**
38
- * Custom tool passed to init(), prompt(), skill(), or task(). init() tools are
39
- * available to every session call; prompt/skill/task tools are scoped to that call.
40
- * Parameters are JSON Schema-compatible. Use `Type` from `@flue/sdk/client` for
41
- * hand-written tools, or pass schemas discovered from adapters such as MCP.
42
- */
43
- interface ToolDef<TParams extends ToolParameters = ToolParameters> {
44
- /** Must be unique across built-in and custom tools. */
45
- name: string;
46
- /** Tells the LLM when and how to use this tool. */
47
- description: string;
48
- /** JSON Schema-compatible parameter schema. */
49
- parameters: TParams;
50
- /** Returns a string result sent back to the LLM. Thrown errors become tool errors. */
51
- execute: (args: Record<string, any>, signal?: AbortSignal) => Promise<string>;
52
- }
53
- interface FileStat {
54
- isFile: boolean;
55
- isDirectory: boolean;
56
- isSymbolicLink: boolean;
57
- size: number;
58
- mtime: Date;
59
- }
60
- /**
61
- * Universal session environment interface. All sandbox modes (isolate, local, remote)
62
- * implement this — no mode-specific branching needed in core logic.
63
- *
64
- * File methods accept both absolute and relative paths (resolved against `cwd`).
65
- */
66
- interface SessionEnv {
67
- exec(command: string, options?: {
68
- cwd?: string;
69
- env?: Record<string, string>;
70
- timeout?: number;
71
- }): Promise<ShellResult>;
72
- /** Create an operation-scoped environment, usually backed by a fresh Bash runtime. */
73
- scope?(options?: {
74
- commands?: Command[];
75
- }): Promise<SessionEnv>;
76
- readFile(path: string): Promise<string>;
77
- readFileBuffer(path: string): Promise<Uint8Array>;
78
- writeFile(path: string, content: string | Uint8Array): Promise<void>;
79
- stat(path: string): Promise<FileStat>;
80
- readdir(path: string): Promise<string[]>;
81
- exists(path: string): Promise<boolean>;
82
- mkdir(path: string, options?: {
83
- recursive?: boolean;
84
- }): Promise<void>;
85
- rm(path: string, options?: {
86
- recursive?: boolean;
87
- force?: boolean;
88
- }): Promise<void>;
89
- cwd: string;
90
- /**
91
- * Resolve a relative path against cwd. Absolute paths pass through.
92
- * File methods resolve internally — only needed when you need the absolute path
93
- * for your own logic (e.g., extracting the parent directory).
94
- */
95
- resolvePath(p: string): string;
96
- cleanup(): Promise<void>;
97
- }
98
- interface CompactionConfig {
99
- enabled?: boolean;
100
- /** Token buffer to keep free in the context window. Default: 16384 */
101
- reserveTokens?: number;
102
- /** Recent tokens to preserve (not summarized). Default: 20000 */
103
- keepRecentTokens?: number;
104
- }
105
- interface ProviderSettings {
106
- /**
107
- * Provider endpoint used by built-in models. Useful for API gateways,
108
- * LiteLLM-style proxies, or enterprise-managed provider endpoints.
109
- */
110
- baseUrl?: string;
111
- /**
112
- * Headers merged into the resolved model's provider-level headers. Values
113
- * here override headers already defined by the built-in model.
114
- */
115
- headers?: Record<string, string>;
116
- /**
117
- * API key returned to the underlying agent runtime for this provider.
118
- * Useful when the gateway requires a dummy key or when credentials should
119
- * come from the agent's runtime env instead of process-global env vars.
120
- */
121
- apiKey?: string;
122
- }
123
- type ProvidersConfig = Record<string, ProviderSettings>;
124
- interface AgentConfig {
125
- /** Discovered at runtime from AGENTS.md + .agents/skills/ in the session's cwd. */
126
- systemPrompt: string;
127
- /** Discovered at runtime from .agents/skills/ in the session's cwd. */
128
- skills: Record<string, Skill>;
129
- roles: Record<string, Role>;
130
- /**
131
- * Agent-wide default model. Undefined when the user explicitly passes
132
- * `init({ model: false })`, so each model-using call must resolve one from a
133
- * role or call-site override.
134
- */
135
- model: Model<any> | undefined;
136
- /** Agent-wide default role. Per-session and per-call roles override this. */
137
- role?: string;
138
- /** Provider runtime settings applied when resolving models. */
139
- providers?: ProvidersConfig;
140
- /** Resolve model config to a Model instance. Throws on invalid model strings. */
141
- resolveModel: (model: ModelConfig | undefined, providers?: ProvidersConfig) => Model<any> | undefined;
142
- compaction?: CompactionConfig;
143
- }
144
- type ModelConfig = string | false;
145
- /**
146
- * Request context passed to agent handler functions. Pass type parameters
147
- * to type `payload` and `env` (e.g. the `Env` interface generated by
148
- * `wrangler types`). Compile-time only — no runtime validation of `payload`.
149
- */
150
- interface FlueContext<TPayload = any, TEnv = Record<string, any>> {
151
- readonly id: string;
152
- readonly payload: TPayload;
153
- /** Platform env bindings (process.env on Node, Worker env on Cloudflare). */
154
- readonly env: TEnv;
155
- /** Initialize an agent runtime with sandbox + persistence. */
156
- init(options: AgentInit): Promise<FlueAgent>;
157
- }
158
- /** Agent runtime options. A default model is required unless explicitly disabled with `model: false`. */
159
- interface AgentInit {
160
- /** Agent/sandbox scope id. Defaults to the route/context id. */
161
- id?: string;
162
- /** Working directory for context discovery, tools, and shell calls. Defaults to the sandbox cwd. */
163
- cwd?: string;
164
- /**
165
- * - `'empty'` (default): In-memory sandbox, no files, no host access.
166
- * - `'local'`: Mounts process.cwd() at /workspace. Node only.
167
- * - `BashFactory`: User-configured just-bash factory. Must return a fresh Bash-like instance.
168
- * - `SandboxFactory`: Connector-wrapped external sandbox (Daytona, CF Containers, etc.).
169
- */
170
- sandbox?: 'empty' | 'local' | SandboxFactory | BashFactory;
171
- /** Defaults to platform store (in-memory on Node, DO SQLite on Cloudflare). */
172
- persist?: SessionStore;
173
- /**
174
- * Default model for this agent. Applies to all prompt(), skill(), and task()
175
- * calls unless overridden by a role or at the call site. Pass `false` to require every
176
- * model-using call to resolve a model from a role or call-site override.
177
- *
178
- * Format: `'provider/modelId'` (e.g. `'anthropic/claude-opus-4-20250514'`).
179
- *
180
- * Precedence (highest wins): per-call `model` > role `model` > agent `model`.
181
- */
182
- model: ModelConfig;
183
- /** Agent-wide default role. Overridden by session-level or per-call roles. */
184
- role?: string;
185
- /**
186
- * Provider runtime settings for every model used by this agent, including
187
- * role-level and per-call model selections.
188
- *
189
- * Example:
190
- *
191
- * ```ts
192
- * await init({
193
- * model: 'anthropic/claude-sonnet-4-6',
194
- * providers: {
195
- * anthropic: {
196
- * baseUrl: env.ANTHROPIC_BASE_URL,
197
- * headers: { 'X-Custom-Auth': env.GATEWAY_KEY },
198
- * apiKey: 'dummy',
199
- * },
200
- * },
201
- * });
202
- * ```
203
- */
204
- providers?: ProvidersConfig;
205
- /**
206
- * Agent-wide tools. Every prompt(), skill(), and task() call can use these.
207
- * Per-call tools are added on top and must not reuse the same names.
208
- */
209
- tools?: ToolDef[];
210
- /**
211
- * Agent-wide commands. Every prompt(), skill(), and shell() call inherits
212
- * this list. Per-call `commands` are merged on top — if a per-call command
213
- * shares a name with an agent command, the per-call version wins for that
214
- * call.
215
- */
216
- commands?: Command[];
217
- }
218
- interface FlueAgent {
219
- readonly id: string;
220
- /** Get or create a session in this agent. Defaults to the "default" session. */
221
- session(id?: string, options?: SessionOptions): Promise<FlueSession>;
222
- /** Explicit session management helpers. */
223
- readonly sessions: FlueSessions;
224
- /** Run a shell command in the agent sandbox without recording it in a conversation. */
225
- shell(command: string, options?: ShellOptions): Promise<ShellResult>;
226
- /** Destroy the agent runtime and clean up the sandbox resources it owns. */
227
- destroy(): Promise<void>;
228
- }
229
- interface FlueSessions {
230
- /** Load an existing session. Throws if it does not exist. */
231
- get(id?: string, options?: SessionOptions): Promise<FlueSession>;
232
- /** Create a new session. Throws if it already exists. */
233
- create(id?: string, options?: SessionOptions): Promise<FlueSession>;
234
- /** Delete a session's stored conversation state. No-op when missing. */
235
- delete(id?: string): Promise<void>;
236
- }
237
- interface SessionOptions {
238
- /** Session-wide default role. Per-call roles override this. */
239
- role?: string;
240
- }
241
- interface FlueSession {
242
- readonly id: string;
243
- prompt<S extends v.GenericSchema>(text: string, options: PromptOptions<S> & {
244
- result: S;
245
- }): Promise<v.InferOutput<S>>;
246
- prompt(text: string, options?: PromptOptions): Promise<PromptResponse>;
247
- shell(command: string, options?: ShellOptions): Promise<ShellResult>;
248
- skill<S extends v.GenericSchema>(name: string, options: SkillOptions<S> & {
249
- result: S;
250
- }): Promise<v.InferOutput<S>>;
251
- skill(name: string, options?: SkillOptions): Promise<PromptResponse>;
252
- task<S extends v.GenericSchema>(text: string, options: TaskOptions<S> & {
253
- result: S;
254
- }): Promise<v.InferOutput<S>>;
255
- task(text: string, options?: TaskOptions): Promise<PromptResponse>;
256
- delete(): Promise<void>;
257
- }
258
- interface PromptResponse {
259
- text: string;
260
- }
261
- interface SessionData {
262
- version: 2;
263
- entries: SessionEntry[];
264
- leafId: string | null;
265
- metadata: Record<string, any>;
266
- createdAt: string;
267
- updatedAt: string;
268
- }
269
- type SessionEntry = MessageEntry | CompactionEntry | BranchSummaryEntry;
270
- interface SessionEntryBase {
271
- type: string;
272
- id: string;
273
- parentId: string | null;
274
- timestamp: string;
275
- }
276
- interface MessageEntry extends SessionEntryBase {
277
- type: 'message';
278
- message: AgentMessage;
279
- source?: 'prompt' | 'skill' | 'shell' | 'task' | 'retry';
280
- }
281
- interface CompactionEntry extends SessionEntryBase {
282
- type: 'compaction';
283
- summary: string;
284
- firstKeptEntryId: string;
285
- tokensBefore: number;
286
- details?: {
287
- readFiles: string[];
288
- modifiedFiles: string[];
289
- };
290
- }
291
- interface BranchSummaryEntry extends SessionEntryBase {
292
- type: 'branch_summary';
293
- fromId: string;
294
- summary: string;
295
- details?: unknown;
296
- }
297
- interface SessionStore {
298
- save(id: string, data: SessionData): Promise<void>;
299
- load(id: string): Promise<SessionData | null>;
300
- delete(id: string): Promise<void>;
301
- }
302
- /** All option fields are scoped to the duration of the call. */
303
- interface PromptOptions<S extends v.GenericSchema | undefined = undefined> {
304
- result?: S;
305
- timeout?: number;
306
- commands?: Command[];
307
- tools?: ToolDef[];
308
- role?: string;
309
- /** e.g., 'anthropic/claude-sonnet-4-20250514' */
310
- model?: string;
311
- }
312
- interface SkillOptions<S extends v.GenericSchema | undefined = undefined> {
313
- args?: Record<string, unknown>;
314
- result?: S;
315
- timeout?: number;
316
- commands?: Command[];
317
- tools?: ToolDef[];
318
- role?: string;
319
- model?: string;
320
- }
321
- interface TaskOptions<S extends v.GenericSchema | undefined = undefined> {
322
- result?: S;
323
- commands?: Command[];
324
- tools?: ToolDef[];
325
- role?: string;
326
- model?: string;
327
- /** Working directory for the detached task session. Defaults to the parent session cwd. */
328
- cwd?: string;
329
- }
330
- interface ShellOptions {
331
- env?: Record<string, string>;
332
- cwd?: string;
333
- timeout?: number;
334
- commands?: Command[];
335
- }
336
- interface ShellResult {
337
- stdout: string;
338
- stderr: string;
339
- exitCode: number;
340
- }
341
- /** Wraps external sandboxes (Daytona, CF Containers, etc.) into Flue's SessionEnv. */
342
- interface SandboxFactory {
343
- createSessionEnv(options: {
344
- id: string;
345
- cwd?: string;
346
- }): Promise<SessionEnv>;
347
- }
348
- /**
349
- * Structural type for duck-type detection of just-bash `Bash` instances in init().
350
- * Purely structural — no just-bash import, so client.ts stays platform-agnostic.
351
- */
352
- interface BashLike {
353
- exec(command: string, options?: {
354
- cwd?: string;
355
- env?: Record<string, string>;
356
- }): Promise<ShellResult>;
357
- getCwd(): string;
358
- fs: {
359
- readFile(path: string, options?: any): Promise<string>;
360
- readFileBuffer(path: string): Promise<Uint8Array>;
361
- writeFile(path: string, content: string | Uint8Array, options?: any): Promise<void>;
362
- stat(path: string): Promise<any>;
363
- readdir(path: string): Promise<string[]>;
364
- exists(path: string): Promise<boolean>;
365
- mkdir(path: string, options?: {
366
- recursive?: boolean;
367
- }): Promise<void>;
368
- rm(path: string, options?: {
369
- recursive?: boolean;
370
- force?: boolean;
371
- }): Promise<void>;
372
- resolvePath(base: string, path: string): string;
373
- };
374
- registerCommand?(cmd: any): void;
375
- }
376
- /** Factory for a fresh Bash-like runtime. Share `fs` inside the closure to persist files. */
377
- type BashFactory = () => BashLike | Promise<BashLike>;
378
- type FlueEvent = ({
379
- type: 'agent_start';
380
- } | {
381
- type: 'text_delta';
382
- text: string;
383
- } | {
384
- type: 'tool_start';
385
- toolName: string;
386
- toolCallId: string;
387
- args?: any;
388
- } | {
389
- type: 'tool_end';
390
- toolName: string;
391
- toolCallId: string;
392
- isError: boolean;
393
- result?: any;
394
- } | {
395
- type: 'turn_end';
396
- } | {
397
- type: 'command_start';
398
- command: string;
399
- args: string[];
400
- } | {
401
- type: 'command_end';
402
- command: string;
403
- exitCode: number;
404
- } | {
405
- type: 'task_start';
406
- taskId: string;
407
- prompt: string;
408
- role?: string;
409
- cwd?: string;
410
- } | {
411
- type: 'task_end';
412
- taskId: string;
413
- isError: boolean;
414
- result?: any;
415
- } | {
416
- type: 'compaction_start';
417
- reason: 'threshold' | 'overflow';
418
- estimatedTokens: number;
419
- } | {
420
- type: 'compaction_end';
421
- messagesBefore: number;
422
- messagesAfter: number;
423
- } | {
424
- type: 'idle';
425
- } | {
426
- type: 'error';
427
- error: string;
428
- }) & {
429
- sessionId?: string;
430
- parentSessionId?: string;
431
- taskId?: string;
432
- };
433
- type FlueEventCallback = (event: FlueEvent) => void;
434
- interface AgentInfo {
435
- name: string;
436
- filePath: string;
437
- triggers: {
438
- webhook?: boolean;
439
- };
440
- }
441
- interface BuildContext {
442
- agents: AgentInfo[];
443
- roles: Record<string, Role>;
444
- /** The workspace root: the directory directly containing agents/ and roles/. */
445
- workspaceDir: string;
446
- /** Where dist/ is written. Typically the project root, independent of workspaceDir. */
447
- outputDir: string;
448
- options: BuildOptions;
449
- }
450
- /**
451
- * Controls the build output format for a target platform.
452
- *
453
- * A plugin can either ship a fully-bundled JavaScript artifact (Node target)
454
- * or hand over a TypeScript/ESM entry source that some downstream tool will
455
- * bundle (Cloudflare target — wrangler does the bundling). Pre-bundling on
456
- * top of a tool that bundles for itself causes subtle resolution conflicts
457
- * (we hit this with `tar`/`fs`/etc. via `nodejs_compat`), so the Cloudflare
458
- * path explicitly opts out.
459
- */
460
- interface BuildPlugin {
461
- name: string;
462
- /**
463
- * The source of the entry point (TS or JS). May be async — the Cloudflare
464
- * plugin reads the user's wrangler config (via wrangler's reader) which is
465
- * a sync call but lives behind a lazy `await import('wrangler')`.
466
- */
467
- generateEntryPoint(ctx: BuildContext): string | Promise<string>;
468
- /**
469
- * Bundling strategy:
470
- * - `'esbuild'` (default): run the SDK's esbuild pass to produce a
471
- * bundled `dist/server.mjs`. Use when the deploy target is "just run
472
- * this file" with no further bundling step.
473
- * - `'none'`: skip esbuild. The entry is written as-is to `dist/` and
474
- * becomes the input for whatever tool will deploy it (e.g. wrangler).
475
- * The plugin must also implement `entryFilename` to set the file name.
476
- */
477
- bundle?: 'esbuild' | 'none';
478
- /**
479
- * The filename to use for the entry, written under `dist/`. Required when
480
- * `bundle === 'none'`. For `bundle === 'esbuild'` the output is always
481
- * `server.mjs` and this field is ignored.
482
- */
483
- entryFilename?: string;
484
- /** esbuild options. Only consulted when `bundle === 'esbuild'`. */
485
- esbuildOptions?(ctx: BuildContext): Record<string, any>;
486
- /** Additional files to write to dist/ (e.g., wrangler.jsonc, Dockerfile). May be async. */
487
- additionalOutputs?(ctx: BuildContext): Record<string, string> | Promise<Record<string, string>>;
488
- }
489
- interface BuildOptions {
490
- /**
491
- * The workspace directory: the directory directly containing agents/ and
492
- * roles/. Pass an explicit path — no .flue/ waterfall is performed here.
493
- * Callers that want the waterfall behavior (e.g. the CLI when --workspace
494
- * is omitted) should resolve it themselves with `resolveWorkspaceFromCwd`.
495
- */
496
- workspaceDir: string;
497
- /**
498
- * Where to write the dist/ directory. Independent of workspaceDir — typically
499
- * the project root, so platform config like wrangler.jsonc ends up where the
500
- * deploy tool expects it.
501
- */
502
- outputDir: string;
503
- target?: 'node' | 'cloudflare';
504
- /** Overrides `target` when provided. */
505
- plugin?: BuildPlugin;
506
- }
507
- //#endregion
508
- export { ShellResult as A, Role as C, SessionOptions as D, SessionEnv as E, ToolParameters as F, SkillOptions as M, TaskOptions as N, SessionStore as O, ToolDef as P, ProvidersConfig as S, SessionData as T, FlueSessions as _, BashLike as a, PromptResponse as b, BuildPlugin as c, FileStat as d, FlueAgent as f, FlueSession as g, FlueEventCallback as h, BashFactory as i, Skill as j, ShellOptions as k, Command as l, FlueEvent as m, AgentInfo as n, BuildContext as o, FlueContext as p, AgentInit as r, BuildOptions as s, AgentConfig as t, CommandDef as u, ModelConfig as v, SandboxFactory as w, ProviderSettings as x, PromptOptions as y };