@steerable/agent-shell 0.6.21 → 0.6.22

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 (48) hide show
  1. package/README.md +34 -0
  2. package/dist/auth/index.d.ts +38 -0
  3. package/dist/auth/index.js +20 -0
  4. package/dist/host/pack-assembly.d.ts +7 -7
  5. package/dist/host/runtime.d.ts +6 -2
  6. package/dist/host/runtime.js +54 -14
  7. package/dist/insights/flush.d.ts +5 -4
  8. package/dist/insights/flush.js +14 -15
  9. package/dist/insights/record.d.ts +6 -5
  10. package/dist/insights/record.js +9 -10
  11. package/dist/llm/index.d.ts +6 -2
  12. package/dist/llm/index.js +19 -9
  13. package/dist/local-backend/prompt-builder.d.ts +10 -4
  14. package/dist/local-backend/prompt-builder.js +13 -12
  15. package/dist/local-backend/router.d.ts +18 -4
  16. package/dist/local-backend/router.js +133 -98
  17. package/dist/local-backend/skills/00-identity/SKILL.md +1 -1
  18. package/dist/local-backend/task-service.d.ts +14 -13
  19. package/dist/local-backend/task-service.js +32 -29
  20. package/dist/local-backend/worktree-service.d.ts +1 -1
  21. package/dist/local-backend/worktree-service.js +6 -6
  22. package/dist/main.js +43 -26
  23. package/dist/server/http-server.d.ts +13 -1
  24. package/dist/server/http-server.js +37 -8
  25. package/dist/server/index.js +4 -90
  26. package/dist/server/start.d.ts +26 -0
  27. package/dist/server/start.js +111 -0
  28. package/dist/sidecar/boot.d.ts +3 -1
  29. package/dist/sidecar/boot.js +6 -7
  30. package/dist/sidecar/reverse-spawn.js +12 -4
  31. package/dist/sidecar/reverse-tools.d.ts +1 -1
  32. package/dist/sidecar/reverse-tools.js +1 -1
  33. package/dist/sidecar/storage-path.js +2 -3
  34. package/dist/storage/driver.d.ts +57 -0
  35. package/dist/storage/driver.js +104 -0
  36. package/dist/storage/index.d.ts +75 -68
  37. package/dist/storage/index.js +506 -301
  38. package/dist/storage/pack-migrations.d.ts +2 -4
  39. package/dist/storage/pack-migrations.js +2 -4
  40. package/dist/storage/scoped-store.d.ts +125 -0
  41. package/dist/storage/scoped-store.js +1 -0
  42. package/dist/storage/sqlite-driver.d.ts +16 -0
  43. package/dist/storage/sqlite-driver.js +135 -0
  44. package/dist/storage/write-lease-error.d.ts +11 -0
  45. package/dist/storage/write-lease-error.js +18 -0
  46. package/package.json +14 -5
  47. package/dist/storage/local-store-singleton.d.ts +0 -28
  48. package/dist/storage/local-store-singleton.js +0 -38
@@ -1,9 +1,11 @@
1
- import Database from 'better-sqlite3';
1
+ import type Database from 'better-sqlite3';
2
2
  import { type LlmSettings } from './llm-settings.js';
3
3
  import { type TelemetrySettings } from './telemetry-settings.js';
4
4
  import { type WebSearchSettings } from './web-search-settings.js';
5
5
  import { type InsightKind, type InsightsProfile, type InsightsSettings, type InsightsSettingsPatch } from './insights-settings.js';
6
6
  import { type UsageSummary } from './usage-summary.js';
7
+ import type { TenantScope } from './driver.js';
8
+ import type { ScopedStore } from './scoped-store.js';
7
9
  export type { UsageModelBucket, UsageSummary } from './usage-summary.js';
8
10
  export interface ChatSessionRecord {
9
11
  id: string;
@@ -122,15 +124,15 @@ export interface InsightOutboxRow {
122
124
  uploadError: string | null;
123
125
  }
124
126
  declare const INSIGHTS_EXPORT_SCHEMA = "deeppath-agent-insights/v1";
125
- export declare class LocalStore {
127
+ export declare class SqliteScopedStore implements ScopedStore {
126
128
  private readonly db;
127
- private readonly writeLease;
128
- constructor();
129
- /**
130
- * 场景包存储扩展点:把同一个 SQLite 连接借给包内存储类(各包的
131
- * <Pack>Store)。包只读写自己 migrations 声明的包前缀表;shell 表结构对包不透明。
132
- */
133
- getPackDb(): Database.Database;
129
+ readonly scope: TenantScope;
130
+ constructor(db: Database.Database, scope: TenantScope);
131
+ /** Initializes schema, cleanup, migrations, and seeds for this scope. */
132
+ initialize(): Promise<void>;
133
+ private migrateScopedSchema;
134
+ private copyLegacyScopeRows;
135
+ private tableColumns;
134
136
  /**
135
137
  * One-time cleanup for rows that became orphaned while `foreign_keys` was
136
138
  * off in earlier versions of the app (deleteChat() previously left
@@ -138,9 +140,8 @@ export declare class LocalStore {
138
140
  */
139
141
  private cleanupOrphanedRows;
140
142
  private migrate;
141
- private readonly appliedPackMigrations;
142
143
  /**
143
- * 应用尚未应用的已注册包迁移(幂等,按包 id 去重)。
144
+ * Applies registered migrations once per driver-persisted pack generation.
144
145
  */
145
146
  applyPackMigrations(): void;
146
147
  /**
@@ -164,11 +165,11 @@ export declare class LocalStore {
164
165
  * integer range, falling back to `fallback` for non-finite input.
165
166
  */
166
167
  private static clampInt;
167
- listChats(page?: number, limit?: number): {
168
+ listChats(page?: number, limit?: number): Promise<{
168
169
  chats: ChatSessionRecord[];
169
170
  total: number;
170
- };
171
- createChat(title?: string, agentId?: string | null, projectId?: string | null): ChatSessionRecord;
171
+ }>;
172
+ createChat(title?: string, agentId?: string | null, projectId?: string | null): Promise<ChatSessionRecord>;
172
173
  /**
173
174
  * 用调用方给定的 id 建会话(**幂等**:已存在则原样返回,不覆盖)。
174
175
  *
@@ -178,32 +179,32 @@ export declare class LocalStore {
178
179
  * 按 URL 里的 id 现场补建,才不会把一次本来能跑的任务打断在
179
180
  * `chat not found`。
180
181
  */
181
- createChatWithId(chatId: string, title?: string, agentId?: string | null, projectId?: string | null): ChatSessionRecord;
182
+ createChatWithId(chatId: string, title?: string, agentId?: string | null, projectId?: string | null): Promise<ChatSessionRecord>;
182
183
  /** 删除项目时调用:把该项目下所有会话降级为无项目对话(不删会话)。 */
183
- clearProjectAssignment(projectId: string): number;
184
- getChat(chatId: string): ChatSessionRecord | null;
185
- updateChat(chatId: string, updates: Partial<Pick<ChatSessionRecord, 'title' | 'systemPrompt' | 'pinnedRefs' | 'isPinned' | 'projectId'>>): ChatSessionRecord | null;
186
- deleteChat(chatId: string): boolean;
187
- chatHasMessages(chatId: string): boolean;
184
+ clearProjectAssignment(projectId: string): Promise<number>;
185
+ getChat(chatId: string): Promise<ChatSessionRecord | null>;
186
+ updateChat(chatId: string, updates: Partial<Pick<ChatSessionRecord, 'title' | 'systemPrompt' | 'pinnedRefs' | 'isPinned' | 'projectId'>>): Promise<ChatSessionRecord | null>;
187
+ deleteChat(chatId: string): Promise<boolean>;
188
+ chatHasMessages(chatId: string): Promise<boolean>;
188
189
  /**
189
190
  * Drop a chat that never received a message. Used when the user leaves a
190
191
  * "新对话" composer without sending — empty sessions must not stay in the
191
192
  * sidebar. Missing or already-populated chats are a no-op (`false`).
192
193
  */
193
- deleteChatIfEmpty(chatId: string): boolean;
194
+ deleteChatIfEmpty(chatId: string): Promise<boolean>;
194
195
  /**
195
196
  * Delete every session with zero messages, optionally keeping `exceptChatId`
196
197
  * (the open composer). Returns the removed ids.
197
198
  */
198
- deleteEmptyChats(exceptChatId?: string | null): string[];
199
+ deleteEmptyChats(exceptChatId?: string | null): Promise<string[]>;
199
200
  /**
200
201
  * W5-2: the chat's ACTIVE durable-record id on the sidecar. Regenerate
201
202
  * forks the record (non-destructive — the old tail stays discoverable as
202
203
  * a branch), so a chat's live record moves from `chatId` to its branch;
203
204
  * null means the chatId itself.
204
205
  */
205
- getChatRecordId(chatId: string): string | null;
206
- setChatRecordId(chatId: string, recordId: string): void;
206
+ getChatRecordId(chatId: string): Promise<string | null>;
207
+ setChatRecordId(chatId: string, recordId: string): Promise<void>;
207
208
  /**
208
209
  * W7-1: durable "a turn is in flight" marker, written BEFORE the stream
209
210
  * starts and cleared only after the terminal assistant message persists
@@ -216,17 +217,17 @@ export declare class LocalStore {
216
217
  * stale marker the detector dismisses once it sees the trailing
217
218
  * assistant message.
218
219
  */
219
- setTurnActive(chatId: string): void;
220
- clearTurnActive(chatId: string): void;
221
- getTurnActive(chatId: string): {
220
+ setTurnActive(chatId: string): Promise<void>;
221
+ clearTurnActive(chatId: string): Promise<void>;
222
+ getTurnActive(chatId: string): Promise<{
222
223
  startedAt: string;
223
- } | null;
224
+ } | null>;
224
225
  /**
225
226
  * Newest first under {@link MESSAGE_ORDER_DESC}, capped at `limit`; callers
226
227
  * that want transcript order reverse it.
227
228
  */
228
- listMessages(chatId: string, limit?: number): ChatMessageRecord[];
229
- getMessage(chatId: string, messageId: string): ChatMessageRecord | null;
229
+ listMessages(chatId: string, limit?: number): Promise<ChatMessageRecord[]>;
230
+ getMessage(chatId: string, messageId: string): Promise<ChatMessageRecord | null>;
230
231
  /**
231
232
  * Deletes `messageId` and every message after it in the same chat. Used by
232
233
  * regenerate: truncate from the assistant reply being regenerated onward, so
@@ -237,14 +238,14 @@ export declare class LocalStore {
237
238
  * "After" is {@link MESSAGE_CUT_FROM_ID}, the same key `listMessages` orders
238
239
  * by, so the cut matches what the user sees below the regenerated reply.
239
240
  */
240
- deleteMessagesFrom(chatId: string, messageId: string): number;
241
- addMessage(chatId: string, role: ChatMessageRecord['role'], content: string, messageMetadata?: string | null): ChatMessageRecord;
241
+ deleteMessagesFrom(chatId: string, messageId: string): Promise<number>;
242
+ addMessage(chatId: string, role: ChatMessageRecord['role'], content: string, messageMetadata?: string | null): Promise<ChatMessageRecord>;
242
243
  /**
243
244
  * 浅合并助手消息的 JSON metadata(例如回合结束后写入 suggestedReplies)。
244
245
  * 不碰 updated_at:这类补丁不是用户可见的会话活动。
245
246
  * metadata 损坏或非对象时从空对象开始合。
246
247
  */
247
- patchMessageMetadata(chatId: string, messageId: string, patch: Record<string, unknown>): ChatMessageRecord | null;
248
+ patchMessageMetadata(chatId: string, messageId: string, patch: Record<string, unknown>): Promise<ChatMessageRecord | null>;
248
249
  /**
249
250
  * W1.2.1: replace the chat's whole message list with a branch projection.
250
251
  * The desktop store is the UI projection of the ACTIVE framework record —
@@ -256,14 +257,14 @@ export declare class LocalStore {
256
257
  replaceChatMessages(chatId: string, messages: Array<{
257
258
  role: ChatMessageRecord['role'];
258
259
  content: string;
259
- }>): void;
260
- listChatAgents(includeArchived?: boolean): ChatAgentRecord[];
261
- getChatAgent(agentId: string): ChatAgentRecord | null;
260
+ }>): Promise<void>;
261
+ listChatAgents(includeArchived?: boolean): Promise<ChatAgentRecord[]>;
262
+ getChatAgent(agentId: string): Promise<ChatAgentRecord | null>;
262
263
  createChatAgent(input: Partial<ChatAgentRecord> & {
263
264
  name: string;
264
- }): ChatAgentRecord;
265
- updateChatAgent(agentId: string, updates: Partial<ChatAgentRecord>): ChatAgentRecord | null;
266
- archiveChatAgent(agentId: string): boolean;
265
+ }): Promise<ChatAgentRecord>;
266
+ updateChatAgent(agentId: string, updates: Partial<ChatAgentRecord>): Promise<ChatAgentRecord | null>;
267
+ archiveChatAgent(agentId: string): Promise<boolean>;
267
268
  saveTrace(input: {
268
269
  id: string;
269
270
  chatId: string;
@@ -272,9 +273,9 @@ export declare class LocalStore {
272
273
  durationMs?: number | null;
273
274
  status: string;
274
275
  payload: Record<string, unknown>;
275
- }): HarnessTraceRecord;
276
- listTracesByChat(chatId: string, limit?: number): HarnessTraceRecord[];
277
- getTrace(traceId: string): HarnessTraceRecord | null;
276
+ }): Promise<HarnessTraceRecord>;
277
+ listTracesByChat(chatId: string, limit?: number): Promise<HarnessTraceRecord[]>;
278
+ getTrace(traceId: string): Promise<HarnessTraceRecord | null>;
278
279
  createTask(input: {
279
280
  chatId: string;
280
281
  task: string;
@@ -285,26 +286,26 @@ export declare class LocalStore {
285
286
  dependsOn?: string[] | null;
286
287
  /** 初始状态(缺省 running;有未就绪依赖时调用方传 blocked)。 */
287
288
  initialStatus?: 'blocked' | 'running';
288
- }): TaskRecord;
289
- getTask(taskId: string): TaskRecord | null;
289
+ }): Promise<TaskRecord>;
290
+ getTask(taskId: string): Promise<TaskRecord | null>;
290
291
  /** 按 chat 列任务(updated_at 新→旧);chatId 缺省时列全部(任务面板的全局视图)。 */
291
- listTasks(chatId?: string, limit?: number): TaskRecord[];
292
+ listTasks(chatId?: string, limit?: number): Promise<TaskRecord[]>;
292
293
  /**
293
294
  * 终态/进度回写。只写传入的字段(undefined 过滤),updated_at 总是刷新。
294
295
  * 与 updateChat 同约定:显式传 null 才是置空。
295
296
  */
296
- updateTask(taskId: string, updates: Partial<Pick<TaskRecord, 'status' | 'answer' | 'error' | 'worktreeState' | 'traceId' | 'recordId'>>): TaskRecord | null;
297
+ updateTask(taskId: string, updates: Partial<Pick<TaskRecord, 'status' | 'answer' | 'error' | 'worktreeState' | 'traceId' | 'recordId'>>): Promise<TaskRecord | null>;
297
298
  /**
298
299
  * 回写推理时间线。故意不碰 updated_at——流过程中的增量不应把任务
299
300
  * 面板按「最近活动」反复顶到最上。
300
301
  */
301
- saveTaskProcess(taskId: string, processJson: string): void;
302
+ saveTaskProcess(taskId: string, processJson: string): Promise<void>;
302
303
  /**
303
304
  * 启动清扫:running 任务只可能属于上一个已死的进程(任务流不跨进程
304
305
  * 存活),全部落成 failed/interrupted——与 W7-1 turn_active 检测器同
305
306
  * 理,残留 running 是崩溃签名,不是真相。
306
307
  */
307
- failRunningTasks(reason: string): number;
308
+ failRunningTasks(reason: string): Promise<number>;
308
309
  /**
309
310
  * 记录一条用量事件(一轮 chat / 一次标题生成 / 一次摘要压缩等)。
310
311
  * `costUsd` 为 null 表示该模型无单价(本地/未知)——存 NULL,面板渲染为 "—"。
@@ -319,38 +320,38 @@ export declare class LocalStore {
319
320
  totalTokens: number;
320
321
  cachedPromptTokens?: number;
321
322
  costUsd?: number | null;
322
- }): void;
323
+ }): Promise<void>;
323
324
  /**
324
325
  * 聚合最近 `sinceDays` 天的用量:按 model 分桶( token 合计 + 成本合计),
325
326
  * 外加总计。成本只统计有单价的模型(cost_usd 非 NULL);无单价模型的
326
327
  * token 照常计入,但成本列不计。返回按 totalTokens 降序。
327
328
  */
328
- getUsageSummary(sinceDays?: number): UsageSummary;
329
- getLlmSettings(): LlmSettings | null;
330
- setLlmSettings(settings: LlmSettings): LlmSettings;
329
+ getUsageSummary(sinceDays?: number): Promise<UsageSummary>;
330
+ getLlmSettings(): Promise<LlmSettings | null>;
331
+ setLlmSettings(settings: LlmSettings): Promise<LlmSettings>;
331
332
  /** 读取遥测设置;从未配置过时返回 null(调用方按"关"处理)。 */
332
- getTelemetrySettings(): TelemetrySettings | null;
333
- setTelemetrySettings(settings: Partial<TelemetrySettings>): TelemetrySettings;
334
- getWebSearchSettings(): WebSearchSettings | null;
335
- setWebSearchSettings(settings: Partial<WebSearchSettings>): WebSearchSettings;
336
- getInsightsSettings(): InsightsSettings | null;
337
- ensureInsightsSettings(): InsightsSettings;
338
- setInsightsSettings(settings: InsightsSettingsPatch): InsightsSettings;
339
- enqueueInsight(kind: InsightKind, payload: Record<string, unknown>): InsightOutboxRow;
333
+ getTelemetrySettings(): Promise<TelemetrySettings | null>;
334
+ setTelemetrySettings(settings: Partial<TelemetrySettings>): Promise<TelemetrySettings>;
335
+ getWebSearchSettings(): Promise<WebSearchSettings | null>;
336
+ setWebSearchSettings(settings: Partial<WebSearchSettings>): Promise<WebSearchSettings>;
337
+ getInsightsSettings(): Promise<InsightsSettings | null>;
338
+ ensureInsightsSettings(): Promise<InsightsSettings>;
339
+ setInsightsSettings(settings: InsightsSettingsPatch): Promise<InsightsSettings>;
340
+ enqueueInsight(kind: InsightKind, payload: Record<string, unknown>): Promise<InsightOutboxRow>;
340
341
  listInsightOutbox(opts?: {
341
342
  uploaded?: boolean;
342
343
  kind?: InsightKind;
343
344
  limit?: number;
344
- }): InsightOutboxRow[];
345
- markInsightUploaded(id: string): void;
346
- markInsightUploadError(id: string, error: string): void;
347
- insightStats(): {
345
+ }): Promise<InsightOutboxRow[]>;
346
+ markInsightUploaded(id: string): Promise<void>;
347
+ markInsightUploadError(id: string, error: string): Promise<void>;
348
+ insightStats(): Promise<{
348
349
  events: number;
349
350
  turns: number;
350
351
  profile: number;
351
352
  pending: number;
352
- };
353
- exportInsightsBundle(): {
353
+ }>;
354
+ exportInsightsBundle(): Promise<{
354
355
  schema: typeof INSIGHTS_EXPORT_SCHEMA;
355
356
  exportedAt: string;
356
357
  installId: string;
@@ -367,13 +368,19 @@ export declare class LocalStore {
367
368
  pending: number;
368
369
  };
369
370
  records: InsightOutboxRow[];
370
- };
371
+ }>;
371
372
  private mapInsightOutbox;
372
373
  private mapChatSession;
373
374
  private mapChatMessage;
374
375
  private mapHarnessTrace;
375
376
  private mapTask;
376
377
  private mapChatAgent;
378
+ private getSetting;
379
+ private setSetting;
377
380
  private safeJson;
378
381
  }
379
- export declare const localStore: LocalStore;
382
+ export type { PackDbAccess, StorageDriver, StorageDriverFactory, TenantScope, } from './driver.js';
383
+ export type { ScopedStore } from './scoped-store.js';
384
+ export { LOCAL_SCOPE, closeStorage, getPackDbAccess, getScopedStore, initializeStorage, selectStorageDriver, } from './driver.js';
385
+ export { registerStorageDriver } from './driver.js';
386
+ export { SqliteStorageDriver } from './sqlite-driver.js';