@1kbirds/chidori 0.1.24 → 3.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/README.md +115 -5
- package/dist/agent.d.ts +487 -0
- package/dist/agent.js +46 -0
- package/dist/index.d.ts +332 -0
- package/dist/index.js +318 -0
- package/package.json +27 -32
- package/src/agent.ts +548 -0
- package/src/index.ts +580 -0
- package/.pytest_cache/README.md +0 -8
- package/CHANGELOG.md +0 -33
- package/Cargo.toml +0 -83
- package/build/stage/v0.1.24/chidori-v0.1.24-node-v108-darwin-arm64-unknown.tar.gz +0 -0
- package/build/stage/v0.1.24/chidori-v0.1.24-node-v93-darwin-arm64-unknown.tar.gz +0 -0
- package/build.rs +0 -7
- package/package_node/index.d.ts +0 -0
- package/package_node/index.js +0 -130
- package/package_node/native/chidori.node +0 -0
- package/package_python/.idea/inspectionProfiles/profiles_settings.xml +0 -6
- package/package_python/.idea/misc.xml +0 -4
- package/package_python/.idea/modules.xml +0 -8
- package/package_python/.idea/package_python.iml +0 -8
- package/package_python/.idea/vcs.xml +0 -6
- package/package_python/chidori/__init__.py +0 -0
- package/package_python/chidori/__pycache__/__init__.cpython-310.pyc +0 -0
- package/package_python/chidori/__pycache__/test_chidori.cpython-310-pytest-7.4.0.pyc +0 -0
- package/package_python/chidori/__pycache__/test_promptgraph.cpython-310-pytest-7.4.0.pyc +0 -0
- package/package_python/chidori/chidori.pyi +0 -32
- package/package_python/chidori/py.typed +0 -0
- package/package_python/chidori/test_chidori.py +0 -36
- package/pyproject.toml +0 -33
- package/src/lib.rs +0 -23
- package/src/translations/mod.rs +0 -9
- package/src/translations/nodejs.rs +0 -739
- package/src/translations/python.rs +0 -920
- package/src/translations/rust.rs +0 -737
- package/src/translations/shared.rs +0 -49
- package/src/translations/wasm.rs +0 -1
- package/tests/nodejs/chidori.test.js +0 -41
- package/tests/nodejs/nodeHandle.test.js +0 -15
package/package.json
CHANGED
|
@@ -1,38 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1kbirds/chidori",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Chidori
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"arm64"
|
|
22
|
-
],
|
|
23
|
-
"binary": {
|
|
24
|
-
"module_name": "chidori",
|
|
25
|
-
"module_path": "./package_node/native",
|
|
26
|
-
"host": "https://github.com/thousandbirdsinc/chidori/releases/download/",
|
|
27
|
-
"package_name": "{module_name}-v{version}-{node_abi}-{platform}-{arch}-{libc}.tar.gz",
|
|
28
|
-
"remote_path": "v{version}"
|
|
3
|
+
"version": "3.3.0",
|
|
4
|
+
"description": "TypeScript SDK for the Chidori agent framework — HTTP client plus agent authoring types.",
|
|
5
|
+
"publishConfig": { "access": "public" },
|
|
6
|
+
"homepage": "https://github.com/ThousandBirdsInc/chidori",
|
|
7
|
+
"repository": { "type": "git", "url": "https://github.com/ThousandBirdsInc/chidori.git" },
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./agent": {
|
|
18
|
+
"import": "./dist/agent.js",
|
|
19
|
+
"types": "./dist/agent.d.ts"
|
|
20
|
+
}
|
|
29
21
|
},
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
22
|
+
"files": ["dist", "src", "README.md"],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc",
|
|
25
|
+
"typecheck": "tsc --noEmit"
|
|
33
26
|
},
|
|
34
27
|
"devDependencies": {
|
|
35
|
-
"
|
|
36
|
-
|
|
28
|
+
"typescript": "^5.4.0"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
37
32
|
}
|
|
38
|
-
}
|
|
33
|
+
}
|
package/src/agent.ts
ADDED
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type declarations for TypeScript agents executed inside the Chidori runtime.
|
|
3
|
+
*
|
|
4
|
+
* These are authoring-time types only. The runtime injects the concrete
|
|
5
|
+
* `chidori` host object when it evaluates an agent or tool module.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type AgentJson =
|
|
9
|
+
| null
|
|
10
|
+
| boolean
|
|
11
|
+
| number
|
|
12
|
+
| string
|
|
13
|
+
| AgentJson[]
|
|
14
|
+
| { [key: string]: AgentJson };
|
|
15
|
+
|
|
16
|
+
export type JsonObject = { [key: string]: AgentJson };
|
|
17
|
+
|
|
18
|
+
export interface JsonSchema {
|
|
19
|
+
type?: "object" | "array" | "string" | "number" | "integer" | "boolean" | "null";
|
|
20
|
+
description?: string;
|
|
21
|
+
properties?: Record<string, JsonSchema>;
|
|
22
|
+
items?: JsonSchema;
|
|
23
|
+
required?: string[];
|
|
24
|
+
enum?: AgentJson[];
|
|
25
|
+
default?: AgentJson;
|
|
26
|
+
additionalProperties?: boolean | JsonSchema;
|
|
27
|
+
[keyword: string]: unknown;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ToolDefinition {
|
|
31
|
+
name: string;
|
|
32
|
+
description: string;
|
|
33
|
+
parameters: JsonSchema & { type: "object" };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type PromptStreamType = "progress" | "draft" | "subagent" | "final" | (string & {});
|
|
37
|
+
|
|
38
|
+
/** Provider prompt-cache lifetime for a cached prefix. */
|
|
39
|
+
export type CacheTtl = "5m" | "1h";
|
|
40
|
+
|
|
41
|
+
export interface PromptOptions {
|
|
42
|
+
type?: PromptStreamType;
|
|
43
|
+
system?: string;
|
|
44
|
+
model?: string;
|
|
45
|
+
maxTokens?: number;
|
|
46
|
+
max_tokens?: number;
|
|
47
|
+
maxTurns?: number;
|
|
48
|
+
max_turns?: number;
|
|
49
|
+
temperature?: number;
|
|
50
|
+
tools?: string[];
|
|
51
|
+
format?: "json" | (string & {});
|
|
52
|
+
stream?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Prompt-cache posture. Defaults to on (`"5m"`): the runtime marks the
|
|
55
|
+
* stable request head (system, tools, conversation prefix) so providers
|
|
56
|
+
* bill repeated prefixes at the cached rate. `false` disables marking for
|
|
57
|
+
* this call; `"1h"` (or `{ ttl: "1h" }`) requests the extended TTL.
|
|
58
|
+
* Caching never changes a response — only how it is billed.
|
|
59
|
+
*/
|
|
60
|
+
cache?: boolean | CacheTtl | { ttl?: CacheTtl };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Structured response from `Context.respond()` — mirrors the provider turn. */
|
|
64
|
+
export interface LlmResponseJson {
|
|
65
|
+
content: string;
|
|
66
|
+
blocks: AgentJson[];
|
|
67
|
+
tool_calls: { id: string; name: string; input: AgentJson }[];
|
|
68
|
+
stop_reason: string;
|
|
69
|
+
input_tokens: number;
|
|
70
|
+
output_tokens: number;
|
|
71
|
+
cache_creation_tokens: number;
|
|
72
|
+
cache_read_tokens: number;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Options for `Context.compact()` — explicit, opt-in window compaction. */
|
|
76
|
+
export interface CompactOptions {
|
|
77
|
+
/** How many of the newest conversation turns to keep verbatim (default 2). */
|
|
78
|
+
keepTurns?: number;
|
|
79
|
+
/**
|
|
80
|
+
* Skip compaction (pure no-op, no host call) while `estimateTokens()` is at
|
|
81
|
+
* or under this budget — lets a loop call `compact()` unconditionally.
|
|
82
|
+
*/
|
|
83
|
+
budgetTokens?: number;
|
|
84
|
+
/** Model for the summarization prompt (defaults like `prompt()`). */
|
|
85
|
+
model?: string;
|
|
86
|
+
/** System instructions for the summarizer (a faithful-brief default). */
|
|
87
|
+
instructions?: string;
|
|
88
|
+
/** `maxTokens` for the summarization prompt. */
|
|
89
|
+
maxTokens?: number;
|
|
90
|
+
/** Cache posture for the summarization prompt (see `PromptOptions.cache`). */
|
|
91
|
+
cache?: boolean | CacheTtl | { ttl?: CacheTtl };
|
|
92
|
+
/** TTL of the fresh cache breakpoint placed on the summary (default "5m"). */
|
|
93
|
+
ttl?: CacheTtl;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* An immutable, content-addressed, turn-structured prompt context.
|
|
98
|
+
*
|
|
99
|
+
* Builder methods return a NEW context that structurally shares this one's
|
|
100
|
+
* segments — `base.user("a")` and `base.user("b")` are independent and share
|
|
101
|
+
* `base`'s prefix — which keeps cache prefixes stable and makes forks cheap.
|
|
102
|
+
* Only `prompt()` / `respond()` perform a durable host call.
|
|
103
|
+
*
|
|
104
|
+
* ```ts
|
|
105
|
+
* const base = chidori.context()
|
|
106
|
+
* .system("You are a policy analyst.")
|
|
107
|
+
* .doc("corpus", corpusText)
|
|
108
|
+
* .cacheBreakpoint("1h");
|
|
109
|
+
* let ctx = base;
|
|
110
|
+
* for (const q of questions) {
|
|
111
|
+
* ctx = ctx.user(q);
|
|
112
|
+
* const { text, context } = await ctx.prompt();
|
|
113
|
+
* ctx = context; // assistant turn appended, prefix still shared
|
|
114
|
+
* }
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export interface Context {
|
|
118
|
+
system(text: string): Context;
|
|
119
|
+
/** Expose registered tools (by name, resolved like `prompt({ tools })`). */
|
|
120
|
+
tools(names: string[]): Context;
|
|
121
|
+
/** A large stable reference block, labelled for the trace. */
|
|
122
|
+
doc(label: string, text: string): Context;
|
|
123
|
+
user(text: string): Context;
|
|
124
|
+
assistant(text: string): Context;
|
|
125
|
+
toolResult(id: string, content: string, isError?: boolean): Context;
|
|
126
|
+
/**
|
|
127
|
+
* Freeze everything appended so far as a cacheable prefix (one provider
|
|
128
|
+
* cache breakpoint). Providers cap breakpoints, so marks are coalesced —
|
|
129
|
+
* latest wins. Most authors never need this: stable heads are auto-marked.
|
|
130
|
+
*/
|
|
131
|
+
cacheBreakpoint(ttl?: CacheTtl): Context;
|
|
132
|
+
/** Send this context; returns the text and the context extended with the
|
|
133
|
+
* assistant turn (including any internal tool-use exchange). */
|
|
134
|
+
prompt(options?: PromptOptions): Promise<{ text: string; context: Context }>;
|
|
135
|
+
/** Single structured turn for author-driven tool loops. */
|
|
136
|
+
respond(options?: PromptOptions): Promise<{ response: LlmResponseJson; context: Context }>;
|
|
137
|
+
/**
|
|
138
|
+
* Summarize the older conversation turns into one durable summary segment
|
|
139
|
+
* (via a recorded `prompt` host call, so it replays deterministically) and
|
|
140
|
+
* return a new context: stable head + summary + fresh cache breakpoint +
|
|
141
|
+
* the kept newest turns. Never automatic — compaction changes what the
|
|
142
|
+
* model sees, so it is always an explicit author decision. Returns this
|
|
143
|
+
* context unchanged (without a host call) when there is nothing to compact
|
|
144
|
+
* or the context is within `budgetTokens`.
|
|
145
|
+
*/
|
|
146
|
+
compact(options?: CompactOptions): Promise<Context>;
|
|
147
|
+
/** Stable content hash of the request this context would assemble. */
|
|
148
|
+
digest(options?: PromptOptions): string;
|
|
149
|
+
/** Rough local token estimate for window budgeting. */
|
|
150
|
+
estimateTokens(): number;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** One recorded exchange in a {@link Conversation} transcript. */
|
|
154
|
+
export interface ConversationTurn {
|
|
155
|
+
role: "user" | "assistant";
|
|
156
|
+
text: string;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Options for `chidori.conversation()`. */
|
|
160
|
+
export interface ConversationOptions {
|
|
161
|
+
/** System prompt — frozen once as the conversation's cacheable prefix. */
|
|
162
|
+
system?: string;
|
|
163
|
+
/** Tool names available on every turn (resolved like `prompt({ tools })`). */
|
|
164
|
+
tools?: string[];
|
|
165
|
+
/** Default stream label for each turn's prompt (default `"final"`). */
|
|
166
|
+
type?: PromptStreamType;
|
|
167
|
+
/** Default model for each turn (a per-turn override still wins). */
|
|
168
|
+
model?: string;
|
|
169
|
+
/** Default output token cap for each turn. */
|
|
170
|
+
maxTokens?: number;
|
|
171
|
+
/** Default sampling temperature for each turn. */
|
|
172
|
+
temperature?: number;
|
|
173
|
+
/** Default cache posture for each turn (see {@link PromptOptions.cache}). */
|
|
174
|
+
cache?: boolean | CacheTtl | { ttl?: CacheTtl };
|
|
175
|
+
/** TTL of the cache breakpoint frozen over the system/tools head. */
|
|
176
|
+
cacheTtl?: CacheTtl;
|
|
177
|
+
/**
|
|
178
|
+
* Opt-in window management: when set, each turn first runs the same budgeted
|
|
179
|
+
* `Context.compact()` — a pure no-op until the running tail exceeds budget,
|
|
180
|
+
* then the older turns fold into one recorded summary segment.
|
|
181
|
+
*/
|
|
182
|
+
compact?: CompactOptions;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** Options for `Conversation.loop()` — an interactive `input()`-driven loop. */
|
|
186
|
+
export interface ConversationLoopOptions {
|
|
187
|
+
/** Prompt shown to the human each turn (or a function of the turn index). */
|
|
188
|
+
prompt?: string | ((turn: number) => string);
|
|
189
|
+
/** Extra options forwarded to `chidori.input()` (defaults to `{ type: "message" }`). */
|
|
190
|
+
inputOptions?: InputOptions;
|
|
191
|
+
/** Words that end the loop, case-insensitive (default `["exit", "quit"]`). */
|
|
192
|
+
exit?: string | string[];
|
|
193
|
+
/** Hard cap on the number of exchanges before returning. */
|
|
194
|
+
maxTurns?: number;
|
|
195
|
+
/** Skip blank input lines instead of sending them (default `true`). */
|
|
196
|
+
skipEmpty?: boolean;
|
|
197
|
+
/** Per-turn prompt options applied to every `say()` in the loop. */
|
|
198
|
+
turn?: PromptOptions;
|
|
199
|
+
/** Called with the assistant reply (and the user message) after each turn. */
|
|
200
|
+
onReply?: (reply: string, message: string) => void | Promise<void>;
|
|
201
|
+
/** Return `true` after a turn to end the loop (checked after `onReply`). */
|
|
202
|
+
until?: (message: string, reply: string) => boolean;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* A small stateful wrapper over {@link Context} for the most common shape — a
|
|
207
|
+
* multi-turn chat assistant. It owns the running context (system + tools frozen
|
|
208
|
+
* as a cacheable prefix) and threads each turn through it, so you write
|
|
209
|
+
* `chat.say(message)` instead of re-plumbing `ctx = (await
|
|
210
|
+
* ctx.user(message).prompt()).context` by hand. Every turn is still one durable
|
|
211
|
+
* `prompt`/`respond` host call that replays for free.
|
|
212
|
+
*
|
|
213
|
+
* ```ts
|
|
214
|
+
* const chat = chidori.conversation({ system: "You are concise." });
|
|
215
|
+
* const a = await chat.say("Hi, who are you?");
|
|
216
|
+
* const b = await chat.say("What can you help with?");
|
|
217
|
+
* // or drive it interactively:
|
|
218
|
+
* const transcript = await chat.loop({ prompt: "you>" });
|
|
219
|
+
* ```
|
|
220
|
+
*/
|
|
221
|
+
export interface Conversation {
|
|
222
|
+
/** The underlying immutable context, for dropping to the lower-level API. */
|
|
223
|
+
readonly context: Context;
|
|
224
|
+
/** Number of completed exchanges (user+assistant pairs) so far. */
|
|
225
|
+
readonly length: number;
|
|
226
|
+
/** The transcript so far as plain `{ role, text }` entries. */
|
|
227
|
+
history(): ConversationTurn[];
|
|
228
|
+
/** Send one user message; resolves to the assistant's reply text. */
|
|
229
|
+
say(message: string, options?: PromptOptions): Promise<string>;
|
|
230
|
+
/**
|
|
231
|
+
* Like `say()`, but resolves to the structured response (`tool_calls`,
|
|
232
|
+
* `blocks`) for author-driven tool loops. Append tool results with
|
|
233
|
+
* `chat.context.toolResult(...)`, then call `say()` again.
|
|
234
|
+
*/
|
|
235
|
+
respond(message: string, options?: PromptOptions): Promise<LlmResponseJson>;
|
|
236
|
+
/**
|
|
237
|
+
* Drive an interactive loop: read a human message via `chidori.input()`
|
|
238
|
+
* (terminal stdin under `chidori run`, a paused session resume under `chidori
|
|
239
|
+
* serve`), reply with `say()`, and repeat until the user types an exit word
|
|
240
|
+
* or `until` returns true. Resolves to the full transcript.
|
|
241
|
+
*/
|
|
242
|
+
loop(options?: ConversationLoopOptions): Promise<ConversationTurn[]>;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface InputOptions {
|
|
246
|
+
type?: string;
|
|
247
|
+
default?: string;
|
|
248
|
+
choices?: string[];
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Who delivered a signal. `kind` distinguishes a human participant from a peer
|
|
253
|
+
* agent; `id` is the participant identity; `runId` is set when an agent sends
|
|
254
|
+
* (its own run id), so agent-to-agent coordination is attributable in the trace.
|
|
255
|
+
*/
|
|
256
|
+
export interface SignalSender {
|
|
257
|
+
kind: "human" | "agent";
|
|
258
|
+
id: string;
|
|
259
|
+
runId?: string;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* A named message delivered into a run mid-flight (`docs/signals.md` §6.1). The
|
|
264
|
+
* inverse of `input()`: an outside party (human or agent) pushes
|
|
265
|
+
* `{ name, payload, from }` at an agent-declared listen point. Every signal is
|
|
266
|
+
* recorded in the call log, so the multiplayer session replays deterministically.
|
|
267
|
+
*/
|
|
268
|
+
export interface Signal<T = AgentJson> {
|
|
269
|
+
name: string;
|
|
270
|
+
payload: T;
|
|
271
|
+
from: SignalSender;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export interface SignalOptions {
|
|
275
|
+
/**
|
|
276
|
+
* Resolve to a {@link SignalTimeout} sentinel after this many milliseconds
|
|
277
|
+
* instead of waiting forever. The deadline is enforced by the supervising
|
|
278
|
+
* server while the run idles; the recorded result (signal or sentinel)
|
|
279
|
+
* replays deterministically. Discriminate with `"timedOut" in result`.
|
|
280
|
+
*/
|
|
281
|
+
timeoutMs?: number;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* The sentinel a `timeoutMs` listen point resolves to when the deadline passes
|
|
286
|
+
* with no matching delivery (`docs/signals.md` §16, pinned:
|
|
287
|
+
* resolve-to-sentinel rather than reject). `name` is the single awaited name,
|
|
288
|
+
* or `null` for a multi-name `signalAny`.
|
|
289
|
+
*/
|
|
290
|
+
export interface SignalTimeout {
|
|
291
|
+
name: string | null;
|
|
292
|
+
payload: null;
|
|
293
|
+
from: null;
|
|
294
|
+
timedOut: true;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export interface ParallelOptions {
|
|
298
|
+
concurrency?: number;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* One `chidori.branch` variant (`docs/branching-execution.md` §6.1). A branch
|
|
303
|
+
* runs its own continuation source module from the parent's anchored state —
|
|
304
|
+
* not a re-run of the parent agent — so `source` is required.
|
|
305
|
+
*/
|
|
306
|
+
export interface BranchVariant {
|
|
307
|
+
/** Branch label, shown in outcomes and the trace. Defaults to `branch-<k>`. */
|
|
308
|
+
label?: string;
|
|
309
|
+
/** Branch source module path, resolved like `callAgent` paths. */
|
|
310
|
+
source: string;
|
|
311
|
+
/** State handed to the branch as its run input. Defaults to `{}`. */
|
|
312
|
+
input?: AgentJson;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export type BranchStatus = "completed" | "paused" | "failed";
|
|
316
|
+
|
|
317
|
+
/** The result of one branch sub-run, returned for comparison (not merged). */
|
|
318
|
+
export interface BranchOutcome<T extends AgentJson = AgentJson> {
|
|
319
|
+
label: string;
|
|
320
|
+
/**
|
|
321
|
+
* `<parent run id>-op<branch seq>-branch-<k>` — identifies the branch
|
|
322
|
+
* sub-run, including for out-of-band `chidori branch-resume` /
|
|
323
|
+
* `branch-rerun` against its persisted store.
|
|
324
|
+
*/
|
|
325
|
+
branchId: string;
|
|
326
|
+
status: BranchStatus;
|
|
327
|
+
/** The branch's output, when `status` is `"completed"`. */
|
|
328
|
+
output?: T;
|
|
329
|
+
/** What the branch is waiting on, when `status` is `"paused"`. */
|
|
330
|
+
pendingPrompt?: string;
|
|
331
|
+
/** The failure message, when `status` is `"failed"`. */
|
|
332
|
+
error?: string;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export interface BranchOptions {
|
|
336
|
+
/**
|
|
337
|
+
* Maximum branches running live at once (cost cap). Defaults to 1 —
|
|
338
|
+
* sequential. Higher values run variants in concurrent waves; outcome
|
|
339
|
+
* order always follows variant order.
|
|
340
|
+
*/
|
|
341
|
+
concurrency?: number;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export interface RetryOptions {
|
|
345
|
+
attempts?: number;
|
|
346
|
+
delayMs?: number;
|
|
347
|
+
backoff?: "fixed" | "exponential";
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export interface TryCallResult<T> {
|
|
351
|
+
ok: boolean;
|
|
352
|
+
value?: T;
|
|
353
|
+
error?: string;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export interface TemplateOptions {
|
|
357
|
+
source?: "file" | "inline";
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export type MemoryAction = "get" | "set" | "delete" | "list" | "clear";
|
|
361
|
+
|
|
362
|
+
export type WorkspaceFileStatus = "complete" | "writing" | "failed";
|
|
363
|
+
|
|
364
|
+
export interface WorkspaceEntry {
|
|
365
|
+
path: string;
|
|
366
|
+
status: WorkspaceFileStatus;
|
|
367
|
+
sha256: string;
|
|
368
|
+
bytes: number;
|
|
369
|
+
language?: string | null;
|
|
370
|
+
attempt?: number | null;
|
|
371
|
+
updatedAt?: string | null;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export interface WorkspaceListOptions {
|
|
375
|
+
completeOnly?: boolean;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export interface WorkspaceWriteOptions {
|
|
379
|
+
language?: string;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export interface WorkspaceHost {
|
|
383
|
+
list(options?: WorkspaceListOptions): Promise<WorkspaceEntry[]>;
|
|
384
|
+
read(path: string): Promise<string>;
|
|
385
|
+
write(path: string, content: string, options?: WorkspaceWriteOptions): Promise<WorkspaceEntry>;
|
|
386
|
+
delete(path: string, reason?: string): Promise<void>;
|
|
387
|
+
remove(path: string, reason?: string): Promise<void>;
|
|
388
|
+
manifest(): Promise<AgentJson>;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
export type TypeScriptImportPolicy = "none" | "relative" | "project";
|
|
392
|
+
export type DatePolicy = "disabled" | "fixed" | "host";
|
|
393
|
+
export type RandomPolicy = "disabled" | "seeded" | "host";
|
|
394
|
+
export type MapSetSnapshotPolicy = "reject" | "serialize";
|
|
395
|
+
|
|
396
|
+
export interface RuntimePolicyConfig {
|
|
397
|
+
typescript?: {
|
|
398
|
+
imports?: TypeScriptImportPolicy;
|
|
399
|
+
};
|
|
400
|
+
runtime?: {
|
|
401
|
+
date?: DatePolicy;
|
|
402
|
+
random?: RandomPolicy;
|
|
403
|
+
};
|
|
404
|
+
snapshot?: {
|
|
405
|
+
mapsSets?: MapSetSnapshotPolicy;
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export interface Chidori {
|
|
410
|
+
workspace: WorkspaceHost;
|
|
411
|
+
/** Start an immutable multi-turn prompt context (optionally seeded). */
|
|
412
|
+
context(seed?: { system?: string; tools?: string[] }): Context;
|
|
413
|
+
/**
|
|
414
|
+
* Start a multi-turn chat assistant — a stateful wrapper over `context()`
|
|
415
|
+
* that owns the running dialogue. Send turns with `chat.say(message)` or drive
|
|
416
|
+
* an interactive `input()` loop with `chat.loop()`.
|
|
417
|
+
*/
|
|
418
|
+
conversation(options?: ConversationOptions): Conversation;
|
|
419
|
+
prompt(text: string, options?: PromptOptions): Promise<string>;
|
|
420
|
+
input(message: string, options?: InputOptions): Promise<string>;
|
|
421
|
+
/**
|
|
422
|
+
* Pause at a named listen point until a matching signal is delivered (or one
|
|
423
|
+
* is already queued in the durable mailbox), then resolve to
|
|
424
|
+
* `{ name, payload, from }`. The inverse of `input()`: the run idles cheaply
|
|
425
|
+
* on disk and an outside party delivers via `POST /sessions/{id}/signal`.
|
|
426
|
+
*/
|
|
427
|
+
signal<T = AgentJson>(name: string): Promise<Signal<T>>;
|
|
428
|
+
signal<T = AgentJson>(
|
|
429
|
+
name: string,
|
|
430
|
+
options: SignalOptions,
|
|
431
|
+
): Promise<Signal<T> | SignalTimeout>;
|
|
432
|
+
/**
|
|
433
|
+
* Non-blocking: consume a queued signal of this name if present, else resolve
|
|
434
|
+
* to `null`. Records the result (value or null) at this seq so replay is
|
|
435
|
+
* deterministic.
|
|
436
|
+
*/
|
|
437
|
+
pollSignal<T = AgentJson>(name: string): Promise<Signal<T> | null>;
|
|
438
|
+
/**
|
|
439
|
+
* Fan-in: pause until ANY of the named signals is delivered (or one is
|
|
440
|
+
* already queued in the durable mailbox). Resolves to the bare consumed
|
|
441
|
+
* signal — its `name` says which fired. Pre-arrived candidates are consumed
|
|
442
|
+
* in delivery order (lowest `delivery_seq` across the whole name set).
|
|
443
|
+
*/
|
|
444
|
+
signalAny<T = AgentJson>(names: string[]): Promise<Signal<T>>;
|
|
445
|
+
signalAny<T = AgentJson>(
|
|
446
|
+
names: string[],
|
|
447
|
+
options: SignalOptions,
|
|
448
|
+
): Promise<Signal<T> | SignalTimeout>;
|
|
449
|
+
/**
|
|
450
|
+
* Durable value checkpoint: run `fn` once and journal its JSON-serializable
|
|
451
|
+
* result; on replay/resume the recorded value (or error) is returned without
|
|
452
|
+
* re-running `fn`. Wrap expensive deterministic computation in a step so a
|
|
453
|
+
* resumed run does not re-pay it. The callback must be pure, synchronous
|
|
454
|
+
* compute — host effects (`chidori.*`), captured randomness, filesystem
|
|
455
|
+
* writes, timers, and async callbacks are refused inside a step.
|
|
456
|
+
*/
|
|
457
|
+
step<T extends AgentJson = AgentJson>(name: string, fn: () => T): Promise<T>;
|
|
458
|
+
callAgent<TInput extends AgentJson = JsonObject, TOutput extends AgentJson = AgentJson>(
|
|
459
|
+
path: string,
|
|
460
|
+
input?: TInput,
|
|
461
|
+
): Promise<TOutput>;
|
|
462
|
+
/**
|
|
463
|
+
* Fork the run into one sub-run per variant from the current anchored state
|
|
464
|
+
* (the VFS plus each variant's explicit `input`), run each variant's own
|
|
465
|
+
* source module, and return every outcome so the agent can compare and pick.
|
|
466
|
+
* The whole fan-out is one recorded durable call: a replay of this run
|
|
467
|
+
* returns the outcomes from cache without re-running the branches.
|
|
468
|
+
*/
|
|
469
|
+
branch<T extends AgentJson = AgentJson>(
|
|
470
|
+
variants: BranchVariant[],
|
|
471
|
+
options?: BranchOptions,
|
|
472
|
+
): Promise<BranchOutcome<T>[]>;
|
|
473
|
+
tool<TArgs extends JsonObject = JsonObject, TResult extends AgentJson = AgentJson>(
|
|
474
|
+
name: string,
|
|
475
|
+
args?: TArgs,
|
|
476
|
+
): Promise<TResult>;
|
|
477
|
+
parallel<TTasks extends readonly (() => Promise<unknown>)[]>(
|
|
478
|
+
tasks: TTasks,
|
|
479
|
+
options?: ParallelOptions,
|
|
480
|
+
): Promise<{ [Index in keyof TTasks]: Awaited<ReturnType<TTasks[Index]>> }>;
|
|
481
|
+
retry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
482
|
+
tryCall<T>(fn: () => Promise<T>): Promise<TryCallResult<T>>;
|
|
483
|
+
template(pathOrText: string, vars?: JsonObject, options?: TemplateOptions): Promise<string>;
|
|
484
|
+
log(message: string, fields?: JsonObject): Promise<void>;
|
|
485
|
+
memory<T extends AgentJson = AgentJson>(
|
|
486
|
+
action: MemoryAction,
|
|
487
|
+
key?: string,
|
|
488
|
+
value?: T,
|
|
489
|
+
options?: JsonObject,
|
|
490
|
+
): Promise<T | AgentJson[] | null>;
|
|
491
|
+
checkpoint(label?: string, data?: AgentJson): Promise<void>;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
export type AgentFunction<TInput extends AgentJson = JsonObject, TOutput extends AgentJson = AgentJson> = (
|
|
495
|
+
input: TInput,
|
|
496
|
+
) => TOutput | Promise<TOutput>;
|
|
497
|
+
|
|
498
|
+
export type ToolFunction<TArgs extends JsonObject = JsonObject, TResult extends AgentJson = AgentJson> = (
|
|
499
|
+
args: TArgs,
|
|
500
|
+
) => TResult | Promise<TResult>;
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* The chidori host object — the durable surface your agents and tools call
|
|
504
|
+
* (`chidori.log`, `chidori.prompt`, `chidori.tool`, `chidori.input`, …).
|
|
505
|
+
*
|
|
506
|
+
* Import it for typed access; the runtime strips this import and supplies the
|
|
507
|
+
* real object at execution time, so there's no actual module dependency (and no
|
|
508
|
+
* need for a `(input, chidori)` second parameter):
|
|
509
|
+
*
|
|
510
|
+
* ```ts
|
|
511
|
+
* import { chidori, run } from "chidori";
|
|
512
|
+
* run(async (input: { topic: string }) => {
|
|
513
|
+
* await chidori.log("starting", { topic: input.topic });
|
|
514
|
+
* return { ok: true };
|
|
515
|
+
* });
|
|
516
|
+
* ```
|
|
517
|
+
*
|
|
518
|
+
* Accessing it from a plain import outside the runtime throws.
|
|
519
|
+
*/
|
|
520
|
+
export const chidori: Chidori = new Proxy({} as Chidori, {
|
|
521
|
+
get(_target, prop) {
|
|
522
|
+
throw new Error(
|
|
523
|
+
`chidori.${String(prop)} is only available inside the chidori runtime; ` +
|
|
524
|
+
`this import is replaced when an agent runs under chidori.`,
|
|
525
|
+
);
|
|
526
|
+
},
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Define the agent entrypoint. Call it once at the top level of an agent module
|
|
531
|
+
* with your handler; the runtime invokes the handler with the run input and
|
|
532
|
+
* uses its return value as the output. This replaces the old "export a function
|
|
533
|
+
* named `agent`" convention.
|
|
534
|
+
*
|
|
535
|
+
* ```ts
|
|
536
|
+
* import { run } from "chidori";
|
|
537
|
+
* run(async (input) => ({ greeting: `hello ${input.name}` }));
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
540
|
+
export function run<TInput extends AgentJson = JsonObject, TOutput extends AgentJson = AgentJson>(
|
|
541
|
+
handler: AgentFunction<TInput, TOutput>,
|
|
542
|
+
): void {
|
|
543
|
+
void handler;
|
|
544
|
+
throw new Error(
|
|
545
|
+
"run() is only available inside the chidori runtime; this import is " +
|
|
546
|
+
"replaced when an agent runs under chidori.",
|
|
547
|
+
);
|
|
548
|
+
}
|