@botiverse/raft-daemon 0.70.3 → 0.71.1

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.
@@ -27788,6 +27788,7 @@ var CliError = class extends Error {
27788
27788
  code;
27789
27789
  exitCode;
27790
27790
  suggestedNextAction;
27791
+ draftSaved;
27791
27792
  constructor(options) {
27792
27793
  super(options.message);
27793
27794
  this.name = "CliError";
@@ -27795,6 +27796,7 @@ var CliError = class extends Error {
27795
27796
  this.exitCode = options.exitCode ?? 1;
27796
27797
  this.cause = options.cause;
27797
27798
  this.suggestedNextAction = options.suggestedNextAction;
27799
+ this.draftSaved = options.draftSaved;
27798
27800
  }
27799
27801
  };
27800
27802
  var CliExit = class extends Error {
@@ -27821,7 +27823,8 @@ function cliError(code, message, options = {}) {
27821
27823
  message,
27822
27824
  exitCode: options.exitCode,
27823
27825
  cause: options.cause,
27824
- suggestedNextAction: options.suggestedNextAction
27826
+ suggestedNextAction: options.suggestedNextAction,
27827
+ draftSaved: options.draftSaved
27825
27828
  });
27826
27829
  }
27827
27830
  function toCliError(err) {
@@ -28615,6 +28618,7 @@ var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28615
28618
  { key: "error_class", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28616
28619
  { key: "query_name", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "query_registry" },
28617
28620
  { key: "phase", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28621
+ { key: "eligibility_subcheck", fieldClass: "query_axis", placement: "event", valueKind: "closed_enum", enumBinding: "pending_457" },
28618
28622
  { key: "hint_source", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
28619
28623
  { key: "resolved_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
28620
28624
  { key: "previous_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
@@ -42459,6 +42463,9 @@ function validateActionCardAction(action) {
42459
42463
  return null;
42460
42464
  }
42461
42465
  init_esm_shims();
42466
+ init_esm_shims();
42467
+ var ATTENTION_HINT_SCHEMA = "attention-dependency-hint.v1";
42468
+ var ATTENTION_HINT_DEFAULT_WINDOW_MS = 7 * 24 * 60 * 60 * 1e3;
42462
42469
  var AGENT_API_BASE_PATH = "/internal/agent-api";
42463
42470
  var optionalStringSchema = external_exports.string().trim().optional();
42464
42471
  var optionalStringArraySchema = external_exports.array(external_exports.string().trim().min(1)).optional();
@@ -42500,6 +42507,24 @@ var agentApiKnowledgeGetResponseSchema = passthroughObject({
42500
42507
  contentType: external_exports.string(),
42501
42508
  content: external_exports.string()
42502
42509
  });
42510
+ var agentApiKnowledgeSearchQuerySchema = passthroughObject({
42511
+ query: external_exports.string().trim().min(1),
42512
+ scope: optionalStringSchema,
42513
+ reason: optionalStringSchema,
42514
+ turn_id: optionalStringSchema,
42515
+ trace_id: optionalStringSchema
42516
+ });
42517
+ var agentApiKnowledgeSearchResultSchema = passthroughObject({
42518
+ slug: external_exports.string(),
42519
+ title: external_exports.string(),
42520
+ firstScreen: external_exports.string()
42521
+ });
42522
+ var agentApiKnowledgeSearchResponseSchema = passthroughObject({
42523
+ ok: external_exports.literal(true),
42524
+ query: external_exports.string(),
42525
+ scope: external_exports.string().nullable(),
42526
+ results: external_exports.array(agentApiKnowledgeSearchResultSchema)
42527
+ });
42503
42528
  var agentApiMessageSearchQuerySchema = passthroughObject({
42504
42529
  q: optionalStringSchema,
42505
42530
  channel: optionalStringSchema,
@@ -42951,7 +42976,14 @@ var agentApiSendSentResponseSchema = passthroughObject({
42951
42976
  messageId: external_exports.string(),
42952
42977
  messageSeq: optionalNumberSchema,
42953
42978
  recentUnread: external_exports.array(agentApiMessageEnvelopeSchema).optional(),
42954
- pendingMentionActions: external_exports.array(agentApiMessageEnvelopeSchema).optional()
42979
+ pendingMentionActions: external_exports.array(agentApiMessageEnvelopeSchema).optional(),
42980
+ attention: passthroughObject({
42981
+ driveByJoinedToPost: passthroughObject({
42982
+ reason: optionalStringSchema,
42983
+ muteCommand: optionalStringSchema,
42984
+ stillArrives: optionalStringArraySchema
42985
+ }).optional()
42986
+ }).optional()
42955
42987
  });
42956
42988
  var agentApiSendResponseSchema = external_exports.discriminatedUnion("state", [
42957
42989
  agentApiSendSentResponseSchema,
@@ -42960,8 +42992,17 @@ var agentApiSendResponseSchema = external_exports.discriminatedUnion("state", [
42960
42992
  var agentApiMessageResolveResponseSchema = passthroughObject({
42961
42993
  message: agentApiMessageEnvelopeSchema
42962
42994
  });
42995
+ var agentApiChannelAttentionSchema = passthroughObject({
42996
+ state: optionalStringSchema,
42997
+ ordinaryActivity: optionalStringSchema,
42998
+ stillArrives: optionalStringArraySchema,
42999
+ threadBoundary: optionalStringSchema,
43000
+ manageCommand: optionalStringSchema,
43001
+ manageApi: optionalStringSchema
43002
+ });
42963
43003
  var agentApiOkResponseSchema = passthroughObject({
42964
- ok: external_exports.literal(true)
43004
+ ok: external_exports.literal(true),
43005
+ attention: agentApiChannelAttentionSchema.optional()
42965
43006
  });
42966
43007
  var agentApiSearchResultSchema = passthroughObject({
42967
43008
  id: external_exports.string(),
@@ -43018,6 +43059,16 @@ var agentApiChannelMuteResponseSchema = passthroughObject({
43018
43059
  catchUp: optionalStringSchema
43019
43060
  }).optional()
43020
43061
  });
43062
+ var agentApiChannelMuteBodySchema = passthroughObject({
43063
+ attentionHintAccepted: passthroughObject({
43064
+ schema: external_exports.literal(ATTENTION_HINT_SCHEMA),
43065
+ trigger: external_exports.enum(["M2", "M3"]),
43066
+ scope: external_exports.string().trim().min(1),
43067
+ suggested_command: optionalStringSchema,
43068
+ copy_version: external_exports.string().trim().min(1),
43069
+ epoch_ms: external_exports.number().int().nonnegative()
43070
+ }).optional()
43071
+ });
43021
43072
  var agentApiTaskClaimResultSchema = passthroughObject({
43022
43073
  taskNumber: external_exports.number().int().positive().optional(),
43023
43074
  messageId: optionalStringSchema,
@@ -43140,6 +43191,16 @@ var agentApiContract = {
43140
43191
  request: { query: agentApiKnowledgeGetQuerySchema },
43141
43192
  response: { body: agentApiKnowledgeGetResponseSchema }
43142
43193
  }),
43194
+ knowledgeSearch: route({
43195
+ key: "knowledgeSearch",
43196
+ method: "GET",
43197
+ path: "/knowledge/search",
43198
+ client: { resource: "knowledge", method: "search" },
43199
+ capability: "knowledge",
43200
+ description: "Search Slock Manual for Agents topics from the current server.",
43201
+ request: { query: agentApiKnowledgeSearchQuerySchema },
43202
+ response: { body: agentApiKnowledgeSearchResponseSchema }
43203
+ }),
43143
43204
  messageSend: route({
43144
43205
  key: "messageSend",
43145
43206
  method: "POST",
@@ -43217,7 +43278,7 @@ var agentApiContract = {
43217
43278
  client: { resource: "channels", method: "mute" },
43218
43279
  capability: "channels",
43219
43280
  description: "Mute ordinary activity delivery for a visible regular channel as the bound agent credential.",
43220
- request: { params: agentApiChannelMembershipParamsSchema },
43281
+ request: { params: agentApiChannelMembershipParamsSchema, body: agentApiChannelMuteBodySchema },
43221
43282
  response: { body: agentApiChannelMuteResponseSchema }
43222
43283
  }),
43223
43284
  channelUnmute: route({
@@ -43863,6 +43924,20 @@ var optionalQueryIntSchema = external_exports.union([external_exports.number().i
43863
43924
  var nullableNumberSchema2 = external_exports.number().finite().nullable();
43864
43925
  var passthroughObject2 = (shape) => external_exports.object(shape).passthrough();
43865
43926
  var daemonApiInboxFlagSchema = external_exports.enum(["mention", "thread", "dm", "task"]);
43927
+ var daemonApiAttentionHintSchema = passthroughObject2({
43928
+ schema: external_exports.literal(ATTENTION_HINT_SCHEMA),
43929
+ trigger: external_exports.enum(["M2", "M3"]),
43930
+ scope: external_exports.string().trim().min(1),
43931
+ suggested_command: external_exports.string().trim().min(1),
43932
+ copy: external_exports.string().trim().min(1),
43933
+ copy_version: external_exports.literal("attention-hint-copy-v1"),
43934
+ epoch_ms: external_exports.number().int().nonnegative(),
43935
+ thresholds: passthroughObject2({
43936
+ K: optionalNonNegativeIntSchema,
43937
+ k: optionalNonNegativeIntSchema,
43938
+ window_ms: external_exports.number().int().positive()
43939
+ })
43940
+ });
43866
43941
  var daemonApiInboxTargetRowSchema = passthroughObject2({
43867
43942
  target: external_exports.string().trim().min(1),
43868
43943
  channelId: optionalStringSchema2,
@@ -43873,8 +43948,9 @@ var daemonApiInboxTargetRowSchema = passthroughObject2({
43873
43948
  latestMsgId: optionalStringSchema2,
43874
43949
  latestSeq: optionalNonNegativeIntSchema,
43875
43950
  latestSenderName: optionalStringSchema2,
43876
- latestSenderType: external_exports.enum(["human", "agent", "system"]).optional(),
43877
- flags: external_exports.array(daemonApiInboxFlagSchema)
43951
+ latestSenderType: external_exports.enum(["human", "agent", "system", "third_party_app"]).optional(),
43952
+ flags: external_exports.array(daemonApiInboxFlagSchema),
43953
+ attentionHint: daemonApiAttentionHintSchema.optional()
43878
43954
  });
43879
43955
  var daemonApiInboxCheckResponseSchema = passthroughObject2({
43880
43956
  rows: external_exports.array(daemonApiInboxTargetRowSchema).optional()
@@ -43897,6 +43973,7 @@ var daemonApiWakeHintSchema = passthroughObject2({
43897
43973
  target_type: optionalStringSchema2,
43898
43974
  reason: optionalStringSchema2,
43899
43975
  wake_reason: optionalStringSchema2,
43976
+ attention_hint: daemonApiAttentionHintSchema.optional(),
43900
43977
  createdAt: optionalStringSchema2,
43901
43978
  created_at: optionalStringSchema2
43902
43979
  });
@@ -44244,6 +44321,7 @@ function formatAgentInboxRowDetails(row) {
44244
44321
  if (row.latestSenderName) parts.push(`latest sender @${row.latestSenderName}`);
44245
44322
  if (row.latestMsgId) parts.push(`latest msg=${shortMessageId(row.latestMsgId)}`);
44246
44323
  parts.push(...row.flags.map(formatAgentInboxFlag));
44324
+ if (row.attentionHint) parts.push(`attention_hint=${formatAttentionHintField(row.attentionHint)}`);
44247
44325
  return parts.join(" \xB7 ");
44248
44326
  }
44249
44327
  function formatAgentInboxFlag(flag) {
@@ -44253,6 +44331,18 @@ function formatAgentInboxFlag(flag) {
44253
44331
  function shortMessageId(value) {
44254
44332
  return value.slice(0, 8);
44255
44333
  }
44334
+ function formatAttentionHintField(hint) {
44335
+ return JSON.stringify({
44336
+ schema: hint.schema,
44337
+ trigger: hint.trigger,
44338
+ scope: hint.scope,
44339
+ suggested_command: hint.suggested_command,
44340
+ copy: hint.copy,
44341
+ copy_version: hint.copy_version,
44342
+ epoch_ms: hint.epoch_ms,
44343
+ thresholds: hint.thresholds
44344
+ });
44345
+ }
44256
44346
  init_esm_shims();
44257
44347
  var EXTERNAL_AGENT_COMMS_PROTOCOL_VERSION = "agent-comms-core.v1";
44258
44348
  var EXTERNAL_AGENT_PROOF_SCHEMA_VERSION = "agent-proof.v1";
@@ -44543,6 +44633,9 @@ var SERVER_CAPABILITY_MATRIX = {
44543
44633
  joinPublicChannels: true
44544
44634
  })
44545
44635
  };
44636
+ init_esm_shims();
44637
+ init_esm_shims();
44638
+ init_esm_shims();
44546
44639
  var BUILTIN_RUNTIME_PROVIDER_ENV_KEYS = PI_BUILTIN_PROVIDER_API_KEY_ENV_KEYS_GENERATED;
44547
44640
  var BUILTIN_RUNTIME_PROVIDERS = Object.entries(BUILTIN_RUNTIME_PROVIDER_ENV_KEYS).map(([id, envKey]) => ({ id, envKey }));
44548
44641
  var PI_BUILTIN_PROVIDER_ENV_KEYS = {
@@ -44622,9 +44715,9 @@ function isExternalAgentRuntime(runtime) {
44622
44715
  return runtime === EXTERNAL_AGENT_RUNTIME_ID;
44623
44716
  }
44624
44717
  var RUNTIMES = [
44625
- { id: "builtin", displayName: "Built-in", binary: "", supported: true },
44626
44718
  { id: "claude", displayName: "Claude Code", binary: "claude", supported: true },
44627
44719
  { id: "codex", displayName: "Codex CLI", binary: "codex", supported: true },
44720
+ { id: "builtin", displayName: "Builtin Pi", binary: "", supported: true },
44628
44721
  { id: "antigravity", displayName: "Antigravity CLI", binary: "agy", supported: true },
44629
44722
  // Kimi: prefer the in-process SDK (`kimi-sdk` → "Kimi Code") for new agents.
44630
44723
  // The legacy `kimi` (kimi-cli child-process) entry stays for backward compat
@@ -44982,7 +45075,8 @@ function createAgentApiSurfaceClient(client) {
44982
45075
  read: (query) => requestClientAsApiResponse(agentApi.history.read(query))
44983
45076
  },
44984
45077
  knowledge: {
44985
- get: (query) => requestClientAsApiResponse(agentApi.knowledge.get(query))
45078
+ get: (query) => requestClientAsApiResponse(agentApi.knowledge.get(query)),
45079
+ search: (query) => requestClientAsApiResponse(agentApi.knowledge.search(query))
44986
45080
  },
44987
45081
  tasks: {
44988
45082
  list: (query) => requestClientAsApiResponse(agentApi.tasks.list(query)),
@@ -45009,7 +45103,7 @@ function createAgentApiSurfaceClient(client) {
45009
45103
  channels: {
45010
45104
  join: (params) => requestClientAsApiResponse(agentApi.channels.join(params)),
45011
45105
  leave: (params) => requestClientAsApiResponse(agentApi.channels.leave(params)),
45012
- mute: (params) => requestClientAsApiResponse(agentApi.channels.mute(params)),
45106
+ mute: (params) => requestClientAsApiResponse(agentApi.channels.mute(params, {})),
45013
45107
  unmute: (params) => requestClientAsApiResponse(agentApi.channels.unmute(params)),
45014
45108
  members: (query) => requestClientAsApiResponse(agentApi.channels.members(query)),
45015
45109
  resolve: (body) => requestClientAsApiResponse(agentApi.channels.resolve(body))
@@ -45713,6 +45807,10 @@ function renderError(io, err) {
45713
45807
  `);
45714
45808
  io.stderr.write(`Code: ${err.code}
45715
45809
  `);
45810
+ if (err.draftSaved !== void 0) {
45811
+ io.stderr.write(`Draft saved: ${err.draftSaved ? "yes" : "no"}
45812
+ `);
45813
+ }
45716
45814
  if (err.suggestedNextAction) {
45717
45815
  io.stderr.write(`Next action: ${err.suggestedNextAction}
45718
45816
  `);
@@ -45734,8 +45832,16 @@ function registerCliCommand(parent, command, runtimeOptions = {}) {
45734
45832
  child.argument(arg);
45735
45833
  }
45736
45834
  for (const option of command.spec.options ?? []) {
45835
+ const commanderOption = option.hidden ? new Option(option.flags, option.description).hideHelp() : null;
45737
45836
  if (option.parse) {
45738
- child.option(option.flags, option.description, option.parse);
45837
+ if (commanderOption) {
45838
+ commanderOption.argParser(option.parse);
45839
+ child.addOption(commanderOption);
45840
+ } else {
45841
+ child.option(option.flags, option.description, option.parse);
45842
+ }
45843
+ } else if (commanderOption) {
45844
+ child.addOption(commanderOption);
45739
45845
  } else {
45740
45846
  child.option(option.flags, option.description);
45741
45847
  }
@@ -48041,6 +48147,156 @@ function formatServerInfo(data) {
48041
48147
  }
48042
48148
  return text;
48043
48149
  }
48150
+ function channelRef(name) {
48151
+ return name.startsWith("#") ? name : `#${name}`;
48152
+ }
48153
+ function channelVisibility(channel) {
48154
+ const type = channel.type?.trim();
48155
+ return type === "private" ? "private" : "public";
48156
+ }
48157
+ function channelMuted(channel) {
48158
+ if (typeof channel.muted === "boolean") return channel.muted;
48159
+ if (typeof channel.activityMuted === "boolean") return channel.activityMuted;
48160
+ return void 0;
48161
+ }
48162
+ function channelStatus(channel) {
48163
+ const parts = [
48164
+ channelVisibility(channel),
48165
+ channel.joined ? "joined" : "not joined"
48166
+ ];
48167
+ const muted = channelMuted(channel);
48168
+ if (muted !== void 0) parts.push(muted ? "muted" : "not muted");
48169
+ if (typeof channel.archived === "boolean") parts.push(channel.archived ? "archived" : "not archived");
48170
+ return parts.join(", ");
48171
+ }
48172
+ function formatPageFooter(page) {
48173
+ if (!page) return "";
48174
+ const start = page.total === 0 ? 0 : Math.min(page.offset + 1, page.total);
48175
+ const end = Math.min(page.offset + page.limit, page.total);
48176
+ const lines = [`
48177
+ Showing ${start}-${end} of ${page.total}.`];
48178
+ if (page.nextCommand && end < page.total) {
48179
+ lines.push(`More: ${page.nextCommand}`);
48180
+ }
48181
+ return `${lines.join("\n")}
48182
+ `;
48183
+ }
48184
+ function formatChannelInfo(channel, memberCounts) {
48185
+ const lines = ["## Channel", ""];
48186
+ lines.push(`Channel: ${channelRef(channel.name)}`);
48187
+ if (channel.id) lines.push(`ID: ${channel.id}`);
48188
+ lines.push(`Visibility: ${channelVisibility(channel)}`);
48189
+ lines.push(`Joined: ${channel.joined ? "yes" : "no"}`);
48190
+ const muted = channelMuted(channel);
48191
+ if (muted !== void 0) lines.push(`Muted: ${muted ? "yes" : "no"}`);
48192
+ if (typeof channel.archived === "boolean") lines.push(`Archived: ${channel.archived ? "yes" : "no"}`);
48193
+ lines.push(`Description: ${channel.description?.trim() || "(none)"}`);
48194
+ if (memberCounts) {
48195
+ const agents = memberCounts.agents ?? 0;
48196
+ const humans = memberCounts.humans ?? 0;
48197
+ lines.push(`Members: ${agents + humans} (${agents} agents, ${humans} humans)`);
48198
+ }
48199
+ lines.push("");
48200
+ lines.push(`More: raft channel members "${channelRef(channel.name)}"`);
48201
+ return `${lines.join("\n")}
48202
+ `;
48203
+ }
48204
+ function formatServerSummary(data) {
48205
+ const channels = data.channels ?? [];
48206
+ const agents = data.agents ?? [];
48207
+ const humans = data.humans ?? [];
48208
+ const joined = channels.filter((channel) => channel.joined).length;
48209
+ const lines = [
48210
+ "## Server",
48211
+ "",
48212
+ `Channels: ${channels.length} visible (${joined} joined)`,
48213
+ `Agents: ${agents.length}`,
48214
+ `Humans: ${humans.length}`,
48215
+ "",
48216
+ "Narrow queries:",
48217
+ "- raft server info --channels",
48218
+ "- raft server info --agents",
48219
+ "- raft server info --humans",
48220
+ "- raft channel info <name>",
48221
+ "- raft user info <name>",
48222
+ "",
48223
+ "Full dump: raft server info --full"
48224
+ ];
48225
+ return `${lines.join("\n")}
48226
+ `;
48227
+ }
48228
+ function formatServerChannels(channels, page) {
48229
+ const lines = [
48230
+ "## Server Channels",
48231
+ "",
48232
+ "Private channels are shown only when this agent is a member. Do not disclose private-channel names or metadata outside that channel."
48233
+ ];
48234
+ if (channels.length === 0) {
48235
+ lines.push("(none)");
48236
+ } else {
48237
+ for (const channel of channels) {
48238
+ const description = channel.description?.trim();
48239
+ lines.push(description ? `${channelRef(channel.name)} [${channelStatus(channel)}] \u2014 ${description}` : `${channelRef(channel.name)} [${channelStatus(channel)}]`);
48240
+ }
48241
+ }
48242
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48243
+ }
48244
+ function formatServerAgents(agents, page) {
48245
+ const lines = [
48246
+ "## Server Agents",
48247
+ "",
48248
+ "Role labels show server-level owner/admin authority; no role label means ordinary member."
48249
+ ];
48250
+ if (agents.length === 0) {
48251
+ lines.push("(none)");
48252
+ } else {
48253
+ for (const agent of agents) {
48254
+ const role = roleLabel(agent.role);
48255
+ const status = agentStatusLabel(agent);
48256
+ lines.push(agent.description ? `@${agent.name} (${status})${role} \u2014 ${agent.description}` : `@${agent.name} (${status})${role}`);
48257
+ }
48258
+ }
48259
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48260
+ }
48261
+ function formatServerHumans(humans, page) {
48262
+ const lines = [
48263
+ "## Server Humans",
48264
+ "",
48265
+ "Role labels show server-level owner/admin authority; no role label means ordinary member."
48266
+ ];
48267
+ if (humans.length === 0) {
48268
+ lines.push("(none)");
48269
+ } else {
48270
+ for (const human of humans) {
48271
+ const role = roleLabel(human.role);
48272
+ lines.push(human.description ? `@${human.name}${role} \u2014 ${human.description}` : `@${human.name}${role}`);
48273
+ }
48274
+ }
48275
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48276
+ }
48277
+ function formatUserInfo(user, memberships, page, skippedChannels = 0) {
48278
+ const name = user.value.name;
48279
+ const role = roleLabel(user.value.role);
48280
+ const lines = ["## User", ""];
48281
+ lines.push(`User: @${name}`);
48282
+ lines.push(`Kind: ${user.kind}`);
48283
+ if (user.kind === "agent") lines.push(`Status: ${agentStatusLabel(user.value)}`);
48284
+ if (role) lines.push(`Role: ${role.slice(2, -1)}`);
48285
+ if (user.value.description) lines.push(`Description: ${user.value.description}`);
48286
+ lines.push("");
48287
+ lines.push("### Visible Channel Memberships");
48288
+ if (memberships.length === 0) {
48289
+ lines.push("(none found in inspected visible channels)");
48290
+ } else {
48291
+ for (const channel of memberships) {
48292
+ lines.push(`${channelRef(channel.name)} [${channelStatus(channel)}]`);
48293
+ }
48294
+ }
48295
+ if (skippedChannels > 0) {
48296
+ lines.push(`Skipped ${skippedChannels} visible channel roster checks because the server rejected them.`);
48297
+ }
48298
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48299
+ }
48044
48300
  function formatChannelMembers(data) {
48045
48301
  let text = "## Channel Members\n\n";
48046
48302
  const ref = data.channel?.ref ?? "(unknown)";
@@ -48108,65 +48364,6 @@ function registerChannelMembersCommand(parent, runtimeOptions) {
48108
48364
  registerCliCommand(parent, channelMembersCommand, runtimeOptions);
48109
48365
  }
48110
48366
  init_esm_shims();
48111
- function normalizeChannelName(raw) {
48112
- return (raw ?? "").trim().replace(/^#/, "");
48113
- }
48114
- function formatCreateChannelResult(channel) {
48115
- const target = `#${channel.name}`;
48116
- const visibility = channel.type === "private" ? "private" : "public";
48117
- return `Created ${target} (${visibility}). You are joined and can send messages there.`;
48118
- }
48119
- var channelCreateCommand = defineCommand(
48120
- {
48121
- name: "create",
48122
- description: "Create a public or private channel when this agent has server admin authority",
48123
- options: [
48124
- {
48125
- flags: "--name <name>",
48126
- description: "Channel name, with or without a leading '#'"
48127
- },
48128
- {
48129
- flags: "--description <description>",
48130
- description: "Optional channel description"
48131
- },
48132
- {
48133
- flags: "--private",
48134
- description: "Create a private channel instead of a public channel"
48135
- }
48136
- ]
48137
- },
48138
- async (ctx, opts) => {
48139
- const name = normalizeChannelName(opts.name);
48140
- if (!name) {
48141
- throw new CliError({
48142
- code: "INVALID_ARG",
48143
- message: "--name is required"
48144
- });
48145
- }
48146
- const agentContext = ctx.loadAgentContext();
48147
- const client = ctx.createApiClient(agentContext);
48148
- const res = await client.request(
48149
- "POST",
48150
- `/internal/agent/${encodeURIComponent(agentContext.agentId)}/channels`,
48151
- {
48152
- name,
48153
- description: opts.description,
48154
- visibility: opts.private ? "private" : "public"
48155
- }
48156
- );
48157
- if (!res.ok || !res.data) {
48158
- throw new CliError({
48159
- code: res.status >= 500 ? "SERVER_5XX" : "CREATE_FAILED",
48160
- message: res.error ?? `HTTP ${res.status}`
48161
- });
48162
- }
48163
- writeText(ctx.io, formatCreateChannelResult(res.data) + "\n");
48164
- }
48165
- );
48166
- function registerChannelCreateCommand(parent, runtimeOptions) {
48167
- registerCliCommand(parent, channelCreateCommand, runtimeOptions);
48168
- }
48169
- init_esm_shims();
48170
48367
  init_esm_shims();
48171
48368
  function parseRegularChannelTarget(target) {
48172
48369
  if (!target.startsWith("#")) return null;
@@ -48174,8 +48371,19 @@ function parseRegularChannelTarget(target) {
48174
48371
  const name = target.slice(1).trim();
48175
48372
  return name.length > 0 ? name : null;
48176
48373
  }
48177
- function formatLeaveChannelResult(target) {
48178
- return `Left ${target}. You can still inspect visible public channel history there, but you can no longer send or receive ordinary channel delivery until you join the public channel again or a human re-adds you to a private channel.`;
48374
+ function formatLeaveChannelResult(target, result2) {
48375
+ const lines = [
48376
+ `Left ${target}. You can still inspect visible public channel history there, but you can no longer send or receive ordinary channel delivery until you join the public channel again or a human re-adds you to a private channel.`
48377
+ ];
48378
+ if (result2?.attention?.ordinaryActivity) lines.push(result2.attention.ordinaryActivity);
48379
+ if (result2?.attention?.stillArrives?.length) {
48380
+ lines.push("Still arrives:");
48381
+ for (const item of result2.attention.stillArrives) lines.push(`- ${item}`);
48382
+ }
48383
+ if (result2?.attention?.threadBoundary) lines.push(result2.attention.threadBoundary);
48384
+ if (result2?.attention?.manageCommand) lines.push(`To stop a followed thread: ${result2.attention.manageCommand}`);
48385
+ if (result2?.attention?.manageApi) lines.push(`Agent API: ${result2.attention.manageApi}`);
48386
+ return lines.join("\n");
48179
48387
  }
48180
48388
  function formatAlreadyNotJoined(target) {
48181
48389
  return `Already not joined in ${target}.`;
@@ -48230,12 +48438,124 @@ var channelLeaveCommand = defineCommand(
48230
48438
  message: leaveRes.error ?? `HTTP ${leaveRes.status}`
48231
48439
  });
48232
48440
  }
48233
- writeText(ctx.io, formatLeaveChannelResult(target) + "\n");
48441
+ writeText(ctx.io, formatLeaveChannelResult(target, leaveRes.data ?? void 0) + "\n");
48234
48442
  }
48235
48443
  );
48236
48444
  function registerChannelLeaveCommand(parent, runtimeOptions) {
48237
48445
  registerCliCommand(parent, channelLeaveCommand, runtimeOptions);
48238
48446
  }
48447
+ function normalizeChannelInfoTarget(target) {
48448
+ const input = target?.trim() ?? "";
48449
+ const normalized = input.startsWith("#") ? input : `#${input}`;
48450
+ const name = parseRegularChannelTarget(normalized);
48451
+ if (!name) {
48452
+ throw new CliError({
48453
+ code: "INVALID_TARGET",
48454
+ message: "Target must be a regular channel name, e.g. '#engineering' or 'engineering'. DMs and thread targets are not supported."
48455
+ });
48456
+ }
48457
+ return { input: normalized, name };
48458
+ }
48459
+ var channelInfoCommand = defineCommand(
48460
+ {
48461
+ name: "info",
48462
+ description: "Show narrow channel facts: existence, joined state, description, and member count when visible",
48463
+ arguments: ["<target>"]
48464
+ },
48465
+ async (ctx, target) => {
48466
+ const { input, name } = normalizeChannelInfoTarget(target);
48467
+ const agentContext = ctx.loadAgentContext();
48468
+ const client = ctx.createApiClient(agentContext);
48469
+ const agentApi = createAgentApiSurfaceClient(client);
48470
+ const infoRes = await agentApi.server.info();
48471
+ if (!infoRes.ok) {
48472
+ throw new CliError({
48473
+ code: infoRes.status >= 500 ? "SERVER_5XX" : "INFO_FAILED",
48474
+ message: infoRes.error ?? `HTTP ${infoRes.status}`
48475
+ });
48476
+ }
48477
+ const channel = (infoRes.data?.channels ?? []).find((candidate) => candidate.name === name);
48478
+ if (!channel) {
48479
+ throw new CliError({
48480
+ code: "NOT_FOUND",
48481
+ message: `Channel not found or not visible: ${input}`,
48482
+ suggestedNextAction: "Run `raft server info --channels --query <name>` to inspect visible channels, or ask a channel member to add you if this is private."
48483
+ });
48484
+ }
48485
+ let memberCounts = null;
48486
+ const membersRes = await agentApi.channels.members({ channel: `#${name}` });
48487
+ if (membersRes.ok) {
48488
+ memberCounts = {
48489
+ agents: membersRes.data?.agents?.length ?? 0,
48490
+ humans: membersRes.data?.humans?.length ?? 0
48491
+ };
48492
+ }
48493
+ writeText(ctx.io, formatChannelInfo(channel, memberCounts));
48494
+ }
48495
+ );
48496
+ function registerChannelInfoCommand(parent, runtimeOptions) {
48497
+ registerCliCommand(parent, channelInfoCommand, runtimeOptions);
48498
+ }
48499
+ init_esm_shims();
48500
+ function normalizeChannelName(raw) {
48501
+ return (raw ?? "").trim().replace(/^#/, "");
48502
+ }
48503
+ function formatCreateChannelResult(channel) {
48504
+ const target = `#${channel.name}`;
48505
+ const visibility = channel.type === "private" ? "private" : "public";
48506
+ return `Created ${target} (${visibility}). You are joined and can send messages there.`;
48507
+ }
48508
+ var channelCreateCommand = defineCommand(
48509
+ {
48510
+ name: "create",
48511
+ description: "Create a public or private channel when this agent has server admin authority",
48512
+ options: [
48513
+ {
48514
+ flags: "--name <name>",
48515
+ description: "Channel name, with or without a leading '#'"
48516
+ },
48517
+ {
48518
+ flags: "--description <description>",
48519
+ description: "Optional channel description"
48520
+ },
48521
+ {
48522
+ flags: "--private",
48523
+ description: "Create a private channel instead of a public channel"
48524
+ }
48525
+ ]
48526
+ },
48527
+ async (ctx, opts) => {
48528
+ const name = normalizeChannelName(opts.name);
48529
+ if (!name) {
48530
+ throw new CliError({
48531
+ code: "INVALID_ARG",
48532
+ message: "--name is required"
48533
+ });
48534
+ }
48535
+ const agentContext = ctx.loadAgentContext();
48536
+ const client = ctx.createApiClient(agentContext);
48537
+ const res = await client.request(
48538
+ "POST",
48539
+ `/internal/agent/${encodeURIComponent(agentContext.agentId)}/channels`,
48540
+ {
48541
+ name,
48542
+ description: opts.description,
48543
+ visibility: opts.private ? "private" : "public"
48544
+ }
48545
+ );
48546
+ if (!res.ok || !res.data) {
48547
+ throw new CliError({
48548
+ code: res.status >= 500 ? "SERVER_5XX" : "CREATE_FAILED",
48549
+ message: res.error ?? `HTTP ${res.status}`
48550
+ });
48551
+ }
48552
+ writeText(ctx.io, formatCreateChannelResult(res.data) + "\n");
48553
+ }
48554
+ );
48555
+ function registerChannelCreateCommand(parent, runtimeOptions) {
48556
+ registerCliCommand(parent, channelCreateCommand, runtimeOptions);
48557
+ }
48558
+ init_esm_shims();
48239
48559
  function normalizeChannelName2(raw) {
48240
48560
  return (raw ?? "").trim().replace(/^#/, "");
48241
48561
  }
@@ -48422,9 +48742,19 @@ init_esm_shims();
48422
48742
  function normalizeHandle2(raw) {
48423
48743
  return (raw ?? "").trim().replace(/^@/, "");
48424
48744
  }
48425
- function formatRemoveMemberResult(target, memberName, wasMember) {
48745
+ function formatRemoveMemberResult(target, memberName, wasMember, result2) {
48426
48746
  const member = `@${memberName}`;
48427
- return wasMember ? `Removed ${member} from ${target}.` : `${member} was not in ${target}.`;
48747
+ if (!wasMember) return `${member} was not in ${target}.`;
48748
+ const lines = [`Removed ${member} from ${target}.`];
48749
+ if (result2?.attention?.ordinaryActivity) lines.push(result2.attention.ordinaryActivity);
48750
+ if (result2?.attention?.stillArrives?.length) {
48751
+ lines.push("Still arrives:");
48752
+ for (const item of result2.attention.stillArrives) lines.push(`- ${item}`);
48753
+ }
48754
+ if (result2?.attention?.threadBoundary) lines.push(result2.attention.threadBoundary);
48755
+ if (result2?.attention?.manageCommand) lines.push(`To stop a followed thread: ${result2.attention.manageCommand}`);
48756
+ if (result2?.attention?.manageApi) lines.push(`Agent API: ${result2.attention.manageApi}`);
48757
+ return lines.join("\n");
48428
48758
  }
48429
48759
  var channelRemoveMemberCommand = defineCommand(
48430
48760
  {
@@ -48494,7 +48824,7 @@ var channelRemoveMemberCommand = defineCommand(
48494
48824
  });
48495
48825
  }
48496
48826
  const memberName = removeRes.data?.member?.name ?? (user || agent);
48497
- writeText(ctx.io, formatRemoveMemberResult(target, memberName, removeRes.data?.wasMember === true) + "\n");
48827
+ writeText(ctx.io, formatRemoveMemberResult(target, memberName, removeRes.data?.wasMember === true, removeRes.data ?? void 0) + "\n");
48498
48828
  }
48499
48829
  );
48500
48830
  function registerChannelRemoveMemberCommand(parent, runtimeOptions) {
@@ -48502,7 +48832,12 @@ function registerChannelRemoveMemberCommand(parent, runtimeOptions) {
48502
48832
  }
48503
48833
  init_esm_shims();
48504
48834
  function formatJoinChannelResult(target) {
48505
- return `Joined ${target}. You can now send messages there and receive ordinary channel delivery.`;
48835
+ return [
48836
+ `Joined ${target}. You can now send messages there and receive ordinary channel delivery.`,
48837
+ "Still arrives:",
48838
+ "- Personal @mentions still reach you even if you later mute ordinary channel updates.",
48839
+ "- Threads you started or follow stay followed even if you later mute this channel."
48840
+ ].join("\n");
48506
48841
  }
48507
48842
  function formatAlreadyJoined(target) {
48508
48843
  return `Already joined ${target}.`;
@@ -48654,12 +48989,90 @@ function registerChannelUnmuteCommand(parent, runtimeOptions) {
48654
48989
  registerCliCommand(parent, channelUnmuteCommand, runtimeOptions);
48655
48990
  }
48656
48991
  init_esm_shims();
48992
+ function parseNonNegativeInt(raw, name, fallback) {
48993
+ if (raw === void 0) return fallback;
48994
+ if (!/^\d+$/.test(raw)) {
48995
+ throw new CliError({
48996
+ code: "INVALID_ARG",
48997
+ message: `${name} must be a non-negative integer`
48998
+ });
48999
+ }
49000
+ return Number(raw);
49001
+ }
49002
+ function parsePositiveInt2(raw, name, fallback) {
49003
+ const value = parseNonNegativeInt(raw, name, fallback);
49004
+ if (value <= 0) {
49005
+ throw new CliError({
49006
+ code: "INVALID_ARG",
49007
+ message: `${name} must be greater than 0`
49008
+ });
49009
+ }
49010
+ return value;
49011
+ }
49012
+ function selectedSections(opts) {
49013
+ const sections = [];
49014
+ if (opts.channels) sections.push("channels");
49015
+ if (opts.agents) sections.push("agents");
49016
+ if (opts.humans) sections.push("humans");
49017
+ return sections;
49018
+ }
49019
+ function hasListModifier(opts) {
49020
+ return Boolean(opts.joined || opts.query !== void 0 || opts.limit !== void 0 || opts.offset !== void 0);
49021
+ }
49022
+ function includesQuery(row, query) {
49023
+ const needle = query?.trim().toLowerCase();
49024
+ if (!needle) return true;
49025
+ const values = Object.values(row).filter((value) => typeof value === "string").map((value) => value.toLowerCase());
49026
+ return values.some((value) => value.includes(needle));
49027
+ }
49028
+ function pageRows(rows, offset, limit) {
49029
+ return rows.slice(offset, offset + limit);
49030
+ }
49031
+ function nextCommand(section, opts, offset, limit, total) {
49032
+ const nextOffset = offset + limit;
49033
+ if (nextOffset >= total) return void 0;
49034
+ const parts = ["raft server info", `--${section}`, `--offset ${nextOffset}`, `--limit ${limit}`];
49035
+ if (opts.query?.trim()) parts.push(`--query ${JSON.stringify(opts.query.trim())}`);
49036
+ if (opts.joined) parts.push("--joined");
49037
+ return parts.join(" ");
49038
+ }
48657
49039
  var serverInfoCommand = defineCommand(
48658
49040
  {
48659
49041
  name: "info",
48660
- description: "List channels, agents, and humans on the current server"
49042
+ description: "Show bounded server facts; use --full for the legacy full inventory",
49043
+ options: [
49044
+ { flags: "--full", description: "Print the full channels, agents, humans, and runtime inventory" },
49045
+ { flags: "--channels", description: "List visible channels only" },
49046
+ { flags: "--agents", description: "List agents only" },
49047
+ { flags: "--humans", description: "List humans only" },
49048
+ { flags: "--joined", description: "With --channels, show only joined channels" },
49049
+ { flags: "--query <text>", description: "Filter the selected list by visible text" },
49050
+ { flags: "--limit <n>", description: "Maximum rows for list output (default: 50)" },
49051
+ { flags: "--offset <n>", description: "Rows to skip for list output (default: 0)" }
49052
+ ]
48661
49053
  },
48662
- async (ctx) => {
49054
+ async (ctx, opts = {}) => {
49055
+ const sections = selectedSections(opts);
49056
+ if (opts.full && sections.length > 0) {
49057
+ throw new CliError({
49058
+ code: "INVALID_ARG",
49059
+ message: "--full cannot be combined with --channels, --agents, or --humans"
49060
+ });
49061
+ }
49062
+ if (sections.length === 0 && hasListModifier(opts)) {
49063
+ throw new CliError({
49064
+ code: "INVALID_ARG",
49065
+ message: "--query, --limit, --offset, and --joined require --channels, --agents, or --humans"
49066
+ });
49067
+ }
49068
+ if (opts.joined && sections.some((section) => section !== "channels")) {
49069
+ throw new CliError({
49070
+ code: "INVALID_ARG",
49071
+ message: "--joined can only be used with --channels"
49072
+ });
49073
+ }
49074
+ const limit = parsePositiveInt2(opts.limit, "--limit", 50);
49075
+ const offset = parseNonNegativeInt(opts.offset, "--offset", 0);
48663
49076
  const agentContext = ctx.loadAgentContext();
48664
49077
  const client = ctx.createApiClient(agentContext);
48665
49078
  const res = await createAgentApiSurfaceClient(client).server.info();
@@ -48670,14 +49083,56 @@ var serverInfoCommand = defineCommand(
48670
49083
  message: res.error ?? `HTTP ${res.status}`
48671
49084
  });
48672
49085
  }
48673
- const data = res.data;
48674
- if (data?.runtimeContext) {
48675
- data.runtimeContext = {
48676
- ...data.runtimeContext,
48677
- workspacePath: data.runtimeContext.workspacePath ?? ctx.env.SLOCK_CURRENT_WORKSPACE_PATH ?? null
48678
- };
49086
+ if (!res.data) {
49087
+ throw new CliError({
49088
+ code: "INVALID_JSON_RESPONSE",
49089
+ message: "Agent API serverInfo returned an empty response body"
49090
+ });
49091
+ }
49092
+ const data = {
49093
+ ...res.data,
49094
+ runtimeContext: {
49095
+ ...res.data.runtimeContext,
49096
+ workspacePath: res.data.runtimeContext.workspacePath ?? ctx.env.SLOCK_CURRENT_WORKSPACE_PATH ?? null
49097
+ }
49098
+ };
49099
+ if (opts.full) {
49100
+ writeText(ctx.io, formatServerInfo(data));
49101
+ return;
49102
+ }
49103
+ if (sections.length === 0) {
49104
+ writeText(ctx.io, formatServerSummary(data));
49105
+ return;
49106
+ }
49107
+ const chunks = [];
49108
+ for (const section of sections) {
49109
+ if (section === "channels") {
49110
+ const rows = (data.channels ?? []).filter((channel) => !opts.joined || channel.joined).filter((channel) => includesQuery(channel, opts.query));
49111
+ chunks.push(formatServerChannels(pageRows(rows, offset, limit), {
49112
+ total: rows.length,
49113
+ offset,
49114
+ limit,
49115
+ nextCommand: nextCommand(section, opts, offset, limit, rows.length)
49116
+ }));
49117
+ } else if (section === "agents") {
49118
+ const rows = (data.agents ?? []).filter((agent) => includesQuery(agent, opts.query));
49119
+ chunks.push(formatServerAgents(pageRows(rows, offset, limit), {
49120
+ total: rows.length,
49121
+ offset,
49122
+ limit,
49123
+ nextCommand: nextCommand(section, opts, offset, limit, rows.length)
49124
+ }));
49125
+ } else {
49126
+ const rows = (data.humans ?? []).filter((human) => includesQuery(human, opts.query));
49127
+ chunks.push(formatServerHumans(pageRows(rows, offset, limit), {
49128
+ total: rows.length,
49129
+ offset,
49130
+ limit,
49131
+ nextCommand: nextCommand(section, opts, offset, limit, rows.length)
49132
+ }));
49133
+ }
48679
49134
  }
48680
- writeText(ctx.io, formatServerInfo(data));
49135
+ writeText(ctx.io, chunks.join("\n"));
48681
49136
  }
48682
49137
  );
48683
49138
  function registerServerInfoCommand(parent, runtimeOptions) {
@@ -49005,6 +49460,98 @@ function registerServerUpdateCommand(parent, runtimeOptions) {
49005
49460
  registerCliCommand(parent, serverUpdateCommand, runtimeOptions);
49006
49461
  }
49007
49462
  init_esm_shims();
49463
+ function parseNonNegativeInt2(raw, name, fallback) {
49464
+ if (raw === void 0) return fallback;
49465
+ if (!/^\d+$/.test(raw)) {
49466
+ throw new CliError({
49467
+ code: "INVALID_ARG",
49468
+ message: `${name} must be a non-negative integer`
49469
+ });
49470
+ }
49471
+ return Number(raw);
49472
+ }
49473
+ function parsePositiveInt3(raw, name, fallback) {
49474
+ const value = parseNonNegativeInt2(raw, name, fallback);
49475
+ if (value <= 0) {
49476
+ throw new CliError({
49477
+ code: "INVALID_ARG",
49478
+ message: `${name} must be greater than 0`
49479
+ });
49480
+ }
49481
+ return value;
49482
+ }
49483
+ function normalizeUserName(target) {
49484
+ const trimmed = target?.trim() ?? "";
49485
+ const name = trimmed.startsWith("@") ? trimmed.slice(1) : trimmed;
49486
+ if (!name) {
49487
+ throw new CliError({
49488
+ code: "INVALID_ARG",
49489
+ message: "user name is required"
49490
+ });
49491
+ }
49492
+ return name;
49493
+ }
49494
+ var userInfoCommand = defineCommand(
49495
+ {
49496
+ name: "info",
49497
+ description: "Show narrow visible facts for a human or agent and its visible channel memberships",
49498
+ arguments: ["<name>"],
49499
+ options: [
49500
+ { flags: "--limit <n>", description: "Maximum visible channels to inspect (default: 50)" },
49501
+ { flags: "--offset <n>", description: "Visible channels to skip before inspection (default: 0)" }
49502
+ ]
49503
+ },
49504
+ async (ctx, target, opts = {}) => {
49505
+ const name = normalizeUserName(target);
49506
+ const limit = parsePositiveInt3(opts.limit, "--limit", 50);
49507
+ const offset = parseNonNegativeInt2(opts.offset, "--offset", 0);
49508
+ const agentContext = ctx.loadAgentContext();
49509
+ const client = ctx.createApiClient(agentContext);
49510
+ const agentApi = createAgentApiSurfaceClient(client);
49511
+ const infoRes = await agentApi.server.info();
49512
+ if (!infoRes.ok) {
49513
+ throw new CliError({
49514
+ code: infoRes.status >= 500 ? "SERVER_5XX" : "INFO_FAILED",
49515
+ message: infoRes.error ?? `HTTP ${infoRes.status}`
49516
+ });
49517
+ }
49518
+ const agent = (infoRes.data?.agents ?? []).find((candidate) => candidate.name === name);
49519
+ const human = (infoRes.data?.humans ?? []).find((candidate) => candidate.name === name);
49520
+ const user = agent ? { kind: "agent", value: agent } : human ? { kind: "human", value: human } : null;
49521
+ if (!user) {
49522
+ throw new CliError({
49523
+ code: "NOT_FOUND",
49524
+ message: `User not found or not visible: @${name}`,
49525
+ suggestedNextAction: "Run `raft server info --agents --query <name>` or `raft server info --humans --query <name>` to inspect visible users."
49526
+ });
49527
+ }
49528
+ const visibleChannels = infoRes.data?.channels ?? [];
49529
+ const inspectedChannels = visibleChannels.slice(offset, offset + limit);
49530
+ const memberships = [];
49531
+ let skippedChannels = 0;
49532
+ for (const channel of inspectedChannels) {
49533
+ const membersRes = await agentApi.channels.members({ channel: `#${channel.name}` });
49534
+ if (!membersRes.ok) {
49535
+ skippedChannels += 1;
49536
+ continue;
49537
+ }
49538
+ const agents = membersRes.data?.agents ?? [];
49539
+ const humans = membersRes.data?.humans ?? [];
49540
+ const found = user.kind === "agent" ? agents.some((candidate) => candidate.name === name) : humans.some((candidate) => candidate.name === name);
49541
+ if (found) memberships.push(channel);
49542
+ }
49543
+ writeText(ctx.io, formatUserInfo(user, memberships, {
49544
+ total: visibleChannels.length,
49545
+ offset,
49546
+ limit,
49547
+ nextCommand: offset + limit < visibleChannels.length ? `raft user info @${name} --offset ${offset + limit} --limit ${limit}` : void 0
49548
+ }, skippedChannels));
49549
+ }
49550
+ );
49551
+ function registerUserInfoCommand(parent, runtimeOptions) {
49552
+ registerCliCommand(parent, userInfoCommand, runtimeOptions);
49553
+ }
49554
+ init_esm_shims();
49008
49555
  function formatKnowledgeStdout(content) {
49009
49556
  return content.endsWith("\n") ? content : `${content}
49010
49557
  `;
@@ -49039,11 +49586,13 @@ var knowledgeGetCommand = defineCommand(
49039
49586
  },
49040
49587
  {
49041
49588
  flags: "--turn-id <id>",
49042
- description: "Optional turn id for correlation in the knowledge event"
49589
+ description: "Diagnostic: override the turn id recorded on the knowledge event",
49590
+ hidden: true
49043
49591
  },
49044
49592
  {
49045
49593
  flags: "--trace-id <id>",
49046
- description: "Optional trace id for correlation in the knowledge event"
49594
+ description: "Diagnostic: override the trace id recorded on the knowledge event",
49595
+ hidden: true
49047
49596
  }
49048
49597
  ],
49049
49598
  helpAfter: "\nTopics:\n Run `raft manual get index` to list available manual topics.\n"
@@ -49078,6 +49627,91 @@ function registerKnowledgeGetCommand(parent, runtimeOptions) {
49078
49627
  registerCliCommand(parent, knowledgeGetCommand, runtimeOptions);
49079
49628
  }
49080
49629
  init_esm_shims();
49630
+ function formatKnowledgeSearchResults(results) {
49631
+ return results.map((result2, index) => {
49632
+ const firstScreen = result2.firstScreen.trim();
49633
+ const body = firstScreen.split(/\r?\n/).filter(Boolean).map((line) => ` ${line}`).join("\n");
49634
+ return `${index + 1}. ${result2.slug} \u2014 ${result2.title}${body ? `
49635
+ ${body}` : ""}`;
49636
+ }).join("\n\n") + "\n";
49637
+ }
49638
+ function toKnowledgeSearchErrorCode(errorCode2, status) {
49639
+ switch (errorCode2) {
49640
+ case "INVALID_JSON_RESPONSE":
49641
+ case "SCOPE_DENIED":
49642
+ case "knowledge_agent_missing":
49643
+ case "knowledge_internal_error":
49644
+ case "knowledge_not_found":
49645
+ case "knowledge_query_invalid":
49646
+ case "knowledge_reason_invalid":
49647
+ case "knowledge_scope_invalid":
49648
+ case "knowledge_source_invalid":
49649
+ case "knowledge_trace_id_invalid":
49650
+ case "knowledge_turn_id_invalid":
49651
+ case "unsupported_capability":
49652
+ return errorCode2;
49653
+ default:
49654
+ return status >= 500 ? "SERVER_5XX" : "KNOWLEDGE_SEARCH_FAILED";
49655
+ }
49656
+ }
49657
+ var knowledgeSearchCommand = defineCommand(
49658
+ {
49659
+ name: "search",
49660
+ description: "Search Raft Manual for Agents topics from the current server",
49661
+ arguments: ["<keywords>"],
49662
+ options: [
49663
+ {
49664
+ flags: "--scope <scope>",
49665
+ description: "Optional search scope. Currently supports: recipes"
49666
+ },
49667
+ {
49668
+ flags: "--reason <text>",
49669
+ description: "Optional rationale for this search (>=12 chars when provided)"
49670
+ },
49671
+ {
49672
+ flags: "--turn-id <id>",
49673
+ description: "Diagnostic: override the turn id recorded on the knowledge event",
49674
+ hidden: true
49675
+ },
49676
+ {
49677
+ flags: "--trace-id <id>",
49678
+ description: "Diagnostic: override the trace id recorded on the knowledge event",
49679
+ hidden: true
49680
+ }
49681
+ ],
49682
+ helpAfter: '\nExamples:\n raft manual search "preview before merge" --scope recipes\n raft manual get recipes/technique/preview-env\n'
49683
+ },
49684
+ async (ctx, keywords, opts) => {
49685
+ const agentContext = ctx.loadAgentContext();
49686
+ const client = ctx.createApiClient(agentContext);
49687
+ const res = await createAgentApiSurfaceClient(client).knowledge.search({
49688
+ query: keywords,
49689
+ scope: opts.scope,
49690
+ reason: opts.reason,
49691
+ turn_id: opts.turnId,
49692
+ trace_id: opts.traceId
49693
+ });
49694
+ if (!res.ok) {
49695
+ throw new CliError({
49696
+ code: toKnowledgeSearchErrorCode(res.errorCode, res.status),
49697
+ message: res.error ?? `HTTP ${res.status}`,
49698
+ suggestedNextAction: res.suggestedNextAction ?? (res.errorCode === "knowledge_not_found" ? "Try different keywords, or run `raft manual get index` to browse available topics." : void 0)
49699
+ });
49700
+ }
49701
+ const data = res.data;
49702
+ if (!data || data.ok !== true || !Array.isArray(data.results)) {
49703
+ throw new CliError({
49704
+ code: "KNOWLEDGE_SEARCH_FAILED",
49705
+ message: "Server returned an unexpected response shape"
49706
+ });
49707
+ }
49708
+ writeText(ctx.io, formatKnowledgeSearchResults(data.results));
49709
+ }
49710
+ );
49711
+ function registerKnowledgeSearchCommand(parent, runtimeOptions) {
49712
+ registerCliCommand(parent, knowledgeSearchCommand, runtimeOptions);
49713
+ }
49714
+ init_esm_shims();
49081
49715
  init_esm_shims();
49082
49716
  var inboxCheckCommand = defineCommand(
49083
49717
  {
@@ -49131,7 +49765,11 @@ function parseThreadTarget(target) {
49131
49765
  return null;
49132
49766
  }
49133
49767
  function formatUnfollowThreadResult(target) {
49134
- return `Unfollowed ${target}. You can still inspect the thread when its parent conversation is visible, but you will no longer receive ordinary thread delivery unless you follow it again or are mentioned.`;
49768
+ return [
49769
+ `Unfollowed ${target}. Ordinary delivery for this thread has stopped.`,
49770
+ "Still arrives: personal @mentions pierce as single messages \u2014 they do NOT re-follow you.",
49771
+ "Posting in this thread re-follows you automatically."
49772
+ ].join("\n");
49135
49773
  }
49136
49774
  var threadUnfollowCommand = defineCommand(
49137
49775
  {
@@ -49762,6 +50400,168 @@ You can also choose not to send anything.
49762
50400
  `
49763
50401
  });
49764
50402
  }
50403
+ function formatDriveByJoinedToPostTip(target, data) {
50404
+ const attention = data.attention?.driveByJoinedToPost;
50405
+ if (!attention) return "";
50406
+ const muteCommand = attention.muteCommand?.trim() || `raft channel mute "${target}"`;
50407
+ const stillArrives = attention.stillArrives?.[0]?.trim() || "@mentions still reach you, and threads you started stay followed.";
50408
+ return [
50409
+ "Tip: you joined this channel to post this message. If you don't need its ordinary updates:",
50410
+ ` ${muteCommand}`,
50411
+ stillArrives
50412
+ ].join("\n");
50413
+ }
50414
+ function markSendFailureDraftSaved(err, draftSaved) {
50415
+ if (err instanceof CliError) {
50416
+ if (err.draftSaved !== void 0) return err;
50417
+ return new CliError({
50418
+ code: err.code,
50419
+ message: err.message,
50420
+ exitCode: err.exitCode,
50421
+ cause: err.cause,
50422
+ suggestedNextAction: err.suggestedNextAction,
50423
+ draftSaved
50424
+ });
50425
+ }
50426
+ const message = err instanceof Error ? err.message : String(err);
50427
+ return new CliError({
50428
+ code: "INTERNAL_BUG",
50429
+ message: `Unexpected error: ${message}`,
50430
+ cause: err,
50431
+ draftSaved
50432
+ });
50433
+ }
50434
+ async function handleMessageSend(ctx, positionalContent, opts, setFailureDraftSaved) {
50435
+ const target = opts.target?.trim() ?? "";
50436
+ if (!target) {
50437
+ throw cliError("INVALID_ARG", "--target is required");
50438
+ }
50439
+ try {
50440
+ rejectArgContent(positionalContent, opts);
50441
+ } catch (err) {
50442
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50443
+ throw err;
50444
+ }
50445
+ try {
50446
+ validateDraftSendFlags(opts);
50447
+ } catch (err) {
50448
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50449
+ throw err;
50450
+ }
50451
+ let content;
50452
+ let outgoingContent = "";
50453
+ let outgoingAttachmentIds = [];
50454
+ let previousDraftReholdCount = 0;
50455
+ let seenUpToSeq;
50456
+ if (opts.sendDraft) {
50457
+ content = await resolveOptionalSendContent(ctx.io.stdin ?? process.stdin);
50458
+ try {
50459
+ rejectSendDraftStdin(content, opts.target);
50460
+ } catch (err) {
50461
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50462
+ throw err;
50463
+ }
50464
+ } else {
50465
+ try {
50466
+ content = await resolveSendContent(ctx.io.stdin ?? process.stdin);
50467
+ } catch (err) {
50468
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50469
+ throw err;
50470
+ }
50471
+ outgoingContent = content;
50472
+ outgoingAttachmentIds = opts.attachmentId && opts.attachmentId.length > 0 ? opts.attachmentId : [];
50473
+ }
50474
+ const agentContext = ctx.loadAgentContext();
50475
+ const client = ctx.createApiClient(agentContext);
50476
+ if (opts.sendDraft) {
50477
+ const savedDraft = getSavedDraft(agentContext.agentId, target);
50478
+ if (!savedDraft) {
50479
+ throw cliError(
50480
+ "SEND_DRAFT_NOT_FOUND",
50481
+ [
50482
+ "No saved draft exists for this target.",
50483
+ "To create or update a draft, send message content normally:",
50484
+ ` raft message send --target "${target}" <<'${MESSAGE_HEREDOC_DELIMITER}'`,
50485
+ " message body",
50486
+ ` ${MESSAGE_HEREDOC_DELIMITER}`
50487
+ ].join("\n")
50488
+ );
50489
+ }
50490
+ outgoingContent = savedDraft.content;
50491
+ outgoingAttachmentIds = savedDraft.attachmentIds;
50492
+ previousDraftReholdCount = savedDraft.reholdCount;
50493
+ seenUpToSeq = savedDraft.seenUpToSeq;
50494
+ setFailureDraftSaved(true);
50495
+ } else {
50496
+ const previousDraft = getSavedDraft(agentContext.agentId, target);
50497
+ previousDraftReholdCount = previousDraft?.reholdCount ?? 0;
50498
+ seenUpToSeq = previousDraft?.seenUpToSeq;
50499
+ }
50500
+ if (seenUpToSeq === void 0) {
50501
+ seenUpToSeq = getConsumedSeq(agentContext.agentId, target);
50502
+ }
50503
+ const body = {
50504
+ target,
50505
+ content: outgoingContent,
50506
+ draftReholdCount: previousDraftReholdCount
50507
+ };
50508
+ if (seenUpToSeq !== void 0) {
50509
+ body.seenUpToSeq = seenUpToSeq;
50510
+ }
50511
+ if (opts.sendDraft) {
50512
+ body.sendDraft = true;
50513
+ if (opts.anyway) body.continueAnyway = true;
50514
+ } else {
50515
+ body.draftReplacedExisting = previousDraftReholdCount > 0;
50516
+ }
50517
+ if (outgoingAttachmentIds.length > 0) {
50518
+ body.attachmentIds = outgoingAttachmentIds;
50519
+ }
50520
+ const agentApi = createAgentApiSurfaceClient(client);
50521
+ const res = await agentApi.messages.send(body);
50522
+ if (!res.ok) {
50523
+ const code = res.status >= 500 ? "SERVER_5XX" : "SEND_FAILED";
50524
+ throw cliError(code, res.error ?? `HTTP ${res.status}`);
50525
+ }
50526
+ const data = res.data;
50527
+ if (!data) {
50528
+ throw cliError("INVALID_JSON_RESPONSE", "Agent API messageSend returned an empty response body");
50529
+ }
50530
+ if (data.state === "held") {
50531
+ if (typeof data.seenUpToSeq === "number" && Number.isFinite(data.seenUpToSeq)) {
50532
+ recordConsumedSeqs(agentContext.agentId, { [target]: data.seenUpToSeq });
50533
+ }
50534
+ setSavedDraft(agentContext.agentId, target, {
50535
+ content: outgoingContent,
50536
+ attachmentIds: outgoingAttachmentIds,
50537
+ savedAt: Date.now(),
50538
+ reholdCount: previousDraftReholdCount + 1,
50539
+ seenUpToSeq: data.seenUpToSeq
50540
+ });
50541
+ writeText(ctx.io, formatHeldSendOutput(target, data));
50542
+ return;
50543
+ }
50544
+ clearSavedDraft(agentContext.agentId, target);
50545
+ const shortId = data.messageId ? data.messageId.slice(0, 8) : null;
50546
+ const replyHint = shortId ? ` (to reply in this message's thread, use target "${target.includes(":") ? target : target + ":" + shortId}")` : "";
50547
+ let unreadSection = "";
50548
+ if (data.recentUnread && data.recentUnread.length > 0) {
50549
+ unreadSection = `
50550
+
50551
+ --- New messages you may have missed ---
50552
+ ${formatMessages(data.recentUnread)}`;
50553
+ }
50554
+ const pendingMentionActions = normalizePendingMentionActions(data);
50555
+ const mentionSection = pendingMentionActions.length > 0 ? `
50556
+
50557
+ ${formatPendingMentionActions(pendingMentionActions, { source: "send" }).trimEnd()}` : "";
50558
+ const driveByTip = formatDriveByJoinedToPostTip(target, data);
50559
+ const driveBySection = driveByTip ? `
50560
+
50561
+ ${driveByTip}` : "";
50562
+ writeText(ctx.io, `Message sent to ${target}. Message ID: ${data.messageId}${replyHint}${driveBySection}${mentionSection}${unreadSection}
50563
+ `);
50564
+ }
49765
50565
  var messageSendCommand = defineCommand(
49766
50566
  {
49767
50567
  name: "send",
@@ -49780,131 +50580,14 @@ var messageSendCommand = defineCommand(
49780
50580
  ]
49781
50581
  },
49782
50582
  async (ctx, positionalContent, opts) => {
49783
- const target = opts.target?.trim() ?? "";
49784
- if (!target) {
49785
- throw cliError("INVALID_ARG", "--target is required");
49786
- }
49787
- try {
49788
- rejectArgContent(positionalContent, opts);
49789
- } catch (err) {
49790
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
49791
- throw err;
49792
- }
50583
+ let failureDraftSaved = false;
49793
50584
  try {
49794
- validateDraftSendFlags(opts);
49795
- } catch (err) {
49796
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
49797
- throw err;
49798
- }
49799
- let content;
49800
- let outgoingContent = "";
49801
- let outgoingAttachmentIds = [];
49802
- let previousDraftReholdCount = 0;
49803
- let seenUpToSeq;
49804
- if (opts.sendDraft) {
49805
- content = await resolveOptionalSendContent(ctx.io.stdin ?? process.stdin);
49806
- try {
49807
- rejectSendDraftStdin(content, opts.target);
49808
- } catch (err) {
49809
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
49810
- throw err;
49811
- }
49812
- } else {
49813
- try {
49814
- content = await resolveSendContent(ctx.io.stdin ?? process.stdin);
49815
- } catch (err) {
49816
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
49817
- throw err;
49818
- }
49819
- outgoingContent = content;
49820
- outgoingAttachmentIds = opts.attachmentId && opts.attachmentId.length > 0 ? opts.attachmentId : [];
49821
- }
49822
- const agentContext = ctx.loadAgentContext();
49823
- const client = ctx.createApiClient(agentContext);
49824
- if (opts.sendDraft) {
49825
- const savedDraft = getSavedDraft(agentContext.agentId, target);
49826
- if (!savedDraft) {
49827
- throw cliError(
49828
- "SEND_DRAFT_NOT_FOUND",
49829
- [
49830
- "No saved draft exists for this target.",
49831
- "To create or update a draft, send message content normally:",
49832
- ` raft message send --target "${target}" <<'${MESSAGE_HEREDOC_DELIMITER}'`,
49833
- " message body",
49834
- ` ${MESSAGE_HEREDOC_DELIMITER}`
49835
- ].join("\n")
49836
- );
49837
- return;
49838
- }
49839
- outgoingContent = savedDraft.content;
49840
- outgoingAttachmentIds = savedDraft.attachmentIds;
49841
- previousDraftReholdCount = savedDraft.reholdCount;
49842
- seenUpToSeq = savedDraft.seenUpToSeq;
49843
- } else {
49844
- const previousDraft = getSavedDraft(agentContext.agentId, target);
49845
- previousDraftReholdCount = previousDraft?.reholdCount ?? 0;
49846
- seenUpToSeq = previousDraft?.seenUpToSeq;
49847
- }
49848
- if (seenUpToSeq === void 0) {
49849
- seenUpToSeq = getConsumedSeq(agentContext.agentId, target);
49850
- }
49851
- const body = {
49852
- target,
49853
- content: outgoingContent,
49854
- draftReholdCount: previousDraftReholdCount
49855
- };
49856
- if (seenUpToSeq !== void 0) {
49857
- body.seenUpToSeq = seenUpToSeq;
49858
- }
49859
- if (opts.sendDraft) {
49860
- body.sendDraft = true;
49861
- if (opts.anyway) body.continueAnyway = true;
49862
- } else {
49863
- body.draftReplacedExisting = previousDraftReholdCount > 0;
49864
- }
49865
- if (outgoingAttachmentIds.length > 0) {
49866
- body.attachmentIds = outgoingAttachmentIds;
49867
- }
49868
- const agentApi = createAgentApiSurfaceClient(client);
49869
- const res = await agentApi.messages.send(body);
49870
- if (!res.ok) {
49871
- const code = res.status >= 500 ? "SERVER_5XX" : "SEND_FAILED";
49872
- throw cliError(code, res.error ?? `HTTP ${res.status}`);
49873
- }
49874
- const data = res.data;
49875
- if (!data) {
49876
- throw cliError("INVALID_JSON_RESPONSE", "Agent API messageSend returned an empty response body");
49877
- }
49878
- if (data.state === "held") {
49879
- if (typeof data.seenUpToSeq === "number" && Number.isFinite(data.seenUpToSeq)) {
49880
- recordConsumedSeqs(agentContext.agentId, { [target]: data.seenUpToSeq });
49881
- }
49882
- setSavedDraft(agentContext.agentId, target, {
49883
- content: outgoingContent,
49884
- attachmentIds: outgoingAttachmentIds,
49885
- savedAt: Date.now(),
49886
- reholdCount: previousDraftReholdCount + 1,
49887
- seenUpToSeq: data.seenUpToSeq
50585
+ await handleMessageSend(ctx, positionalContent, opts, (draftSaved) => {
50586
+ failureDraftSaved = draftSaved;
49888
50587
  });
49889
- writeText(ctx.io, formatHeldSendOutput(target, data));
49890
- return;
49891
- }
49892
- clearSavedDraft(agentContext.agentId, target);
49893
- const shortId = data.messageId ? data.messageId.slice(0, 8) : null;
49894
- const replyHint = shortId ? ` (to reply in this message's thread, use target "${target.includes(":") ? target : target + ":" + shortId}")` : "";
49895
- let unreadSection = "";
49896
- if (data.recentUnread && data.recentUnread.length > 0) {
49897
- unreadSection = `
49898
-
49899
- --- New messages you may have missed ---
49900
- ${formatMessages(data.recentUnread)}`;
50588
+ } catch (err) {
50589
+ throw markSendFailureDraftSaved(err, failureDraftSaved);
49901
50590
  }
49902
- const pendingMentionActions = normalizePendingMentionActions(data);
49903
- const mentionSection = pendingMentionActions.length > 0 ? `
49904
-
49905
- ${formatPendingMentionActions(pendingMentionActions, { source: "send" }).trimEnd()}` : "";
49906
- writeText(ctx.io, `Message sent to ${target}. Message ID: ${data.messageId}${replyHint}${mentionSection}${unreadSection}
49907
- `);
49908
50591
  }
49909
50592
  );
49910
50593
  function registerSendCommand(parent, runtimeOptions = {}) {
@@ -50004,7 +50687,7 @@ function requireTargetAlias(opts) {
50004
50687
  }
50005
50688
  return target;
50006
50689
  }
50007
- function parsePositiveInt2(name, raw) {
50690
+ function parsePositiveInt4(name, raw) {
50008
50691
  if (raw === void 0) return void 0;
50009
50692
  const n = Number(raw);
50010
50693
  if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {
@@ -50043,7 +50726,7 @@ function mapReadFailure(res) {
50043
50726
  }
50044
50727
  function validateReadOpts(opts) {
50045
50728
  const channel = requireTargetAlias(opts);
50046
- const limit = parsePositiveInt2("limit", opts.limit);
50729
+ const limit = parsePositiveInt4("limit", opts.limit);
50047
50730
  const before = opts.before?.trim();
50048
50731
  const after = opts.after?.trim();
50049
50732
  return {
@@ -50133,7 +50816,7 @@ function normalizeMemberHandleRef(raw) {
50133
50816
  }
50134
50817
  return handle;
50135
50818
  }
50136
- function parsePositiveInt3(name, raw) {
50819
+ function parsePositiveInt5(name, raw) {
50137
50820
  if (raw === void 0) return void 0;
50138
50821
  const n = Number(raw);
50139
50822
  if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {
@@ -50144,7 +50827,7 @@ function parsePositiveInt3(name, raw) {
50144
50827
  }
50145
50828
  return n;
50146
50829
  }
50147
- function parseNonNegativeInt(name, raw) {
50830
+ function parseNonNegativeInt3(name, raw) {
50148
50831
  if (raw === void 0) return void 0;
50149
50832
  const n = Number(raw);
50150
50833
  if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0) {
@@ -50178,8 +50861,8 @@ function normalizeSearchOpts(opts) {
50178
50861
  message: "--sort relevance requires --query; filter-only search is sorted by recent"
50179
50862
  });
50180
50863
  }
50181
- const limit = parsePositiveInt3("limit", opts.limit);
50182
- const offset = parseNonNegativeInt("offset", opts.offset);
50864
+ const limit = parsePositiveInt5("limit", opts.limit);
50865
+ const offset = parseNonNegativeInt3("offset", opts.offset);
50183
50866
  const sort = opts.sort ?? (query ? void 0 : "recent");
50184
50867
  return {
50185
50868
  ...query ? { query } : {},
@@ -52149,6 +52832,15 @@ function safeUrl2(value, label) {
52149
52832
  }
52150
52833
  return url2;
52151
52834
  }
52835
+ function substituteEndpointPathParams(endpointPath, payload) {
52836
+ return endpointPath.replace(/\{([A-Za-z][A-Za-z0-9_]*)\}/g, (_match, name) => {
52837
+ const value = payload[name];
52838
+ if (value === void 0 || value === null || value === "") {
52839
+ throw cliError("INVALID_ARG", `missing path parameter ${name}`);
52840
+ }
52841
+ return encodeURIComponent(typeof value === "string" ? value : JSON.stringify(value));
52842
+ });
52843
+ }
52152
52844
  function resolveActionUrl(input) {
52153
52845
  const base = input.manifest.execution.base_url ?? input.manifest.app_origin ?? input.service.homepageUrl ?? (input.service.returnUrl ? safeUrl2(input.service.returnUrl, "service return URL").origin : null);
52154
52846
  if (!base) {
@@ -52158,7 +52850,7 @@ function resolveActionUrl(input) {
52158
52850
  );
52159
52851
  }
52160
52852
  const baseUrl = safeUrl2(base, "action base URL");
52161
- return new URL(input.action.endpoint.path, baseUrl);
52853
+ return new URL(substituteEndpointPathParams(input.action.endpoint.path, input.payload), baseUrl);
52162
52854
  }
52163
52855
  function appendPayloadAsQuery(url2, payload) {
52164
52856
  for (const [key, value] of Object.entries(payload)) {
@@ -52166,6 +52858,13 @@ function appendPayloadAsQuery(url2, payload) {
52166
52858
  url2.searchParams.set(key, typeof value === "string" ? value : JSON.stringify(value));
52167
52859
  }
52168
52860
  }
52861
+ function appendResourceLocatorQuery(input) {
52862
+ const { url: url2, action, payload } = input;
52863
+ if (/\{id\}/.test(action.endpoint.path)) return;
52864
+ const id = payload.id;
52865
+ if (id === void 0 || id === null || id === "" || url2.searchParams.has("id")) return;
52866
+ url2.searchParams.set("id", typeof id === "string" ? id : JSON.stringify(id));
52867
+ }
52169
52868
  async function invokeHttpAction(input) {
52170
52869
  const url2 = new URL(input.url);
52171
52870
  const cookie = cookieHeaderForUrl(input.cookies, url2);
@@ -52187,6 +52886,7 @@ async function invokeHttpAction(input) {
52187
52886
  if (input.action.endpoint.method === "GET") {
52188
52887
  appendPayloadAsQuery(url2, input.payload);
52189
52888
  } else {
52889
+ appendResourceLocatorQuery({ url: url2, action: input.action, payload: input.payload });
52190
52890
  headers["content-type"] = "application/json";
52191
52891
  init.body = JSON.stringify(input.payload);
52192
52892
  }
@@ -52243,6 +52943,9 @@ function formatActions(input) {
52243
52943
  lines.push(` endpoint: ${action.endpoint.method} ${action.endpoint.path}`);
52244
52944
  if (action.description) lines.push(` description: ${action.description}`);
52245
52945
  if (required2.length > 0) lines.push(` required params: ${required2.join(", ")}`);
52946
+ if (action.endpoint.method !== "GET" && Object.hasOwn(action.parameters ?? {}, "id") && !/\{id\}/.test(action.endpoint.path)) {
52947
+ lines.push(" note: id is treated as the resource locator and is also sent as query ?id=; JSON body is preserved");
52948
+ }
52246
52949
  }
52247
52950
  lines.push(`next: raft integration invoke --service ${JSON.stringify(input.service.clientId)} --action ${JSON.stringify(actions[0]?.name ?? "<name>")}`);
52248
52951
  return lines.join("\n");
@@ -52352,7 +53055,7 @@ var integrationInvokeCommand = defineCommand(
52352
53055
  { flags: "--list-actions", description: "List manifest actions instead of invoking one" },
52353
53056
  {
52354
53057
  flags: "--param <key=value>",
52355
- description: "Action parameter; repeatable. Use key=@file or key=@- to read text",
53058
+ description: "Action parameter; repeatable. Use key=@file or key=@- to read text. For non-GET actions, id is also sent as query ?id= when the manifest path has no {id}",
52356
53059
  parse: (value, previous = []) => {
52357
53060
  previous.push(value);
52358
53061
  return previous;
@@ -52480,7 +53183,7 @@ var integrationInvokeCommand = defineCommand(
52480
53183
  });
52481
53184
  cookies = session.cookies;
52482
53185
  }
52483
- const url2 = resolveActionUrl({ service, manifest, action });
53186
+ const url2 = resolveActionUrl({ service, manifest, action, payload });
52484
53187
  const result2 = await invokeHttpAction({ url: url2, action, payload, cookies, service });
52485
53188
  if (opts.json) {
52486
53189
  writeJson(cmdCtx.io, {
@@ -53051,6 +53754,7 @@ registerAgentLoginCommand(agentCmd);
53051
53754
  registerAgentListCommand(agentCmd);
53052
53755
  registerAgentBridgeCommand(agentCmd);
53053
53756
  var channelCmd = program2.command("channel").description("Channel membership and attention operations");
53757
+ registerChannelInfoCommand(channelCmd);
53054
53758
  registerChannelMembersCommand(channelCmd);
53055
53759
  registerChannelCreateCommand(channelCmd);
53056
53760
  registerChannelUpdateCommand(channelCmd);
@@ -53065,10 +53769,17 @@ registerThreadUnfollowCommand(threadCmd);
53065
53769
  var serverCmd = program2.command("server").description("Server / workspace introspection");
53066
53770
  registerServerInfoCommand(serverCmd);
53067
53771
  registerServerUpdateCommand(serverCmd);
53068
- var manualCmd = program2.command("manual").description("Raft Manual for Agents retrieval (canonical operating topics)");
53772
+ var userCmd = program2.command("user").description("User and agent introspection");
53773
+ registerUserInfoCommand(userCmd);
53774
+ var manualCmd = program2.command("manual").description("Look up Raft operating topics and agent recipes").addHelpText(
53775
+ "after",
53776
+ '\nCommon agent flows:\n raft manual get index\n raft manual get recipes/seeded\n raft manual get recipes/technique/preview-env\n raft manual search "preview before merge" --scope recipes\n\nUse `raft manual get --help` and `raft manual search --help` for options.\n'
53777
+ );
53069
53778
  registerKnowledgeGetCommand(manualCmd);
53779
+ registerKnowledgeSearchCommand(manualCmd);
53070
53780
  var knowledgeCmd = program2.command("knowledge").description("Legacy alias for `raft manual`");
53071
53781
  registerKnowledgeGetCommand(knowledgeCmd);
53782
+ registerKnowledgeSearchCommand(knowledgeCmd);
53072
53783
  var inboxCmd = program2.command("inbox").description("Inbox target summary operations");
53073
53784
  registerInboxCheckCommand(inboxCmd);
53074
53785
  var messageCmd = program2.command("message").description("Message operations");