@slock-ai/daemon 0.55.4 → 0.55.6

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.
@@ -1303,28 +1303,29 @@ Use the \`slock\` CLI for chat / task / attachment operations. The daemon inject
1303
1303
  5. **\`slock channel join\`** \u2014 Join a visible public channel. This only affects your own agent membership.
1304
1304
  6. **\`slock channel leave\`** \u2014 Leave a regular channel you have joined. This only affects your own agent membership.
1305
1305
  7. **\`slock thread unfollow\`** \u2014 Stop receiving ordinary delivery for a thread you no longer need to follow. This only affects your own agent attention state.
1306
- 8. **\`slock message read\`** \u2014 Read past messages from a channel, DM, or thread. Supports \`before\` / \`after\` pagination and \`around\` for centered context.
1306
+ 8. **\`slock message read\`** \u2014 Read past messages from a channel, DM, or thread. Supports \`before\` / \`after\` anchors and \`around\` for centered context.
1307
1307
  9. **\`slock message search\`** \u2014 Search messages visible to you, then inspect a hit with \`slock message read\`.
1308
- 10. **\`slock message react\`** \u2014 Add or remove your reaction on a message. Use sparingly: prefer acknowledgement/follow-up signals like \u{1F440}, and do not auto-react to every merge, deploy, or task completion with celebratory emoji.
1309
- 11. **\`slock task list\`** \u2014 View a channel's task board.
1310
- 12. **\`slock task create\`** \u2014 Create new task-messages in a channel (supports batch titles; equivalent to sending a new message and publishing it as a task-message, not claiming it for yourself).
1311
- 13. **\`slock task claim\`** \u2014 Claim tasks by number or message ID (supports batch, handles conflicts).
1312
- 14. **\`slock task unclaim\`** \u2014 Release your claim on a task.
1313
- 15. **\`slock task update\`** \u2014 Change a task's status (e.g. to in_review or done).
1314
- 16. **\`slock attachment upload\`** \u2014 Upload a file to attach to a message. Uses content sniffing for image previews; pass \`--mime-type\` only when you know the exact type. Returns an attachment ID to pass to \`slock message send\`.
1315
- 17. **\`slock attachment view\`** \u2014 Download an attached file by its attachment ID so you can inspect it locally.
1316
- 18. **\`slock profile show\`** \u2014 Show your own profile, or another visible profile via \`@handle\`. Mirrors the canonical Slock profile view.
1317
- 19. **\`slock profile update\`** \u2014 Update your own profile. Supports \`--avatar-file <path>\`, \`--avatar-url pixel:random:<seed>\`, \`--display-name <name>\`, and \`--description <text>\`. Use \`--avatar-url pixel:random:<seed>\` when you want a new pixel avatar but do not have a local image file. Values must be non-empty. Provide at least one flag per call; multiple flags can be combined.
1318
- 20. **\`slock integration list\`** \u2014 List built-in Slock apps, registered third-party services, and this agent's active Slock Agent Logins.
1319
- 21. **\`slock integration login\`** \u2014 Provision or reuse this agent's login for a built-in Slock app or registered third-party service.
1320
- 22. **\`slock integration env\`** \u2014 Print per-agent local CLI environment for a manifest-backed service that requires isolated HOME/XDG state.
1321
- 23. **\`slock reminder schedule\`** \u2014 Schedule a reminder for yourself later, at a specific time, or on a recurring cadence.
1322
- 24. **\`slock reminder list\`** \u2014 List your reminders, including lifecycle history for each reminder.
1323
- 25. **\`slock reminder snooze\`** \u2014 Push a reminder later without replacing it.
1324
- 26. **\`slock reminder update\`** \u2014 Change a reminder's title, schedule, or recurrence without creating a new reminder.
1325
- 27. **\`slock reminder cancel\`** \u2014 Cancel one of your reminders by ID.
1326
- 28. **\`slock reminder log\`** \u2014 Show the event log for a reminder, including fires, dismissals, and reschedules.
1327
- 29. **\`slock action prepare\`** \u2014 Prepare an action card for a human to commit (B-mode quick-commit shortcut). Posts a card the human can click to execute the action under their own identity. Pass \`--target <ch>\` and pipe the action JSON on stdin (variants: \`channel:create\`, \`agent:create\`).
1308
+ 10. **\`slock message resolve\`** \u2014 Verify that a cited message id exists exactly and print its canonical message row. Use this when checking whether a referenced id is real; \`read --around\` is for context, not proof.
1309
+ 11. **\`slock message react\`** \u2014 Add or remove your reaction on a message. Use sparingly: prefer acknowledgement/follow-up signals like \u{1F440}, and do not auto-react to every merge, deploy, or task completion with celebratory emoji.
1310
+ 12. **\`slock task list\`** \u2014 View a channel's task board.
1311
+ 13. **\`slock task create\`** \u2014 Create new task-messages in a channel (supports batch titles; equivalent to sending a new message and publishing it as a task-message, not claiming it for yourself).
1312
+ 14. **\`slock task claim\`** \u2014 Claim tasks by number or message ID (supports batch, handles conflicts).
1313
+ 15. **\`slock task unclaim\`** \u2014 Release your claim on a task.
1314
+ 16. **\`slock task update\`** \u2014 Change a task's status (e.g. to in_review or done).
1315
+ 17. **\`slock attachment upload\`** \u2014 Upload a file to attach to a message. Uses content sniffing for image previews; pass \`--mime-type\` only when you know the exact type. Returns an attachment ID to pass to \`slock message send\`.
1316
+ 18. **\`slock attachment view\`** \u2014 Download an attached file by its attachment ID so you can inspect it locally.
1317
+ 19. **\`slock profile show\`** \u2014 Show your own profile, or another visible profile via \`@handle\`. Mirrors the canonical Slock profile view.
1318
+ 20. **\`slock profile update\`** \u2014 Update your own profile. Supports \`--avatar-file <path>\`, \`--avatar-url pixel:random:<seed>\`, \`--display-name <name>\`, and \`--description <text>\`. Use \`--avatar-url pixel:random:<seed>\` when you want a new pixel avatar but do not have a local image file. Values must be non-empty. Provide at least one flag per call; multiple flags can be combined.
1319
+ 21. **\`slock integration list\`** \u2014 List built-in Slock apps, registered third-party services, and this agent's active Slock Agent Logins.
1320
+ 22. **\`slock integration login\`** \u2014 Provision or reuse this agent's login for a built-in Slock app or registered third-party service.
1321
+ 23. **\`slock integration env\`** \u2014 Print per-agent local CLI environment for a manifest-backed service that requires isolated HOME/XDG state.
1322
+ 24. **\`slock reminder schedule\`** \u2014 Schedule a reminder for yourself later, at a specific time, or on a recurring cadence.
1323
+ 25. **\`slock reminder list\`** \u2014 List your reminders, including lifecycle history for each reminder.
1324
+ 26. **\`slock reminder snooze\`** \u2014 Push a reminder later without replacing it.
1325
+ 27. **\`slock reminder update\`** \u2014 Change a reminder's title, schedule, or recurrence without creating a new reminder.
1326
+ 28. **\`slock reminder cancel\`** \u2014 Cancel one of your reminders by ID.
1327
+ 29. **\`slock reminder log\`** \u2014 Show the event log for a reminder, including fires, dismissals, and reschedules.
1328
+ 30. **\`slock action prepare\`** \u2014 Prepare an action card for a human to commit (B-mode quick-commit shortcut). Posts a card the human can click to execute the action under their own identity. Pass \`--target <ch>\` and pipe the action JSON on stdin (variants: \`channel:create\`, \`agent:create\`).
1328
1329
 
1329
1330
  The CLI prints human-readable canonical text on success (matching the format you see in received messages and history). On failure it prints JSON to stderr:
1330
1331
  - failure \u2192 stderr \`{"ok":false,"code":"...","message":"..."}\` with non-zero exit
@@ -1437,7 +1438,9 @@ If a built-in Slock app or registered third-party service requires login, use Sl
1437
1438
 
1438
1439
  \`slock message read --channel "#channel-name"\` or \`slock message read --channel dm:@peer-name\` or \`slock message read --channel "#channel:shortid"\`
1439
1440
 
1440
- To jump directly to a specific hit with nearby context, use \`slock message read --channel "..." --around "messageId"\` or \`slock message read --channel "..." --around 12345\`.` : `### Reading history
1441
+ To jump directly to a specific hit with nearby context, use \`slock message read --channel "..." --around "messageId"\` or \`slock message read --channel "..." --around 12345\`.
1442
+
1443
+ When verifying a cited message id, use \`slock message resolve <id>\`. It is exact-only and fails closed for missing or ambiguous ids; \`read --around\` is only a context-navigation command.` : `### Reading history
1441
1444
 
1442
1445
  Use ${readCmd} with the \`channel\` parameter set to \`"#channel-name"\`, \`"dm:@peer-name"\`, or a thread target like \`"#channel:shortid"\`.
1443
1446
 
@@ -2349,6 +2352,7 @@ function routeFamilyForPath(pathname) {
2349
2352
  if (pathname === "/internal/agent-api/tasks/update-status") return "tasks/update";
2350
2353
  if (pathname === "/internal/agent-api/tasks" || pathname.startsWith("/internal/agent-api/tasks/")) return "tasks";
2351
2354
  if (pathname.startsWith("/internal/agent-api/attachments/")) return "agent-api/attachments";
2355
+ if (/^\/internal\/agent-api\/messages\/[^/]+\/resolve$/.test(pathname)) return "agent-api/messages/resolve";
2352
2356
  if (/^\/internal\/agent-api\/messages\/[^/]+\/reactions$/.test(pathname)) return "agent-api/messages/reactions";
2353
2357
  if (pathname === "/internal/agent-api/server") return "server";
2354
2358
  if (pathname.startsWith("/internal/agent-api/history")) return "agent-api/events";
@@ -2769,7 +2773,7 @@ function shouldBufferJsonResponse(upstream, pathname, registration) {
2769
2773
  if (!registration.inboxCoordinator) return false;
2770
2774
  const contentType = upstream.headers.get("content-type") ?? "";
2771
2775
  if (!contentType.includes("application/json")) return false;
2772
- return pathname === "/internal/agent-api/send" || pathname === "/internal/agent-api/events" || pathname === "/internal/agent-api/history";
2776
+ return pathname === "/internal/agent-api/send" || pathname === "/internal/agent-api/events" || pathname === "/internal/agent-api/history" || /^\/internal\/agent-api\/messages\/[^/]+\/resolve$/.test(pathname);
2773
2777
  }
2774
2778
  function consumeVisibleResponse(registration, targetUrl, sendTarget, responseText) {
2775
2779
  const coordinator = registration.inboxCoordinator;
@@ -3171,7 +3175,7 @@ function collectModelUsageAttrs(value) {
3171
3175
  modelUsageMaxOutputTokens: aggregate.maxOutputTokens
3172
3176
  });
3173
3177
  }
3174
- function parseClaudeResultUsageTelemetry(event) {
3178
+ function parseClaudeResultUsageTelemetry(event, sessionId) {
3175
3179
  const usage = event.usage && typeof event.usage === "object" ? event.usage : void 0;
3176
3180
  const totalCostUsd = finiteNumber(event.total_cost_usd);
3177
3181
  const modelUsageAttrs = collectModelUsageAttrs(event.modelUsage);
@@ -3220,12 +3224,16 @@ function parseClaudeResultUsageTelemetry(event) {
3220
3224
  name: "token_usage",
3221
3225
  source: "claude_result_usage",
3222
3226
  usageKind: "per_turn",
3223
- ...typeof event.session_id === "string" && event.session_id ? { sessionId: event.session_id } : {},
3227
+ ...sessionId ? { sessionId } : {},
3224
3228
  ...typeof event.uuid === "string" && event.uuid ? { runtimeResultId: event.uuid } : {},
3225
3229
  attrs
3226
3230
  };
3227
3231
  }
3228
3232
  var ClaudeEventNormalizer = class {
3233
+ currentSession = null;
3234
+ get currentSessionId() {
3235
+ return this.currentSession;
3236
+ }
3229
3237
  normalizeLine(line) {
3230
3238
  let event;
3231
3239
  try {
@@ -3234,13 +3242,17 @@ var ClaudeEventNormalizer = class {
3234
3242
  return [];
3235
3243
  }
3236
3244
  const events = [];
3245
+ const eventSessionId = finiteString(event.session_id);
3246
+ if (eventSessionId) {
3247
+ this.currentSession = eventSessionId;
3248
+ }
3237
3249
  const pushResultError = (message, fallback) => {
3238
3250
  events.push({ kind: "error", message: collectResultErrorDetail(message, fallback) });
3239
3251
  };
3240
3252
  switch (event.type) {
3241
3253
  case "system":
3242
- if (event.subtype === "init" && event.session_id) {
3243
- events.push({ kind: "session_init", sessionId: event.session_id });
3254
+ if (event.subtype === "init" && eventSessionId) {
3255
+ events.push({ kind: "session_init", sessionId: eventSessionId });
3244
3256
  }
3245
3257
  if (event.subtype === "status" && event.status === "compacting") {
3246
3258
  events.push({ kind: "compaction_started" });
@@ -3299,7 +3311,8 @@ var ClaudeEventNormalizer = class {
3299
3311
  case "result": {
3300
3312
  const subtype = typeof event.subtype === "string" ? event.subtype : "success";
3301
3313
  const stopReason = typeof event.stop_reason === "string" ? event.stop_reason : null;
3302
- const usageTelemetry = parseClaudeResultUsageTelemetry(event);
3314
+ const resultSessionId = eventSessionId ?? this.currentSession;
3315
+ const usageTelemetry = parseClaudeResultUsageTelemetry(event, resultSessionId);
3303
3316
  switch (subtype) {
3304
3317
  case "success":
3305
3318
  if (event.is_error && stopReason !== "max_tokens") {
@@ -3322,7 +3335,7 @@ var ClaudeEventNormalizer = class {
3322
3335
  break;
3323
3336
  }
3324
3337
  if (usageTelemetry) events.push(usageTelemetry);
3325
- events.push({ kind: "turn_end", sessionId: event.session_id });
3338
+ events.push({ kind: "turn_end", sessionId: resultSessionId || void 0 });
3326
3339
  break;
3327
3340
  }
3328
3341
  }
@@ -3676,6 +3689,9 @@ var ClaudeDriver = class {
3676
3689
  parseLine(line) {
3677
3690
  return this.eventNormalizer.normalizeLine(line);
3678
3691
  }
3692
+ get currentSessionId() {
3693
+ return this.eventNormalizer.currentSessionId;
3694
+ }
3679
3695
  encodeStdinMessage(text, sessionId, _opts) {
3680
3696
  return JSON.stringify({
3681
3697
  type: "user",
@@ -3857,6 +3873,9 @@ function rawResponseItemProgressEvent(message) {
3857
3873
  payloadBytes
3858
3874
  };
3859
3875
  }
3876
+ function nonEmptyString(value) {
3877
+ return typeof value === "string" && value.length > 0 ? value : void 0;
3878
+ }
3860
3879
  var CodexEventNormalizer = class {
3861
3880
  mcpToolPrefix;
3862
3881
  currentThreadId = null;
@@ -3909,10 +3928,17 @@ var CodexEventNormalizer = class {
3909
3928
  }
3910
3929
  const telemetry = parseCodexTelemetryEvent(message);
3911
3930
  if (telemetry) {
3931
+ const telemetrySessionId = nonEmptyString(message.params?.threadId) ?? nonEmptyString(message.params?.thread?.id) ?? nonEmptyString(message.params?.sessionId);
3932
+ const telemetryTurnId = nonEmptyString(message.params?.turnId) ?? nonEmptyString(message.params?.turn?.id);
3933
+ if (telemetrySessionId) {
3934
+ this.currentThreadId = telemetrySessionId;
3935
+ }
3936
+ const sessionId = telemetrySessionId ?? this.currentThreadId ?? void 0;
3937
+ const turnId = telemetryTurnId ?? this.turnState.activeTurnId ?? void 0;
3912
3938
  events.push({
3913
3939
  ...telemetry,
3914
- ...this.currentThreadId ? { sessionId: this.currentThreadId } : {},
3915
- ...this.turnState.activeTurnId ? { turnId: this.turnState.activeTurnId } : {}
3940
+ ...sessionId ? { sessionId } : {},
3941
+ ...turnId ? { turnId } : {}
3916
3942
  });
3917
3943
  return { events };
3918
3944
  }
@@ -4361,6 +4387,9 @@ var CodexDriver = class {
4361
4387
  }
4362
4388
  return result.events;
4363
4389
  }
4390
+ get currentSessionId() {
4391
+ return this.normalizer.threadId;
4392
+ }
4364
4393
  encodeStdinMessage(text, sessionId, opts) {
4365
4394
  if (!this.normalizer.threadId && sessionId) {
4366
4395
  this.normalizer.adoptThreadId(sessionId);
@@ -7720,6 +7749,26 @@ function runtimeTraceCounterAttrs(ap) {
7720
7749
  runtime_thinking_events_count: ap.runtimeTraceCounters.thinkingEvents
7721
7750
  };
7722
7751
  }
7752
+ var RUNTIME_TELEMETRY_RESERVED_ATTR_KEYS = /* @__PURE__ */ new Set([
7753
+ "agentId",
7754
+ "launchId",
7755
+ "runtime",
7756
+ "model",
7757
+ "telemetry_name",
7758
+ "source",
7759
+ "usageKind",
7760
+ "sessionId",
7761
+ "turnId",
7762
+ "runtimeResultId"
7763
+ ]);
7764
+ function sanitizeRuntimeTelemetryPayloadAttrs(attrs) {
7765
+ const sanitized = {};
7766
+ for (const [key, value] of Object.entries(attrs)) {
7767
+ if (RUNTIME_TELEMETRY_RESERVED_ATTR_KEYS.has(key)) continue;
7768
+ sanitized[key] = value;
7769
+ }
7770
+ return sanitized;
7771
+ }
7723
7772
  function getMessageDeliveryText(driver) {
7724
7773
  return driver.supportsStdinNotification ? "New messages may be delivered to you automatically while your process stays alive." : "The daemon will automatically restart you when new messages arrive.";
7725
7774
  }
@@ -10454,11 +10503,13 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
10454
10503
  }
10455
10504
  }
10456
10505
  recordRuntimeTelemetry(agentId, ap, event) {
10506
+ const sessionId = ap.driver.currentSessionId ?? event.sessionId;
10507
+ const payloadAttrs = sanitizeRuntimeTelemetryPayloadAttrs(event.attrs);
10457
10508
  const telemetryAttrs = {
10458
- ...event.attrs,
10509
+ ...payloadAttrs,
10459
10510
  ...event.source ? { source: event.source } : {},
10460
10511
  ...event.usageKind ? { usageKind: event.usageKind } : {},
10461
- ...event.sessionId ? { sessionId: event.sessionId } : {},
10512
+ ...sessionId ? { sessionId } : {},
10462
10513
  ...event.turnId ? { turnId: event.turnId } : {},
10463
10514
  ...event.runtimeResultId ? { runtimeResultId: event.runtimeResultId } : {}
10464
10515
  };
package/dist/cli/index.js CHANGED
@@ -294,6 +294,10 @@ var ApiClient = class {
294
294
  if (suffix === "/send") return "/internal/agent-api/send";
295
295
  if (suffix.startsWith("/history")) return `/internal/agent-api/history${suffix.slice("/history".length)}`;
296
296
  if (suffix.startsWith("/search")) return `/internal/agent-api/search${suffix.slice("/search".length)}`;
297
+ const messageResolve = /^\/messages\/([^/]+)\/resolve$/.exec(suffix);
298
+ if (messageResolve) {
299
+ return `/internal/agent-api/messages/${messageResolve[1]}/resolve`;
300
+ }
297
301
  if (suffix.startsWith("/channel-members")) return `/internal/agent-api/channel-members${suffix.slice("/channel-members".length)}`;
298
302
  if (suffix === "/knowledge" || suffix.startsWith("/knowledge?")) {
299
303
  return `/internal/agent-api/knowledge${suffix.slice("/knowledge".length)}`;
@@ -16463,6 +16467,32 @@ function buildReadPath(agentId, opts) {
16463
16467
  if (opts.limit !== void 0) params.set("limit", String(opts.limit));
16464
16468
  return `/internal/agent/${encodeURIComponent(agentId)}/history?${params.toString()}`;
16465
16469
  }
16470
+ function mapReadFailure(res) {
16471
+ if (res.errorCode === "NOT_FOUND") {
16472
+ return new CliError({
16473
+ code: "NOT_FOUND",
16474
+ message: res.error ?? `HTTP ${res.status}`,
16475
+ suggestedNextAction: res.suggestedNextAction ?? void 0
16476
+ });
16477
+ }
16478
+ if (res.errorCode === "AMBIGUOUS_ID") {
16479
+ return new CliError({
16480
+ code: "AMBIGUOUS_ID",
16481
+ message: res.error ?? `HTTP ${res.status}`,
16482
+ suggestedNextAction: res.suggestedNextAction ?? "Use the full message UUID instead of the 8-character short id."
16483
+ });
16484
+ }
16485
+ if (res.errorCode === "INVALID_ARG") {
16486
+ return new CliError({
16487
+ code: "INVALID_ARG",
16488
+ message: res.error ?? `HTTP ${res.status}`
16489
+ });
16490
+ }
16491
+ return new CliError({
16492
+ code: res.status >= 500 ? "SERVER_5XX" : "READ_FAILED",
16493
+ message: res.error ?? `HTTP ${res.status}`
16494
+ });
16495
+ }
16466
16496
  function validateReadOpts(opts) {
16467
16497
  const channel = opts.channel?.trim();
16468
16498
  if (!channel) {
@@ -16471,13 +16501,13 @@ function validateReadOpts(opts) {
16471
16501
  message: "--channel is required"
16472
16502
  });
16473
16503
  }
16474
- const before = parsePositiveInt("before", opts.before);
16475
- const after = parsePositiveInt("after", opts.after);
16476
16504
  const limit = parsePositiveInt("limit", opts.limit);
16505
+ const before = opts.before?.trim();
16506
+ const after = opts.after?.trim();
16477
16507
  return {
16478
16508
  channel,
16479
- ...before !== void 0 ? { before } : {},
16480
- ...after !== void 0 ? { after } : {},
16509
+ ...before ? { before } : {},
16510
+ ...after ? { after } : {},
16481
16511
  ...opts.around !== void 0 ? { around: opts.around } : {},
16482
16512
  ...limit !== void 0 ? { limit } : {}
16483
16513
  };
@@ -16488,9 +16518,9 @@ var messageReadCommand = defineCommand(
16488
16518
  description: "Read message history for a channel, DM, or thread",
16489
16519
  options: [
16490
16520
  { flags: "--channel <target>", description: "Target: '#channel', 'dm:@peer', '#channel:threadId', 'dm:@peer:threadId'" },
16491
- { flags: "--before <seq>", description: "Return messages strictly before this seq (paginate backwards)" },
16492
- { flags: "--after <seq>", description: "Return messages strictly after this seq (paginate forwards)" },
16493
- { flags: "--around <idOrSeq>", description: "Center the window on this messageId or seq" },
16521
+ { flags: "--before <idOrSeq>", description: "Return messages strictly before this message id or seq anchor" },
16522
+ { flags: "--after <idOrSeq>", description: "Return messages strictly after this message id or seq anchor" },
16523
+ { flags: "--around <idOrSeq>", description: "Center the window on this message id or seq anchor" },
16494
16524
  { flags: "--limit <n>", description: "Max messages to return (server default applies if omitted)" }
16495
16525
  ]
16496
16526
  },
@@ -16503,10 +16533,7 @@ var messageReadCommand = defineCommand(
16503
16533
  buildReadPath(agentContext.agentId, readOpts)
16504
16534
  );
16505
16535
  if (!res.ok) {
16506
- throw new CliError({
16507
- code: res.status >= 500 ? "SERVER_5XX" : "READ_FAILED",
16508
- message: res.error ?? `HTTP ${res.status}`
16509
- });
16536
+ throw mapReadFailure(res);
16510
16537
  }
16511
16538
  writeText(
16512
16539
  ctx.io,
@@ -16640,6 +16667,77 @@ function registerSearchCommand(parent, runtimeOptions) {
16640
16667
  registerCliCommand(parent, messageSearchCommand, runtimeOptions);
16641
16668
  }
16642
16669
 
16670
+ // src/commands/message/resolve.ts
16671
+ function buildResolvePath(agentId, id) {
16672
+ return `/internal/agent/${encodeURIComponent(agentId)}/messages/${encodeURIComponent(id)}/resolve`;
16673
+ }
16674
+ function mapResolveError(res) {
16675
+ const message = res.error ?? `HTTP ${res.status}`;
16676
+ if (res.errorCode === "AMBIGUOUS_ID") {
16677
+ return {
16678
+ code: "AMBIGUOUS_ID",
16679
+ message,
16680
+ suggestedNextAction: "Use the full message UUID instead of the 8-character short id."
16681
+ };
16682
+ }
16683
+ if (res.errorCode === "NOT_FOUND" || res.status === 404) {
16684
+ return {
16685
+ code: "NOT_FOUND",
16686
+ message,
16687
+ suggestedNextAction: "Use slock message search to find the message, or slock message read --around only when you want nearby context rather than proof that this id exists."
16688
+ };
16689
+ }
16690
+ if (res.errorCode === "INVALID_ARG" || res.status === 400) {
16691
+ return { code: "INVALID_ARG", message };
16692
+ }
16693
+ return {
16694
+ code: res.status >= 500 ? "SERVER_5XX" : "READ_FAILED",
16695
+ message
16696
+ };
16697
+ }
16698
+ var messageResolveCommand = defineCommand(
16699
+ {
16700
+ name: "resolve",
16701
+ description: "Resolve a message id exactly and print the canonical message",
16702
+ arguments: ["<id>"]
16703
+ },
16704
+ async (ctx, rawId) => {
16705
+ const id = rawId?.trim();
16706
+ if (!id) {
16707
+ throw new CliError({
16708
+ code: "INVALID_ARG",
16709
+ message: "<id> is required"
16710
+ });
16711
+ }
16712
+ const agentContext = ctx.loadAgentContext();
16713
+ const client = ctx.createApiClient(agentContext);
16714
+ const res = await client.request(
16715
+ "GET",
16716
+ buildResolvePath(agentContext.agentId, id)
16717
+ );
16718
+ if (!res.ok) {
16719
+ const mapped = mapResolveError(res);
16720
+ throw new CliError(mapped);
16721
+ }
16722
+ const message = res.data?.message;
16723
+ if (!message) {
16724
+ throw new CliError({
16725
+ code: "INVALID_JSON_RESPONSE",
16726
+ message: "Missing message in resolve response"
16727
+ });
16728
+ }
16729
+ writeText(ctx.io, `${formatMessages([{
16730
+ ...message,
16731
+ parent_channel_type: message.parent_channel_type ?? void 0,
16732
+ parent_channel_name: message.parent_channel_name ?? void 0
16733
+ }])}
16734
+ `);
16735
+ }
16736
+ );
16737
+ function registerResolveCommand(parent, runtimeOptions) {
16738
+ registerCliCommand(parent, messageResolveCommand, runtimeOptions);
16739
+ }
16740
+
16643
16741
  // src/commands/message/react.ts
16644
16742
  function normalizeReactionEmoji(value) {
16645
16743
  const emoji3 = value.trim();
@@ -16653,7 +16751,7 @@ var messageReactCommand = defineCommand(
16653
16751
  name: "react",
16654
16752
  description: "Add or remove your reaction on a message",
16655
16753
  options: [
16656
- { flags: "--message-id <id>", description: "Message UUID to react to" },
16754
+ { flags: "--message-id <id>", description: "Message id (full or short) to react to" },
16657
16755
  { flags: "--emoji <emoji>", description: "Reaction emoji" },
16658
16756
  { flags: "--remove", description: "Remove your reaction instead of adding it" }
16659
16757
  ],
@@ -18486,6 +18584,7 @@ registerSendCommand(messageCmd);
18486
18584
  registerCheckCommand(messageCmd);
18487
18585
  registerReadCommand(messageCmd);
18488
18586
  registerSearchCommand(messageCmd);
18587
+ registerResolveCommand(messageCmd);
18489
18588
  registerReactCommand(messageCmd);
18490
18589
  var attachmentCmd = program.command("attachment").description("Attachment operations");
18491
18590
  registerAttachmentUploadCommand(attachmentCmd);
package/dist/core.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  resolveSlockCliPath,
10
10
  resolveWorkspaceDirectoryPath,
11
11
  scanWorkspaceDirectories
12
- } from "./chunk-S5AEBH3V.js";
12
+ } from "./chunk-HAZSZDOZ.js";
13
13
  import {
14
14
  subscribeDaemonLogs
15
15
  } from "./chunk-M2KQBJR3.js";
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  DAEMON_CLI_USAGE,
4
4
  DaemonCore,
5
5
  parseDaemonCliArgs
6
- } from "./chunk-S5AEBH3V.js";
6
+ } from "./chunk-HAZSZDOZ.js";
7
7
  import "./chunk-M2KQBJR3.js";
8
8
 
9
9
  // src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slock-ai/daemon",
3
- "version": "0.55.4",
3
+ "version": "0.55.6",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "slock-daemon": "dist/index.js"