toolnexus 0.18.1 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/acp.d.ts +42 -0
- package/dist/acp.js +246 -0
- package/dist/agents/agent.d.ts +12 -1
- package/dist/agents/agent.js +3 -2
- package/dist/agents/home.js +4 -2
- package/dist/agents/loop.d.ts +21 -0
- package/dist/agents/loop.js +38 -2
- package/dist/agents/runtime.d.ts +76 -6
- package/dist/agents/runtime.js +92 -22
- package/dist/builtin.d.ts +32 -2
- package/dist/builtin.js +342 -58
- package/dist/classifier.d.ts +23 -0
- package/dist/classifier.js +33 -25
- package/dist/client.d.ts +116 -16
- package/dist/client.js +197 -43
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/order.d.ts +46 -0
- package/dist/order.js +71 -0
- package/dist/skill.d.ts +13 -0
- package/dist/skill.js +110 -27
- package/dist/types.d.ts +11 -0
- package/dist/types.js +22 -0
- package/package.json +2 -2
- package/src/acp.ts +308 -0
- package/src/agents/agent.ts +15 -3
- package/src/agents/home.ts +4 -2
- package/src/agents/loop.ts +40 -2
- package/src/agents/runtime.ts +154 -29
- package/src/builtin.ts +379 -55
- package/src/classifier.ts +45 -27
- package/src/client.ts +220 -51
- package/src/index.ts +1 -0
- package/src/order.ts +70 -0
- package/src/skill.ts +121 -27
- package/src/types.ts +22 -0
package/dist/classifier.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { redactErrorBody, capErrorBody } from "./client.js";
|
|
1
2
|
import { retryAfterMs, isRetryableStatus } from "./retry.js";
|
|
2
3
|
// ---------------------------------------------------------------- constants
|
|
3
4
|
/** The System One endpoint base. */
|
|
@@ -8,6 +9,11 @@ export const DEFAULT_CLASSIFIER_MODEL = "jev-latest";
|
|
|
8
9
|
export const DEFAULT_CLASSIFIER_API_KEY_ENV = "TYPESAFE_API_KEY";
|
|
9
10
|
/** Bounds ONE request; a classifier has no loop to bound. */
|
|
10
11
|
export const DEFAULT_CLASSIFIER_TIMEOUT_MS = 10_000;
|
|
12
|
+
/** The two servable pairings, as configurations rather than six independently-choosable cells. */
|
|
13
|
+
export const CLASSIFIER_BACKENDS = {
|
|
14
|
+
typesafe: { baseUrl: DEFAULT_CLASSIFIER_BASE_URL, model: DEFAULT_CLASSIFIER_MODEL, apiKeyEnv: DEFAULT_CLASSIFIER_API_KEY_ENV },
|
|
15
|
+
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "typesafe/jev-1.13", apiKeyEnv: "OPENROUTER_API_KEY" },
|
|
16
|
+
};
|
|
11
17
|
/** Client-side cap on a choice's named options (§8B). */
|
|
12
18
|
export const MAX_CHOICE_OPTIONS = 255;
|
|
13
19
|
/** Bounds of a score rubric (§8B). */
|
|
@@ -261,9 +267,13 @@ export class Classifier {
|
|
|
261
267
|
constructor(opts) {
|
|
262
268
|
this.opts = opts;
|
|
263
269
|
this.style = opts.style ?? "systemone";
|
|
264
|
-
|
|
265
|
-
this.
|
|
266
|
-
this.
|
|
270
|
+
const preset = CLASSIFIER_BACKENDS[opts.backend ?? "typesafe"];
|
|
271
|
+
this.baseUrl = opts.baseUrl ?? preset.baseUrl;
|
|
272
|
+
this.model = opts.model ?? preset.model;
|
|
273
|
+
this.apiKeyEnv = opts.apiKeyEnv ?? preset.apiKeyEnv;
|
|
274
|
+
const mismatch = backendMismatch(this.baseUrl, this.model);
|
|
275
|
+
if (mismatch)
|
|
276
|
+
throw new Error(mismatch);
|
|
267
277
|
this.timeoutMs = opts.timeoutMs ?? DEFAULT_CLASSIFIER_TIMEOUT_MS;
|
|
268
278
|
switch (this.style) {
|
|
269
279
|
case "systemone":
|
|
@@ -433,8 +443,10 @@ export class Classifier {
|
|
|
433
443
|
let lastErr;
|
|
434
444
|
for (let attempt = 0;; attempt++) {
|
|
435
445
|
const timer = new AbortController();
|
|
446
|
+
// NOT unref'd: this watchdog is the only thing that will end a request an
|
|
447
|
+
// injected `fetch` never settles, and an unref'd timer cannot keep the
|
|
448
|
+
// loop alive long enough to fire. It is cleared on every exit path below.
|
|
436
449
|
const t = setTimeout(() => timer.abort(new Error(`classifier: request timeout after ${this.timeoutMs}ms`)), this.timeoutMs);
|
|
437
|
-
t.unref?.();
|
|
438
450
|
const onOuter = () => timer.abort(signal.reason);
|
|
439
451
|
if (signal) {
|
|
440
452
|
if (signal.aborted) {
|
|
@@ -512,7 +524,8 @@ export class Classifier {
|
|
|
512
524
|
'{"type":"choice","choice":"<one offered option id>","probabilities":{"<every offered option id>":<0..1>},"confidence":<0..1>}. ' +
|
|
513
525
|
'A "score" answer is {"type":"score","score":<a number within the rubric bounds, fractional allowed>,' +
|
|
514
526
|
'"legend":{"0":"<level 0>",…},"probabilities":{"0":<0..1>,…},"confidence":<0..1>}.';
|
|
515
|
-
|
|
527
|
+
// No toolkit at all: a classifier has no loop and executes nothing (SPEC §0.10, ADR 0023).
|
|
528
|
+
const run = await this.opts.client.run(prompt, { signal });
|
|
516
529
|
const payload = firstJsonObject(run.text);
|
|
517
530
|
let parsed;
|
|
518
531
|
try {
|
|
@@ -579,10 +592,22 @@ export function degenerateCriteria(criteria) {
|
|
|
579
592
|
function cause(status, body) {
|
|
580
593
|
if (status === 401 || status === 403)
|
|
581
594
|
return "";
|
|
582
|
-
|
|
583
|
-
|
|
595
|
+
// ONE policy, now shared with the §8 client path: redact account identifiers, then cap.
|
|
596
|
+
const s = capErrorBody(redactErrorBody(body));
|
|
597
|
+
return s ? ": " + s : "";
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* The one mixture known to fail, caught before the wire: TypeSafe's unqualified `jev-*` model id
|
|
601
|
+
* pointed at the OpenRouter gateway, which has never heard of it. Returns the message to fail
|
|
602
|
+
* with, or `""` when the pairing is fine.
|
|
603
|
+
*/
|
|
604
|
+
export function backendMismatch(baseUrl, model) {
|
|
605
|
+
const host = baseUrl.replace(/^[a-z]+:\/\//i, "").split("/")[0].split(":")[0].toLowerCase();
|
|
606
|
+
if (host !== "openrouter.ai" && !host.endsWith(".openrouter.ai"))
|
|
607
|
+
return "";
|
|
608
|
+
if (!/^jev-/.test(model))
|
|
584
609
|
return "";
|
|
585
|
-
return
|
|
610
|
+
return `classifier: model "${model}" is TypeSafe's spelling; on openrouter.ai use "${CLASSIFIER_BACKENDS.openrouter.model}"`;
|
|
586
611
|
}
|
|
587
612
|
/** `${ENV_VAR}` expands at call time; an unset var expands to the empty string, as §2. */
|
|
588
613
|
function expandEnv(value) {
|
|
@@ -611,20 +636,3 @@ function sleep(ms) {
|
|
|
611
636
|
setTimeout(resolve, ms);
|
|
612
637
|
});
|
|
613
638
|
}
|
|
614
|
-
/**
|
|
615
|
-
* The `llm` style declares no tools — a classifier has no loop and executes nothing. The §8
|
|
616
|
-
* `run` takes a Toolkit, so this is the empty one; the cast is the price of not exposing a
|
|
617
|
-
* public "no tools" Toolkit constructor just for this path.
|
|
618
|
-
*/
|
|
619
|
-
const EMPTY_TOOLKIT = {
|
|
620
|
-
skillsPrompt: () => "",
|
|
621
|
-
toOpenAI: () => [],
|
|
622
|
-
toAnthropic: () => [],
|
|
623
|
-
toGemini: () => [],
|
|
624
|
-
get: () => undefined,
|
|
625
|
-
list: () => [],
|
|
626
|
-
execute: async () => {
|
|
627
|
-
throw new Error("classifier: the llm style declares no tools");
|
|
628
|
-
},
|
|
629
|
-
close: async () => { },
|
|
630
|
-
};
|
package/dist/client.d.ts
CHANGED
|
@@ -41,7 +41,18 @@ export interface ClientOptions {
|
|
|
41
41
|
/** §10 Suspension resolver. When a tool returns Pending (metadata.pending), the client calls
|
|
42
42
|
* this, then retries the tool with Context.answer = the resolution. Its interior is unconstrained
|
|
43
43
|
* (open a browser, message a channel, watch a file, forward to another agent). Omit for a durable
|
|
44
|
-
* host: run() does not hang — it returns { status:"pending", pending:request } to resume later.
|
|
44
|
+
* host: run() does not hang — it returns { status:"pending", pending:request } to resume later.
|
|
45
|
+
*
|
|
46
|
+
* IDEMPOTENCY CONTRACT (SPEC §7D rewind-to-checkpoint). A durable resume REPLAYS the suspended
|
|
47
|
+
* turn from its PRE-TURN checkpoint: "continues from its checkpoint" means the transcript is
|
|
48
|
+
* REWOUND, not carried. EVERY tool that ran in that turn RUNS AGAIN, and the suspended tool
|
|
49
|
+
* itself is always re-executed (with `ctx.answer`) — that is §10's resolution mechanism, not a
|
|
50
|
+
* bug. Reattachment by task key makes a re-run `task` call idempotent; a leaf agent's own
|
|
51
|
+
* side-effecting tools (`git push`, a charge, a delete) have NO equivalent and are the host's
|
|
52
|
+
* responsibility. Any tool reachable in a suspendable turn must be idempotent.
|
|
53
|
+
* Replaying the leaf's stored transcript instead is DEFERRED to its own change; it would not
|
|
54
|
+
* remove this requirement anyway.
|
|
55
|
+
*/
|
|
45
56
|
waitFor?: (request: Request) => Promise<Answer>;
|
|
46
57
|
/** §8 Gap 1. Extra top-level keys shallow-merged into EVERY LLM body after the client builds
|
|
47
58
|
* its own — a requestParams key WINS on collision (e.g. max_tokens overrides the anthropic
|
|
@@ -68,6 +79,60 @@ export interface ClientOptions {
|
|
|
68
79
|
* text placeholder. Unset ⇒ attached parts error, derived parts degrade. */
|
|
69
80
|
onUnsupportedPart?: UnsupportedPartMode;
|
|
70
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* The §8 CLIENT status vocabulary, as a value. It is a DIFFERENT, smaller closed set than the
|
|
84
|
+
* §7D AGENT vocabulary (`agents.TASK_STATUSES`), which also contains `"timeout"`, `"closed"`,
|
|
85
|
+
* `"interrupted"` and `"error"`. Two fields are called `status`; they are not interchangeable.
|
|
86
|
+
* A run that fails at a deadline THROWS here — it never comes back as a `RunResult`.
|
|
87
|
+
*/
|
|
88
|
+
export declare const RUN_STATUSES: readonly ["done", "pending", "incomplete"];
|
|
89
|
+
export type RunStatus = (typeof RUN_STATUSES)[number];
|
|
90
|
+
/** Account-identifier keys blanked out of a provider error body before it reaches a message,
|
|
91
|
+
* a log or a metric. The shape survives; the value does not (ADR 0027 D3.2). */
|
|
92
|
+
export declare const REDACTED_BODY_KEYS: readonly ["user_id", "account_id", "org_id", "organization"];
|
|
93
|
+
/** What a redacted value is replaced with — identical in all seven ports. */
|
|
94
|
+
export declare const REDACTION_PLACEHOLDER = "\u00ABredacted\u00BB";
|
|
95
|
+
/** A redacted body is capped at this many characters IN THE MESSAGE ONLY. The typed `body`
|
|
96
|
+
* field carries the full redacted body — a host that opted into a typed error asked for the
|
|
97
|
+
* whole thing (ADR 0027 D3 / addendum A5). */
|
|
98
|
+
export declare const ERROR_BODY_CAP = 200;
|
|
99
|
+
/**
|
|
100
|
+
* Redact known account identifiers, then cap. A CAP IS NOT REDACTION: the body that leaked
|
|
101
|
+
* `user_2…` in issue #92 was 96 bytes, well inside the cap, so both steps are needed and
|
|
102
|
+
* redaction runs FIRST (capping first could split a key/value pair and hide it from the regex).
|
|
103
|
+
*/
|
|
104
|
+
export declare function redactErrorBody(body: string): string;
|
|
105
|
+
/** Cap a already-redacted body for interpolation into a MESSAGE. Redaction is not a cap and a
|
|
106
|
+
* cap is not redaction: they are independent and both are needed. */
|
|
107
|
+
export declare function capErrorBody(body: string): string;
|
|
108
|
+
/**
|
|
109
|
+
* A provider failure carried as a VALUE, not a sentence (ADR 0027 D3.1). A host that must
|
|
110
|
+
* decide what to log can read `status` / `retryAfter` instead of parsing a message.
|
|
111
|
+
*
|
|
112
|
+
* `body` is ALREADY redacted and capped, and is `""` on 401/403 — an auth body routinely
|
|
113
|
+
* reflects the credential or the header that was sent. `rawBody` is never populated by the
|
|
114
|
+
* library; the SPEC credentials guarantee now covers error messages too.
|
|
115
|
+
*/
|
|
116
|
+
export declare class LlmHttpError extends Error {
|
|
117
|
+
/** The HTTP status the provider answered with. */
|
|
118
|
+
readonly status: number;
|
|
119
|
+
/** The provider's FULL redacted body; `""` on 401/403 and when empty. Uncapped — the cap
|
|
120
|
+
* applies to `message` only. */
|
|
121
|
+
readonly body: string;
|
|
122
|
+
/** The `Retry-After` header verbatim, when the provider sent one. */
|
|
123
|
+
readonly retryAfter?: string | undefined;
|
|
124
|
+
readonly name = "LlmHttpError";
|
|
125
|
+
constructor(
|
|
126
|
+
/** The HTTP status the provider answered with. */
|
|
127
|
+
status: number,
|
|
128
|
+
/** The provider's FULL redacted body; `""` on 401/403 and when empty. Uncapped — the cap
|
|
129
|
+
* applies to `message` only. */
|
|
130
|
+
body: string,
|
|
131
|
+
/** The `Retry-After` header verbatim, when the provider sent one. */
|
|
132
|
+
retryAfter?: string | undefined);
|
|
133
|
+
}
|
|
134
|
+
/** Build the typed error from a non-2xx provider response (reads the body once). */
|
|
135
|
+
export declare function llmHttpError(res: Response): Promise<LlmHttpError>;
|
|
71
136
|
/** §8 Resilience. What to do with a failed LLM call. */
|
|
72
137
|
export type ErrorTier = "retry" | "fail";
|
|
73
138
|
/** §8 Resilience. Context passed to `onError` for each failed LLM attempt. */
|
|
@@ -284,8 +349,14 @@ export declare class Client {
|
|
|
284
349
|
private endRun;
|
|
285
350
|
/** Emit a `run` error metric event (once, on a thrown run). */
|
|
286
351
|
private emitRunError;
|
|
287
|
-
|
|
288
|
-
|
|
352
|
+
/**
|
|
353
|
+
* Run the loop. `ctx` — and `ctx.toolkit` inside it — are OPTIONAL: an absent toolkit is a
|
|
354
|
+
* COMPLETION (SPEC §0.10). The system message is then the system prompt alone, and the
|
|
355
|
+
* request body carries no `tools` and no `tool_choice` key (not an empty array). An empty
|
|
356
|
+
* toolkit and no toolkit are observably identical on the wire.
|
|
357
|
+
*/
|
|
358
|
+
run(prompt: PromptInput, ctx?: {
|
|
359
|
+
toolkit?: Toolkit;
|
|
289
360
|
signal?: AbortSignal;
|
|
290
361
|
history?: any[];
|
|
291
362
|
}): Promise<RunResult>;
|
|
@@ -317,15 +388,15 @@ export declare class Client {
|
|
|
317
388
|
* the answer — so the next `ask` with the same `id` continues it. Without an
|
|
318
389
|
* `id` it is a stateless one-shot (identical to `run`).
|
|
319
390
|
*/
|
|
320
|
-
ask(prompt: PromptInput, ctx
|
|
321
|
-
toolkit
|
|
391
|
+
ask(prompt: PromptInput, ctx?: {
|
|
392
|
+
toolkit?: Toolkit;
|
|
322
393
|
id?: string;
|
|
323
394
|
on_text?: (delta: string) => void;
|
|
324
395
|
signal?: AbortSignal;
|
|
325
396
|
}): Promise<RunResult>;
|
|
326
397
|
/** A stateful multi-turn conversation that retains history across sends. */
|
|
327
|
-
conversation(ctx
|
|
328
|
-
toolkit
|
|
398
|
+
conversation(ctx?: {
|
|
399
|
+
toolkit?: Toolkit;
|
|
329
400
|
signal?: AbortSignal;
|
|
330
401
|
}): Conversation;
|
|
331
402
|
/**
|
|
@@ -333,13 +404,25 @@ export declare class Client {
|
|
|
333
404
|
* With an `id`, it is stateful (like `ask`): the thread's transcript is loaded as history before
|
|
334
405
|
* streaming, and saved back to the ConversationStore on the terminal `done` event. No `id` ⇒ stateless.
|
|
335
406
|
*/
|
|
336
|
-
stream(prompt: PromptInput, ctx
|
|
337
|
-
toolkit
|
|
407
|
+
stream(prompt: PromptInput, ctx?: {
|
|
408
|
+
toolkit?: Toolkit;
|
|
338
409
|
id?: string;
|
|
339
410
|
signal?: AbortSignal;
|
|
340
411
|
}): AsyncGenerator<StreamEvent, void, unknown>;
|
|
412
|
+
/** §0.10 system message. The toolkit is OPTIONAL — with none there is no skills prompt and
|
|
413
|
+
* the system message is the system prompt alone. This deref was issue #86 (ADR 0023). */
|
|
341
414
|
private system;
|
|
342
|
-
/**
|
|
415
|
+
/** Run-scoped timeout timers, cleared by `releaseSignal` when the run settles. */
|
|
416
|
+
private readonly runTimers;
|
|
417
|
+
/** Drop a run's timeout timer. Idempotent, and safe on a signal that never had one. */
|
|
418
|
+
private releaseSignal;
|
|
419
|
+
/** Build a run-scoped abort signal from the optional run-level timeout + an external signal.
|
|
420
|
+
*
|
|
421
|
+
* The timer is deliberately NOT `unref()`d. An unref'd timer cannot keep the event loop
|
|
422
|
+
* alive, so a run whose only pending work is a request that never settles — an injected
|
|
423
|
+
* `fetch`, an in-process transport, a stalled stream — drains the loop and the timeout never
|
|
424
|
+
* fires at all, which is the one case `timeoutMs` exists for. It is RELEASED instead: the
|
|
425
|
+
* caller clears it however the run leaves, so a finished run holds nothing open. */
|
|
343
426
|
private makeSignal;
|
|
344
427
|
/** fetch with retry + exponential backoff on the default retryable set (429/500/502/503/504/529)
|
|
345
428
|
* plus network errors and anything `retryableStatuses` added, honoring Retry-After; aborts via signal.
|
|
@@ -352,6 +435,10 @@ export declare class Client {
|
|
|
352
435
|
/** One non-streaming LLM call, with an `llm` metric event (ok/error + per-call tokens + ms). */
|
|
353
436
|
private llmCallJson;
|
|
354
437
|
private runOpenAI;
|
|
438
|
+
private runAnthropic;
|
|
439
|
+
private streamOpenAI;
|
|
440
|
+
private streamAnthropic;
|
|
441
|
+
private runOpenAIWithSignal;
|
|
355
442
|
private result;
|
|
356
443
|
/** §10: a run halted because a tool suspended and no `waitFor` was configured. */
|
|
357
444
|
private pendingRun;
|
|
@@ -361,9 +448,9 @@ export declare class Client {
|
|
|
361
448
|
* no `waitFor` is configured (the run should stop and surface the request).
|
|
362
449
|
*/
|
|
363
450
|
private resolvePending;
|
|
364
|
-
private
|
|
365
|
-
private
|
|
366
|
-
private
|
|
451
|
+
private runAnthropicWithSignal;
|
|
452
|
+
private streamOpenAIWithSignal;
|
|
453
|
+
private streamAnthropicWithSignal;
|
|
367
454
|
}
|
|
368
455
|
export declare function createClient(opts: ClientOptions): Client;
|
|
369
456
|
/** One tool call an in-process model asks for. Flat on purpose: the nested
|
|
@@ -400,6 +487,17 @@ export type InProcessOptions = Omit<ClientOptions, "baseUrl" | "apiKey" | "style
|
|
|
400
487
|
/** Your model. Receives the assembled request, returns one assistant message. */
|
|
401
488
|
generate: (request: InProcessRequest) => InProcessResponse | Promise<InProcessResponse>;
|
|
402
489
|
};
|
|
490
|
+
/**
|
|
491
|
+
* Build a `fetch`-shaped adapter over a semantic `generate` function (ADR 0030):
|
|
492
|
+
* the reusable piece of {@link createInProcessClient} — assembles the wire request,
|
|
493
|
+
* calls `generate`, and re-encodes its answer as an OpenAI-shaped `Response`. Every
|
|
494
|
+
* caller that wants an in-process model behind a `fetch` slot (the top-level client,
|
|
495
|
+
* or the agent runtime's `inProcess` option) goes through this ONE function, so there
|
|
496
|
+
* is no second copy of the request/response assembly to drift.
|
|
497
|
+
*
|
|
498
|
+
* Streaming is refused rather than faked — see the thrown error.
|
|
499
|
+
*/
|
|
500
|
+
export declare function createInProcessFetch(generate: (request: InProcessRequest) => InProcessResponse | Promise<InProcessResponse>): typeof fetch;
|
|
403
501
|
/**
|
|
404
502
|
* A client backed by a model running IN THIS PROCESS — no server, no socket, and no
|
|
405
503
|
* HTTP types to construct.
|
|
@@ -407,18 +505,20 @@ export type InProcessOptions = Omit<ClientOptions, "baseUrl" | "apiKey" | "style
|
|
|
407
505
|
* This is a second constructor, not a second seam: it builds on the same injectable
|
|
408
506
|
* transport that `fetch`/`httpClient` uses, so the tool-calling loop, MCP servers,
|
|
409
507
|
* skills, sub-agents, hooks, metrics and the completion gate all behave identically.
|
|
508
|
+
* The `fetch`-shaped adapter itself is {@link createInProcessFetch} — this function
|
|
509
|
+
* is just that adapter wired into a `Client`.
|
|
410
510
|
*
|
|
411
|
-
* Streaming is refused rather than faked — see
|
|
511
|
+
* Streaming is refused rather than faked — see {@link createInProcessFetch}.
|
|
412
512
|
*/
|
|
413
513
|
export declare function createInProcessClient(opts: InProcessOptions): Client;
|
|
414
514
|
/** Stateful multi-turn conversation: each send() continues the same transcript (memory). */
|
|
415
515
|
export declare class Conversation {
|
|
416
516
|
private readonly client;
|
|
417
|
-
private readonly toolkit
|
|
517
|
+
private readonly toolkit?;
|
|
418
518
|
private readonly signal?;
|
|
419
519
|
/** Full running transcript (system + user + assistant + tool messages). */
|
|
420
520
|
messages: any[];
|
|
421
|
-
constructor(client: Client, toolkit
|
|
521
|
+
constructor(client: Client, toolkit?: Toolkit | undefined, signal?: AbortSignal | undefined);
|
|
422
522
|
/** Send the next user turn; prior history is retained automatically. */
|
|
423
523
|
send(prompt: PromptInput): Promise<RunResult>;
|
|
424
524
|
/** Reset the conversation memory. */
|