@pi-oxide/pi-host-web 0.4.0 → 0.7.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.
Files changed (90) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +2535 -0
  3. package/dist/sdk/agent.d.ts +21 -0
  4. package/dist/sdk/agent.d.ts.map +1 -0
  5. package/dist/sdk/artifacts.d.ts +29 -0
  6. package/dist/sdk/artifacts.d.ts.map +1 -0
  7. package/dist/sdk/context.d.ts +2 -0
  8. package/dist/sdk/context.d.ts.map +1 -0
  9. package/dist/sdk/errors.d.ts +8 -0
  10. package/dist/sdk/errors.d.ts.map +1 -0
  11. package/dist/sdk/events.d.ts +9 -0
  12. package/dist/sdk/events.d.ts.map +1 -0
  13. package/dist/sdk/index.d.ts +16 -0
  14. package/dist/sdk/index.d.ts.map +1 -0
  15. package/dist/sdk/init.d.ts +30 -0
  16. package/dist/sdk/init.d.ts.map +1 -0
  17. package/dist/sdk/internal/engine.d.ts +91 -0
  18. package/dist/sdk/internal/engine.d.ts.map +1 -0
  19. package/dist/sdk/internal/events.d.ts +30 -0
  20. package/dist/sdk/internal/events.d.ts.map +1 -0
  21. package/dist/sdk/internal/logger.d.ts +51 -0
  22. package/dist/sdk/internal/logger.d.ts.map +1 -0
  23. package/dist/sdk/internal/providers/anthropic.d.ts +75 -0
  24. package/dist/sdk/internal/providers/anthropic.d.ts.map +1 -0
  25. package/dist/sdk/internal/providers/openai.d.ts +13 -0
  26. package/dist/sdk/internal/providers/openai.d.ts.map +1 -0
  27. package/dist/sdk/internal/providers/types.d.ts +57 -0
  28. package/dist/sdk/internal/providers/types.d.ts.map +1 -0
  29. package/dist/sdk/internal/stores/indexedDb.d.ts +3 -0
  30. package/dist/sdk/internal/stores/indexedDb.d.ts.map +1 -0
  31. package/dist/sdk/internal/stores/persistence.d.ts +13 -0
  32. package/dist/sdk/internal/stores/persistence.d.ts.map +1 -0
  33. package/dist/sdk/internal/tools/artifact.d.ts +3 -0
  34. package/dist/sdk/internal/tools/artifact.d.ts.map +1 -0
  35. package/dist/sdk/internal/tools/browser.d.ts +19 -0
  36. package/dist/sdk/internal/tools/browser.d.ts.map +1 -0
  37. package/dist/sdk/internal/tools/browserRuntime.d.ts +47 -0
  38. package/dist/sdk/internal/tools/browserRuntime.d.ts.map +1 -0
  39. package/dist/sdk/internal/tools/liveRuntime.d.ts +12 -0
  40. package/dist/sdk/internal/tools/liveRuntime.d.ts.map +1 -0
  41. package/dist/sdk/internal/tools/registry.d.ts +17 -0
  42. package/dist/sdk/internal/tools/registry.d.ts.map +1 -0
  43. package/dist/sdk/internal/tools/service.d.ts +15 -0
  44. package/dist/sdk/internal/tools/service.d.ts.map +1 -0
  45. package/dist/sdk/internal/util/types.d.ts +6 -0
  46. package/dist/sdk/internal/util/types.d.ts.map +1 -0
  47. package/dist/sdk/model.d.ts +16 -0
  48. package/dist/sdk/model.d.ts.map +1 -0
  49. package/dist/sdk/snapshot.d.ts +7 -0
  50. package/dist/sdk/snapshot.d.ts.map +1 -0
  51. package/dist/sdk/stores.d.ts +22 -0
  52. package/dist/sdk/stores.d.ts.map +1 -0
  53. package/dist/sdk/tools.d.ts +32 -0
  54. package/dist/sdk/tools.d.ts.map +1 -0
  55. package/dist/sdk/types.d.ts +200 -0
  56. package/dist/sdk/types.d.ts.map +1 -0
  57. package/package.json +69 -39
  58. package/pi_host_web.d.ts +4 -1
  59. package/pi_host_web.js +11 -0
  60. package/pi_host_web_bg.wasm +0 -0
  61. package/pi_host_web_bg.wasm.d.ts +36 -0
  62. package/sdk/agent.ts +0 -274
  63. package/sdk/artifacts.ts +0 -35
  64. package/sdk/context.ts +0 -4
  65. package/sdk/errors.ts +0 -24
  66. package/sdk/events.ts +0 -52
  67. package/sdk/index.d.ts +0 -29
  68. package/sdk/index.js +0 -111
  69. package/sdk/index.ts +0 -53
  70. package/sdk/init.ts +0 -58
  71. package/sdk/internal/engine.ts +0 -614
  72. package/sdk/internal/events.ts +0 -241
  73. package/sdk/internal/providers/anthropic.ts +0 -440
  74. package/sdk/internal/providers/openai.ts +0 -177
  75. package/sdk/internal/providers/types.ts +0 -64
  76. package/sdk/internal/stores/indexedDb.ts +0 -24
  77. package/sdk/internal/stores/persistence.ts +0 -71
  78. package/sdk/internal/tools/artifact.ts +0 -24
  79. package/sdk/internal/tools/browser.ts +0 -449
  80. package/sdk/internal/tools/browserRuntime.ts +0 -48
  81. package/sdk/internal/tools/liveRuntime.ts +0 -151
  82. package/sdk/internal/tools/registry.ts +0 -174
  83. package/sdk/internal/tools/service.ts +0 -157
  84. package/sdk/model.ts +0 -35
  85. package/sdk/react/index.ts +0 -1
  86. package/sdk/react/useAgent.ts +0 -334
  87. package/sdk/snapshot.ts +0 -25
  88. package/sdk/stores.ts +0 -72
  89. package/sdk/tools.ts +0 -47
  90. package/sdk/types.ts +0 -252
package/sdk/agent.ts DELETED
@@ -1,274 +0,0 @@
1
- // Public Agent class — the primary SDK surface.
2
- // Thin facade over the internal engine. No WASM imports here.
3
-
4
- import { EventEmitter } from "./events.ts";
5
- import type {
6
- AgentConfig,
7
- AgentInput,
8
- AgentRunOptions,
9
- AgentRunResult,
10
- AgentEventName,
11
- AgentEventHandler,
12
- AgentStatus,
13
- Unsubscribe,
14
- AgentError,
15
- } from "./types.ts";
16
- import { createAgentError } from "./errors.ts";
17
- import type { HostAgent } from "./internal/engine.ts";
18
- import {
19
- runAgentTurn,
20
- resetAgentState,
21
- steerAgent,
22
- createEngineAgent,
23
- destroyEngineAgent,
24
- } from "./internal/engine.ts";
25
-
26
- export class Agent {
27
- private config: AgentConfig;
28
- private emitter: EventEmitter;
29
- private status: AgentStatus = { state: "idle" };
30
- private currentRun: Promise<AgentRunResult> | null = null;
31
- private currentAbortController: AbortController | null = null;
32
- private disposed = false;
33
- private engineAgent: HostAgent | null = null;
34
-
35
- constructor(config: AgentConfig) {
36
- this.config = config;
37
- this.emitter = new EventEmitter();
38
- }
39
-
40
- on<E extends AgentEventName>(
41
- event: E,
42
- handler: AgentEventHandler<E>,
43
- ): Unsubscribe {
44
- if (this.disposed) {
45
- return () => {};
46
- }
47
- return this.emitter.on(event, handler);
48
- }
49
-
50
- async run(
51
- input: string | AgentInput,
52
- options?: AgentRunOptions,
53
- ): Promise<AgentRunResult> {
54
- if (this.disposed) {
55
- const error = createAgentError(
56
- "agent_disposed",
57
- "Agent has been disposed",
58
- { recoverable: false },
59
- );
60
- const result: AgentRunResult = {
61
- status: "failed",
62
- text: "",
63
- toolCalls: [],
64
- artifacts: [],
65
- error,
66
- };
67
- this.emitter.emit("error", error);
68
- this.emitter.emit("status", { state: "failed", message: error.message });
69
- this.emitter.emit("done", result);
70
- return result;
71
- }
72
-
73
- if (this.currentRun) {
74
- const error = createAgentError(
75
- "agent_busy",
76
- "Agent is already running a turn",
77
- { recoverable: true },
78
- );
79
- const result: AgentRunResult = {
80
- status: "failed",
81
- text: "",
82
- toolCalls: [],
83
- artifacts: [],
84
- error,
85
- };
86
- this.emitter.emit("error", error);
87
- this.emitter.emit("status", { state: "failed", message: error.message });
88
- this.emitter.emit("done", result);
89
- return result;
90
- }
91
-
92
- const abortController = new AbortController();
93
- this.currentAbortController = abortController;
94
-
95
- // Merge external signal if provided
96
- if (options?.signal) {
97
- if (options.signal.aborted) {
98
- abortController.abort(options.signal.reason);
99
- } else {
100
- options.signal.addEventListener(
101
- "abort",
102
- () => {
103
- abortController.abort(options.signal!.reason);
104
- },
105
- { once: true },
106
- );
107
- }
108
- }
109
-
110
- const runPromise = this._doRun(input, options, abortController.signal);
111
- this.currentRun = runPromise;
112
-
113
- try {
114
- const result = await runPromise;
115
- this.emitter.emit("done", result);
116
- return result;
117
- } catch (e) {
118
- // Safety net: convert any unexpected throw to a failed result
119
- const error = createAgentError(
120
- "internal_error",
121
- e instanceof Error ? e.message : String(e),
122
- { cause: e, recoverable: false },
123
- );
124
- const failedResult: AgentRunResult = {
125
- status: "failed",
126
- text: "",
127
- toolCalls: [],
128
- artifacts: [],
129
- error,
130
- };
131
- this.emitter.emit("error", error);
132
- this.emitter.emit("status", { state: "failed", message: error.message });
133
- this.emitter.emit("done", failedResult);
134
- return failedResult;
135
- } finally {
136
- this.currentRun = null;
137
- this.currentAbortController = null;
138
- }
139
- }
140
-
141
- private async _doRun(
142
- input: string | AgentInput,
143
- options: AgentRunOptions | undefined,
144
- signal: AbortSignal,
145
- ): Promise<AgentRunResult> {
146
- // Lazy initialization on first run
147
- if (!this.engineAgent) {
148
- this.engineAgent = await createEngineAgent(this.config, {
149
- onEvent: (event) => this.emitter.emit(event.type as AgentEventName, event.payload),
150
- onStatus: (status) => {
151
- this.status = status;
152
- this.emitter.emit("status", status);
153
- },
154
- });
155
- }
156
-
157
- try {
158
- return await runAgentTurn(
159
- this.engineAgent,
160
- this.config,
161
- input,
162
- options,
163
- signal,
164
- {
165
- onEvent: (event) =>
166
- this.emitter.emit(event.type as AgentEventName, event.payload),
167
- onStatus: (status) => {
168
- this.status = status;
169
- this.emitter.emit("status", status);
170
- },
171
- },
172
- );
173
- } catch (e) {
174
- const isAbort =
175
- signal.aborted ||
176
- (e instanceof Error && e.name === "AbortError") ||
177
- (e instanceof Error && e.message.includes("user_aborted"));
178
-
179
- if (isAbort) {
180
- const abortedResult: AgentRunResult = {
181
- status: "aborted",
182
- text: "",
183
- toolCalls: [],
184
- artifacts: [],
185
- };
186
- this.emitter.emit("status", {
187
- state: "aborted",
188
- message: "Stopped by user",
189
- });
190
- return abortedResult;
191
- }
192
-
193
- const code =
194
- e instanceof Error && "code" in e && typeof (e as { code: unknown }).code === "string"
195
- ? ((e as { code: string }).code as AgentError["code"])
196
- : "internal_error";
197
- const error = createAgentError(
198
- code,
199
- e instanceof Error ? e.message : String(e),
200
- { cause: e, recoverable: false },
201
- );
202
- const failedResult: AgentRunResult = {
203
- status: "failed",
204
- text: "",
205
- toolCalls: [],
206
- artifacts: [],
207
- error,
208
- };
209
- this.emitter.emit("error", error);
210
- this.emitter.emit("status", { state: "failed", message: error.message });
211
- return failedResult;
212
- }
213
- }
214
-
215
- stop(reason?: string): void {
216
- if (this.disposed || !this.currentAbortController) return;
217
- this.currentAbortController.abort(reason ?? "user-requested");
218
- }
219
-
220
- async steer(input: string | AgentInput): Promise<void> {
221
- if (this.disposed) {
222
- throw createAgentError(
223
- "agent_disposed",
224
- "Agent has been disposed",
225
- { recoverable: false },
226
- );
227
- }
228
- if (!this.engineAgent) {
229
- throw createAgentError(
230
- "agent_not_initialized",
231
- "Agent has not been run yet",
232
- { recoverable: true },
233
- );
234
- }
235
- return steerAgent(this.engineAgent, input);
236
- }
237
-
238
- async reset(): Promise<void> {
239
- if (this.disposed) {
240
- throw createAgentError(
241
- "agent_disposed",
242
- "Agent has been disposed",
243
- { recoverable: false },
244
- );
245
- }
246
- if (this.engineAgent) {
247
- await resetAgentState(this.engineAgent);
248
- this.engineAgent = null;
249
- }
250
- this.currentRun = null;
251
- this.currentAbortController = null;
252
- this.status = { state: "idle" };
253
- this.emitter.emit("status", this.status);
254
- }
255
-
256
- dispose(): void {
257
- if (this.disposed) return;
258
- this.disposed = true;
259
- if (this.currentAbortController) {
260
- this.currentAbortController.abort("disposed");
261
- this.currentAbortController = null;
262
- }
263
- if (this.engineAgent) {
264
- destroyEngineAgent(this.engineAgent);
265
- this.engineAgent = null;
266
- }
267
- this.emitter.clear();
268
- this.currentRun = null;
269
- }
270
-
271
- getStatus(): AgentStatus {
272
- return this.status;
273
- }
274
- }
package/sdk/artifacts.ts DELETED
@@ -1,35 +0,0 @@
1
- // Artifact types for the pi-oxide SDK.
2
- // These are public objects, not leaked host internals.
3
-
4
- export interface AgentArtifact {
5
- id: string;
6
- kind: "text" | "json" | "binary";
7
- content: string | Uint8Array | unknown;
8
- mimeType?: string;
9
- title?: string;
10
- metadata?: Record<string, unknown>;
11
- createdAt: number;
12
- }
13
-
14
- export interface AgentArtifactRef {
15
- id: string;
16
- kind: AgentArtifact["kind"];
17
- title?: string;
18
- mimeType?: string;
19
- }
20
-
21
- export interface ArtifactPolicy {
22
- mode: "inline" | "external";
23
- }
24
-
25
- export interface ArtifactSearchQuery {
26
- text: string;
27
- limit?: number;
28
- }
29
-
30
- export interface ArtifactSearchResult {
31
- artifact: AgentArtifactRef;
32
- snippet?: string;
33
- score?: number;
34
- matchCount?: number;
35
- }
package/sdk/context.ts DELETED
@@ -1,4 +0,0 @@
1
- // Context policy types for the pi-oxide SDK.
2
- // Re-exported from types.ts for a cleaner public API surface.
3
-
4
- export type { AgentContextPolicy, AgentSummarizer } from "./types.ts";
package/sdk/errors.ts DELETED
@@ -1,24 +0,0 @@
1
- // AgentError interface and factory.
2
- // AgentError is an interface, NOT a class — it is a plain object.
3
-
4
- import type { AgentError } from "./types.ts";
5
-
6
- export type { AgentError } from "./types.ts";
7
-
8
- export function createAgentError(
9
- code: AgentError["code"],
10
- message: string,
11
- options?: {
12
- cause?: unknown;
13
- recoverable?: boolean;
14
- metadata?: Record<string, unknown>;
15
- },
16
- ): AgentError {
17
- return {
18
- code,
19
- message,
20
- cause: options?.cause,
21
- recoverable: options?.recoverable ?? false,
22
- metadata: options?.metadata,
23
- };
24
- }
package/sdk/events.ts DELETED
@@ -1,52 +0,0 @@
1
- // Lightweight, type-safe EventEmitter (not Node's).
2
- // Maps event names to typed handlers using the SDK's AgentEventName union.
3
-
4
- import type { AgentEventName, AgentEventHandler } from "./types.ts";
5
-
6
- type AnyHandler = (payload: unknown) => void;
7
-
8
- export class EventEmitter {
9
- private handlers: Partial<Record<AgentEventName, Set<AnyHandler>>> = {};
10
-
11
- on<E extends AgentEventName>(
12
- event: E,
13
- handler: AgentEventHandler<E>,
14
- ): () => void {
15
- const set = (this.handlers[event] ??= new Set()) as Set<AnyHandler>;
16
- set.add(handler as AnyHandler);
17
-
18
- return () => {
19
- set.delete(handler as AnyHandler);
20
- if (set.size === 0) {
21
- delete this.handlers[event];
22
- }
23
- };
24
- }
25
-
26
- off<E extends AgentEventName>(
27
- event: E,
28
- handler: AgentEventHandler<E>,
29
- ): void {
30
- const set = this.handlers[event];
31
- if (!set) return;
32
- set.delete(handler as AnyHandler);
33
- if (set.size === 0) {
34
- delete this.handlers[event];
35
- }
36
- }
37
-
38
- emit<E extends AgentEventName>(
39
- event: E,
40
- payload: Parameters<AgentEventHandler<E>>[0],
41
- ): void {
42
- const set = this.handlers[event];
43
- if (!set) return;
44
- for (const handler of set) {
45
- handler(payload);
46
- }
47
- }
48
-
49
- clear(): void {
50
- this.handlers = {};
51
- }
52
- }
package/sdk/index.d.ts DELETED
@@ -1,29 +0,0 @@
1
- /**
2
- * High-level JS SDK for @pi-oxide/pi-host-web.
3
- *
4
- * Re-exports all raw types so consumers never need to import from ./raw.
5
- */
6
-
7
- export * from "../pi_host_web";
8
-
9
- export declare function ensureInit(): Promise<void>;
10
-
11
- export declare function toolResult(
12
- text: string,
13
- opts?: { terminate?: boolean; details?: object },
14
- ): {
15
- content: Array<{ type: "text"; text: string }>;
16
- terminate?: boolean;
17
- details?: object;
18
- };
19
-
20
- export declare class HostError extends Error {
21
- code: string;
22
- constructor(code: string, message: string);
23
- }
24
-
25
- export declare function unwrap<T>(result: {
26
- ok: boolean;
27
- data?: T;
28
- error?: { code: string; message: string };
29
- }): T;
package/sdk/index.js DELETED
@@ -1,111 +0,0 @@
1
- /**
2
- * High-level JS SDK for @pi-oxide/pi-host-web.
3
- *
4
- * Hides WASM loading and numeric handles.
5
- * Supports streaming LLM responses and full agent lifecycle.
6
- *
7
- * Import from the package root:
8
- * import { ensureInit, toolResult } from "@pi-oxide/pi-host-web";
9
- */
10
-
11
- import {
12
- default as init,
13
- initSync,
14
- createHostAgent,
15
- destroyHostAgent,
16
- startTurn,
17
- hostFeedLlmChunk,
18
- hostLlmDone,
19
- hostToolDone,
20
- hostAcceptCompaction,
21
- hostContinueTurn,
22
- getHostStatePersistData,
23
- restoreHostState,
24
- restoreHostStateFromJson,
25
- hostReadArtifact,
26
- hostSearchArtifacts,
27
- hostToolCancelled,
28
- hostAbort,
29
- getHostAgentPersistData,
30
- restoreHostAgent,
31
- createHostState,
32
- destroyHostState,
33
- hostSteer,
34
- hostReset,
35
- estimateTokens,
36
- estimateTokensForText,
37
- setLogLevel,
38
- } from "../pi_host_web.js";
39
-
40
- export {
41
- createHostState,
42
- destroyHostState,
43
- createHostAgent,
44
- destroyHostAgent,
45
- startTurn,
46
- hostFeedLlmChunk,
47
- hostLlmDone,
48
- hostToolDone,
49
- hostAcceptCompaction,
50
- hostContinueTurn,
51
- getHostStatePersistData,
52
- restoreHostState,
53
- restoreHostStateFromJson,
54
- hostReadArtifact,
55
- hostSearchArtifacts,
56
- hostToolCancelled,
57
- hostAbort,
58
- getHostAgentPersistData,
59
- restoreHostAgent,
60
- hostSteer,
61
- hostReset,
62
- estimateTokens,
63
- estimateTokensForText,
64
- setLogLevel,
65
- };
66
-
67
- let initialized = false;
68
-
69
- /** Ensure the WASM module is loaded. Safe to call multiple times. */
70
- export async function ensureInit() {
71
- if (initialized) return;
72
- if (typeof process !== "undefined" && process.versions?.node) {
73
- const { readFileSync } = await import("node:fs");
74
- const bytes = readFileSync(
75
- new URL("../pi_host_web_bg.wasm", import.meta.url),
76
- );
77
- initSync({ module: bytes });
78
- } else {
79
- await init();
80
- }
81
- initialized = true;
82
- }
83
-
84
- export class HostError extends Error {
85
- constructor(code, message) {
86
- super(message);
87
- this.code = code;
88
- this.name = "HostError";
89
- }
90
- }
91
-
92
- export function unwrap(result) {
93
- if (!result.ok) {
94
- throw new HostError(result.error.code, result.error.message);
95
- }
96
- return result.data;
97
- }
98
-
99
- /** Build a successful tool result payload. */
100
- export function toolResult(text, opts = {}) {
101
- const payload = {
102
- content: [{ type: "text", text }],
103
- };
104
- if (opts.terminate) {
105
- payload.terminate = true;
106
- }
107
- if (opts.details) {
108
- payload.details = opts.details;
109
- }
110
- return payload;
111
- }
package/sdk/index.ts DELETED
@@ -1,53 +0,0 @@
1
- // Public SDK exports — the only surface normal apps should import.
2
- // Internal engine details are hidden in sdk/internal/.
3
-
4
- export { ensureInit, HostError, unwrap, toolResult } from "./init.ts";
5
-
6
- // SDK exports
7
- export { Agent } from "./agent.ts";
8
- export { defineModel } from "./model.ts";
9
- export { anthropic } from "./internal/providers/anthropic.ts";
10
- export { openai, openaiCompatible } from "./internal/providers/openai.ts";
11
- export { defineTools, tool } from "./tools.ts";
12
- export { browserTools } from "./internal/tools/browser.ts";
13
- export { artifactTools } from "./internal/tools/artifact.ts";
14
- export { indexedDbStore, memoryStore, localStorageStore, httpStore } from "./stores.ts";
15
- export { useAgent } from "./react/index.ts";
16
-
17
- export type {
18
- AgentArtifact,
19
- AgentArtifactRef,
20
- ArtifactPolicy,
21
- ArtifactSearchQuery,
22
- ArtifactSearchResult,
23
- } from "./artifacts.ts";
24
-
25
- export type {
26
- AgentConfig,
27
- AgentInput,
28
- AgentRunOptions,
29
- AgentRunResult,
30
- AgentEventName,
31
- AgentEventHandler,
32
- AgentMessage,
33
- AgentContentBlock,
34
- AgentToolRun,
35
- AgentStatus,
36
- AgentModel,
37
- ModelRequest,
38
- ModelResponse,
39
- ModelEvent,
40
- AgentTools,
41
- AgentToolDefinition,
42
- AgentStore,
43
- AgentSnapshot,
44
- AgentContextPolicy,
45
- AgentSummarizer,
46
- AgentTelemetry,
47
- AgentError,
48
- Unsubscribe,
49
- TokenUsage,
50
- UseAgentResult,
51
- } from "./types.ts";
52
-
53
- export { createAgentError } from "./errors.ts";
package/sdk/init.ts DELETED
@@ -1,58 +0,0 @@
1
- // WASM initialization and low-level helpers.
2
- // Kept separate from index.ts to avoid circular imports with internal modules.
3
-
4
- import {
5
- default as init,
6
- initSync,
7
- } from "../pi_host_web.js";
8
-
9
- let initialized = false;
10
-
11
- /** Ensure the WASM module is loaded. Safe to call multiple times. */
12
- export async function ensureInit() {
13
- if (initialized) return;
14
- if (typeof process !== "undefined" && process.versions?.node) {
15
- const { readFileSync } = await import("node:fs");
16
- const bytes = readFileSync(
17
- new URL("../pi_host_web_bg.wasm", import.meta.url),
18
- );
19
- initSync({ module: bytes });
20
- } else {
21
- await init();
22
- }
23
- initialized = true;
24
- }
25
-
26
- export class HostError extends Error {
27
- code: string;
28
- constructor(code: string, message: string) {
29
- super(message);
30
- this.code = code;
31
- this.name = "HostError";
32
- }
33
- }
34
-
35
- export function unwrap(result: { ok: boolean; data?: unknown; error?: { code: string; message: string } }): unknown {
36
- if (!result.ok) {
37
- throw new HostError(result.error!.code, result.error!.message);
38
- }
39
- return result.data;
40
- }
41
-
42
- /** Build a successful tool result payload. */
43
- export function toolResult(text: string, opts: { terminate?: boolean; details?: object } = {}) {
44
- const payload: {
45
- content: Array<{ type: "text"; text: string }>;
46
- terminate?: boolean;
47
- details?: object;
48
- } = {
49
- content: [{ type: "text", text }],
50
- };
51
- if (opts.terminate) {
52
- payload.terminate = true;
53
- }
54
- if (opts.details) {
55
- payload.details = opts.details;
56
- }
57
- return payload;
58
- }