libfx 0.0.14-dev.1534.g6afa7c33dac5 → 0.0.14
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 +49 -4
- package/chatgpt.js +2 -1
- package/durable/local.mjs +12 -12
- package/durable/vercel.mjs +1 -1
- package/durable/world.mjs +1 -1
- package/durable.js +229 -68
- package/fx-core.wasm +0 -0
- package/fx-sdk.js +82 -7
- package/fx-term.wasm +0 -0
- package/libfx.darwin-arm64.node +0 -0
- package/libfx.darwin-x64.node +0 -0
- package/libfx.linux-arm64.node +0 -0
- package/libfx.linux-x64.node +0 -0
- package/mcp.js +11 -2
- package/node.cjs +396 -48
- package/node.js +2 -0
- package/package.json +1 -1
- package/subscription.js +2 -0
- package/tool-observation.js +185 -0
- package/types/browser.d.ts +7 -0
- package/types/durable-world.d.ts +7 -1
- package/types/libfx.d.cts +129 -3
- package/types/mcp.d.ts +6 -1
- package/types/node.d.cts +7 -0
- package/types/wasm.d.ts +7 -0
package/node.js
CHANGED
|
@@ -710,6 +710,8 @@ export const createFxAgent = createDurableAgentFactory({
|
|
|
710
710
|
name: "createFxAgent",
|
|
711
711
|
label: "fx agent",
|
|
712
712
|
defaultDurability: environmentDurability,
|
|
713
|
+
// One durability per environment, so agents created without one share it.
|
|
714
|
+
defaultShared: true,
|
|
713
715
|
harness: fxHarness({
|
|
714
716
|
createEngine: createFxEngine,
|
|
715
717
|
// An explicit key, then the durability's own credential, such as a
|
package/package.json
CHANGED
package/subscription.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
//
|
|
8
8
|
// A provider spec supplies what differs: which requests it authorizes, how its
|
|
9
9
|
// credentials are checked and refreshed, and which headers carry them.
|
|
10
|
+
//
|
|
11
|
+
// TLA+ model: `tests/tla/sdk/ProviderAuth.tla`.
|
|
10
12
|
|
|
11
13
|
const refreshSkewMs = 5 * 60 * 1000;
|
|
12
14
|
const maxRememberedCredentials = 256;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// Observations of host-owned effects. Helpers call the effect exactly once,
|
|
2
|
+
// preserve its value/error, and never await an instrumentation callback.
|
|
3
|
+
export function toolObservation(scope, callId, hooks, emit, signal) {
|
|
4
|
+
const report = (error) => {
|
|
5
|
+
try {
|
|
6
|
+
Promise.resolve(hooks.onError?.(error)).catch(() => {});
|
|
7
|
+
} catch {}
|
|
8
|
+
};
|
|
9
|
+
let next = 0;
|
|
10
|
+
const id = () => `host:${scope.executionId}:${callId}:${++next}`;
|
|
11
|
+
const publish = (type, data, content = {}) =>
|
|
12
|
+
emit({
|
|
13
|
+
...scope,
|
|
14
|
+
type,
|
|
15
|
+
data,
|
|
16
|
+
timestamp: Date.now(),
|
|
17
|
+
contentCaptured: hooks.captureContent === true,
|
|
18
|
+
contentTruncated: content.truncated === true,
|
|
19
|
+
});
|
|
20
|
+
const capture = () => {
|
|
21
|
+
let remaining = 64 * 1024;
|
|
22
|
+
return {
|
|
23
|
+
truncated: false,
|
|
24
|
+
text(value) {
|
|
25
|
+
if (hooks.captureContent !== true || value == null) return undefined;
|
|
26
|
+
value = String(value);
|
|
27
|
+
let prefix = value.slice(0, remaining);
|
|
28
|
+
if (prefix.length && /[\uD800-\uDBFF]/.test(prefix.at(-1))) prefix = prefix.slice(0, -1);
|
|
29
|
+
const bytes = new TextEncoder().encode(prefix);
|
|
30
|
+
let end = Math.min(bytes.length, remaining);
|
|
31
|
+
while (end > 0 && end < bytes.length && (bytes[end] & 0xc0) === 0x80) end--;
|
|
32
|
+
remaining -= end;
|
|
33
|
+
this.truncated ||= prefix.length < value.length || end < bytes.length;
|
|
34
|
+
return new TextDecoder().decode(bytes.subarray(0, end));
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
function terminal(end) {
|
|
39
|
+
let ended = false;
|
|
40
|
+
const finish = (...args) => {
|
|
41
|
+
if (ended) return;
|
|
42
|
+
ended = true;
|
|
43
|
+
signal.removeEventListener("abort", abort);
|
|
44
|
+
try {
|
|
45
|
+
end(...args);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
report(error);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const abort = () => finish("cancelled", undefined);
|
|
51
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
52
|
+
if (signal.aborted) abort();
|
|
53
|
+
return finish;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
async wait(request, run) {
|
|
57
|
+
if (
|
|
58
|
+
!request ||
|
|
59
|
+
!["approval", "question", "mcp_form", "mcp_url"].includes(request.kind) ||
|
|
60
|
+
typeof run !== "function"
|
|
61
|
+
)
|
|
62
|
+
throw new TypeError("wait needs an input request and an effect");
|
|
63
|
+
if (signal.aborted) return run();
|
|
64
|
+
const requestId = id();
|
|
65
|
+
const content = capture();
|
|
66
|
+
content.truncated ||=
|
|
67
|
+
(request.questions?.length ?? 0) > 128 ||
|
|
68
|
+
(request.questions ?? [])
|
|
69
|
+
.slice(0, 128)
|
|
70
|
+
.some((question) => (question.options?.length ?? 0) > 128);
|
|
71
|
+
publish(
|
|
72
|
+
"wait.start",
|
|
73
|
+
{
|
|
74
|
+
requestId,
|
|
75
|
+
kind: request.kind,
|
|
76
|
+
callId,
|
|
77
|
+
externalId: request.externalId ?? null,
|
|
78
|
+
server: request.server ?? null,
|
|
79
|
+
schemaJson: content.text(request.schemaJson),
|
|
80
|
+
prompt: content.text(request.prompt),
|
|
81
|
+
questionCount: request.questions?.length ?? 0,
|
|
82
|
+
...(hooks.captureContent === true
|
|
83
|
+
? {
|
|
84
|
+
questions: (request.questions ?? []).slice(0, 128).map((question) => ({
|
|
85
|
+
question: content.text(question.question),
|
|
86
|
+
options: (question.options ?? []).slice(0, 128).map((option) => ({
|
|
87
|
+
label: content.text(option.label),
|
|
88
|
+
description: content.text(option.description),
|
|
89
|
+
})),
|
|
90
|
+
})),
|
|
91
|
+
}
|
|
92
|
+
: {}),
|
|
93
|
+
},
|
|
94
|
+
content,
|
|
95
|
+
);
|
|
96
|
+
const finish = terminal((outcome, result, error) => {
|
|
97
|
+
const content = capture();
|
|
98
|
+
content.truncated ||= (result?.answers?.length ?? 0) > 128;
|
|
99
|
+
publish(
|
|
100
|
+
"wait.end",
|
|
101
|
+
{
|
|
102
|
+
requestId,
|
|
103
|
+
outcome,
|
|
104
|
+
error: error?.name ?? null,
|
|
105
|
+
...(hooks.captureContent === true
|
|
106
|
+
? {
|
|
107
|
+
answers: (result?.answers ?? [])
|
|
108
|
+
.slice(0, 128)
|
|
109
|
+
.map((answer) => content.text(answer)),
|
|
110
|
+
}
|
|
111
|
+
: {}),
|
|
112
|
+
},
|
|
113
|
+
content,
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
try {
|
|
117
|
+
const result = await run();
|
|
118
|
+
let outcome = "accepted";
|
|
119
|
+
try {
|
|
120
|
+
outcome = result?.outcome ?? outcome;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
report(error);
|
|
123
|
+
}
|
|
124
|
+
finish(outcome, result);
|
|
125
|
+
return result;
|
|
126
|
+
} catch (error) {
|
|
127
|
+
finish(
|
|
128
|
+
signal.aborted || error?.name === "AbortError"
|
|
129
|
+
? "cancelled"
|
|
130
|
+
: error?.name === "TimeoutError"
|
|
131
|
+
? "timed_out"
|
|
132
|
+
: "failed",
|
|
133
|
+
undefined,
|
|
134
|
+
error,
|
|
135
|
+
);
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
async mcp(identity, run) {
|
|
140
|
+
if (signal.aborted) return run({ correlationId: identity.correlationId });
|
|
141
|
+
const operationId = id();
|
|
142
|
+
publish("mcp.start", {
|
|
143
|
+
operationId,
|
|
144
|
+
callId,
|
|
145
|
+
server: identity.server ?? null,
|
|
146
|
+
tool: identity.tool,
|
|
147
|
+
transport: null,
|
|
148
|
+
});
|
|
149
|
+
if (identity.correlationId !== undefined)
|
|
150
|
+
publish("mcp.request", {
|
|
151
|
+
operationId,
|
|
152
|
+
requestId: identity.correlationId,
|
|
153
|
+
requestIdKind: "correlation",
|
|
154
|
+
});
|
|
155
|
+
const finish = terminal((status, error) =>
|
|
156
|
+
publish("mcp.end", { operationId, status, error: error?.name ?? null }),
|
|
157
|
+
);
|
|
158
|
+
try {
|
|
159
|
+
const result = await run({ correlationId: identity.correlationId });
|
|
160
|
+
let status = "unknown";
|
|
161
|
+
try {
|
|
162
|
+
status = result?.isError ? "failure" : "success";
|
|
163
|
+
} catch (error) {
|
|
164
|
+
report(error);
|
|
165
|
+
}
|
|
166
|
+
finish(status);
|
|
167
|
+
return result;
|
|
168
|
+
} catch (error) {
|
|
169
|
+
finish(signal.aborted || error?.name === "AbortError" ? "cancelled" : "failure", error);
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
childHooks() {
|
|
174
|
+
return {
|
|
175
|
+
...hooks,
|
|
176
|
+
parent: {
|
|
177
|
+
rootSessionId: scope.rootSessionId,
|
|
178
|
+
sessionId: scope.sessionId,
|
|
179
|
+
turnId: scope.turnId,
|
|
180
|
+
callId,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
}
|
package/types/browser.d.ts
CHANGED
|
@@ -53,6 +53,10 @@ export type {
|
|
|
53
53
|
FxGatewayProvider,
|
|
54
54
|
FxGrokProvider,
|
|
55
55
|
FxHostTool,
|
|
56
|
+
FxHooks,
|
|
57
|
+
FxHookEvent,
|
|
58
|
+
FxHookMessage,
|
|
59
|
+
FxHookToolCall,
|
|
56
60
|
FxIdleResult,
|
|
57
61
|
FxImageBlock,
|
|
58
62
|
FxJsonSchema,
|
|
@@ -92,6 +96,9 @@ export type {
|
|
|
92
96
|
FxTextBlock,
|
|
93
97
|
FxTool,
|
|
94
98
|
FxToolContext,
|
|
99
|
+
FxToolObservation,
|
|
100
|
+
FxWaitRequest,
|
|
101
|
+
FxWaitResponse,
|
|
95
102
|
FxToolImage,
|
|
96
103
|
FxToolResult,
|
|
97
104
|
FxTools,
|
package/types/durable-world.d.ts
CHANGED
|
@@ -41,7 +41,13 @@ export type WorldSource = World | (() => World | Promise<World>);
|
|
|
41
41
|
export type WorldOptions = {
|
|
42
42
|
/** The durability's name in errors. Default `"world"`. */
|
|
43
43
|
name?: string;
|
|
44
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* The store this World keeps sessions in. Queue messages name it, so one route hands each delivery to the agents on
|
|
46
|
+
* its store, and on one store an agent name belongs to one configuration. Give each customer of an app a store of its
|
|
47
|
+
* own. Default the durability's `name`.
|
|
48
|
+
*/
|
|
49
|
+
store?: string;
|
|
50
|
+
/** The queue keeps a message until a delivery acknowledges it, across crashes. `prompt()` stores the prompt first either way. Default false. */
|
|
45
51
|
queueDurable?: boolean;
|
|
46
52
|
/** How often a waiting worker reads the session again. Default 1000. */
|
|
47
53
|
pollMs?: number;
|
package/types/libfx.d.cts
CHANGED
|
@@ -144,6 +144,32 @@ export interface FxToolContext {
|
|
|
144
144
|
sessionId: string;
|
|
145
145
|
/** The JSON passed as `context` to the `session()` call whose prompt or steer started the turn. */
|
|
146
146
|
context?: JsonValue;
|
|
147
|
+
/** Present when hooks are installed. Observe host-owned input waits and child engines. */
|
|
148
|
+
observation?: FxToolObservation;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface FxWaitRequest {
|
|
152
|
+
kind: "approval" | "question" | "mcp_form" | "mcp_url";
|
|
153
|
+
externalId?: string | number;
|
|
154
|
+
server?: string;
|
|
155
|
+
prompt?: string;
|
|
156
|
+
schemaJson?: string;
|
|
157
|
+
questions?: { question: string; options?: { label: string; description?: string }[] }[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface FxWaitResponse<T = unknown> {
|
|
161
|
+
outcome: "accepted" | "denied" | "cancelled" | "failed" | "timed_out";
|
|
162
|
+
answers?: string[];
|
|
163
|
+
value?: T;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface FxToolObservation {
|
|
167
|
+
/** Calls the host effect once and preserves its response/error. Never makes a permission decision. */
|
|
168
|
+
wait<T>(request: FxWaitRequest, run: () => FxWaitResponse<T> | Promise<FxWaitResponse<T>>): Promise<FxWaitResponse<T>>;
|
|
169
|
+
/** Used by the MCP adapter to bind a remote call to this tool invocation. */
|
|
170
|
+
mcp<T>(identity: { server: string | null; tool: string; correlationId?: string | undefined }, run: (request: { correlationId: string | undefined }) => T | Promise<T>): Promise<T>;
|
|
171
|
+
/** Install these hooks on a host-created child engine to retain the parent tool relationship. */
|
|
172
|
+
childHooks(): FxHooks;
|
|
147
173
|
}
|
|
148
174
|
|
|
149
175
|
/** An image in a typed tool result: base64 `data`, or a `sourceRef` with no `data`. */
|
|
@@ -294,6 +320,8 @@ export type FxSessionEvent = FxEventBase & (
|
|
|
294
320
|
| { type: "session.fenced"; sessionId: string; epoch: number }
|
|
295
321
|
/** A message for a session of the agent `agent` reached this one, which sent it on. */
|
|
296
322
|
| { type: "session.forwarded"; sessionId: string; agent: string }
|
|
323
|
+
/** A queue delivery named an input the session's log does not hold, or none at all, so it ran nothing. */
|
|
324
|
+
| { type: "session.refused"; sessionId?: string; messageId?: string; reason: "unknown message" | "malformed message" }
|
|
297
325
|
/** `cutoffs`: the times in a row the deadline cut off the same step, this one included. */
|
|
298
326
|
| { type: "session.deadline"; sessionId: string; epoch: number; cutoffs: number }
|
|
299
327
|
| { type: "ui.error"; sessionId: string; error: string }
|
|
@@ -305,8 +333,107 @@ export type FxAgentEvent = FxEngineEvent | FxSessionEvent;
|
|
|
305
333
|
// ---------------------------------------------------------------------------
|
|
306
334
|
// Options shared by agents and engines
|
|
307
335
|
|
|
336
|
+
/** Semantic observation, independent of diagnostics, UI events, permissions, and tracing libraries. */
|
|
337
|
+
export interface FxHooks {
|
|
338
|
+
/** Parent of a host-created child engine. Normally supplied by `context.observation.childHooks()`. */
|
|
339
|
+
parent?: { rootSessionId: string; sessionId: string; turnId: string; callId: string };
|
|
340
|
+
/** Include bounded messages, instructions, tool arguments/results, and schemas. Default false. */
|
|
341
|
+
captureContent?: boolean;
|
|
342
|
+
/** Called in event order, but returned promises are not awaited. The host owns buffering and flushing. */
|
|
343
|
+
onEvent(event: FxHookEvent): void | Promise<void>;
|
|
344
|
+
/** Receives callback throws and rejected promises. Errors here are contained too. */
|
|
345
|
+
onError?(error: unknown): void | Promise<void>;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/** An authoritative model call identity, with no provider replay or credentials. */
|
|
349
|
+
export interface FxHookToolCall {
|
|
350
|
+
callId: string;
|
|
351
|
+
name: string;
|
|
352
|
+
provenance: "fx_local" | "provider_executed";
|
|
353
|
+
/** Present only with content capture. May be a truncated JSON string. */
|
|
354
|
+
argumentsJson?: string | null;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export interface FxHookMessage {
|
|
358
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
359
|
+
content?: string | null;
|
|
360
|
+
toolCallId: string | null;
|
|
361
|
+
toolName: string | null;
|
|
362
|
+
toolResultStatus: "success" | "failure" | null;
|
|
363
|
+
imageCount: number;
|
|
364
|
+
toolCalls: FxHookToolCall[];
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
interface FxHookEnvelope {
|
|
368
|
+
version: 1;
|
|
369
|
+
sessionId: string;
|
|
370
|
+
rootSessionId: string;
|
|
371
|
+
parentSessionId: string | null;
|
|
372
|
+
sourceSessionId: string | null;
|
|
373
|
+
workId: string | null;
|
|
374
|
+
parentTurnId?: string;
|
|
375
|
+
parentCallId?: string;
|
|
376
|
+
/** Stable host turn ID; null for session-scoped journal receipts. */
|
|
377
|
+
turnId: string | null;
|
|
378
|
+
/** Fresh for each execution/resume, not a trace or durable operation ID. */
|
|
379
|
+
executionId: string | null;
|
|
380
|
+
/** One-based within this execution, or 0 outside a step. */
|
|
381
|
+
stepIndex: number;
|
|
382
|
+
/** Milliseconds since the epoch, sampled at the semantic boundary. */
|
|
383
|
+
timestamp: number;
|
|
384
|
+
contentCaptured: boolean;
|
|
385
|
+
/** A content budget or collection limit omitted information. */
|
|
386
|
+
contentTruncated: boolean;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/** Versioned execution facts. The host chooses topology, conventions, redaction, and export. */
|
|
390
|
+
export type FxHookEvent = FxHookEnvelope & (
|
|
391
|
+
| { type: "turn.start"; data: { resumed: boolean; input?: string | null } }
|
|
392
|
+
| { type: "turn.end"; data: { outcome: "completed" | "interrupted" | "failed" | "paused" | "yielded" | "cancelled" | "fenced"; error: string | null; handoff?: boolean } }
|
|
393
|
+
| { type: "step.start" | "step.end"; data: Record<string, never> }
|
|
394
|
+
| { type: "model.start"; data: {
|
|
395
|
+
/** Scoped to executionId. Retries have distinct IDs. */
|
|
396
|
+
modelCallId: number;
|
|
397
|
+
parentCallId: string | null;
|
|
398
|
+
purpose: "agent" | "compaction" | "vision" | "title" | "permission_review" | "auxiliary";
|
|
399
|
+
model: string; toolChoice: string; maxOutputTokens: number | null; messageCount: number;
|
|
400
|
+
instructions?: FxHookMessage[]; messages?: FxHookMessage[];
|
|
401
|
+
toolsJson?: string | null;
|
|
402
|
+
tools: { name: string; description?: string | null; inputSchemaJson?: string | null }[];
|
|
403
|
+
} }
|
|
404
|
+
| { type: "model.admitted" | "model.output_start"; data: { modelCallId: number } }
|
|
405
|
+
| { type: "model.end"; data: {
|
|
406
|
+
modelCallId: number; error: string | null; cancelled: boolean; output?: string | null;
|
|
407
|
+
finishReason?: string | null; generationId?: string | null; provider?: string | null;
|
|
408
|
+
usage?: { inputTokens: number | null; outputTokens: number | null; cacheReadTokens: number | null; cacheWriteTokens: number | null; reasoningTokens: number | null };
|
|
409
|
+
toolCalls?: FxHookToolCall[];
|
|
410
|
+
} }
|
|
411
|
+
| { type: "tool.start"; data: { call: FxHookToolCall; rerun: boolean } }
|
|
412
|
+
| { type: "permission.start"; data: { call: FxHookToolCall } }
|
|
413
|
+
| { type: "tool.end"; data: {
|
|
414
|
+
call: FxHookToolCall; output?: string | null; status: "success" | "failure" | "cancelled"; error: string | null;
|
|
415
|
+
usage?: { inputTokens: number; outputTokens: number; webSearchRequests: number };
|
|
416
|
+
} }
|
|
417
|
+
/** Acceptance into conversation memory, not proof of durable storage. */
|
|
418
|
+
| { type: "tool.result"; data: { call: FxHookToolCall; output?: string | null; status: "success" | "failure" } }
|
|
419
|
+
/** Permission evaluation can complete without a human prompt. */
|
|
420
|
+
| { type: "permission.end"; data: { call: FxHookToolCall; decision: "once" | "always" | "deny" | "policy_denied" | "permission_required" | null; error: string | null } }
|
|
421
|
+
| { type: "wait.start"; data: { requestId: number | string; kind: FxWaitRequest["kind"]; callId: string | null; externalId: string | number | null; server: string | null; prompt?: string | null; schemaJson?: string | null; questionCount: number; questions?: { question: string; submission?: "none" | "input" | "choice"; options: { label: string; description?: string | null }[] }[] } }
|
|
422
|
+
| { type: "wait.end"; data: { requestId: number | string; outcome: FxWaitResponse["outcome"]; error: string | null; answers?: string[] } }
|
|
423
|
+
| { type: "mcp.start"; data: { operationId: number | string; callId: string | null; server: string | null; tool: string; transport: string | null } }
|
|
424
|
+
| { type: "mcp.request"; data: { operationId: number | string; requestId: number | string; requestIdKind: "jsonrpc" | "engine" | "correlation" } }
|
|
425
|
+
| { type: "mcp.end"; data: { operationId: number | string; status: "success" | "failure" | "cancelled" | "input_required" | "unavailable" | "unknown"; error: string | null } }
|
|
426
|
+
| { type: "delegation"; data: { callId: string; childSessionId: string; workId: string; operationId: string | null; phase: "dispatched" | "completed" | "yielded" | "replayed" | "failed" | "cancelled" | "feedback_queued" | "feedback_applied" | "feedback_not_applied" } }
|
|
427
|
+
/** Emitted only after append resolves and its cursor validates. */
|
|
428
|
+
| { type: "journal.commit"; data: { cursor: string; firstSeq: number | null; lastSeq: number | null; eventCount: number } }
|
|
429
|
+
| { type: "journal.restore"; data: { cursor: string | null; lastSeq: number; resumable: boolean; openTurnId: string | null; lastTurnId: string | null } }
|
|
430
|
+
| { type: "journal.error"; data: { error: string; fenced: boolean } }
|
|
431
|
+
);
|
|
432
|
+
|
|
308
433
|
/** Options `createFxAgent()` and `createFxEngine()` share. */
|
|
309
434
|
export interface FxSharedOptions<Event> {
|
|
435
|
+
/** Host-owned instrumentation of native and Wasm execution. Disabled by default. */
|
|
436
|
+
hooks?: FxHooks;
|
|
310
437
|
/** The complete host-owned system context, up to 64 KiB of UTF-8. An array is joined with blank lines. */
|
|
311
438
|
instructions?: string | readonly string[];
|
|
312
439
|
tools?: FxTools;
|
|
@@ -627,7 +754,7 @@ export type FxAgentOptions = Omit<FxSharedOptions<FxAgentEvent>, "tools"> & FxMo
|
|
|
627
754
|
|
|
628
755
|
/** Options for `agent.session()`. Each applies to the turns this session object starts. */
|
|
629
756
|
export interface FxSessionOptions {
|
|
630
|
-
/** JSON every tool call of those turns receives as `context
|
|
757
|
+
/** JSON every tool call of those turns receives as `context`, copied when `session()` is called. */
|
|
631
758
|
context?: JsonValue;
|
|
632
759
|
/** The model for those turns instead of the agent's whole model choice: a model ID, or a model object. */
|
|
633
760
|
model?: string | FxModelOptions;
|
|
@@ -647,8 +774,7 @@ export interface FxPromptOptions {
|
|
|
647
774
|
export interface FxSteerOptions {
|
|
648
775
|
/**
|
|
649
776
|
* The steer's id, so a retried request adds nothing. Follows the session id rule. Reusing a prompt's id rejects
|
|
650
|
-
* with `FX_MESSAGE_ID_IN_USE
|
|
651
|
-
* `session.error` with that code instead.
|
|
777
|
+
* with `FX_MESSAGE_ID_IN_USE`.
|
|
652
778
|
*/
|
|
653
779
|
messageId?: string;
|
|
654
780
|
}
|
package/types/mcp.d.ts
CHANGED
|
@@ -10,7 +10,8 @@ export interface McpClient {
|
|
|
10
10
|
/** Resolves to the tools array or `{ tools, nextCursor? }`. */
|
|
11
11
|
listTools(params?: { cursor: string }): unknown;
|
|
12
12
|
/** Called with the tool's original name, the model's arguments, and the turn's `signal` in `options`. */
|
|
13
|
-
callTool(params: { name: string; arguments?: unknown }, resultSchema?: unknown, options?: { signal?: AbortSignal }): unknown;
|
|
13
|
+
callTool(params: { name: string; arguments?: unknown; _meta?: { "libfx/correlationId": string } }, resultSchema?: unknown, options?: { signal?: AbortSignal }): unknown;
|
|
14
|
+
getServerVersion?(): { name?: string } | undefined;
|
|
14
15
|
/** Required when `resources` is given. */
|
|
15
16
|
readResource?(params: { uri: string }): unknown;
|
|
16
17
|
/** Required when `prompts` is given. */
|
|
@@ -20,6 +21,10 @@ export interface McpClient {
|
|
|
20
21
|
|
|
21
22
|
/** Options for `createMcpAdapter()`. */
|
|
22
23
|
export interface McpAdapterOptions {
|
|
24
|
+
/** Local server identity for hook events. Defaults to the client's reported server name, or null. */
|
|
25
|
+
serverName?: string;
|
|
26
|
+
/** Send an opaque UUID as `_meta["libfx/correlationId"]`. Default false; doesn't request MCP progress notifications. */
|
|
27
|
+
propagateCorrelation?: boolean;
|
|
23
28
|
/** Prepended to each tool name: letters, digits, `_`, or `-`. */
|
|
24
29
|
prefix?: string;
|
|
25
30
|
/** Resource URIs whose text becomes instructions. */
|
package/types/node.d.cts
CHANGED
|
@@ -62,6 +62,10 @@ export type {
|
|
|
62
62
|
FxGatewayProvider,
|
|
63
63
|
FxGrokProvider,
|
|
64
64
|
FxHostTool,
|
|
65
|
+
FxHooks,
|
|
66
|
+
FxHookEvent,
|
|
67
|
+
FxHookMessage,
|
|
68
|
+
FxHookToolCall,
|
|
65
69
|
FxIdleResult,
|
|
66
70
|
FxImageBlock,
|
|
67
71
|
FxJsonSchema,
|
|
@@ -103,6 +107,9 @@ export type {
|
|
|
103
107
|
FxTextBlock,
|
|
104
108
|
FxTool,
|
|
105
109
|
FxToolContext,
|
|
110
|
+
FxToolObservation,
|
|
111
|
+
FxWaitRequest,
|
|
112
|
+
FxWaitResponse,
|
|
106
113
|
FxToolImage,
|
|
107
114
|
FxToolResult,
|
|
108
115
|
FxTools,
|
package/types/wasm.d.ts
CHANGED
|
@@ -35,6 +35,10 @@ export type {
|
|
|
35
35
|
FxGatewayProvider,
|
|
36
36
|
FxGrokProvider,
|
|
37
37
|
FxHostTool,
|
|
38
|
+
FxHooks,
|
|
39
|
+
FxHookEvent,
|
|
40
|
+
FxHookMessage,
|
|
41
|
+
FxHookToolCall,
|
|
38
42
|
FxImageBlock,
|
|
39
43
|
FxJsonSchema,
|
|
40
44
|
FxKeyedTool,
|
|
@@ -62,6 +66,9 @@ export type {
|
|
|
62
66
|
FxTextBlock,
|
|
63
67
|
FxTool,
|
|
64
68
|
FxToolContext,
|
|
69
|
+
FxToolObservation,
|
|
70
|
+
FxWaitRequest,
|
|
71
|
+
FxWaitResponse,
|
|
65
72
|
FxToolImage,
|
|
66
73
|
FxToolResult,
|
|
67
74
|
FxTools,
|