@prismer/runtime 1.9.6 → 1.9.9

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/index.d.cts CHANGED
@@ -28,6 +28,11 @@ interface AdapterDef {
28
28
  workspaceSchema: z.ZodSchema;
29
29
  /** Long-running: ensure the underlying service is reachable. May spawn or just connect. */
30
30
  ensureService?(profile: AgentProfile): Promise<AdapterService>;
31
+ /**
32
+ * Optional preflight called when the daemon syncs a profile. This should
33
+ * prepare local profile files/config without starting a long-running service.
34
+ */
35
+ prepareProfile?(profile: AgentProfile): Promise<void>;
31
36
  /** Interactive: one-shot dispatch (spawn-per-task). */
32
37
  dispatch?(profile: AgentProfile, task: TaskInput): Promise<TaskResult>;
33
38
  /** Validate config before persisting `AgentProfile.config`. */
@@ -208,6 +213,48 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
208
213
  */
209
214
  hermesSourceDir: z.ZodOptional<z.ZodString>;
210
215
  nativeMirrorTimeoutMs: z.ZodDefault<z.ZodNumber>;
216
+ /** Task authority level: executor (default) or orchestrator. */
217
+ taskAuthority: z.ZodDefault<z.ZodOptional<z.ZodEnum<["executor", "orchestrator"]>>>;
218
+ /** Human approval escalation policy. Enforcement is currently prompt/cloud-side. */
219
+ approvalPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<["strict", "auto-low-risk", "autonomous"]>>>;
220
+ /** Agent-level MCP tool allowlist. Empty/null means all tools. Supports exact names and trailing * wildcards. */
221
+ mcpAllowlist: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
222
+ /** Agent-level operating principles injected through /v1/runs instructions. */
223
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
224
+ /**
225
+ * Role-template snapshot carried in AgentProfile.config by cloud ACP.
226
+ * Expected fields used here:
227
+ * - roleTemplate.mcpServers[].toolsAllowlist
228
+ * - roleTemplate.operatingPrinciples
229
+ */
230
+ roleTemplate: z.ZodOptional<z.ZodObject<{
231
+ mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
232
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
233
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
234
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
235
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
236
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
237
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
238
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
239
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
240
+ mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
241
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
242
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
243
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
244
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
245
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
246
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
247
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
248
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
249
+ mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
250
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
251
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
252
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
253
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
254
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
255
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
256
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
257
+ }, z.ZodTypeAny, "passthrough">>>;
211
258
  }, "strip", z.ZodTypeAny, {
212
259
  port: number;
213
260
  apiKey: string;
@@ -221,10 +268,24 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
221
268
  mirrorNativeKanban: boolean;
222
269
  mirrorNativeGoals: boolean;
223
270
  nativeMirrorTimeoutMs: number;
271
+ taskAuthority: "executor" | "orchestrator";
272
+ approvalPolicy: "strict" | "auto-low-risk" | "autonomous";
224
273
  hermesProfileName?: string | undefined;
225
274
  prismerMcpServerPath?: string | undefined;
226
275
  prismerProviderBaseUrl?: string | undefined;
227
276
  hermesSourceDir?: string | undefined;
277
+ mcpAllowlist?: string[] | null | undefined;
278
+ operatingPrinciples?: string | Record<string, string> | undefined;
279
+ roleTemplate?: z.objectOutputType<{
280
+ mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
281
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
282
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
283
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
284
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
285
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
286
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
287
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
288
+ }, z.ZodTypeAny, "passthrough"> | undefined;
228
289
  }, {
229
290
  apiKey: string;
230
291
  hermesProfileName?: string | undefined;
@@ -242,6 +303,20 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
242
303
  mirrorNativeGoals?: boolean | undefined;
243
304
  hermesSourceDir?: string | undefined;
244
305
  nativeMirrorTimeoutMs?: number | undefined;
306
+ taskAuthority?: "executor" | "orchestrator" | undefined;
307
+ approvalPolicy?: "strict" | "auto-low-risk" | "autonomous" | undefined;
308
+ mcpAllowlist?: string[] | null | undefined;
309
+ operatingPrinciples?: string | Record<string, string> | undefined;
310
+ roleTemplate?: z.objectInputType<{
311
+ mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
312
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
313
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
314
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
315
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
316
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
317
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
318
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
319
+ }, z.ZodTypeAny, "passthrough"> | undefined;
245
320
  }>;
246
321
  type HermesProfileConfig = z.infer<typeof HermesProfileConfigSchema>;
247
322
  declare const hermesAdapter: AdapterDef;
@@ -306,7 +381,7 @@ type LocalDb = Database.Database;
306
381
  declare function openLocalDb(path: string): LocalDb;
307
382
  declare function runMigrations(db: LocalDb): void;
308
383
  declare function currentSchemaVersion(db: LocalDb): number;
309
- declare const TARGET_SCHEMA_VERSION = 2;
384
+ declare const TARGET_SCHEMA_VERSION = 3;
310
385
 
311
386
  type SyncResourceType = 'workspace' | 'agent' | 'agent_profile';
312
387
  type SyncOperation = 'create' | 'update' | 'delete';
@@ -883,6 +958,9 @@ interface HostAckedPayload {
883
958
  [key: string]: number;
884
959
  };
885
960
  profilesToSync: string[];
961
+ /** Profile IDs the daemon declared but that no longer exist on the cloud
962
+ * (soft-deleted). The daemon should remove these from its local store. */
963
+ profilesToDelete: string[];
886
964
  }
887
965
  interface AgentStatusChangedPayload {
888
966
  agentImUserId: string;
@@ -1160,6 +1238,71 @@ declare class OutboxWatcher {
1160
1238
  private upload;
1161
1239
  }
1162
1240
 
1241
+ interface AssetMetadataRow {
1242
+ assetId: string;
1243
+ contentHash: string;
1244
+ filename: string | null;
1245
+ folderPath: string | null;
1246
+ mime: string;
1247
+ kind: string;
1248
+ sizeBytes: number;
1249
+ description: string | null;
1250
+ assetIndexSeq: number;
1251
+ }
1252
+ interface AssetMetadataIndexOptions {
1253
+ db: LocalDb;
1254
+ cloud: CloudClient;
1255
+ workspaceId: string;
1256
+ /**
1257
+ * Per-workspace state dir. Caller should pass ~/.prismer/<wid>/ so different
1258
+ * paired workspaces don't race on the cursor file.
1259
+ */
1260
+ workspaceStateDir: string;
1261
+ }
1262
+ /**
1263
+ * AssetMetadataIndex mirrors cloud-side asset metadata into SQLite for fast
1264
+ * local `#filename` lookup. The cursor file is the only piece of state that
1265
+ * must survive daemon restart; the SQLite mirror is incremental between restarts
1266
+ * (cursor catch-up). Idempotent — safe to retry pullDelta() on errors.
1267
+ */
1268
+ declare class AssetMetadataIndex {
1269
+ private readonly db;
1270
+ private readonly cloud;
1271
+ /** Workspace ID — exposed for prismer:// URI construction. */
1272
+ readonly workspaceId: string;
1273
+ private readonly cursorPath;
1274
+ private _lastSyncMs;
1275
+ constructor(opts: AssetMetadataIndexOptions);
1276
+ /** Persisted cursor for this workspace, or 0 on first run / corrupted file. */
1277
+ readCursor(): number;
1278
+ private writeCursor;
1279
+ /**
1280
+ * Pull incremental asset metadata changes since the persisted cursor and
1281
+ * upsert into the local index. Newer rows overwrite older ones by
1282
+ * (workspace_id, asset_id) primary key.
1283
+ *
1284
+ * Returns the count of items applied + the new cursor. Throttled: if called
1285
+ * within 30s of the last successful pull, returns immediately.
1286
+ */
1287
+ pullDelta(opts?: {
1288
+ signal?: AbortSignal;
1289
+ }): Promise<{
1290
+ applied: number;
1291
+ cursor: number;
1292
+ }>;
1293
+ /**
1294
+ * Search local index by filename or description substring.
1295
+ * Escapes LIKE wildcards (% and _). Default limit 8.
1296
+ */
1297
+ search(query: string, limit?: number): AssetMetadataRow[];
1298
+ /** Exact match on filename column. Returns undefined if not indexed. */
1299
+ resolveByFilename(filename: string): AssetMetadataRow | undefined;
1300
+ resolveByAssetId(assetId: string): AssetMetadataRow | undefined;
1301
+ resolveByContentHash(contentHash: string): AssetMetadataRow | undefined;
1302
+ /** Batch exact match — returns Map for O(1) access. */
1303
+ resolveByFilenames(filenames: string[]): Map<string, AssetMetadataRow>;
1304
+ }
1305
+
1163
1306
  interface DispatchDeps {
1164
1307
  registry: AdapterRegistry;
1165
1308
  cloud: CloudClient;
@@ -1183,6 +1326,11 @@ interface DispatchDeps {
1183
1326
  outboxWatcher?: OutboxWatcher;
1184
1327
  /** Daemon paths — used to derive the per-task outbox dir. */
1185
1328
  paths?: ConfigPaths;
1329
+ /**
1330
+ * Multi-workspace asset metadata indexes for #filename resolution.
1331
+ * Keyed by workspaceId. If absent, #ref resolution is skipped entirely.
1332
+ */
1333
+ assetMetadataIndexes?: Map<string, AssetMetadataIndex>;
1186
1334
  }
1187
1335
  declare function handleDispatch(payload: TaskDispatchRequestPayload, requestId: string | undefined, deps: DispatchDeps): Promise<TaskDispatchReplyPayload>;
1188
1336
  /**
@@ -1250,6 +1398,14 @@ interface LocalServerOptions {
1250
1398
  * Sink receives the parsed JSON body and returns a structured result.
1251
1399
  */
1252
1400
  onAssetWrite?: (body: unknown) => Promise<AssetWriteHandlerResult>;
1401
+ /**
1402
+ * Optional handler for `/local/asset/*` routes. Returns true if the request
1403
+ * was handled (response written); false to let the normal route table fall
1404
+ * through. Wired by the daemon runner from `attachAssetRpc()` in
1405
+ * `daemon/asset/rpc.ts` when asset metadata index is enabled.
1406
+ * When set, /healthz reports `assetReady: true`.
1407
+ */
1408
+ attachAsset?: (req: IncomingMessage, res: ServerResponse) => Promise<boolean>;
1253
1409
  }
1254
1410
  interface AssetWriteHandlerResult {
1255
1411
  status: 200 | 400 | 502;
@@ -1320,6 +1476,7 @@ interface LocalServerState {
1320
1476
  runningTaskIds: string[];
1321
1477
  observability?: {
1322
1478
  adapters?: Record<string, unknown>;
1479
+ assetSync?: Record<string, unknown>;
1323
1480
  lastTaskError?: {
1324
1481
  taskId: string;
1325
1482
  message: string;
@@ -1334,6 +1491,7 @@ declare class LocalServer {
1334
1491
  start(): Promise<void>;
1335
1492
  stop(): Promise<void>;
1336
1493
  private route;
1494
+ private runHandlers;
1337
1495
  private routeStandard;
1338
1496
  /**
1339
1497
  * POST /v1/agents/install — cloud/controller installs one hosted agent on
@@ -1405,6 +1563,16 @@ declare class Runner extends EventEmitter {
1405
1563
  private localServer?;
1406
1564
  private outboxWatcher?;
1407
1565
  private memoryWiring?;
1566
+ private assetMetadataIndexes;
1567
+ private workspaceMirrors;
1568
+ private assetOriginOutbox?;
1569
+ private dropFolderAdapter?;
1570
+ private dropFolderUploadRunner?;
1571
+ private dropFolderTimer?;
1572
+ private dropFolderWorkspaceId;
1573
+ private dropFolderWorkspaceDir;
1574
+ private dropFolderTickInFlight;
1575
+ private readonly dropFolderStable;
1408
1576
  private state;
1409
1577
  private startedAt;
1410
1578
  private workspaceId;
@@ -1431,6 +1599,7 @@ declare class Runner extends EventEmitter {
1431
1599
  * `agent_profiles` table (filled by host.acked sync).
1432
1600
  */
1433
1601
  loadAgentsFromDb(): void;
1602
+ private prepareLocalProfiles;
1434
1603
  /**
1435
1604
  * Register an in-process AgentProfile snapshot (called by agent CLI / sync layer).
1436
1605
  * Used to populate the `agents` list in agent.host.declare.
@@ -1458,8 +1627,34 @@ declare class Runner extends EventEmitter {
1458
1627
  private syncProfileFromCloud;
1459
1628
  private resolveOwnedAgent;
1460
1629
  private onWorkspaceChanged;
1630
+ private onAssetChanged;
1461
1631
  private onWorkspaceFileChanged;
1462
1632
  private snapshotAdapterObservability;
1633
+ private snapshotAssetSyncObservability;
1634
+ /**
1635
+ * Ensure an AssetMetadataIndex exists for the given workspace and pull
1636
+ * delta from cloud. Idempotent — creates the index on first call, reuses
1637
+ * it on subsequent calls. Same cursor-catch-up semantics as WorkspaceMirror.
1638
+ */
1639
+ private syncAssetMetadata;
1640
+ /**
1641
+ * Ensure a WorkspaceMirror exists for the workspace and pull path→asset
1642
+ * bindings from cloud. Cold-start daemons previously only had this table
1643
+ * populated by WS push or per-path URI fallback, so local asset state looked
1644
+ * empty even though cloud files existed.
1645
+ */
1646
+ private syncWorkspaceFiles;
1647
+ private syncAssetState;
1648
+ /**
1649
+ * Desktop asset ingress: watch a user-visible local asset folder
1650
+ * and upload new files as IMAssets, preserving nested relative dirs in
1651
+ * IMAsset.folderPath. The lower-level adapter/outbox/uploader already
1652
+ * existed; this method wires them into the real daemon lifecycle.
1653
+ */
1654
+ private ensureDropFolderRuntime;
1655
+ private stopDropFolderRuntime;
1656
+ private runDropFolderTick;
1657
+ private isDropFolderObservationStable;
1463
1658
  /**
1464
1659
  * SyncWorker FlushFn — pushes local writes to cloud.
1465
1660
  *
@@ -1557,29 +1752,29 @@ declare const CCConfigSchema: z.ZodObject<{
1557
1752
  cwd: string;
1558
1753
  maxTurns: number;
1559
1754
  route: "default" | "prismer" | "omniroute";
1560
- systemPrompt?: string | undefined;
1561
- allowedTools?: string[] | undefined;
1562
- envVars?: Record<string, string> | undefined;
1563
1755
  mcpServers?: {
1564
1756
  name: string;
1565
1757
  command: string;
1566
1758
  env?: Record<string, string> | undefined;
1567
1759
  args?: string[] | undefined;
1568
1760
  }[] | undefined;
1761
+ systemPrompt?: string | undefined;
1762
+ allowedTools?: string[] | undefined;
1763
+ envVars?: Record<string, string> | undefined;
1569
1764
  baseURL?: string | undefined;
1570
1765
  apiKeyRef?: string | undefined;
1571
1766
  }, {
1572
1767
  cwd: string;
1573
1768
  model?: string | undefined;
1574
- systemPrompt?: string | undefined;
1575
- allowedTools?: string[] | undefined;
1576
- envVars?: Record<string, string> | undefined;
1577
1769
  mcpServers?: {
1578
1770
  name: string;
1579
1771
  command: string;
1580
1772
  env?: Record<string, string> | undefined;
1581
1773
  args?: string[] | undefined;
1582
1774
  }[] | undefined;
1775
+ systemPrompt?: string | undefined;
1776
+ allowedTools?: string[] | undefined;
1777
+ envVars?: Record<string, string> | undefined;
1583
1778
  maxTurns?: number | undefined;
1584
1779
  baseURL?: string | undefined;
1585
1780
  apiKeyRef?: string | undefined;
package/dist/index.d.ts CHANGED
@@ -28,6 +28,11 @@ interface AdapterDef {
28
28
  workspaceSchema: z.ZodSchema;
29
29
  /** Long-running: ensure the underlying service is reachable. May spawn or just connect. */
30
30
  ensureService?(profile: AgentProfile): Promise<AdapterService>;
31
+ /**
32
+ * Optional preflight called when the daemon syncs a profile. This should
33
+ * prepare local profile files/config without starting a long-running service.
34
+ */
35
+ prepareProfile?(profile: AgentProfile): Promise<void>;
31
36
  /** Interactive: one-shot dispatch (spawn-per-task). */
32
37
  dispatch?(profile: AgentProfile, task: TaskInput): Promise<TaskResult>;
33
38
  /** Validate config before persisting `AgentProfile.config`. */
@@ -208,6 +213,48 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
208
213
  */
209
214
  hermesSourceDir: z.ZodOptional<z.ZodString>;
210
215
  nativeMirrorTimeoutMs: z.ZodDefault<z.ZodNumber>;
216
+ /** Task authority level: executor (default) or orchestrator. */
217
+ taskAuthority: z.ZodDefault<z.ZodOptional<z.ZodEnum<["executor", "orchestrator"]>>>;
218
+ /** Human approval escalation policy. Enforcement is currently prompt/cloud-side. */
219
+ approvalPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<["strict", "auto-low-risk", "autonomous"]>>>;
220
+ /** Agent-level MCP tool allowlist. Empty/null means all tools. Supports exact names and trailing * wildcards. */
221
+ mcpAllowlist: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
222
+ /** Agent-level operating principles injected through /v1/runs instructions. */
223
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
224
+ /**
225
+ * Role-template snapshot carried in AgentProfile.config by cloud ACP.
226
+ * Expected fields used here:
227
+ * - roleTemplate.mcpServers[].toolsAllowlist
228
+ * - roleTemplate.operatingPrinciples
229
+ */
230
+ roleTemplate: z.ZodOptional<z.ZodObject<{
231
+ mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
232
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
233
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
234
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
235
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
236
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
237
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
238
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
239
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
240
+ mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
241
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
242
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
243
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
244
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
245
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
246
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
247
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
248
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
249
+ mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
250
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
251
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
252
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
253
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
254
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
255
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
256
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
257
+ }, z.ZodTypeAny, "passthrough">>>;
211
258
  }, "strip", z.ZodTypeAny, {
212
259
  port: number;
213
260
  apiKey: string;
@@ -221,10 +268,24 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
221
268
  mirrorNativeKanban: boolean;
222
269
  mirrorNativeGoals: boolean;
223
270
  nativeMirrorTimeoutMs: number;
271
+ taskAuthority: "executor" | "orchestrator";
272
+ approvalPolicy: "strict" | "auto-low-risk" | "autonomous";
224
273
  hermesProfileName?: string | undefined;
225
274
  prismerMcpServerPath?: string | undefined;
226
275
  prismerProviderBaseUrl?: string | undefined;
227
276
  hermesSourceDir?: string | undefined;
277
+ mcpAllowlist?: string[] | null | undefined;
278
+ operatingPrinciples?: string | Record<string, string> | undefined;
279
+ roleTemplate?: z.objectOutputType<{
280
+ mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
281
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
282
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
283
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
284
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
285
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
286
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
287
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
288
+ }, z.ZodTypeAny, "passthrough"> | undefined;
228
289
  }, {
229
290
  apiKey: string;
230
291
  hermesProfileName?: string | undefined;
@@ -242,6 +303,20 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
242
303
  mirrorNativeGoals?: boolean | undefined;
243
304
  hermesSourceDir?: string | undefined;
244
305
  nativeMirrorTimeoutMs?: number | undefined;
306
+ taskAuthority?: "executor" | "orchestrator" | undefined;
307
+ approvalPolicy?: "strict" | "auto-low-risk" | "autonomous" | undefined;
308
+ mcpAllowlist?: string[] | null | undefined;
309
+ operatingPrinciples?: string | Record<string, string> | undefined;
310
+ roleTemplate?: z.objectInputType<{
311
+ mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
312
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
313
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
314
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
315
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
316
+ toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
317
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
318
+ operatingPrinciples: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
319
+ }, z.ZodTypeAny, "passthrough"> | undefined;
245
320
  }>;
246
321
  type HermesProfileConfig = z.infer<typeof HermesProfileConfigSchema>;
247
322
  declare const hermesAdapter: AdapterDef;
@@ -306,7 +381,7 @@ type LocalDb = Database.Database;
306
381
  declare function openLocalDb(path: string): LocalDb;
307
382
  declare function runMigrations(db: LocalDb): void;
308
383
  declare function currentSchemaVersion(db: LocalDb): number;
309
- declare const TARGET_SCHEMA_VERSION = 2;
384
+ declare const TARGET_SCHEMA_VERSION = 3;
310
385
 
311
386
  type SyncResourceType = 'workspace' | 'agent' | 'agent_profile';
312
387
  type SyncOperation = 'create' | 'update' | 'delete';
@@ -883,6 +958,9 @@ interface HostAckedPayload {
883
958
  [key: string]: number;
884
959
  };
885
960
  profilesToSync: string[];
961
+ /** Profile IDs the daemon declared but that no longer exist on the cloud
962
+ * (soft-deleted). The daemon should remove these from its local store. */
963
+ profilesToDelete: string[];
886
964
  }
887
965
  interface AgentStatusChangedPayload {
888
966
  agentImUserId: string;
@@ -1160,6 +1238,71 @@ declare class OutboxWatcher {
1160
1238
  private upload;
1161
1239
  }
1162
1240
 
1241
+ interface AssetMetadataRow {
1242
+ assetId: string;
1243
+ contentHash: string;
1244
+ filename: string | null;
1245
+ folderPath: string | null;
1246
+ mime: string;
1247
+ kind: string;
1248
+ sizeBytes: number;
1249
+ description: string | null;
1250
+ assetIndexSeq: number;
1251
+ }
1252
+ interface AssetMetadataIndexOptions {
1253
+ db: LocalDb;
1254
+ cloud: CloudClient;
1255
+ workspaceId: string;
1256
+ /**
1257
+ * Per-workspace state dir. Caller should pass ~/.prismer/<wid>/ so different
1258
+ * paired workspaces don't race on the cursor file.
1259
+ */
1260
+ workspaceStateDir: string;
1261
+ }
1262
+ /**
1263
+ * AssetMetadataIndex mirrors cloud-side asset metadata into SQLite for fast
1264
+ * local `#filename` lookup. The cursor file is the only piece of state that
1265
+ * must survive daemon restart; the SQLite mirror is incremental between restarts
1266
+ * (cursor catch-up). Idempotent — safe to retry pullDelta() on errors.
1267
+ */
1268
+ declare class AssetMetadataIndex {
1269
+ private readonly db;
1270
+ private readonly cloud;
1271
+ /** Workspace ID — exposed for prismer:// URI construction. */
1272
+ readonly workspaceId: string;
1273
+ private readonly cursorPath;
1274
+ private _lastSyncMs;
1275
+ constructor(opts: AssetMetadataIndexOptions);
1276
+ /** Persisted cursor for this workspace, or 0 on first run / corrupted file. */
1277
+ readCursor(): number;
1278
+ private writeCursor;
1279
+ /**
1280
+ * Pull incremental asset metadata changes since the persisted cursor and
1281
+ * upsert into the local index. Newer rows overwrite older ones by
1282
+ * (workspace_id, asset_id) primary key.
1283
+ *
1284
+ * Returns the count of items applied + the new cursor. Throttled: if called
1285
+ * within 30s of the last successful pull, returns immediately.
1286
+ */
1287
+ pullDelta(opts?: {
1288
+ signal?: AbortSignal;
1289
+ }): Promise<{
1290
+ applied: number;
1291
+ cursor: number;
1292
+ }>;
1293
+ /**
1294
+ * Search local index by filename or description substring.
1295
+ * Escapes LIKE wildcards (% and _). Default limit 8.
1296
+ */
1297
+ search(query: string, limit?: number): AssetMetadataRow[];
1298
+ /** Exact match on filename column. Returns undefined if not indexed. */
1299
+ resolveByFilename(filename: string): AssetMetadataRow | undefined;
1300
+ resolveByAssetId(assetId: string): AssetMetadataRow | undefined;
1301
+ resolveByContentHash(contentHash: string): AssetMetadataRow | undefined;
1302
+ /** Batch exact match — returns Map for O(1) access. */
1303
+ resolveByFilenames(filenames: string[]): Map<string, AssetMetadataRow>;
1304
+ }
1305
+
1163
1306
  interface DispatchDeps {
1164
1307
  registry: AdapterRegistry;
1165
1308
  cloud: CloudClient;
@@ -1183,6 +1326,11 @@ interface DispatchDeps {
1183
1326
  outboxWatcher?: OutboxWatcher;
1184
1327
  /** Daemon paths — used to derive the per-task outbox dir. */
1185
1328
  paths?: ConfigPaths;
1329
+ /**
1330
+ * Multi-workspace asset metadata indexes for #filename resolution.
1331
+ * Keyed by workspaceId. If absent, #ref resolution is skipped entirely.
1332
+ */
1333
+ assetMetadataIndexes?: Map<string, AssetMetadataIndex>;
1186
1334
  }
1187
1335
  declare function handleDispatch(payload: TaskDispatchRequestPayload, requestId: string | undefined, deps: DispatchDeps): Promise<TaskDispatchReplyPayload>;
1188
1336
  /**
@@ -1250,6 +1398,14 @@ interface LocalServerOptions {
1250
1398
  * Sink receives the parsed JSON body and returns a structured result.
1251
1399
  */
1252
1400
  onAssetWrite?: (body: unknown) => Promise<AssetWriteHandlerResult>;
1401
+ /**
1402
+ * Optional handler for `/local/asset/*` routes. Returns true if the request
1403
+ * was handled (response written); false to let the normal route table fall
1404
+ * through. Wired by the daemon runner from `attachAssetRpc()` in
1405
+ * `daemon/asset/rpc.ts` when asset metadata index is enabled.
1406
+ * When set, /healthz reports `assetReady: true`.
1407
+ */
1408
+ attachAsset?: (req: IncomingMessage, res: ServerResponse) => Promise<boolean>;
1253
1409
  }
1254
1410
  interface AssetWriteHandlerResult {
1255
1411
  status: 200 | 400 | 502;
@@ -1320,6 +1476,7 @@ interface LocalServerState {
1320
1476
  runningTaskIds: string[];
1321
1477
  observability?: {
1322
1478
  adapters?: Record<string, unknown>;
1479
+ assetSync?: Record<string, unknown>;
1323
1480
  lastTaskError?: {
1324
1481
  taskId: string;
1325
1482
  message: string;
@@ -1334,6 +1491,7 @@ declare class LocalServer {
1334
1491
  start(): Promise<void>;
1335
1492
  stop(): Promise<void>;
1336
1493
  private route;
1494
+ private runHandlers;
1337
1495
  private routeStandard;
1338
1496
  /**
1339
1497
  * POST /v1/agents/install — cloud/controller installs one hosted agent on
@@ -1405,6 +1563,16 @@ declare class Runner extends EventEmitter {
1405
1563
  private localServer?;
1406
1564
  private outboxWatcher?;
1407
1565
  private memoryWiring?;
1566
+ private assetMetadataIndexes;
1567
+ private workspaceMirrors;
1568
+ private assetOriginOutbox?;
1569
+ private dropFolderAdapter?;
1570
+ private dropFolderUploadRunner?;
1571
+ private dropFolderTimer?;
1572
+ private dropFolderWorkspaceId;
1573
+ private dropFolderWorkspaceDir;
1574
+ private dropFolderTickInFlight;
1575
+ private readonly dropFolderStable;
1408
1576
  private state;
1409
1577
  private startedAt;
1410
1578
  private workspaceId;
@@ -1431,6 +1599,7 @@ declare class Runner extends EventEmitter {
1431
1599
  * `agent_profiles` table (filled by host.acked sync).
1432
1600
  */
1433
1601
  loadAgentsFromDb(): void;
1602
+ private prepareLocalProfiles;
1434
1603
  /**
1435
1604
  * Register an in-process AgentProfile snapshot (called by agent CLI / sync layer).
1436
1605
  * Used to populate the `agents` list in agent.host.declare.
@@ -1458,8 +1627,34 @@ declare class Runner extends EventEmitter {
1458
1627
  private syncProfileFromCloud;
1459
1628
  private resolveOwnedAgent;
1460
1629
  private onWorkspaceChanged;
1630
+ private onAssetChanged;
1461
1631
  private onWorkspaceFileChanged;
1462
1632
  private snapshotAdapterObservability;
1633
+ private snapshotAssetSyncObservability;
1634
+ /**
1635
+ * Ensure an AssetMetadataIndex exists for the given workspace and pull
1636
+ * delta from cloud. Idempotent — creates the index on first call, reuses
1637
+ * it on subsequent calls. Same cursor-catch-up semantics as WorkspaceMirror.
1638
+ */
1639
+ private syncAssetMetadata;
1640
+ /**
1641
+ * Ensure a WorkspaceMirror exists for the workspace and pull path→asset
1642
+ * bindings from cloud. Cold-start daemons previously only had this table
1643
+ * populated by WS push or per-path URI fallback, so local asset state looked
1644
+ * empty even though cloud files existed.
1645
+ */
1646
+ private syncWorkspaceFiles;
1647
+ private syncAssetState;
1648
+ /**
1649
+ * Desktop asset ingress: watch a user-visible local asset folder
1650
+ * and upload new files as IMAssets, preserving nested relative dirs in
1651
+ * IMAsset.folderPath. The lower-level adapter/outbox/uploader already
1652
+ * existed; this method wires them into the real daemon lifecycle.
1653
+ */
1654
+ private ensureDropFolderRuntime;
1655
+ private stopDropFolderRuntime;
1656
+ private runDropFolderTick;
1657
+ private isDropFolderObservationStable;
1463
1658
  /**
1464
1659
  * SyncWorker FlushFn — pushes local writes to cloud.
1465
1660
  *
@@ -1557,29 +1752,29 @@ declare const CCConfigSchema: z.ZodObject<{
1557
1752
  cwd: string;
1558
1753
  maxTurns: number;
1559
1754
  route: "default" | "prismer" | "omniroute";
1560
- systemPrompt?: string | undefined;
1561
- allowedTools?: string[] | undefined;
1562
- envVars?: Record<string, string> | undefined;
1563
1755
  mcpServers?: {
1564
1756
  name: string;
1565
1757
  command: string;
1566
1758
  env?: Record<string, string> | undefined;
1567
1759
  args?: string[] | undefined;
1568
1760
  }[] | undefined;
1761
+ systemPrompt?: string | undefined;
1762
+ allowedTools?: string[] | undefined;
1763
+ envVars?: Record<string, string> | undefined;
1569
1764
  baseURL?: string | undefined;
1570
1765
  apiKeyRef?: string | undefined;
1571
1766
  }, {
1572
1767
  cwd: string;
1573
1768
  model?: string | undefined;
1574
- systemPrompt?: string | undefined;
1575
- allowedTools?: string[] | undefined;
1576
- envVars?: Record<string, string> | undefined;
1577
1769
  mcpServers?: {
1578
1770
  name: string;
1579
1771
  command: string;
1580
1772
  env?: Record<string, string> | undefined;
1581
1773
  args?: string[] | undefined;
1582
1774
  }[] | undefined;
1775
+ systemPrompt?: string | undefined;
1776
+ allowedTools?: string[] | undefined;
1777
+ envVars?: Record<string, string> | undefined;
1583
1778
  maxTurns?: number | undefined;
1584
1779
  baseURL?: string | undefined;
1585
1780
  apiKeyRef?: string | undefined;