@hachej/boring-agent 0.1.71 → 0.1.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { u as AgentConfig, b as Agent } from '../harness-DN9KdrT7.js';
2
- export { a as AGENT_NOT_IMPLEMENTED_UNTIL_T1, c as AgentActor, d as AgentCoreHarness, e as AgentCoreHarnessFactory, f as AgentCorePromptInput, g as AgentCoreSessionAdapter, h as AgentCoreSessionSnapshot, i as AgentEvent, k as AgentMessageContent, l as AgentMessagePart, m as AgentNotImplementedError, n as AgentReadiness, o as AgentReadinessStatus, p as AgentResolveInputResponse, q as AgentRuntimeAdapter, r as AgentSendInput, s as AgentStartReceipt, t as AgentStreamOptions } from '../harness-DN9KdrT7.js';
3
- import '../piChatEvent-B6Lg9ft-.js';
1
+ import { u as AgentConfig, b as Agent } from '../harness-Dwxh6USt.js';
2
+ export { a as AGENT_NOT_IMPLEMENTED_UNTIL_T1, c as AgentActor, d as AgentCoreHarness, e as AgentCoreHarnessFactory, f as AgentCorePromptInput, g as AgentCoreSessionAdapter, h as AgentCoreSessionSnapshot, i as AgentEvent, k as AgentMessageContent, l as AgentMessagePart, m as AgentNotImplementedError, n as AgentReadiness, o as AgentReadinessStatus, p as AgentResolveInputResponse, q as AgentRuntimeAdapter, r as AgentSendInput, s as AgentStartReceipt, t as AgentStreamOptions } from '../harness-Dwxh6USt.js';
3
+ import '../session-DKMQNtNG.js';
4
4
  import 'zod';
5
5
  import '@mariozechner/pi-coding-agent';
6
6
 
@@ -1,8 +1,8 @@
1
1
  import * as react from 'react';
2
2
  import { ComponentProps, HTMLAttributes, FormEvent, ReactNode, ComponentType } from 'react';
3
3
  import { FileUIPart, ChatStatus, UIMessage } from 'ai';
4
- import { T as ToolUiMetadata, B as BoringChatPart, e as BoringChatMessage, k as PiChatStatus, Q as QueuedUserMessage, C as ChatError, P as PiChatEvent, n as SessionSummary } from '../piChatEvent-B6Lg9ft-.js';
5
- import { P as PromptPayload, c as PromptReceipt, F as FollowUpPayload, a as FollowUpReceipt, Q as QueueClearPayload, d as QueueClearReceipt, I as InterruptPayload, C as CommandReceipt, S as StopPayload, e as StopReceipt } from '../piChatCommand-C5ZM-AMG.js';
4
+ import { T as ToolUiMetadata, B as BoringChatPart, e as BoringChatMessage, k as PiChatStatus, Q as QueuedUserMessage, C as ChatError, P as PiChatEvent, n as SessionSummary } from '../session-DKMQNtNG.js';
5
+ import { P as PromptPayload, c as PromptReceipt, F as FollowUpPayload, a as FollowUpReceipt, Q as QueueClearPayload, d as QueueClearReceipt, I as InterruptPayload, C as CommandReceipt, S as StopPayload, e as StopReceipt } from '../piChatCommand-CSepU1NX.js';
6
6
  import { InputGroupAddon, InputGroupButton, InputGroupTextarea, Button, Collapsible, CollapsibleContent, CollapsibleTrigger } from '@hachej/boring-ui-kit';
7
7
  import { Streamdown } from 'streamdown';
8
8
  import { StickToBottom } from 'use-stick-to-bottom';
@@ -1,4 +1,4 @@
1
- import { S as SessionCtx, P as PiChatEvent, a as SessionStore } from './piChatEvent-B6Lg9ft-.js';
1
+ import { S as SessionCtx, P as PiChatEvent, a as SessionStore } from './session-DKMQNtNG.js';
2
2
  import { AgentSessionEvent, PromptOptions } from '@mariozechner/pi-coding-agent';
3
3
 
4
4
  interface TelemetrySink {
@@ -1,5 +1,5 @@
1
1
  import { C as ChatSubmitPayload } from './chatSubmitPayload-DwOHyiqR.js';
2
- import { Q as QueuedUserMessage } from './piChatEvent-B6Lg9ft-.js';
2
+ import { Q as QueuedUserMessage } from './session-DKMQNtNG.js';
3
3
 
4
4
  type PromptPayload = ChatSubmitPayload;
5
5
  interface FollowUpPayload {
@@ -1,10 +1,10 @@
1
- import { j as WorkspaceRuntimeContext, S as Sandbox, f as SandboxHandleStore, e as SandboxHandleRecord, W as Workspace, F as FileSearch, g as Stat, E as Entry, b as ExecResult, k as WorkspaceChangeEvent, a as ExecOptions, P as PluginRestartWarning } from '../agentPluginEvents-ChUzG2Lh.js';
1
+ import { j as WorkspaceRuntimeContext, S as Sandbox, f as SandboxHandleStore, e as SandboxHandleRecord, W as Workspace, F as FileSearch, g as Stat, E as Entry, b as ExecResult, k as WorkspaceChangeEvent, a as ExecOptions, P as PluginRestartWarning } from '../agentPluginEvents-CqLTEdG2.js';
2
2
  import { Sandbox as Sandbox$1 } from '@vercel/sandbox';
3
- import { v as TelemetrySink, C as ToolReadinessRequirement, i as AgentEvent, b as Agent, c as AgentActor, A as AgentTool, D as AgentHarnessFactory } from '../harness-DN9KdrT7.js';
4
- export { u as AgentConfig, E as AgentHarnessFactoryInput } from '../harness-DN9KdrT7.js';
3
+ import { v as TelemetrySink, C as ToolReadinessRequirement, i as AgentEvent, b as Agent, c as AgentActor, A as AgentTool, D as AgentHarnessFactory } from '../harness-Dwxh6USt.js';
4
+ export { u as AgentConfig, E as AgentHarnessFactoryInput } from '../harness-Dwxh6USt.js';
5
5
  import { FastifyInstance, FastifyRequest, FastifyPluginAsync } from 'fastify';
6
6
  export { createAgent } from '../core/index.js';
7
- import { S as SessionCtx, f as ErrorCode } from '../piChatEvent-B6Lg9ft-.js';
7
+ import { S as SessionCtx, f as ErrorCode } from '../session-DKMQNtNG.js';
8
8
  import { IncomingMessage, ServerResponse } from 'node:http';
9
9
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
10
10
  import { PackageSource, ExtensionFactory, SettingsManager } from '@mariozechner/pi-coding-agent';
@@ -456,6 +456,7 @@ interface RuntimeFilesystemBindingOperations {
456
456
  path: string;
457
457
  }): Promise<{
458
458
  content: string;
459
+ mtimeMs?: number;
459
460
  metadata?: unknown;
460
461
  }>;
461
462
  list(descriptor: {
@@ -2655,11 +2655,16 @@ function classifyError(err, reply, subject) {
2655
2655
  const statusCode = err?.statusCode;
2656
2656
  const stableCode = err?.code;
2657
2657
  if (typeof statusCode === "number" && statusCode >= 400 && statusCode < 600) {
2658
+ const details = err?.details;
2659
+ const conflictDetails = stableCode === ERROR_CODE_CONFLICT && details && typeof details === "object" && !Array.isArray(details) ? details : null;
2658
2660
  return reply.code(statusCode).send({
2659
2661
  error: {
2660
2662
  code: typeof stableCode === "string" ? stableCode : ERROR_CODE_INTERNAL,
2661
2663
  message,
2662
- details: err?.details
2664
+ ...conflictDetails ? {
2665
+ currentMtimeMs: conflictDetails.currentMtimeMs,
2666
+ expectedMtimeMs: conflictDetails.expectedMtimeMs
2667
+ } : { details }
2663
2668
  }
2664
2669
  });
2665
2670
  }
@@ -2888,7 +2893,7 @@ function fileRoutes(app, opts, done) {
2888
2893
  const binding = await resolveFilesystemBinding(request, filesystem);
2889
2894
  if (!binding) return sendNotFoundOrDenied(reply);
2890
2895
  const result = await binding.operations.read({ filesystem, path: path4 });
2891
- return { content: result.content, access: binding.access };
2896
+ return { content: result.content, mtimeMs: result.mtimeMs, access: binding.access };
2892
2897
  } catch {
2893
2898
  return sendNotFoundOrDenied(reply);
2894
2899
  }
@@ -7383,7 +7388,7 @@ function withFilesystemParameter(parameters, filesystemIds2, dynamicBindings = f
7383
7388
  ...properties,
7384
7389
  filesystem: {
7385
7390
  type: "string",
7386
- description: filesystemIds2.length > 0 ? "Logical filesystem to use. Omit or use user for workspace files; use an advertised named filesystem for bound readonly context." : "Logical filesystem to use. Omit or use user for workspace files.",
7391
+ description: filesystemIds2.length > 0 ? "Logical filesystem to use. Omit or use user for workspace files; use an advertised named filesystem for bound context." : "Logical filesystem to use. Omit or use user for workspace files.",
7387
7392
  ...dynamicBindings ? {} : { enum: ["user", ...filesystemIds2] }
7388
7393
  }
7389
7394
  }
@@ -7408,12 +7413,9 @@ function assertNotFilesystemPathSpoof(path4, filesystemIds2) {
7408
7413
  }
7409
7414
  }
7410
7415
  function filesystemBinding(bindings, filesystem) {
7411
- return bindings.find((binding) => binding.filesystem === filesystem);
7412
- }
7413
- function boundOperations(bindings, filesystem) {
7414
- const binding = filesystemBinding(bindings, filesystem);
7416
+ const binding = bindings.find((entry) => entry.filesystem === filesystem);
7415
7417
  if (!binding) throw new Error(`No filesystem binding is available for ${filesystem}`);
7416
- return binding.operations;
7418
+ return binding;
7417
7419
  }
7418
7420
  function formatBoundRead(content) {
7419
7421
  return { content: [{ type: "text", text: content }] };
@@ -7427,10 +7429,32 @@ function formatBoundFind(paths) {
7427
7429
  function formatBoundGrep(matches) {
7428
7430
  return { content: [{ type: "text", text: matches.map((match) => `${match.path}:${match.line}:${match.text}`).join("\n") }] };
7429
7431
  }
7432
+ function applyExactEdits(original, edits) {
7433
+ if (edits.length === 0) throw new Error("edit requires at least one edit");
7434
+ const ranges = edits.map((edit) => {
7435
+ if (!edit.oldText) throw new Error("edit oldText must not be empty");
7436
+ const start = original.indexOf(edit.oldText);
7437
+ const duplicate = start >= 0 ? original.indexOf(edit.oldText, start + 1) : -1;
7438
+ if (start < 0 || duplicate >= 0) {
7439
+ const occurrences = start < 0 ? 0 : 2;
7440
+ throw new Error(`edit requires oldText to match exactly once; found ${occurrences}`);
7441
+ }
7442
+ return { ...edit, start, end: start + edit.oldText.length };
7443
+ }).sort((left, right) => left.start - right.start);
7444
+ for (let index = 1; index < ranges.length; index += 1) {
7445
+ if (ranges[index].start < ranges[index - 1].end) throw new Error("edit ranges must not overlap");
7446
+ }
7447
+ let output = original;
7448
+ for (const range of ranges.reverse()) {
7449
+ output = `${output.slice(0, range.start)}${range.newText}${output.slice(range.end)}`;
7450
+ }
7451
+ return output;
7452
+ }
7430
7453
  async function executeBoundFilesystemTool(toolName, filesystem, params, bindings) {
7431
7454
  const path4 = boundFilesystemPath(params);
7432
- assertNotFilesystemPathSpoof(path4, bindings.map((binding) => binding.filesystem));
7433
- const operations = boundOperations(bindings, filesystem);
7455
+ assertNotFilesystemPathSpoof(path4, bindings.map((binding2) => binding2.filesystem));
7456
+ const binding = filesystemBinding(bindings, filesystem);
7457
+ const operations = binding.operations;
7434
7458
  if (toolName === "read") {
7435
7459
  const result = await operations.read({ filesystem, path: path4 });
7436
7460
  return { ...formatBoundRead(result.content), details: { metadata: result.metadata } };
@@ -7451,8 +7475,37 @@ async function executeBoundFilesystemTool(toolName, filesystem, params, bindings
7451
7475
  const result = await operations.grep({ filesystem, path: path4 }, pattern, { limit });
7452
7476
  return { ...formatBoundGrep(result.matches), details: { metadata: result.metadata } };
7453
7477
  }
7454
- if (toolName === "write" || toolName === "edit") {
7455
- operations.rejectMutation(toolName, { filesystem, path: path4 });
7478
+ if (toolName === "write") {
7479
+ if (binding.access !== "readwrite" || !operations.write) operations.rejectMutation(toolName, { filesystem, path: path4 });
7480
+ const write = operations.write;
7481
+ if (!write) throw new Error(`Tool ${toolName} does not support filesystem ${filesystem}`);
7482
+ const content = typeof params.content === "string" ? params.content : "";
7483
+ const parent = path4.includes("/") ? path4.slice(0, path4.lastIndexOf("/")) || "/" : null;
7484
+ if (parent && operations.mkdir) await operations.mkdir({ filesystem, path: parent, recursive: true });
7485
+ const result = await write({ filesystem, path: path4, content });
7486
+ return { content: [{ type: "text", text: `Wrote ${path4}` }], details: { metadata: result.metadata, mtimeMs: result.mtimeMs } };
7487
+ }
7488
+ if (toolName === "edit") {
7489
+ if (binding.access !== "readwrite" || !operations.write) operations.rejectMutation(toolName, { filesystem, path: path4 });
7490
+ const write = operations.write;
7491
+ if (!write) throw new Error(`Tool ${toolName} does not support filesystem ${filesystem}`);
7492
+ const edits = Array.isArray(params.edits) ? params.edits.map((edit) => {
7493
+ if (!edit || typeof edit !== "object") throw new Error("edit entries must be objects");
7494
+ const record = edit;
7495
+ if (typeof record.oldText !== "string" || typeof record.newText !== "string") {
7496
+ throw new Error("edit entries require string oldText and newText");
7497
+ }
7498
+ return { oldText: record.oldText, newText: record.newText };
7499
+ }) : [];
7500
+ const current = await operations.read({ filesystem, path: path4 });
7501
+ const content = applyExactEdits(current.content, edits);
7502
+ const result = await write({
7503
+ filesystem,
7504
+ path: path4,
7505
+ content,
7506
+ ...current.mtimeMs !== void 0 ? { expectedMtimeMs: current.mtimeMs } : {}
7507
+ });
7508
+ return { content: [{ type: "text", text: `Edited ${path4}` }], details: { metadata: result.metadata, mtimeMs: result.mtimeMs } };
7456
7509
  }
7457
7510
  throw new Error(`Tool ${toolName} does not support filesystem ${filesystem}`);
7458
7511
  }
@@ -7461,8 +7514,8 @@ function withBoundFilesystemPromptGuidance(promptSnippet, filesystemIds2, dynami
7461
7514
  const target = filesystemIds2.length > 0 ? ` (${filesystemIds2.join(", ")})` : "";
7462
7515
  const guidance = [
7463
7516
  "Named filesystem bindings: file tools default to the user workspace when filesystem is omitted.",
7464
- `Use the filesystem parameter explicitly for bound readonly context${target}, and start browsing at / unless told otherwise.`,
7465
- "Readonly filesystem bindings reject writes; do not use path prefixes like filesystem:/x to switch filesystem."
7517
+ `Use the filesystem parameter explicitly for named context${target}, and start browsing at / unless told otherwise.`,
7518
+ "A binding may be readonly or readwrite; do not use path prefixes like filesystem:/x to switch filesystem."
7466
7519
  ].join("\n");
7467
7520
  return [promptSnippet, guidance].filter(Boolean).join("\n");
7468
7521
  }
@@ -1,12 +1,12 @@
1
- import { A as AgentTool } from '../harness-DN9KdrT7.js';
2
- export { a as AGENT_NOT_IMPLEMENTED_UNTIL_T1, b as Agent, c as AgentActor, d as AgentCoreHarness, e as AgentCoreHarnessFactory, f as AgentCorePromptInput, g as AgentCoreSessionAdapter, h as AgentCoreSessionSnapshot, i as AgentEvent, j as AgentHarness, k as AgentMessageContent, l as AgentMessagePart, m as AgentNotImplementedError, n as AgentReadiness, o as AgentReadinessStatus, p as AgentResolveInputResponse, q as AgentRuntimeAdapter, r as AgentSendInput, s as AgentStartReceipt, t as AgentStreamOptions, u as CoreAgentConfig, J as JSONSchema, M as MessageAttachment, R as RunContext, S as SendMessageInput, T as TelemetryEvent, v as TelemetrySink, w as ToolExecContext, x as ToolResult, y as noopTelemetry, z as safeCapture, B as sessionStreamPath } from '../harness-DN9KdrT7.js';
3
- import { W as Workspace, S as Sandbox, F as FileSearch } from '../agentPluginEvents-ChUzG2Lh.js';
4
- export { C as CommandNotifyPayload, E as Entry, a as ExecOptions, b as ExecResult, I as IsolatedCodeInput, c as IsolatedCodeOutput, d as SandboxCapability, e as SandboxHandleRecord, f as SandboxHandleStore, g as Stat, h as WORKSPACE_AGENT_PLUGINS_RELOADED_EVENT, i as WORKSPACE_COMMAND_NOTIFY_EVENT, j as WorkspaceRuntimeContext } from '../agentPluginEvents-ChUzG2Lh.js';
5
- import { B as BoringChatPart, T as ToolUiMetadata } from '../piChatEvent-B6Lg9ft-.js';
6
- export { A as ApiErrorPayload, b as ApiErrorPayloadSchema, c as ApiErrorResponse, d as ApiErrorResponseSchema, e as BoringChatMessage, C as ChatError, E as ERROR_CODES, f as ErrorCode, g as ErrorLogFields, h as ErrorLogFieldsSchema, P as PiChatEvent, i as PiChatHeartbeatFrame, j as PiChatSnapshot, k as PiChatStatus, l as PiChatStreamFrame, Q as QueuedUserMessage, S as SessionCtx, m as SessionDetail, a as SessionStore, n as SessionSummary, o as extractToolUiMetadata, p as isToolUiMetadata } from '../piChatEvent-B6Lg9ft-.js';
1
+ import { A as AgentTool } from '../harness-Dwxh6USt.js';
2
+ export { a as AGENT_NOT_IMPLEMENTED_UNTIL_T1, b as Agent, c as AgentActor, d as AgentCoreHarness, e as AgentCoreHarnessFactory, f as AgentCorePromptInput, g as AgentCoreSessionAdapter, h as AgentCoreSessionSnapshot, i as AgentEvent, j as AgentHarness, k as AgentMessageContent, l as AgentMessagePart, m as AgentNotImplementedError, n as AgentReadiness, o as AgentReadinessStatus, p as AgentResolveInputResponse, q as AgentRuntimeAdapter, r as AgentSendInput, s as AgentStartReceipt, t as AgentStreamOptions, u as CoreAgentConfig, J as JSONSchema, M as MessageAttachment, R as RunContext, S as SendMessageInput, T as TelemetryEvent, v as TelemetrySink, w as ToolExecContext, x as ToolResult, y as noopTelemetry, z as safeCapture, B as sessionStreamPath } from '../harness-Dwxh6USt.js';
3
+ import { W as Workspace, S as Sandbox, F as FileSearch } from '../agentPluginEvents-CqLTEdG2.js';
4
+ export { C as CommandNotifyPayload, E as Entry, a as ExecOptions, b as ExecResult, I as IsolatedCodeInput, c as IsolatedCodeOutput, d as SandboxCapability, e as SandboxHandleRecord, f as SandboxHandleStore, g as Stat, h as WORKSPACE_AGENT_PLUGINS_RELOADED_EVENT, i as WORKSPACE_COMMAND_NOTIFY_EVENT, j as WorkspaceRuntimeContext } from '../agentPluginEvents-CqLTEdG2.js';
5
+ import { B as BoringChatPart, T as ToolUiMetadata } from '../session-DKMQNtNG.js';
6
+ export { A as ApiErrorPayload, b as ApiErrorPayloadSchema, c as ApiErrorResponse, d as ApiErrorResponseSchema, e as BoringChatMessage, C as ChatError, E as ERROR_CODES, f as ErrorCode, g as ErrorLogFields, h as ErrorLogFieldsSchema, P as PiChatEvent, i as PiChatHeartbeatFrame, j as PiChatSnapshot, k as PiChatStatus, l as PiChatStreamFrame, Q as QueuedUserMessage, S as SessionCtx, m as SessionDetail, a as SessionStore, n as SessionSummary, o as extractToolUiMetadata, p as isToolUiMetadata } from '../session-DKMQNtNG.js';
7
7
  import { z } from 'zod';
8
8
  export { a as ChatAttachmentPayload, b as ChatModelSelection, C as ChatSubmitPayload, T as ThinkingLevel } from '../chatSubmitPayload-DwOHyiqR.js';
9
- export { C as CommandReceipt, F as FollowUpPayload, a as FollowUpReceipt, I as InterruptPayload, b as InterruptReceipt, P as PromptPayload, c as PromptReceipt, Q as QueueClearPayload, d as QueueClearReceipt, S as StopPayload, e as StopReceipt } from '../piChatCommand-C5ZM-AMG.js';
9
+ export { C as CommandReceipt, F as FollowUpPayload, a as FollowUpReceipt, I as InterruptPayload, b as InterruptReceipt, P as PromptPayload, c as PromptReceipt, Q as QueueClearPayload, d as QueueClearReceipt, S as StopPayload, e as StopReceipt } from '../piChatCommand-CSepU1NX.js';
10
10
  import '@mariozechner/pi-coding-agent';
11
11
 
12
12
  declare const ToolUiMetadataSchema: z.ZodObject<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hachej/boring-agent",
3
- "version": "0.1.71",
3
+ "version": "0.1.72",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Pane-embeddable coding agent. Ships direct/local/vercel-sandbox execution modes behind one interface.",
@@ -63,7 +63,7 @@
63
63
  "@tanstack/react-query": "^5.101.1",
64
64
  "@vercel/blob": "^2.5.0",
65
65
  "@vercel/sandbox": "2.3.0",
66
- "ai": "^7.0.2",
66
+ "ai": "^7.0.9",
67
67
  "chokidar": "^5.0.0",
68
68
  "class-variance-authority": "^0.7.1",
69
69
  "clsx": "^2.1.1",
@@ -79,7 +79,7 @@
79
79
  "use-stick-to-bottom": "^1.1.6",
80
80
  "yaml": "^2.9.0",
81
81
  "zod": "^3.25.76",
82
- "@hachej/boring-ui-kit": "0.1.71"
82
+ "@hachej/boring-ui-kit": "0.1.72"
83
83
  },
84
84
  "devDependencies": {
85
85
  "@antithesishq/bombadil": "0.6.1",
@@ -285,10 +285,6 @@ interface IsolatedCodeOutput {
285
285
  exitCode: number;
286
286
  }
287
287
 
288
- interface FileSearch {
289
- search(glob: string, limit?: number): Promise<string[]>;
290
- }
291
-
292
288
  interface SandboxHandleRecord {
293
289
  workspaceId: string;
294
290
  sandboxId: string;
@@ -303,6 +299,10 @@ interface SandboxHandleStore {
303
299
  list(): Promise<SandboxHandleRecord[]>;
304
300
  }
305
301
 
302
+ interface FileSearch {
303
+ search(glob: string, limit?: number): Promise<string[]>;
304
+ }
305
+
306
306
  /**
307
307
  * Browser CustomEvent name dispatched on `window` after the workspace's
308
308
  * agent-plugin hot reload subscriber commits a registry change (load,
@@ -1,31 +1,5 @@
1
1
  import { z } from 'zod';
2
2
 
3
- interface SessionStore {
4
- list(ctx: SessionCtx, options?: SessionListOptions): Promise<SessionSummary[]>;
5
- create(ctx: SessionCtx, init?: {
6
- title?: string;
7
- }): Promise<SessionSummary>;
8
- load(ctx: SessionCtx, sessionId: string): Promise<SessionDetail>;
9
- delete(ctx: SessionCtx, sessionId: string): Promise<void>;
10
- }
11
- interface SessionCtx {
12
- workspaceId?: string;
13
- userId?: string;
14
- }
15
- interface SessionListOptions {
16
- limit?: number;
17
- offset?: number;
18
- includeId?: string;
19
- }
20
- interface SessionSummary {
21
- id: string;
22
- title: string;
23
- createdAt: string;
24
- updatedAt: string;
25
- turnCount: number;
26
- }
27
- type SessionDetail = SessionSummary;
28
-
29
3
  interface ToolUiMetadata {
30
4
  /** Renderer key registered by the app shell, e.g. `pi-subagent`. */
31
5
  rendererId?: string;
@@ -294,4 +268,30 @@ interface PiChatHeartbeatFrame {
294
268
  }
295
269
  type PiChatStreamFrame = PiChatEvent | PiChatHeartbeatFrame;
296
270
 
271
+ interface SessionStore {
272
+ list(ctx: SessionCtx, options?: SessionListOptions): Promise<SessionSummary[]>;
273
+ create(ctx: SessionCtx, init?: {
274
+ title?: string;
275
+ }): Promise<SessionSummary>;
276
+ load(ctx: SessionCtx, sessionId: string): Promise<SessionDetail>;
277
+ delete(ctx: SessionCtx, sessionId: string): Promise<void>;
278
+ }
279
+ interface SessionCtx {
280
+ workspaceId?: string;
281
+ userId?: string;
282
+ }
283
+ interface SessionListOptions {
284
+ limit?: number;
285
+ offset?: number;
286
+ includeId?: string;
287
+ }
288
+ interface SessionSummary {
289
+ id: string;
290
+ title: string;
291
+ createdAt: string;
292
+ updatedAt: string;
293
+ turnCount: number;
294
+ }
295
+ type SessionDetail = SessionSummary;
296
+
297
297
  export { type ApiErrorPayload as A, type BoringChatPart as B, type ChatError as C, ERROR_CODES as E, type PiChatEvent as P, type QueuedUserMessage as Q, type SessionCtx as S, type ToolUiMetadata as T, type SessionStore as a, ApiErrorPayloadSchema as b, type ApiErrorResponse as c, ApiErrorResponseSchema as d, type BoringChatMessage as e, ErrorCode as f, type ErrorLogFields as g, ErrorLogFieldsSchema as h, type PiChatHeartbeatFrame as i, type PiChatSnapshot as j, type PiChatStatus as k, type PiChatStreamFrame as l, type SessionDetail as m, type SessionSummary as n, extractToolUiMetadata as o, isToolUiMetadata as p };