@prismer/runtime 2.0.0 → 2.0.2

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
@@ -746,7 +746,15 @@ declare function saveConfig(config: Config, paths?: ConfigPaths): void;
746
746
  /** Derive a `wss?://` URL from a `https?://` base. Trailing `/ws` appended. */
747
747
  declare function deriveWsUrl(httpBase: string): string;
748
748
 
749
- declare function newDaemonId(): string;
749
+ interface NewDaemonIdOptions {
750
+ /** API key — when provided, the suffix becomes a deterministic sha256(hostname|apiKey)
751
+ * slice(0,12). Pass this so re-running `prismer setup` yields the same daemonId
752
+ * and cloud-side upsert dedupes the IMContainer row instead of accumulating. */
753
+ apiKey?: string;
754
+ /** Optional explicit hostname (test only). */
755
+ hostnameOverride?: string;
756
+ }
757
+ declare function newDaemonId(opts?: NewDaemonIdOptions): string;
750
758
  declare function isDaemonId(s: string): boolean;
751
759
 
752
760
  interface CloudClientOptions {
@@ -865,6 +873,38 @@ declare class AssetCache {
865
873
  signal?: AbortSignal;
866
874
  assetId?: string;
867
875
  }): Promise<CachedAsset>;
876
+ /**
877
+ * Fetch a public http(s) URL, content-hash dedup, cache locally.
878
+ *
879
+ * Mirrors `getOrFetch` (cache key = sha256 of body bytes), but the input
880
+ * is a URL whose hash we don't know up front. The fetcher applies:
881
+ *
882
+ * - SSRF guard (resolve hostname, reject loopback / RFC1918 / link-local
883
+ * / cloud-metadata / IPv6 ULA + link-local). Cross-host redirects
884
+ * re-validate the new host before each hop.
885
+ * - manual redirect handling (max 3 hops).
886
+ * - hard timeout (default 15 s, override via env
887
+ * `PRISMER_URL_FETCH_TIMEOUT_MS`).
888
+ * - streaming body read with abort-at-limit (default 5 MiB, override
889
+ * via env `PRISMER_URL_FETCH_MAX_BYTES`). Truncated bodies are NOT
890
+ * cached.
891
+ * - non-2xx → throws (caller should leave the URL in place and emit
892
+ * an `error` observation).
893
+ *
894
+ * On success returns { cached, finalUrl, durationMs }; the caller can
895
+ * pin / unpin the hash like any other asset.
896
+ */
897
+ getOrFetchUrl(url: string, opts?: {
898
+ signal?: AbortSignal;
899
+ userAgent?: string;
900
+ maxBytes?: number;
901
+ timeoutMs?: number;
902
+ maxRedirects?: number;
903
+ }): Promise<{
904
+ cached: CachedAsset;
905
+ finalUrl: string;
906
+ durationMs: number;
907
+ }>;
868
908
  /** Insert an already-on-disk asset into the cache (e.g., asset just produced by adapter). */
869
909
  registerLocal(hash: string, localPath: string, mime?: string): CachedAsset;
870
910
  /** Total bytes across all rows (incl. pinned). */
@@ -1022,68 +1062,6 @@ declare class ParseClaimController {
1022
1062
  }): HeartbeatHandle;
1023
1063
  }
1024
1064
 
1025
- type PrismerUriType = 'asset' | 'file';
1026
- interface ParsedPrismerUri {
1027
- /** Original full URI string. */
1028
- raw: string;
1029
- /**
1030
- * Owner segment for legacy `prismer://<owner>/...` form (informational,
1031
- * not ACL-checked). For `prismer://workspace/<wid>/...` this is the
1032
- * literal string 'workspace' — prefer `workspaceId` instead.
1033
- */
1034
- owner: string;
1035
- type: PrismerUriType;
1036
- /** For type='asset': the sha256 hash. For legacy file URIs: '<wsId>/<path>'. */
1037
- rest: string;
1038
- /** Convenience parses for type='file' and for workspace-form 'asset'. */
1039
- workspaceId?: string;
1040
- filePath?: string;
1041
- }
1042
- /**
1043
- * Find every recognized `prismer://...` reference in a string.
1044
- * Only `asset` and `file` types are recognized — other types (memory,
1045
- * context, conversation, evolution, task, pair) pass through untouched.
1046
- */
1047
- declare function parseUris(text: string): ParsedPrismerUri[];
1048
- interface UriResolverOptions {
1049
- db: LocalDb;
1050
- cloud: CloudClient;
1051
- assetCache: AssetCache;
1052
- }
1053
- declare class UriResolver {
1054
- private readonly db;
1055
- private readonly cloud;
1056
- private readonly assetCache;
1057
- constructor(opts: UriResolverOptions);
1058
- /**
1059
- * Resolve a single URI to a local file path. Throws on auth/4xx;
1060
- * caller decides whether to leave the URI in place (best-effort) or fail.
1061
- */
1062
- resolveOne(uri: ParsedPrismerUri, opts?: {
1063
- signal?: AbortSignal;
1064
- }): Promise<string>;
1065
- /**
1066
- * Walk a string, replace every `prismer://(asset|file)/...` with `file://<localPath>`.
1067
- * Unrecognized URIs pass through. Returns rewritten text + the list of pinned hashes.
1068
- */
1069
- rewrite(text: string, opts?: {
1070
- pin?: boolean;
1071
- signal?: AbortSignal;
1072
- }): Promise<{
1073
- text: string;
1074
- resolvedHashes: string[];
1075
- }>;
1076
- /** Bulk-rewrite an array of strings (e.g. context entries' content). */
1077
- rewriteAll(texts: string[], opts?: {
1078
- pin?: boolean;
1079
- signal?: AbortSignal;
1080
- }): Promise<{
1081
- texts: string[];
1082
- resolvedHashes: string[];
1083
- }>;
1084
- private lookupFile;
1085
- }
1086
-
1087
1065
  type IMAgentStatus = 'online' | 'busy' | 'idle' | 'offline';
1088
1066
  interface HostedAgentDeclaration {
1089
1067
  imUserId: string;
@@ -1185,15 +1163,22 @@ interface TaskDispatchProgressPayload {
1185
1163
  detail?: Record<string, unknown>;
1186
1164
  }
1187
1165
  /** Wave-8 W1: how the daemon handled a single AssetRef. */
1188
- type AssetDispatchStrategy = 'inline-text' | 'inline-text-truncated' | 'uri-only' | 'error';
1166
+ type AssetDispatchStrategy = 'inline-text' | 'inline-text-truncated' | 'uri-only' | 'fetched-https' | 'error';
1189
1167
  interface AssetDispatchObservation {
1190
- assetId: string;
1168
+ /** AssetRef.assetId for cloud-attached refs; undefined for L5 https fetches. */
1169
+ assetId?: string;
1191
1170
  contentHash: string;
1192
1171
  mime: string | null;
1193
1172
  sizeBytes: number | null;
1194
1173
  strategy: AssetDispatchStrategy;
1195
1174
  inlinedBytes?: number;
1196
1175
  error?: string;
1176
+ /** L5: original URL the user wrote in the prompt. */
1177
+ originalUrl?: string;
1178
+ /** L5: post-redirect URL the body was actually downloaded from. */
1179
+ finalUrl?: string;
1180
+ /** L5: end-to-end fetch duration in ms (DNS + connect + body read). */
1181
+ durationMs?: number;
1197
1182
  }
1198
1183
  interface TaskDispatchReplyPayload {
1199
1184
  taskId: string;
@@ -1254,6 +1239,106 @@ interface AssetChangedPayload {
1254
1239
  revision?: number;
1255
1240
  }
1256
1241
 
1242
+ type PrismerUriType = 'asset' | 'file';
1243
+ interface ParsedPrismerUri {
1244
+ /** Original full URI string. */
1245
+ raw: string;
1246
+ /**
1247
+ * Owner segment for legacy `prismer://<owner>/...` form (informational,
1248
+ * not ACL-checked). For `prismer://workspace/<wid>/...` this is the
1249
+ * literal string 'workspace' — prefer `workspaceId` instead.
1250
+ */
1251
+ owner: string;
1252
+ type: PrismerUriType;
1253
+ /** For type='asset': the sha256 hash. For legacy file URIs: '<wsId>/<path>'. */
1254
+ rest: string;
1255
+ /** Convenience parses for type='file' and for workspace-form 'asset'. */
1256
+ workspaceId?: string;
1257
+ filePath?: string;
1258
+ }
1259
+ /**
1260
+ * Find every recognized `prismer://...` reference in a string.
1261
+ * Only `asset` and `file` types are recognized — other types (memory,
1262
+ * context, conversation, evolution, task, pair) pass through untouched.
1263
+ */
1264
+ declare function parseUris(text: string): ParsedPrismerUri[];
1265
+ interface UriResolverOptions {
1266
+ db: LocalDb;
1267
+ cloud: CloudClient;
1268
+ assetCache: AssetCache;
1269
+ }
1270
+ declare class UriResolver {
1271
+ private readonly db;
1272
+ private readonly cloud;
1273
+ private readonly assetCache;
1274
+ constructor(opts: UriResolverOptions);
1275
+ /**
1276
+ * Resolve a single URI to a local file path. Throws on auth/4xx;
1277
+ * caller decides whether to leave the URI in place (best-effort) or fail.
1278
+ */
1279
+ resolveOne(uri: ParsedPrismerUri, opts?: {
1280
+ signal?: AbortSignal;
1281
+ }): Promise<string>;
1282
+ /**
1283
+ * Walk a string, replace every `prismer://(asset|file)/...` and
1284
+ * `https://…` / `http://…` URL with `file://<localPath>`.
1285
+ *
1286
+ * Unrecognized URIs pass through unchanged. Returns rewritten text, the
1287
+ * list of pinned hashes, and one observation per http(s) URL the resolver
1288
+ * attempted (success + error both surface) so the dispatch can include
1289
+ * them in `reply.assetObservability`.
1290
+ *
1291
+ * `urlCache` lets the caller dedupe URL fetches across multiple rewrite
1292
+ * calls within a single dispatch (e.g. prompt + each context entry).
1293
+ * Pass the same Map instance to every rewrite() / rewriteAll() call.
1294
+ */
1295
+ rewrite(text: string, opts?: {
1296
+ pin?: boolean;
1297
+ signal?: AbortSignal;
1298
+ /** L5: opt out of http(s) URL fetching for this string (e.g. memory/goal text). */
1299
+ fetchUrls?: boolean;
1300
+ /** L5: shared per-dispatch dedup map (originalUrl → cached resolution). */
1301
+ urlCache?: Map<string, UrlResolution>;
1302
+ /** L5: append url observations here (caller-owned array). */
1303
+ urlObservations?: AssetDispatchObservation[];
1304
+ }): Promise<{
1305
+ text: string;
1306
+ resolvedHashes: string[];
1307
+ }>;
1308
+ /** Bulk-rewrite an array of strings (e.g. context entries' content). */
1309
+ rewriteAll(texts: string[], opts?: {
1310
+ pin?: boolean;
1311
+ signal?: AbortSignal;
1312
+ fetchUrls?: boolean;
1313
+ urlCache?: Map<string, UrlResolution>;
1314
+ urlObservations?: AssetDispatchObservation[];
1315
+ }): Promise<{
1316
+ texts: string[];
1317
+ resolvedHashes: string[];
1318
+ }>;
1319
+ private lookupFile;
1320
+ }
1321
+ /**
1322
+ * L5: per-dispatch resolution record for a fetched http(s) URL. The same
1323
+ * record is reused across every reference to the URL in this dispatch
1324
+ * (prompt + N context entries) so we resolve once even if the URL appears
1325
+ * many times.
1326
+ */
1327
+ interface UrlResolution {
1328
+ hash: string;
1329
+ localPath: string;
1330
+ sizeBytes: number;
1331
+ mime: string | null;
1332
+ finalUrl: string;
1333
+ durationMs: number;
1334
+ }
1335
+ /**
1336
+ * Extract http(s) URLs from a string. Each match has trailing punctuation
1337
+ * stripped so callers can replace the exact match in the source text.
1338
+ * Duplicates are de-duped: the first occurrence wins.
1339
+ */
1340
+ declare function extractHttpUrls(text: string): string[];
1341
+
1257
1342
  interface OutboxWatcherOptions {
1258
1343
  /**
1259
1344
  * Default directory to watch when no setActiveTask has narrowed it.
@@ -1904,8 +1989,19 @@ declare class Runner extends EventEmitter {
1904
1989
  private lastTaskError?;
1905
1990
  private heartbeatTimer?;
1906
1991
  private taskReaperTimer?;
1992
+ private skillResyncTimer?;
1993
+ private skillSyncInFlight;
1907
1994
  constructor(opts?: RunnerOptions);
1908
1995
  start(): Promise<void>;
1996
+ /**
1997
+ * F16 (2026-05-20) — enumerate every non-deleted local agent_profile and
1998
+ * fan-out `syncInstalledSkillsForDispatch` via `syncAllAgentSkills`.
1999
+ * Fire-and-forget — failures are logged per profile but never throw.
2000
+ * Re-entrant guard so an overlong sync doesn't stack with the next tick.
2001
+ */
2002
+ private syncAllSkillsBackground;
2003
+ /** F16 — read all live agent_profiles from local DB → AgentProfile[]. */
2004
+ private loadAllProfiles;
1909
2005
  stop(): Promise<void>;
1910
2006
  isRunning(): boolean;
1911
2007
  /**
@@ -2198,4 +2294,4 @@ declare const codexAdapter: AdapterDef;
2198
2294
  declare function buildProgram(): Command;
2199
2295
  declare function runCli(argv?: string[]): Promise<void>;
2200
2296
 
2201
- export { type AcquireResult, type AdapterDef, type AdapterKind, AdapterRegistry, type AdapterService, type AgentChangedPayload, type AgentDispatchReplyAttachment, type AgentDispatchReplyPayload, type AgentDispatchReplyStatus, type AgentDispatchRequest, type AgentDispatchResponse, type AgentHostDeclarePayload, type AgentProfile, type AgentProfileChangedPayload, type AgentStatusChangedPayload, AssetCache, type AssetCacheOptions, type AssetChangedPayload, type AssetDispatchObservation, type AssetDispatchStrategy, type AssetRef, BUILTIN_ROLE_TEMPLATES, type CachedAsset, type ClaudeCodeConfig, CloudClient, type CloudClientOptions, CloudError, type CloudResponse, type CodexConfig, type Config, type ConfigPaths, ConfigSchema, type DispatchDeps, type Envelope, type FlushFn, type FlushResult, type HealthStatus, type HermesProfileConfig, type HostAckedPayload, type HostedAgentDeclaration, type IMAgentStatus, type IMWSMessage, type LocalDb, LocalServer, type LocalServerOptions, type LocalServerState, type MessageDispatchAgent, type MessageDispatchDeps, type MessageDispatchHandle, type MessageDispatchTaskInput, type NormalizedContent, type OpenClawProfileConfig, type PairOptions, type PairResult, type ParseClaim, ParseClaimController, type ParseClaimControllerOptions, type ParsedPrismerUri, type PrismerUriType, type RoleTemplate, Runner, type RunnerOptions, ServicePool, type SyncOperation, SyncQueue, type SyncQueueRow, type SyncResourceType, type SyncStatus, SyncWorker, type SyncWorkerOptions, TARGET_SCHEMA_VERSION, type TaskCancelPayload, type TaskDispatchContextEntry, type TaskDispatchProgressPayload, type TaskDispatchReplyPayload, type TaskDispatchRequestPayload, type TaskInput, type TaskResult, UriResolver, type UriResolverOptions, type ValidationResult, WS_CLOSE, type WorkspaceChangedPayload, type WorkspaceFileBinding, type WorkspaceFileChangedPayload, WorkspaceMirror, type WorkspaceMirrorOptions, WsClient, type WsClientOptions, buildProgram, claudeCodeAdapter, codexAdapter, composePrompt, configExists, currentSchemaVersion, deriveWsUrl, envelope, getRoleTemplate, handleAgentMessageDispatch, handleDispatch, hermesAdapter, isDaemonId, listRoleTemplates, loadConfig, newDaemonId, nextBackoffMs, openLocalDb, openclawAdapter, pair, parseCodexOutput, parseUris, resolvePaths, runCli, runMigrations, saveConfig };
2297
+ export { type AcquireResult, type AdapterDef, type AdapterKind, AdapterRegistry, type AdapterService, type AgentChangedPayload, type AgentDispatchReplyAttachment, type AgentDispatchReplyPayload, type AgentDispatchReplyStatus, type AgentDispatchRequest, type AgentDispatchResponse, type AgentHostDeclarePayload, type AgentProfile, type AgentProfileChangedPayload, type AgentStatusChangedPayload, AssetCache, type AssetCacheOptions, type AssetChangedPayload, type AssetDispatchObservation, type AssetDispatchStrategy, type AssetRef, BUILTIN_ROLE_TEMPLATES, type CachedAsset, type ClaudeCodeConfig, CloudClient, type CloudClientOptions, CloudError, type CloudResponse, type CodexConfig, type Config, type ConfigPaths, ConfigSchema, type DispatchDeps, type Envelope, type FlushFn, type FlushResult, type HealthStatus, type HermesProfileConfig, type HostAckedPayload, type HostedAgentDeclaration, type IMAgentStatus, type IMWSMessage, type LocalDb, LocalServer, type LocalServerOptions, type LocalServerState, type MessageDispatchAgent, type MessageDispatchDeps, type MessageDispatchHandle, type MessageDispatchTaskInput, type NormalizedContent, type OpenClawProfileConfig, type PairOptions, type PairResult, type ParseClaim, ParseClaimController, type ParseClaimControllerOptions, type ParsedPrismerUri, type PrismerUriType, type RoleTemplate, Runner, type RunnerOptions, ServicePool, type SyncOperation, SyncQueue, type SyncQueueRow, type SyncResourceType, type SyncStatus, SyncWorker, type SyncWorkerOptions, TARGET_SCHEMA_VERSION, type TaskCancelPayload, type TaskDispatchContextEntry, type TaskDispatchProgressPayload, type TaskDispatchReplyPayload, type TaskDispatchRequestPayload, type TaskInput, type TaskResult, UriResolver, type UriResolverOptions, type UrlResolution, type ValidationResult, WS_CLOSE, type WorkspaceChangedPayload, type WorkspaceFileBinding, type WorkspaceFileChangedPayload, WorkspaceMirror, type WorkspaceMirrorOptions, WsClient, type WsClientOptions, buildProgram, claudeCodeAdapter, codexAdapter, composePrompt, configExists, currentSchemaVersion, deriveWsUrl, envelope, extractHttpUrls, getRoleTemplate, handleAgentMessageDispatch, handleDispatch, hermesAdapter, isDaemonId, listRoleTemplates, loadConfig, newDaemonId, nextBackoffMs, openLocalDb, openclawAdapter, pair, parseCodexOutput, parseUris, resolvePaths, runCli, runMigrations, saveConfig };
package/dist/index.d.ts CHANGED
@@ -746,7 +746,15 @@ declare function saveConfig(config: Config, paths?: ConfigPaths): void;
746
746
  /** Derive a `wss?://` URL from a `https?://` base. Trailing `/ws` appended. */
747
747
  declare function deriveWsUrl(httpBase: string): string;
748
748
 
749
- declare function newDaemonId(): string;
749
+ interface NewDaemonIdOptions {
750
+ /** API key — when provided, the suffix becomes a deterministic sha256(hostname|apiKey)
751
+ * slice(0,12). Pass this so re-running `prismer setup` yields the same daemonId
752
+ * and cloud-side upsert dedupes the IMContainer row instead of accumulating. */
753
+ apiKey?: string;
754
+ /** Optional explicit hostname (test only). */
755
+ hostnameOverride?: string;
756
+ }
757
+ declare function newDaemonId(opts?: NewDaemonIdOptions): string;
750
758
  declare function isDaemonId(s: string): boolean;
751
759
 
752
760
  interface CloudClientOptions {
@@ -865,6 +873,38 @@ declare class AssetCache {
865
873
  signal?: AbortSignal;
866
874
  assetId?: string;
867
875
  }): Promise<CachedAsset>;
876
+ /**
877
+ * Fetch a public http(s) URL, content-hash dedup, cache locally.
878
+ *
879
+ * Mirrors `getOrFetch` (cache key = sha256 of body bytes), but the input
880
+ * is a URL whose hash we don't know up front. The fetcher applies:
881
+ *
882
+ * - SSRF guard (resolve hostname, reject loopback / RFC1918 / link-local
883
+ * / cloud-metadata / IPv6 ULA + link-local). Cross-host redirects
884
+ * re-validate the new host before each hop.
885
+ * - manual redirect handling (max 3 hops).
886
+ * - hard timeout (default 15 s, override via env
887
+ * `PRISMER_URL_FETCH_TIMEOUT_MS`).
888
+ * - streaming body read with abort-at-limit (default 5 MiB, override
889
+ * via env `PRISMER_URL_FETCH_MAX_BYTES`). Truncated bodies are NOT
890
+ * cached.
891
+ * - non-2xx → throws (caller should leave the URL in place and emit
892
+ * an `error` observation).
893
+ *
894
+ * On success returns { cached, finalUrl, durationMs }; the caller can
895
+ * pin / unpin the hash like any other asset.
896
+ */
897
+ getOrFetchUrl(url: string, opts?: {
898
+ signal?: AbortSignal;
899
+ userAgent?: string;
900
+ maxBytes?: number;
901
+ timeoutMs?: number;
902
+ maxRedirects?: number;
903
+ }): Promise<{
904
+ cached: CachedAsset;
905
+ finalUrl: string;
906
+ durationMs: number;
907
+ }>;
868
908
  /** Insert an already-on-disk asset into the cache (e.g., asset just produced by adapter). */
869
909
  registerLocal(hash: string, localPath: string, mime?: string): CachedAsset;
870
910
  /** Total bytes across all rows (incl. pinned). */
@@ -1022,68 +1062,6 @@ declare class ParseClaimController {
1022
1062
  }): HeartbeatHandle;
1023
1063
  }
1024
1064
 
1025
- type PrismerUriType = 'asset' | 'file';
1026
- interface ParsedPrismerUri {
1027
- /** Original full URI string. */
1028
- raw: string;
1029
- /**
1030
- * Owner segment for legacy `prismer://<owner>/...` form (informational,
1031
- * not ACL-checked). For `prismer://workspace/<wid>/...` this is the
1032
- * literal string 'workspace' — prefer `workspaceId` instead.
1033
- */
1034
- owner: string;
1035
- type: PrismerUriType;
1036
- /** For type='asset': the sha256 hash. For legacy file URIs: '<wsId>/<path>'. */
1037
- rest: string;
1038
- /** Convenience parses for type='file' and for workspace-form 'asset'. */
1039
- workspaceId?: string;
1040
- filePath?: string;
1041
- }
1042
- /**
1043
- * Find every recognized `prismer://...` reference in a string.
1044
- * Only `asset` and `file` types are recognized — other types (memory,
1045
- * context, conversation, evolution, task, pair) pass through untouched.
1046
- */
1047
- declare function parseUris(text: string): ParsedPrismerUri[];
1048
- interface UriResolverOptions {
1049
- db: LocalDb;
1050
- cloud: CloudClient;
1051
- assetCache: AssetCache;
1052
- }
1053
- declare class UriResolver {
1054
- private readonly db;
1055
- private readonly cloud;
1056
- private readonly assetCache;
1057
- constructor(opts: UriResolverOptions);
1058
- /**
1059
- * Resolve a single URI to a local file path. Throws on auth/4xx;
1060
- * caller decides whether to leave the URI in place (best-effort) or fail.
1061
- */
1062
- resolveOne(uri: ParsedPrismerUri, opts?: {
1063
- signal?: AbortSignal;
1064
- }): Promise<string>;
1065
- /**
1066
- * Walk a string, replace every `prismer://(asset|file)/...` with `file://<localPath>`.
1067
- * Unrecognized URIs pass through. Returns rewritten text + the list of pinned hashes.
1068
- */
1069
- rewrite(text: string, opts?: {
1070
- pin?: boolean;
1071
- signal?: AbortSignal;
1072
- }): Promise<{
1073
- text: string;
1074
- resolvedHashes: string[];
1075
- }>;
1076
- /** Bulk-rewrite an array of strings (e.g. context entries' content). */
1077
- rewriteAll(texts: string[], opts?: {
1078
- pin?: boolean;
1079
- signal?: AbortSignal;
1080
- }): Promise<{
1081
- texts: string[];
1082
- resolvedHashes: string[];
1083
- }>;
1084
- private lookupFile;
1085
- }
1086
-
1087
1065
  type IMAgentStatus = 'online' | 'busy' | 'idle' | 'offline';
1088
1066
  interface HostedAgentDeclaration {
1089
1067
  imUserId: string;
@@ -1185,15 +1163,22 @@ interface TaskDispatchProgressPayload {
1185
1163
  detail?: Record<string, unknown>;
1186
1164
  }
1187
1165
  /** Wave-8 W1: how the daemon handled a single AssetRef. */
1188
- type AssetDispatchStrategy = 'inline-text' | 'inline-text-truncated' | 'uri-only' | 'error';
1166
+ type AssetDispatchStrategy = 'inline-text' | 'inline-text-truncated' | 'uri-only' | 'fetched-https' | 'error';
1189
1167
  interface AssetDispatchObservation {
1190
- assetId: string;
1168
+ /** AssetRef.assetId for cloud-attached refs; undefined for L5 https fetches. */
1169
+ assetId?: string;
1191
1170
  contentHash: string;
1192
1171
  mime: string | null;
1193
1172
  sizeBytes: number | null;
1194
1173
  strategy: AssetDispatchStrategy;
1195
1174
  inlinedBytes?: number;
1196
1175
  error?: string;
1176
+ /** L5: original URL the user wrote in the prompt. */
1177
+ originalUrl?: string;
1178
+ /** L5: post-redirect URL the body was actually downloaded from. */
1179
+ finalUrl?: string;
1180
+ /** L5: end-to-end fetch duration in ms (DNS + connect + body read). */
1181
+ durationMs?: number;
1197
1182
  }
1198
1183
  interface TaskDispatchReplyPayload {
1199
1184
  taskId: string;
@@ -1254,6 +1239,106 @@ interface AssetChangedPayload {
1254
1239
  revision?: number;
1255
1240
  }
1256
1241
 
1242
+ type PrismerUriType = 'asset' | 'file';
1243
+ interface ParsedPrismerUri {
1244
+ /** Original full URI string. */
1245
+ raw: string;
1246
+ /**
1247
+ * Owner segment for legacy `prismer://<owner>/...` form (informational,
1248
+ * not ACL-checked). For `prismer://workspace/<wid>/...` this is the
1249
+ * literal string 'workspace' — prefer `workspaceId` instead.
1250
+ */
1251
+ owner: string;
1252
+ type: PrismerUriType;
1253
+ /** For type='asset': the sha256 hash. For legacy file URIs: '<wsId>/<path>'. */
1254
+ rest: string;
1255
+ /** Convenience parses for type='file' and for workspace-form 'asset'. */
1256
+ workspaceId?: string;
1257
+ filePath?: string;
1258
+ }
1259
+ /**
1260
+ * Find every recognized `prismer://...` reference in a string.
1261
+ * Only `asset` and `file` types are recognized — other types (memory,
1262
+ * context, conversation, evolution, task, pair) pass through untouched.
1263
+ */
1264
+ declare function parseUris(text: string): ParsedPrismerUri[];
1265
+ interface UriResolverOptions {
1266
+ db: LocalDb;
1267
+ cloud: CloudClient;
1268
+ assetCache: AssetCache;
1269
+ }
1270
+ declare class UriResolver {
1271
+ private readonly db;
1272
+ private readonly cloud;
1273
+ private readonly assetCache;
1274
+ constructor(opts: UriResolverOptions);
1275
+ /**
1276
+ * Resolve a single URI to a local file path. Throws on auth/4xx;
1277
+ * caller decides whether to leave the URI in place (best-effort) or fail.
1278
+ */
1279
+ resolveOne(uri: ParsedPrismerUri, opts?: {
1280
+ signal?: AbortSignal;
1281
+ }): Promise<string>;
1282
+ /**
1283
+ * Walk a string, replace every `prismer://(asset|file)/...` and
1284
+ * `https://…` / `http://…` URL with `file://<localPath>`.
1285
+ *
1286
+ * Unrecognized URIs pass through unchanged. Returns rewritten text, the
1287
+ * list of pinned hashes, and one observation per http(s) URL the resolver
1288
+ * attempted (success + error both surface) so the dispatch can include
1289
+ * them in `reply.assetObservability`.
1290
+ *
1291
+ * `urlCache` lets the caller dedupe URL fetches across multiple rewrite
1292
+ * calls within a single dispatch (e.g. prompt + each context entry).
1293
+ * Pass the same Map instance to every rewrite() / rewriteAll() call.
1294
+ */
1295
+ rewrite(text: string, opts?: {
1296
+ pin?: boolean;
1297
+ signal?: AbortSignal;
1298
+ /** L5: opt out of http(s) URL fetching for this string (e.g. memory/goal text). */
1299
+ fetchUrls?: boolean;
1300
+ /** L5: shared per-dispatch dedup map (originalUrl → cached resolution). */
1301
+ urlCache?: Map<string, UrlResolution>;
1302
+ /** L5: append url observations here (caller-owned array). */
1303
+ urlObservations?: AssetDispatchObservation[];
1304
+ }): Promise<{
1305
+ text: string;
1306
+ resolvedHashes: string[];
1307
+ }>;
1308
+ /** Bulk-rewrite an array of strings (e.g. context entries' content). */
1309
+ rewriteAll(texts: string[], opts?: {
1310
+ pin?: boolean;
1311
+ signal?: AbortSignal;
1312
+ fetchUrls?: boolean;
1313
+ urlCache?: Map<string, UrlResolution>;
1314
+ urlObservations?: AssetDispatchObservation[];
1315
+ }): Promise<{
1316
+ texts: string[];
1317
+ resolvedHashes: string[];
1318
+ }>;
1319
+ private lookupFile;
1320
+ }
1321
+ /**
1322
+ * L5: per-dispatch resolution record for a fetched http(s) URL. The same
1323
+ * record is reused across every reference to the URL in this dispatch
1324
+ * (prompt + N context entries) so we resolve once even if the URL appears
1325
+ * many times.
1326
+ */
1327
+ interface UrlResolution {
1328
+ hash: string;
1329
+ localPath: string;
1330
+ sizeBytes: number;
1331
+ mime: string | null;
1332
+ finalUrl: string;
1333
+ durationMs: number;
1334
+ }
1335
+ /**
1336
+ * Extract http(s) URLs from a string. Each match has trailing punctuation
1337
+ * stripped so callers can replace the exact match in the source text.
1338
+ * Duplicates are de-duped: the first occurrence wins.
1339
+ */
1340
+ declare function extractHttpUrls(text: string): string[];
1341
+
1257
1342
  interface OutboxWatcherOptions {
1258
1343
  /**
1259
1344
  * Default directory to watch when no setActiveTask has narrowed it.
@@ -1904,8 +1989,19 @@ declare class Runner extends EventEmitter {
1904
1989
  private lastTaskError?;
1905
1990
  private heartbeatTimer?;
1906
1991
  private taskReaperTimer?;
1992
+ private skillResyncTimer?;
1993
+ private skillSyncInFlight;
1907
1994
  constructor(opts?: RunnerOptions);
1908
1995
  start(): Promise<void>;
1996
+ /**
1997
+ * F16 (2026-05-20) — enumerate every non-deleted local agent_profile and
1998
+ * fan-out `syncInstalledSkillsForDispatch` via `syncAllAgentSkills`.
1999
+ * Fire-and-forget — failures are logged per profile but never throw.
2000
+ * Re-entrant guard so an overlong sync doesn't stack with the next tick.
2001
+ */
2002
+ private syncAllSkillsBackground;
2003
+ /** F16 — read all live agent_profiles from local DB → AgentProfile[]. */
2004
+ private loadAllProfiles;
1909
2005
  stop(): Promise<void>;
1910
2006
  isRunning(): boolean;
1911
2007
  /**
@@ -2198,4 +2294,4 @@ declare const codexAdapter: AdapterDef;
2198
2294
  declare function buildProgram(): Command;
2199
2295
  declare function runCli(argv?: string[]): Promise<void>;
2200
2296
 
2201
- export { type AcquireResult, type AdapterDef, type AdapterKind, AdapterRegistry, type AdapterService, type AgentChangedPayload, type AgentDispatchReplyAttachment, type AgentDispatchReplyPayload, type AgentDispatchReplyStatus, type AgentDispatchRequest, type AgentDispatchResponse, type AgentHostDeclarePayload, type AgentProfile, type AgentProfileChangedPayload, type AgentStatusChangedPayload, AssetCache, type AssetCacheOptions, type AssetChangedPayload, type AssetDispatchObservation, type AssetDispatchStrategy, type AssetRef, BUILTIN_ROLE_TEMPLATES, type CachedAsset, type ClaudeCodeConfig, CloudClient, type CloudClientOptions, CloudError, type CloudResponse, type CodexConfig, type Config, type ConfigPaths, ConfigSchema, type DispatchDeps, type Envelope, type FlushFn, type FlushResult, type HealthStatus, type HermesProfileConfig, type HostAckedPayload, type HostedAgentDeclaration, type IMAgentStatus, type IMWSMessage, type LocalDb, LocalServer, type LocalServerOptions, type LocalServerState, type MessageDispatchAgent, type MessageDispatchDeps, type MessageDispatchHandle, type MessageDispatchTaskInput, type NormalizedContent, type OpenClawProfileConfig, type PairOptions, type PairResult, type ParseClaim, ParseClaimController, type ParseClaimControllerOptions, type ParsedPrismerUri, type PrismerUriType, type RoleTemplate, Runner, type RunnerOptions, ServicePool, type SyncOperation, SyncQueue, type SyncQueueRow, type SyncResourceType, type SyncStatus, SyncWorker, type SyncWorkerOptions, TARGET_SCHEMA_VERSION, type TaskCancelPayload, type TaskDispatchContextEntry, type TaskDispatchProgressPayload, type TaskDispatchReplyPayload, type TaskDispatchRequestPayload, type TaskInput, type TaskResult, UriResolver, type UriResolverOptions, type ValidationResult, WS_CLOSE, type WorkspaceChangedPayload, type WorkspaceFileBinding, type WorkspaceFileChangedPayload, WorkspaceMirror, type WorkspaceMirrorOptions, WsClient, type WsClientOptions, buildProgram, claudeCodeAdapter, codexAdapter, composePrompt, configExists, currentSchemaVersion, deriveWsUrl, envelope, getRoleTemplate, handleAgentMessageDispatch, handleDispatch, hermesAdapter, isDaemonId, listRoleTemplates, loadConfig, newDaemonId, nextBackoffMs, openLocalDb, openclawAdapter, pair, parseCodexOutput, parseUris, resolvePaths, runCli, runMigrations, saveConfig };
2297
+ export { type AcquireResult, type AdapterDef, type AdapterKind, AdapterRegistry, type AdapterService, type AgentChangedPayload, type AgentDispatchReplyAttachment, type AgentDispatchReplyPayload, type AgentDispatchReplyStatus, type AgentDispatchRequest, type AgentDispatchResponse, type AgentHostDeclarePayload, type AgentProfile, type AgentProfileChangedPayload, type AgentStatusChangedPayload, AssetCache, type AssetCacheOptions, type AssetChangedPayload, type AssetDispatchObservation, type AssetDispatchStrategy, type AssetRef, BUILTIN_ROLE_TEMPLATES, type CachedAsset, type ClaudeCodeConfig, CloudClient, type CloudClientOptions, CloudError, type CloudResponse, type CodexConfig, type Config, type ConfigPaths, ConfigSchema, type DispatchDeps, type Envelope, type FlushFn, type FlushResult, type HealthStatus, type HermesProfileConfig, type HostAckedPayload, type HostedAgentDeclaration, type IMAgentStatus, type IMWSMessage, type LocalDb, LocalServer, type LocalServerOptions, type LocalServerState, type MessageDispatchAgent, type MessageDispatchDeps, type MessageDispatchHandle, type MessageDispatchTaskInput, type NormalizedContent, type OpenClawProfileConfig, type PairOptions, type PairResult, type ParseClaim, ParseClaimController, type ParseClaimControllerOptions, type ParsedPrismerUri, type PrismerUriType, type RoleTemplate, Runner, type RunnerOptions, ServicePool, type SyncOperation, SyncQueue, type SyncQueueRow, type SyncResourceType, type SyncStatus, SyncWorker, type SyncWorkerOptions, TARGET_SCHEMA_VERSION, type TaskCancelPayload, type TaskDispatchContextEntry, type TaskDispatchProgressPayload, type TaskDispatchReplyPayload, type TaskDispatchRequestPayload, type TaskInput, type TaskResult, UriResolver, type UriResolverOptions, type UrlResolution, type ValidationResult, WS_CLOSE, type WorkspaceChangedPayload, type WorkspaceFileBinding, type WorkspaceFileChangedPayload, WorkspaceMirror, type WorkspaceMirrorOptions, WsClient, type WsClientOptions, buildProgram, claudeCodeAdapter, codexAdapter, composePrompt, configExists, currentSchemaVersion, deriveWsUrl, envelope, extractHttpUrls, getRoleTemplate, handleAgentMessageDispatch, handleDispatch, hermesAdapter, isDaemonId, listRoleTemplates, loadConfig, newDaemonId, nextBackoffMs, openLocalDb, openclawAdapter, pair, parseCodexOutput, parseUris, resolvePaths, runCli, runMigrations, saveConfig };