@botiverse/raft-daemon 0.70.2 → 0.71.0

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) {
@@ -28565,6 +28568,18 @@ function defineTraceFields(definitions) {
28565
28568
  }
28566
28569
  return definitions;
28567
28570
  }
28571
+ var TRACE_LIFECYCLE_SHADOW_SIGNAL_SITE_VALUES = [
28572
+ "daemon_ingest",
28573
+ "delivery_ack",
28574
+ "hint_resolution",
28575
+ "lifecycle_plan",
28576
+ "preserve_rebroadcast",
28577
+ "ready_online",
28578
+ "runtime_error",
28579
+ "slock_action_status",
28580
+ "starting_resolve",
28581
+ "synthetic_repair"
28582
+ ];
28568
28583
  var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28569
28584
  { key: "row_kind", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "stable" },
28570
28585
  { key: "trace_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
@@ -28587,10 +28602,13 @@ var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28587
28602
  { key: "route_pattern", fieldClass: "query_axis", placement: "span", valueKind: "route" },
28588
28603
  { key: "caller_kind", fieldClass: "query_axis", placement: "span", valueKind: "closed_enum", enumBinding: "stable" },
28589
28604
  { key: "server_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
28605
+ { key: "channel_id", fieldClass: "query_axis", placement: "span_or_event", valueKind: "identity", highCardinality: true },
28590
28606
  { key: "machine_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
28591
28607
  { key: "agent_id", fieldClass: "query_axis", placement: "span_or_event", valueKind: "identity", highCardinality: true },
28608
+ { key: "job_id", fieldClass: "query_axis", placement: "span_or_event", valueKind: "identity", highCardinality: true },
28592
28609
  { key: "launch_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
28593
28610
  { key: "session_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
28611
+ { key: "outcome", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28594
28612
  { key: "observation_class", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28595
28613
  { key: "action", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28596
28614
  { key: "source", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
@@ -28600,6 +28618,7 @@ var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28600
28618
  { key: "error_class", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28601
28619
  { key: "query_name", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "query_registry" },
28602
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" },
28603
28622
  { key: "hint_source", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
28604
28623
  { key: "resolved_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
28605
28624
  { key: "previous_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
@@ -28609,7 +28628,7 @@ var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28609
28628
  { key: "activity_source", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
28610
28629
  { key: "status_bucket", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
28611
28630
  { key: "shadow_agent_id", fieldClass: "family_query_axis", placement: "event", valueKind: "identity", scope: "family:lifecycle_shadow", highCardinality: true },
28612
- { key: "shadow_signal_site", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
28631
+ { key: "shadow_signal_site", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457", enumValues: TRACE_LIFECYCLE_SHADOW_SIGNAL_SITE_VALUES },
28613
28632
  { key: "shadow_observation_class", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
28614
28633
  { key: "shadow_prior_projection", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
28615
28634
  { key: "shadow_projection", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
@@ -28619,6 +28638,8 @@ var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28619
28638
  { key: "shadow_direction", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
28620
28639
  { key: "shadow_plan_kind", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
28621
28640
  { key: "row_count", fieldClass: "detail", placement: "span_or_event", valueKind: "detail" },
28641
+ { key: "rows_copied", fieldClass: "detail", placement: "span_or_event", valueKind: "numeric" },
28642
+ { key: "batch_index", fieldClass: "detail", placement: "span_or_event", valueKind: "numeric" },
28622
28643
  { key: "retry_count", fieldClass: "detail", placement: "span_or_event", valueKind: "detail" },
28623
28644
  { key: "error_message", fieldClass: "detail", placement: "span_or_event", valueKind: "detail", contentRule: "scrub_and_short_retention" },
28624
28645
  { key: "query_text", fieldClass: "content_safety", placement: "span_or_event", valueKind: "content", contentRule: "scrub_and_short_retention" },
@@ -42483,6 +42504,24 @@ var agentApiKnowledgeGetResponseSchema = passthroughObject({
42483
42504
  contentType: external_exports.string(),
42484
42505
  content: external_exports.string()
42485
42506
  });
42507
+ var agentApiKnowledgeSearchQuerySchema = passthroughObject({
42508
+ query: external_exports.string().trim().min(1),
42509
+ scope: optionalStringSchema,
42510
+ reason: optionalStringSchema,
42511
+ turn_id: optionalStringSchema,
42512
+ trace_id: optionalStringSchema
42513
+ });
42514
+ var agentApiKnowledgeSearchResultSchema = passthroughObject({
42515
+ slug: external_exports.string(),
42516
+ title: external_exports.string(),
42517
+ firstScreen: external_exports.string()
42518
+ });
42519
+ var agentApiKnowledgeSearchResponseSchema = passthroughObject({
42520
+ ok: external_exports.literal(true),
42521
+ query: external_exports.string(),
42522
+ scope: external_exports.string().nullable(),
42523
+ results: external_exports.array(agentApiKnowledgeSearchResultSchema)
42524
+ });
42486
42525
  var agentApiMessageSearchQuerySchema = passthroughObject({
42487
42526
  q: optionalStringSchema,
42488
42527
  channel: optionalStringSchema,
@@ -42934,7 +42973,14 @@ var agentApiSendSentResponseSchema = passthroughObject({
42934
42973
  messageId: external_exports.string(),
42935
42974
  messageSeq: optionalNumberSchema,
42936
42975
  recentUnread: external_exports.array(agentApiMessageEnvelopeSchema).optional(),
42937
- pendingMentionActions: external_exports.array(agentApiMessageEnvelopeSchema).optional()
42976
+ pendingMentionActions: external_exports.array(agentApiMessageEnvelopeSchema).optional(),
42977
+ attention: passthroughObject({
42978
+ driveByJoinedToPost: passthroughObject({
42979
+ reason: optionalStringSchema,
42980
+ muteCommand: optionalStringSchema,
42981
+ stillArrives: optionalStringArraySchema
42982
+ }).optional()
42983
+ }).optional()
42938
42984
  });
42939
42985
  var agentApiSendResponseSchema = external_exports.discriminatedUnion("state", [
42940
42986
  agentApiSendSentResponseSchema,
@@ -43123,6 +43169,16 @@ var agentApiContract = {
43123
43169
  request: { query: agentApiKnowledgeGetQuerySchema },
43124
43170
  response: { body: agentApiKnowledgeGetResponseSchema }
43125
43171
  }),
43172
+ knowledgeSearch: route({
43173
+ key: "knowledgeSearch",
43174
+ method: "GET",
43175
+ path: "/knowledge/search",
43176
+ client: { resource: "knowledge", method: "search" },
43177
+ capability: "knowledge",
43178
+ description: "Search Slock Manual for Agents topics from the current server.",
43179
+ request: { query: agentApiKnowledgeSearchQuerySchema },
43180
+ response: { body: agentApiKnowledgeSearchResponseSchema }
43181
+ }),
43126
43182
  messageSend: route({
43127
43183
  key: "messageSend",
43128
43184
  method: "POST",
@@ -44406,7 +44462,8 @@ var SUPPORTED_TRANSLATION_LANGUAGE_CODES = [
44406
44462
  "es",
44407
44463
  "fr",
44408
44464
  "de",
44409
- "pt-br"
44465
+ "pt-br",
44466
+ "it"
44410
44467
  ];
44411
44468
  var SUPPORTED_TRANSLATION_LANGUAGE_SET = new Set(
44412
44469
  SUPPORTED_TRANSLATION_LANGUAGE_CODES
@@ -44525,6 +44582,9 @@ var SERVER_CAPABILITY_MATRIX = {
44525
44582
  joinPublicChannels: true
44526
44583
  })
44527
44584
  };
44585
+ init_esm_shims();
44586
+ init_esm_shims();
44587
+ init_esm_shims();
44528
44588
  var BUILTIN_RUNTIME_PROVIDER_ENV_KEYS = PI_BUILTIN_PROVIDER_API_KEY_ENV_KEYS_GENERATED;
44529
44589
  var BUILTIN_RUNTIME_PROVIDERS = Object.entries(BUILTIN_RUNTIME_PROVIDER_ENV_KEYS).map(([id, envKey]) => ({ id, envKey }));
44530
44590
  var PI_BUILTIN_PROVIDER_ENV_KEYS = {
@@ -44964,7 +45024,8 @@ function createAgentApiSurfaceClient(client) {
44964
45024
  read: (query) => requestClientAsApiResponse(agentApi.history.read(query))
44965
45025
  },
44966
45026
  knowledge: {
44967
- get: (query) => requestClientAsApiResponse(agentApi.knowledge.get(query))
45027
+ get: (query) => requestClientAsApiResponse(agentApi.knowledge.get(query)),
45028
+ search: (query) => requestClientAsApiResponse(agentApi.knowledge.search(query))
44968
45029
  },
44969
45030
  tasks: {
44970
45031
  list: (query) => requestClientAsApiResponse(agentApi.tasks.list(query)),
@@ -45695,6 +45756,10 @@ function renderError(io, err) {
45695
45756
  `);
45696
45757
  io.stderr.write(`Code: ${err.code}
45697
45758
  `);
45759
+ if (err.draftSaved !== void 0) {
45760
+ io.stderr.write(`Draft saved: ${err.draftSaved ? "yes" : "no"}
45761
+ `);
45762
+ }
45698
45763
  if (err.suggestedNextAction) {
45699
45764
  io.stderr.write(`Next action: ${err.suggestedNextAction}
45700
45765
  `);
@@ -48023,6 +48088,156 @@ function formatServerInfo(data) {
48023
48088
  }
48024
48089
  return text;
48025
48090
  }
48091
+ function channelRef(name) {
48092
+ return name.startsWith("#") ? name : `#${name}`;
48093
+ }
48094
+ function channelVisibility(channel) {
48095
+ const type = channel.type?.trim();
48096
+ return type === "private" ? "private" : "public";
48097
+ }
48098
+ function channelMuted(channel) {
48099
+ if (typeof channel.muted === "boolean") return channel.muted;
48100
+ if (typeof channel.activityMuted === "boolean") return channel.activityMuted;
48101
+ return void 0;
48102
+ }
48103
+ function channelStatus(channel) {
48104
+ const parts = [
48105
+ channelVisibility(channel),
48106
+ channel.joined ? "joined" : "not joined"
48107
+ ];
48108
+ const muted = channelMuted(channel);
48109
+ if (muted !== void 0) parts.push(muted ? "muted" : "not muted");
48110
+ if (typeof channel.archived === "boolean") parts.push(channel.archived ? "archived" : "not archived");
48111
+ return parts.join(", ");
48112
+ }
48113
+ function formatPageFooter(page) {
48114
+ if (!page) return "";
48115
+ const start = page.total === 0 ? 0 : Math.min(page.offset + 1, page.total);
48116
+ const end = Math.min(page.offset + page.limit, page.total);
48117
+ const lines = [`
48118
+ Showing ${start}-${end} of ${page.total}.`];
48119
+ if (page.nextCommand && end < page.total) {
48120
+ lines.push(`More: ${page.nextCommand}`);
48121
+ }
48122
+ return `${lines.join("\n")}
48123
+ `;
48124
+ }
48125
+ function formatChannelInfo(channel, memberCounts) {
48126
+ const lines = ["## Channel", ""];
48127
+ lines.push(`Channel: ${channelRef(channel.name)}`);
48128
+ if (channel.id) lines.push(`ID: ${channel.id}`);
48129
+ lines.push(`Visibility: ${channelVisibility(channel)}`);
48130
+ lines.push(`Joined: ${channel.joined ? "yes" : "no"}`);
48131
+ const muted = channelMuted(channel);
48132
+ if (muted !== void 0) lines.push(`Muted: ${muted ? "yes" : "no"}`);
48133
+ if (typeof channel.archived === "boolean") lines.push(`Archived: ${channel.archived ? "yes" : "no"}`);
48134
+ lines.push(`Description: ${channel.description?.trim() || "(none)"}`);
48135
+ if (memberCounts) {
48136
+ const agents = memberCounts.agents ?? 0;
48137
+ const humans = memberCounts.humans ?? 0;
48138
+ lines.push(`Members: ${agents + humans} (${agents} agents, ${humans} humans)`);
48139
+ }
48140
+ lines.push("");
48141
+ lines.push(`More: raft channel members "${channelRef(channel.name)}"`);
48142
+ return `${lines.join("\n")}
48143
+ `;
48144
+ }
48145
+ function formatServerSummary(data) {
48146
+ const channels = data.channels ?? [];
48147
+ const agents = data.agents ?? [];
48148
+ const humans = data.humans ?? [];
48149
+ const joined = channels.filter((channel) => channel.joined).length;
48150
+ const lines = [
48151
+ "## Server",
48152
+ "",
48153
+ `Channels: ${channels.length} visible (${joined} joined)`,
48154
+ `Agents: ${agents.length}`,
48155
+ `Humans: ${humans.length}`,
48156
+ "",
48157
+ "Narrow queries:",
48158
+ "- raft server info --channels",
48159
+ "- raft server info --agents",
48160
+ "- raft server info --humans",
48161
+ "- raft channel info <name>",
48162
+ "- raft user info <name>",
48163
+ "",
48164
+ "Full dump: raft server info --full"
48165
+ ];
48166
+ return `${lines.join("\n")}
48167
+ `;
48168
+ }
48169
+ function formatServerChannels(channels, page) {
48170
+ const lines = [
48171
+ "## Server Channels",
48172
+ "",
48173
+ "Private channels are shown only when this agent is a member. Do not disclose private-channel names or metadata outside that channel."
48174
+ ];
48175
+ if (channels.length === 0) {
48176
+ lines.push("(none)");
48177
+ } else {
48178
+ for (const channel of channels) {
48179
+ const description = channel.description?.trim();
48180
+ lines.push(description ? `${channelRef(channel.name)} [${channelStatus(channel)}] \u2014 ${description}` : `${channelRef(channel.name)} [${channelStatus(channel)}]`);
48181
+ }
48182
+ }
48183
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48184
+ }
48185
+ function formatServerAgents(agents, page) {
48186
+ const lines = [
48187
+ "## Server Agents",
48188
+ "",
48189
+ "Role labels show server-level owner/admin authority; no role label means ordinary member."
48190
+ ];
48191
+ if (agents.length === 0) {
48192
+ lines.push("(none)");
48193
+ } else {
48194
+ for (const agent of agents) {
48195
+ const role = roleLabel(agent.role);
48196
+ const status = agentStatusLabel(agent);
48197
+ lines.push(agent.description ? `@${agent.name} (${status})${role} \u2014 ${agent.description}` : `@${agent.name} (${status})${role}`);
48198
+ }
48199
+ }
48200
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48201
+ }
48202
+ function formatServerHumans(humans, page) {
48203
+ const lines = [
48204
+ "## Server Humans",
48205
+ "",
48206
+ "Role labels show server-level owner/admin authority; no role label means ordinary member."
48207
+ ];
48208
+ if (humans.length === 0) {
48209
+ lines.push("(none)");
48210
+ } else {
48211
+ for (const human of humans) {
48212
+ const role = roleLabel(human.role);
48213
+ lines.push(human.description ? `@${human.name}${role} \u2014 ${human.description}` : `@${human.name}${role}`);
48214
+ }
48215
+ }
48216
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48217
+ }
48218
+ function formatUserInfo(user, memberships, page, skippedChannels = 0) {
48219
+ const name = user.value.name;
48220
+ const role = roleLabel(user.value.role);
48221
+ const lines = ["## User", ""];
48222
+ lines.push(`User: @${name}`);
48223
+ lines.push(`Kind: ${user.kind}`);
48224
+ if (user.kind === "agent") lines.push(`Status: ${agentStatusLabel(user.value)}`);
48225
+ if (role) lines.push(`Role: ${role.slice(2, -1)}`);
48226
+ if (user.value.description) lines.push(`Description: ${user.value.description}`);
48227
+ lines.push("");
48228
+ lines.push("### Visible Channel Memberships");
48229
+ if (memberships.length === 0) {
48230
+ lines.push("(none found in inspected visible channels)");
48231
+ } else {
48232
+ for (const channel of memberships) {
48233
+ lines.push(`${channelRef(channel.name)} [${channelStatus(channel)}]`);
48234
+ }
48235
+ }
48236
+ if (skippedChannels > 0) {
48237
+ lines.push(`Skipped ${skippedChannels} visible channel roster checks because the server rejected them.`);
48238
+ }
48239
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48240
+ }
48026
48241
  function formatChannelMembers(data) {
48027
48242
  let text = "## Channel Members\n\n";
48028
48243
  const ref = data.channel?.ref ?? "(unknown)";
@@ -48090,65 +48305,6 @@ function registerChannelMembersCommand(parent, runtimeOptions) {
48090
48305
  registerCliCommand(parent, channelMembersCommand, runtimeOptions);
48091
48306
  }
48092
48307
  init_esm_shims();
48093
- function normalizeChannelName(raw) {
48094
- return (raw ?? "").trim().replace(/^#/, "");
48095
- }
48096
- function formatCreateChannelResult(channel) {
48097
- const target = `#${channel.name}`;
48098
- const visibility = channel.type === "private" ? "private" : "public";
48099
- return `Created ${target} (${visibility}). You are joined and can send messages there.`;
48100
- }
48101
- var channelCreateCommand = defineCommand(
48102
- {
48103
- name: "create",
48104
- description: "Create a public or private channel when this agent has server admin authority",
48105
- options: [
48106
- {
48107
- flags: "--name <name>",
48108
- description: "Channel name, with or without a leading '#'"
48109
- },
48110
- {
48111
- flags: "--description <description>",
48112
- description: "Optional channel description"
48113
- },
48114
- {
48115
- flags: "--private",
48116
- description: "Create a private channel instead of a public channel"
48117
- }
48118
- ]
48119
- },
48120
- async (ctx, opts) => {
48121
- const name = normalizeChannelName(opts.name);
48122
- if (!name) {
48123
- throw new CliError({
48124
- code: "INVALID_ARG",
48125
- message: "--name is required"
48126
- });
48127
- }
48128
- const agentContext = ctx.loadAgentContext();
48129
- const client = ctx.createApiClient(agentContext);
48130
- const res = await client.request(
48131
- "POST",
48132
- `/internal/agent/${encodeURIComponent(agentContext.agentId)}/channels`,
48133
- {
48134
- name,
48135
- description: opts.description,
48136
- visibility: opts.private ? "private" : "public"
48137
- }
48138
- );
48139
- if (!res.ok || !res.data) {
48140
- throw new CliError({
48141
- code: res.status >= 500 ? "SERVER_5XX" : "CREATE_FAILED",
48142
- message: res.error ?? `HTTP ${res.status}`
48143
- });
48144
- }
48145
- writeText(ctx.io, formatCreateChannelResult(res.data) + "\n");
48146
- }
48147
- );
48148
- function registerChannelCreateCommand(parent, runtimeOptions) {
48149
- registerCliCommand(parent, channelCreateCommand, runtimeOptions);
48150
- }
48151
- init_esm_shims();
48152
48308
  init_esm_shims();
48153
48309
  function parseRegularChannelTarget(target) {
48154
48310
  if (!target.startsWith("#")) return null;
@@ -48218,6 +48374,118 @@ var channelLeaveCommand = defineCommand(
48218
48374
  function registerChannelLeaveCommand(parent, runtimeOptions) {
48219
48375
  registerCliCommand(parent, channelLeaveCommand, runtimeOptions);
48220
48376
  }
48377
+ function normalizeChannelInfoTarget(target) {
48378
+ const input = target?.trim() ?? "";
48379
+ const normalized = input.startsWith("#") ? input : `#${input}`;
48380
+ const name = parseRegularChannelTarget(normalized);
48381
+ if (!name) {
48382
+ throw new CliError({
48383
+ code: "INVALID_TARGET",
48384
+ message: "Target must be a regular channel name, e.g. '#engineering' or 'engineering'. DMs and thread targets are not supported."
48385
+ });
48386
+ }
48387
+ return { input: normalized, name };
48388
+ }
48389
+ var channelInfoCommand = defineCommand(
48390
+ {
48391
+ name: "info",
48392
+ description: "Show narrow channel facts: existence, joined state, description, and member count when visible",
48393
+ arguments: ["<target>"]
48394
+ },
48395
+ async (ctx, target) => {
48396
+ const { input, name } = normalizeChannelInfoTarget(target);
48397
+ const agentContext = ctx.loadAgentContext();
48398
+ const client = ctx.createApiClient(agentContext);
48399
+ const agentApi = createAgentApiSurfaceClient(client);
48400
+ const infoRes = await agentApi.server.info();
48401
+ if (!infoRes.ok) {
48402
+ throw new CliError({
48403
+ code: infoRes.status >= 500 ? "SERVER_5XX" : "INFO_FAILED",
48404
+ message: infoRes.error ?? `HTTP ${infoRes.status}`
48405
+ });
48406
+ }
48407
+ const channel = (infoRes.data?.channels ?? []).find((candidate) => candidate.name === name);
48408
+ if (!channel) {
48409
+ throw new CliError({
48410
+ code: "NOT_FOUND",
48411
+ message: `Channel not found or not visible: ${input}`,
48412
+ suggestedNextAction: "Run `raft server info --channels --query <name>` to inspect visible channels, or ask a channel member to add you if this is private."
48413
+ });
48414
+ }
48415
+ let memberCounts = null;
48416
+ const membersRes = await agentApi.channels.members({ channel: `#${name}` });
48417
+ if (membersRes.ok) {
48418
+ memberCounts = {
48419
+ agents: membersRes.data?.agents?.length ?? 0,
48420
+ humans: membersRes.data?.humans?.length ?? 0
48421
+ };
48422
+ }
48423
+ writeText(ctx.io, formatChannelInfo(channel, memberCounts));
48424
+ }
48425
+ );
48426
+ function registerChannelInfoCommand(parent, runtimeOptions) {
48427
+ registerCliCommand(parent, channelInfoCommand, runtimeOptions);
48428
+ }
48429
+ init_esm_shims();
48430
+ function normalizeChannelName(raw) {
48431
+ return (raw ?? "").trim().replace(/^#/, "");
48432
+ }
48433
+ function formatCreateChannelResult(channel) {
48434
+ const target = `#${channel.name}`;
48435
+ const visibility = channel.type === "private" ? "private" : "public";
48436
+ return `Created ${target} (${visibility}). You are joined and can send messages there.`;
48437
+ }
48438
+ var channelCreateCommand = defineCommand(
48439
+ {
48440
+ name: "create",
48441
+ description: "Create a public or private channel when this agent has server admin authority",
48442
+ options: [
48443
+ {
48444
+ flags: "--name <name>",
48445
+ description: "Channel name, with or without a leading '#'"
48446
+ },
48447
+ {
48448
+ flags: "--description <description>",
48449
+ description: "Optional channel description"
48450
+ },
48451
+ {
48452
+ flags: "--private",
48453
+ description: "Create a private channel instead of a public channel"
48454
+ }
48455
+ ]
48456
+ },
48457
+ async (ctx, opts) => {
48458
+ const name = normalizeChannelName(opts.name);
48459
+ if (!name) {
48460
+ throw new CliError({
48461
+ code: "INVALID_ARG",
48462
+ message: "--name is required"
48463
+ });
48464
+ }
48465
+ const agentContext = ctx.loadAgentContext();
48466
+ const client = ctx.createApiClient(agentContext);
48467
+ const res = await client.request(
48468
+ "POST",
48469
+ `/internal/agent/${encodeURIComponent(agentContext.agentId)}/channels`,
48470
+ {
48471
+ name,
48472
+ description: opts.description,
48473
+ visibility: opts.private ? "private" : "public"
48474
+ }
48475
+ );
48476
+ if (!res.ok || !res.data) {
48477
+ throw new CliError({
48478
+ code: res.status >= 500 ? "SERVER_5XX" : "CREATE_FAILED",
48479
+ message: res.error ?? `HTTP ${res.status}`
48480
+ });
48481
+ }
48482
+ writeText(ctx.io, formatCreateChannelResult(res.data) + "\n");
48483
+ }
48484
+ );
48485
+ function registerChannelCreateCommand(parent, runtimeOptions) {
48486
+ registerCliCommand(parent, channelCreateCommand, runtimeOptions);
48487
+ }
48488
+ init_esm_shims();
48221
48489
  function normalizeChannelName2(raw) {
48222
48490
  return (raw ?? "").trim().replace(/^#/, "");
48223
48491
  }
@@ -48484,7 +48752,12 @@ function registerChannelRemoveMemberCommand(parent, runtimeOptions) {
48484
48752
  }
48485
48753
  init_esm_shims();
48486
48754
  function formatJoinChannelResult(target) {
48487
- return `Joined ${target}. You can now send messages there and receive ordinary channel delivery.`;
48755
+ return [
48756
+ `Joined ${target}. You can now send messages there and receive ordinary channel delivery.`,
48757
+ "Still arrives:",
48758
+ "- Personal @mentions still reach you even if you later mute ordinary channel updates.",
48759
+ "- Threads you started or follow stay followed even if you later mute this channel."
48760
+ ].join("\n");
48488
48761
  }
48489
48762
  function formatAlreadyJoined(target) {
48490
48763
  return `Already joined ${target}.`;
@@ -48636,12 +48909,90 @@ function registerChannelUnmuteCommand(parent, runtimeOptions) {
48636
48909
  registerCliCommand(parent, channelUnmuteCommand, runtimeOptions);
48637
48910
  }
48638
48911
  init_esm_shims();
48912
+ function parseNonNegativeInt(raw, name, fallback) {
48913
+ if (raw === void 0) return fallback;
48914
+ if (!/^\d+$/.test(raw)) {
48915
+ throw new CliError({
48916
+ code: "INVALID_ARG",
48917
+ message: `${name} must be a non-negative integer`
48918
+ });
48919
+ }
48920
+ return Number(raw);
48921
+ }
48922
+ function parsePositiveInt2(raw, name, fallback) {
48923
+ const value = parseNonNegativeInt(raw, name, fallback);
48924
+ if (value <= 0) {
48925
+ throw new CliError({
48926
+ code: "INVALID_ARG",
48927
+ message: `${name} must be greater than 0`
48928
+ });
48929
+ }
48930
+ return value;
48931
+ }
48932
+ function selectedSections(opts) {
48933
+ const sections = [];
48934
+ if (opts.channels) sections.push("channels");
48935
+ if (opts.agents) sections.push("agents");
48936
+ if (opts.humans) sections.push("humans");
48937
+ return sections;
48938
+ }
48939
+ function hasListModifier(opts) {
48940
+ return Boolean(opts.joined || opts.query !== void 0 || opts.limit !== void 0 || opts.offset !== void 0);
48941
+ }
48942
+ function includesQuery(row, query) {
48943
+ const needle = query?.trim().toLowerCase();
48944
+ if (!needle) return true;
48945
+ const values = Object.values(row).filter((value) => typeof value === "string").map((value) => value.toLowerCase());
48946
+ return values.some((value) => value.includes(needle));
48947
+ }
48948
+ function pageRows(rows, offset, limit) {
48949
+ return rows.slice(offset, offset + limit);
48950
+ }
48951
+ function nextCommand(section, opts, offset, limit, total) {
48952
+ const nextOffset = offset + limit;
48953
+ if (nextOffset >= total) return void 0;
48954
+ const parts = ["raft server info", `--${section}`, `--offset ${nextOffset}`, `--limit ${limit}`];
48955
+ if (opts.query?.trim()) parts.push(`--query ${JSON.stringify(opts.query.trim())}`);
48956
+ if (opts.joined) parts.push("--joined");
48957
+ return parts.join(" ");
48958
+ }
48639
48959
  var serverInfoCommand = defineCommand(
48640
48960
  {
48641
48961
  name: "info",
48642
- description: "List channels, agents, and humans on the current server"
48962
+ description: "Show bounded server facts; use --full for the legacy full inventory",
48963
+ options: [
48964
+ { flags: "--full", description: "Print the full channels, agents, humans, and runtime inventory" },
48965
+ { flags: "--channels", description: "List visible channels only" },
48966
+ { flags: "--agents", description: "List agents only" },
48967
+ { flags: "--humans", description: "List humans only" },
48968
+ { flags: "--joined", description: "With --channels, show only joined channels" },
48969
+ { flags: "--query <text>", description: "Filter the selected list by visible text" },
48970
+ { flags: "--limit <n>", description: "Maximum rows for list output (default: 50)" },
48971
+ { flags: "--offset <n>", description: "Rows to skip for list output (default: 0)" }
48972
+ ]
48643
48973
  },
48644
- async (ctx) => {
48974
+ async (ctx, opts = {}) => {
48975
+ const sections = selectedSections(opts);
48976
+ if (opts.full && sections.length > 0) {
48977
+ throw new CliError({
48978
+ code: "INVALID_ARG",
48979
+ message: "--full cannot be combined with --channels, --agents, or --humans"
48980
+ });
48981
+ }
48982
+ if (sections.length === 0 && hasListModifier(opts)) {
48983
+ throw new CliError({
48984
+ code: "INVALID_ARG",
48985
+ message: "--query, --limit, --offset, and --joined require --channels, --agents, or --humans"
48986
+ });
48987
+ }
48988
+ if (opts.joined && sections.some((section) => section !== "channels")) {
48989
+ throw new CliError({
48990
+ code: "INVALID_ARG",
48991
+ message: "--joined can only be used with --channels"
48992
+ });
48993
+ }
48994
+ const limit = parsePositiveInt2(opts.limit, "--limit", 50);
48995
+ const offset = parseNonNegativeInt(opts.offset, "--offset", 0);
48645
48996
  const agentContext = ctx.loadAgentContext();
48646
48997
  const client = ctx.createApiClient(agentContext);
48647
48998
  const res = await createAgentApiSurfaceClient(client).server.info();
@@ -48652,14 +49003,56 @@ var serverInfoCommand = defineCommand(
48652
49003
  message: res.error ?? `HTTP ${res.status}`
48653
49004
  });
48654
49005
  }
48655
- const data = res.data;
48656
- if (data?.runtimeContext) {
48657
- data.runtimeContext = {
48658
- ...data.runtimeContext,
48659
- workspacePath: data.runtimeContext.workspacePath ?? ctx.env.SLOCK_CURRENT_WORKSPACE_PATH ?? null
48660
- };
49006
+ if (!res.data) {
49007
+ throw new CliError({
49008
+ code: "INVALID_JSON_RESPONSE",
49009
+ message: "Agent API serverInfo returned an empty response body"
49010
+ });
49011
+ }
49012
+ const data = {
49013
+ ...res.data,
49014
+ runtimeContext: {
49015
+ ...res.data.runtimeContext,
49016
+ workspacePath: res.data.runtimeContext.workspacePath ?? ctx.env.SLOCK_CURRENT_WORKSPACE_PATH ?? null
49017
+ }
49018
+ };
49019
+ if (opts.full) {
49020
+ writeText(ctx.io, formatServerInfo(data));
49021
+ return;
48661
49022
  }
48662
- writeText(ctx.io, formatServerInfo(data));
49023
+ if (sections.length === 0) {
49024
+ writeText(ctx.io, formatServerSummary(data));
49025
+ return;
49026
+ }
49027
+ const chunks = [];
49028
+ for (const section of sections) {
49029
+ if (section === "channels") {
49030
+ const rows = (data.channels ?? []).filter((channel) => !opts.joined || channel.joined).filter((channel) => includesQuery(channel, opts.query));
49031
+ chunks.push(formatServerChannels(pageRows(rows, offset, limit), {
49032
+ total: rows.length,
49033
+ offset,
49034
+ limit,
49035
+ nextCommand: nextCommand(section, opts, offset, limit, rows.length)
49036
+ }));
49037
+ } else if (section === "agents") {
49038
+ const rows = (data.agents ?? []).filter((agent) => includesQuery(agent, opts.query));
49039
+ chunks.push(formatServerAgents(pageRows(rows, offset, limit), {
49040
+ total: rows.length,
49041
+ offset,
49042
+ limit,
49043
+ nextCommand: nextCommand(section, opts, offset, limit, rows.length)
49044
+ }));
49045
+ } else {
49046
+ const rows = (data.humans ?? []).filter((human) => includesQuery(human, opts.query));
49047
+ chunks.push(formatServerHumans(pageRows(rows, offset, limit), {
49048
+ total: rows.length,
49049
+ offset,
49050
+ limit,
49051
+ nextCommand: nextCommand(section, opts, offset, limit, rows.length)
49052
+ }));
49053
+ }
49054
+ }
49055
+ writeText(ctx.io, chunks.join("\n"));
48663
49056
  }
48664
49057
  );
48665
49058
  function registerServerInfoCommand(parent, runtimeOptions) {
@@ -48987,6 +49380,98 @@ function registerServerUpdateCommand(parent, runtimeOptions) {
48987
49380
  registerCliCommand(parent, serverUpdateCommand, runtimeOptions);
48988
49381
  }
48989
49382
  init_esm_shims();
49383
+ function parseNonNegativeInt2(raw, name, fallback) {
49384
+ if (raw === void 0) return fallback;
49385
+ if (!/^\d+$/.test(raw)) {
49386
+ throw new CliError({
49387
+ code: "INVALID_ARG",
49388
+ message: `${name} must be a non-negative integer`
49389
+ });
49390
+ }
49391
+ return Number(raw);
49392
+ }
49393
+ function parsePositiveInt3(raw, name, fallback) {
49394
+ const value = parseNonNegativeInt2(raw, name, fallback);
49395
+ if (value <= 0) {
49396
+ throw new CliError({
49397
+ code: "INVALID_ARG",
49398
+ message: `${name} must be greater than 0`
49399
+ });
49400
+ }
49401
+ return value;
49402
+ }
49403
+ function normalizeUserName(target) {
49404
+ const trimmed = target?.trim() ?? "";
49405
+ const name = trimmed.startsWith("@") ? trimmed.slice(1) : trimmed;
49406
+ if (!name) {
49407
+ throw new CliError({
49408
+ code: "INVALID_ARG",
49409
+ message: "user name is required"
49410
+ });
49411
+ }
49412
+ return name;
49413
+ }
49414
+ var userInfoCommand = defineCommand(
49415
+ {
49416
+ name: "info",
49417
+ description: "Show narrow visible facts for a human or agent and its visible channel memberships",
49418
+ arguments: ["<name>"],
49419
+ options: [
49420
+ { flags: "--limit <n>", description: "Maximum visible channels to inspect (default: 50)" },
49421
+ { flags: "--offset <n>", description: "Visible channels to skip before inspection (default: 0)" }
49422
+ ]
49423
+ },
49424
+ async (ctx, target, opts = {}) => {
49425
+ const name = normalizeUserName(target);
49426
+ const limit = parsePositiveInt3(opts.limit, "--limit", 50);
49427
+ const offset = parseNonNegativeInt2(opts.offset, "--offset", 0);
49428
+ const agentContext = ctx.loadAgentContext();
49429
+ const client = ctx.createApiClient(agentContext);
49430
+ const agentApi = createAgentApiSurfaceClient(client);
49431
+ const infoRes = await agentApi.server.info();
49432
+ if (!infoRes.ok) {
49433
+ throw new CliError({
49434
+ code: infoRes.status >= 500 ? "SERVER_5XX" : "INFO_FAILED",
49435
+ message: infoRes.error ?? `HTTP ${infoRes.status}`
49436
+ });
49437
+ }
49438
+ const agent = (infoRes.data?.agents ?? []).find((candidate) => candidate.name === name);
49439
+ const human = (infoRes.data?.humans ?? []).find((candidate) => candidate.name === name);
49440
+ const user = agent ? { kind: "agent", value: agent } : human ? { kind: "human", value: human } : null;
49441
+ if (!user) {
49442
+ throw new CliError({
49443
+ code: "NOT_FOUND",
49444
+ message: `User not found or not visible: @${name}`,
49445
+ suggestedNextAction: "Run `raft server info --agents --query <name>` or `raft server info --humans --query <name>` to inspect visible users."
49446
+ });
49447
+ }
49448
+ const visibleChannels = infoRes.data?.channels ?? [];
49449
+ const inspectedChannels = visibleChannels.slice(offset, offset + limit);
49450
+ const memberships = [];
49451
+ let skippedChannels = 0;
49452
+ for (const channel of inspectedChannels) {
49453
+ const membersRes = await agentApi.channels.members({ channel: `#${channel.name}` });
49454
+ if (!membersRes.ok) {
49455
+ skippedChannels += 1;
49456
+ continue;
49457
+ }
49458
+ const agents = membersRes.data?.agents ?? [];
49459
+ const humans = membersRes.data?.humans ?? [];
49460
+ const found = user.kind === "agent" ? agents.some((candidate) => candidate.name === name) : humans.some((candidate) => candidate.name === name);
49461
+ if (found) memberships.push(channel);
49462
+ }
49463
+ writeText(ctx.io, formatUserInfo(user, memberships, {
49464
+ total: visibleChannels.length,
49465
+ offset,
49466
+ limit,
49467
+ nextCommand: offset + limit < visibleChannels.length ? `raft user info @${name} --offset ${offset + limit} --limit ${limit}` : void 0
49468
+ }, skippedChannels));
49469
+ }
49470
+ );
49471
+ function registerUserInfoCommand(parent, runtimeOptions) {
49472
+ registerCliCommand(parent, userInfoCommand, runtimeOptions);
49473
+ }
49474
+ init_esm_shims();
48990
49475
  function formatKnowledgeStdout(content) {
48991
49476
  return content.endsWith("\n") ? content : `${content}
48992
49477
  `;
@@ -49060,6 +49545,89 @@ function registerKnowledgeGetCommand(parent, runtimeOptions) {
49060
49545
  registerCliCommand(parent, knowledgeGetCommand, runtimeOptions);
49061
49546
  }
49062
49547
  init_esm_shims();
49548
+ function formatKnowledgeSearchResults(results) {
49549
+ return results.map((result2, index) => {
49550
+ const firstScreen = result2.firstScreen.trim();
49551
+ const body = firstScreen.split(/\r?\n/).filter(Boolean).map((line) => ` ${line}`).join("\n");
49552
+ return `${index + 1}. ${result2.slug} \u2014 ${result2.title}${body ? `
49553
+ ${body}` : ""}`;
49554
+ }).join("\n\n") + "\n";
49555
+ }
49556
+ function toKnowledgeSearchErrorCode(errorCode2, status) {
49557
+ switch (errorCode2) {
49558
+ case "INVALID_JSON_RESPONSE":
49559
+ case "SCOPE_DENIED":
49560
+ case "knowledge_agent_missing":
49561
+ case "knowledge_internal_error":
49562
+ case "knowledge_not_found":
49563
+ case "knowledge_query_invalid":
49564
+ case "knowledge_reason_invalid":
49565
+ case "knowledge_scope_invalid":
49566
+ case "knowledge_source_invalid":
49567
+ case "knowledge_trace_id_invalid":
49568
+ case "knowledge_turn_id_invalid":
49569
+ case "unsupported_capability":
49570
+ return errorCode2;
49571
+ default:
49572
+ return status >= 500 ? "SERVER_5XX" : "KNOWLEDGE_SEARCH_FAILED";
49573
+ }
49574
+ }
49575
+ var knowledgeSearchCommand = defineCommand(
49576
+ {
49577
+ name: "search",
49578
+ description: "Search Raft Manual for Agents topics from the current server",
49579
+ arguments: ["<keywords>"],
49580
+ options: [
49581
+ {
49582
+ flags: "--scope <scope>",
49583
+ description: "Optional search scope. Currently supports: recipes"
49584
+ },
49585
+ {
49586
+ flags: "--reason <text>",
49587
+ description: "Optional rationale for this search (>=12 chars when provided)"
49588
+ },
49589
+ {
49590
+ flags: "--turn-id <id>",
49591
+ description: "Optional turn id for correlation in the knowledge event"
49592
+ },
49593
+ {
49594
+ flags: "--trace-id <id>",
49595
+ description: "Optional trace id for correlation in the knowledge event"
49596
+ }
49597
+ ],
49598
+ helpAfter: '\nExamples:\n raft manual search "preview before merge" --scope recipes\n raft manual get recipes/technique/preview-env\n'
49599
+ },
49600
+ async (ctx, keywords, opts) => {
49601
+ const agentContext = ctx.loadAgentContext();
49602
+ const client = ctx.createApiClient(agentContext);
49603
+ const res = await createAgentApiSurfaceClient(client).knowledge.search({
49604
+ query: keywords,
49605
+ scope: opts.scope,
49606
+ reason: opts.reason,
49607
+ turn_id: opts.turnId,
49608
+ trace_id: opts.traceId
49609
+ });
49610
+ if (!res.ok) {
49611
+ throw new CliError({
49612
+ code: toKnowledgeSearchErrorCode(res.errorCode, res.status),
49613
+ message: res.error ?? `HTTP ${res.status}`,
49614
+ suggestedNextAction: res.suggestedNextAction ?? (res.errorCode === "knowledge_not_found" ? "Try different keywords, or run `raft manual get index` to browse available topics." : void 0)
49615
+ });
49616
+ }
49617
+ const data = res.data;
49618
+ if (!data || data.ok !== true || !Array.isArray(data.results)) {
49619
+ throw new CliError({
49620
+ code: "KNOWLEDGE_SEARCH_FAILED",
49621
+ message: "Server returned an unexpected response shape"
49622
+ });
49623
+ }
49624
+ writeText(ctx.io, formatKnowledgeSearchResults(data.results));
49625
+ }
49626
+ );
49627
+ function registerKnowledgeSearchCommand(parent, runtimeOptions) {
49628
+ registerCliCommand(parent, knowledgeSearchCommand, runtimeOptions);
49629
+ }
49630
+ init_esm_shims();
49063
49631
  init_esm_shims();
49064
49632
  var inboxCheckCommand = defineCommand(
49065
49633
  {
@@ -49113,7 +49681,11 @@ function parseThreadTarget(target) {
49113
49681
  return null;
49114
49682
  }
49115
49683
  function formatUnfollowThreadResult(target) {
49116
- 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.`;
49684
+ return [
49685
+ `Unfollowed ${target}. Ordinary delivery for this thread has stopped.`,
49686
+ "Still arrives: personal @mentions pierce as single messages \u2014 they do NOT re-follow you.",
49687
+ "Posting in this thread re-follows you automatically."
49688
+ ].join("\n");
49117
49689
  }
49118
49690
  var threadUnfollowCommand = defineCommand(
49119
49691
  {
@@ -49744,6 +50316,168 @@ You can also choose not to send anything.
49744
50316
  `
49745
50317
  });
49746
50318
  }
50319
+ function formatDriveByJoinedToPostTip(target, data) {
50320
+ const attention = data.attention?.driveByJoinedToPost;
50321
+ if (!attention) return "";
50322
+ const muteCommand = attention.muteCommand?.trim() || `raft channel mute "${target}"`;
50323
+ const stillArrives = attention.stillArrives?.[0]?.trim() || "@mentions still reach you, and threads you started stay followed.";
50324
+ return [
50325
+ "Tip: you joined this channel to post this message. If you don't need its ordinary updates:",
50326
+ ` ${muteCommand}`,
50327
+ stillArrives
50328
+ ].join("\n");
50329
+ }
50330
+ function markSendFailureDraftSaved(err, draftSaved) {
50331
+ if (err instanceof CliError) {
50332
+ if (err.draftSaved !== void 0) return err;
50333
+ return new CliError({
50334
+ code: err.code,
50335
+ message: err.message,
50336
+ exitCode: err.exitCode,
50337
+ cause: err.cause,
50338
+ suggestedNextAction: err.suggestedNextAction,
50339
+ draftSaved
50340
+ });
50341
+ }
50342
+ const message = err instanceof Error ? err.message : String(err);
50343
+ return new CliError({
50344
+ code: "INTERNAL_BUG",
50345
+ message: `Unexpected error: ${message}`,
50346
+ cause: err,
50347
+ draftSaved
50348
+ });
50349
+ }
50350
+ async function handleMessageSend(ctx, positionalContent, opts, setFailureDraftSaved) {
50351
+ const target = opts.target?.trim() ?? "";
50352
+ if (!target) {
50353
+ throw cliError("INVALID_ARG", "--target is required");
50354
+ }
50355
+ try {
50356
+ rejectArgContent(positionalContent, opts);
50357
+ } catch (err) {
50358
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50359
+ throw err;
50360
+ }
50361
+ try {
50362
+ validateDraftSendFlags(opts);
50363
+ } catch (err) {
50364
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50365
+ throw err;
50366
+ }
50367
+ let content;
50368
+ let outgoingContent = "";
50369
+ let outgoingAttachmentIds = [];
50370
+ let previousDraftReholdCount = 0;
50371
+ let seenUpToSeq;
50372
+ if (opts.sendDraft) {
50373
+ content = await resolveOptionalSendContent(ctx.io.stdin ?? process.stdin);
50374
+ try {
50375
+ rejectSendDraftStdin(content, opts.target);
50376
+ } catch (err) {
50377
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50378
+ throw err;
50379
+ }
50380
+ } else {
50381
+ try {
50382
+ content = await resolveSendContent(ctx.io.stdin ?? process.stdin);
50383
+ } catch (err) {
50384
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50385
+ throw err;
50386
+ }
50387
+ outgoingContent = content;
50388
+ outgoingAttachmentIds = opts.attachmentId && opts.attachmentId.length > 0 ? opts.attachmentId : [];
50389
+ }
50390
+ const agentContext = ctx.loadAgentContext();
50391
+ const client = ctx.createApiClient(agentContext);
50392
+ if (opts.sendDraft) {
50393
+ const savedDraft = getSavedDraft(agentContext.agentId, target);
50394
+ if (!savedDraft) {
50395
+ throw cliError(
50396
+ "SEND_DRAFT_NOT_FOUND",
50397
+ [
50398
+ "No saved draft exists for this target.",
50399
+ "To create or update a draft, send message content normally:",
50400
+ ` raft message send --target "${target}" <<'${MESSAGE_HEREDOC_DELIMITER}'`,
50401
+ " message body",
50402
+ ` ${MESSAGE_HEREDOC_DELIMITER}`
50403
+ ].join("\n")
50404
+ );
50405
+ }
50406
+ outgoingContent = savedDraft.content;
50407
+ outgoingAttachmentIds = savedDraft.attachmentIds;
50408
+ previousDraftReholdCount = savedDraft.reholdCount;
50409
+ seenUpToSeq = savedDraft.seenUpToSeq;
50410
+ setFailureDraftSaved(true);
50411
+ } else {
50412
+ const previousDraft = getSavedDraft(agentContext.agentId, target);
50413
+ previousDraftReholdCount = previousDraft?.reholdCount ?? 0;
50414
+ seenUpToSeq = previousDraft?.seenUpToSeq;
50415
+ }
50416
+ if (seenUpToSeq === void 0) {
50417
+ seenUpToSeq = getConsumedSeq(agentContext.agentId, target);
50418
+ }
50419
+ const body = {
50420
+ target,
50421
+ content: outgoingContent,
50422
+ draftReholdCount: previousDraftReholdCount
50423
+ };
50424
+ if (seenUpToSeq !== void 0) {
50425
+ body.seenUpToSeq = seenUpToSeq;
50426
+ }
50427
+ if (opts.sendDraft) {
50428
+ body.sendDraft = true;
50429
+ if (opts.anyway) body.continueAnyway = true;
50430
+ } else {
50431
+ body.draftReplacedExisting = previousDraftReholdCount > 0;
50432
+ }
50433
+ if (outgoingAttachmentIds.length > 0) {
50434
+ body.attachmentIds = outgoingAttachmentIds;
50435
+ }
50436
+ const agentApi = createAgentApiSurfaceClient(client);
50437
+ const res = await agentApi.messages.send(body);
50438
+ if (!res.ok) {
50439
+ const code = res.status >= 500 ? "SERVER_5XX" : "SEND_FAILED";
50440
+ throw cliError(code, res.error ?? `HTTP ${res.status}`);
50441
+ }
50442
+ const data = res.data;
50443
+ if (!data) {
50444
+ throw cliError("INVALID_JSON_RESPONSE", "Agent API messageSend returned an empty response body");
50445
+ }
50446
+ if (data.state === "held") {
50447
+ if (typeof data.seenUpToSeq === "number" && Number.isFinite(data.seenUpToSeq)) {
50448
+ recordConsumedSeqs(agentContext.agentId, { [target]: data.seenUpToSeq });
50449
+ }
50450
+ setSavedDraft(agentContext.agentId, target, {
50451
+ content: outgoingContent,
50452
+ attachmentIds: outgoingAttachmentIds,
50453
+ savedAt: Date.now(),
50454
+ reholdCount: previousDraftReholdCount + 1,
50455
+ seenUpToSeq: data.seenUpToSeq
50456
+ });
50457
+ writeText(ctx.io, formatHeldSendOutput(target, data));
50458
+ return;
50459
+ }
50460
+ clearSavedDraft(agentContext.agentId, target);
50461
+ const shortId = data.messageId ? data.messageId.slice(0, 8) : null;
50462
+ const replyHint = shortId ? ` (to reply in this message's thread, use target "${target.includes(":") ? target : target + ":" + shortId}")` : "";
50463
+ let unreadSection = "";
50464
+ if (data.recentUnread && data.recentUnread.length > 0) {
50465
+ unreadSection = `
50466
+
50467
+ --- New messages you may have missed ---
50468
+ ${formatMessages(data.recentUnread)}`;
50469
+ }
50470
+ const pendingMentionActions = normalizePendingMentionActions(data);
50471
+ const mentionSection = pendingMentionActions.length > 0 ? `
50472
+
50473
+ ${formatPendingMentionActions(pendingMentionActions, { source: "send" }).trimEnd()}` : "";
50474
+ const driveByTip = formatDriveByJoinedToPostTip(target, data);
50475
+ const driveBySection = driveByTip ? `
50476
+
50477
+ ${driveByTip}` : "";
50478
+ writeText(ctx.io, `Message sent to ${target}. Message ID: ${data.messageId}${replyHint}${driveBySection}${mentionSection}${unreadSection}
50479
+ `);
50480
+ }
49747
50481
  var messageSendCommand = defineCommand(
49748
50482
  {
49749
50483
  name: "send",
@@ -49762,131 +50496,14 @@ var messageSendCommand = defineCommand(
49762
50496
  ]
49763
50497
  },
49764
50498
  async (ctx, positionalContent, opts) => {
49765
- const target = opts.target?.trim() ?? "";
49766
- if (!target) {
49767
- throw cliError("INVALID_ARG", "--target is required");
49768
- }
50499
+ let failureDraftSaved = false;
49769
50500
  try {
49770
- rejectArgContent(positionalContent, opts);
49771
- } catch (err) {
49772
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
49773
- throw err;
49774
- }
49775
- try {
49776
- validateDraftSendFlags(opts);
49777
- } catch (err) {
49778
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
49779
- throw err;
49780
- }
49781
- let content;
49782
- let outgoingContent = "";
49783
- let outgoingAttachmentIds = [];
49784
- let previousDraftReholdCount = 0;
49785
- let seenUpToSeq;
49786
- if (opts.sendDraft) {
49787
- content = await resolveOptionalSendContent(ctx.io.stdin ?? process.stdin);
49788
- try {
49789
- rejectSendDraftStdin(content, opts.target);
49790
- } catch (err) {
49791
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
49792
- throw err;
49793
- }
49794
- } else {
49795
- try {
49796
- content = await resolveSendContent(ctx.io.stdin ?? process.stdin);
49797
- } catch (err) {
49798
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
49799
- throw err;
49800
- }
49801
- outgoingContent = content;
49802
- outgoingAttachmentIds = opts.attachmentId && opts.attachmentId.length > 0 ? opts.attachmentId : [];
49803
- }
49804
- const agentContext = ctx.loadAgentContext();
49805
- const client = ctx.createApiClient(agentContext);
49806
- if (opts.sendDraft) {
49807
- const savedDraft = getSavedDraft(agentContext.agentId, target);
49808
- if (!savedDraft) {
49809
- throw cliError(
49810
- "SEND_DRAFT_NOT_FOUND",
49811
- [
49812
- "No saved draft exists for this target.",
49813
- "To create or update a draft, send message content normally:",
49814
- ` raft message send --target "${target}" <<'${MESSAGE_HEREDOC_DELIMITER}'`,
49815
- " message body",
49816
- ` ${MESSAGE_HEREDOC_DELIMITER}`
49817
- ].join("\n")
49818
- );
49819
- return;
49820
- }
49821
- outgoingContent = savedDraft.content;
49822
- outgoingAttachmentIds = savedDraft.attachmentIds;
49823
- previousDraftReholdCount = savedDraft.reholdCount;
49824
- seenUpToSeq = savedDraft.seenUpToSeq;
49825
- } else {
49826
- const previousDraft = getSavedDraft(agentContext.agentId, target);
49827
- previousDraftReholdCount = previousDraft?.reholdCount ?? 0;
49828
- seenUpToSeq = previousDraft?.seenUpToSeq;
49829
- }
49830
- if (seenUpToSeq === void 0) {
49831
- seenUpToSeq = getConsumedSeq(agentContext.agentId, target);
49832
- }
49833
- const body = {
49834
- target,
49835
- content: outgoingContent,
49836
- draftReholdCount: previousDraftReholdCount
49837
- };
49838
- if (seenUpToSeq !== void 0) {
49839
- body.seenUpToSeq = seenUpToSeq;
49840
- }
49841
- if (opts.sendDraft) {
49842
- body.sendDraft = true;
49843
- if (opts.anyway) body.continueAnyway = true;
49844
- } else {
49845
- body.draftReplacedExisting = previousDraftReholdCount > 0;
49846
- }
49847
- if (outgoingAttachmentIds.length > 0) {
49848
- body.attachmentIds = outgoingAttachmentIds;
49849
- }
49850
- const agentApi = createAgentApiSurfaceClient(client);
49851
- const res = await agentApi.messages.send(body);
49852
- if (!res.ok) {
49853
- const code = res.status >= 500 ? "SERVER_5XX" : "SEND_FAILED";
49854
- throw cliError(code, res.error ?? `HTTP ${res.status}`);
49855
- }
49856
- const data = res.data;
49857
- if (!data) {
49858
- throw cliError("INVALID_JSON_RESPONSE", "Agent API messageSend returned an empty response body");
49859
- }
49860
- if (data.state === "held") {
49861
- if (typeof data.seenUpToSeq === "number" && Number.isFinite(data.seenUpToSeq)) {
49862
- recordConsumedSeqs(agentContext.agentId, { [target]: data.seenUpToSeq });
49863
- }
49864
- setSavedDraft(agentContext.agentId, target, {
49865
- content: outgoingContent,
49866
- attachmentIds: outgoingAttachmentIds,
49867
- savedAt: Date.now(),
49868
- reholdCount: previousDraftReholdCount + 1,
49869
- seenUpToSeq: data.seenUpToSeq
50501
+ await handleMessageSend(ctx, positionalContent, opts, (draftSaved) => {
50502
+ failureDraftSaved = draftSaved;
49870
50503
  });
49871
- writeText(ctx.io, formatHeldSendOutput(target, data));
49872
- return;
49873
- }
49874
- clearSavedDraft(agentContext.agentId, target);
49875
- const shortId = data.messageId ? data.messageId.slice(0, 8) : null;
49876
- const replyHint = shortId ? ` (to reply in this message's thread, use target "${target.includes(":") ? target : target + ":" + shortId}")` : "";
49877
- let unreadSection = "";
49878
- if (data.recentUnread && data.recentUnread.length > 0) {
49879
- unreadSection = `
49880
-
49881
- --- New messages you may have missed ---
49882
- ${formatMessages(data.recentUnread)}`;
50504
+ } catch (err) {
50505
+ throw markSendFailureDraftSaved(err, failureDraftSaved);
49883
50506
  }
49884
- const pendingMentionActions = normalizePendingMentionActions(data);
49885
- const mentionSection = pendingMentionActions.length > 0 ? `
49886
-
49887
- ${formatPendingMentionActions(pendingMentionActions, { source: "send" }).trimEnd()}` : "";
49888
- writeText(ctx.io, `Message sent to ${target}. Message ID: ${data.messageId}${replyHint}${mentionSection}${unreadSection}
49889
- `);
49890
50507
  }
49891
50508
  );
49892
50509
  function registerSendCommand(parent, runtimeOptions = {}) {
@@ -49986,7 +50603,7 @@ function requireTargetAlias(opts) {
49986
50603
  }
49987
50604
  return target;
49988
50605
  }
49989
- function parsePositiveInt2(name, raw) {
50606
+ function parsePositiveInt4(name, raw) {
49990
50607
  if (raw === void 0) return void 0;
49991
50608
  const n = Number(raw);
49992
50609
  if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {
@@ -50025,7 +50642,7 @@ function mapReadFailure(res) {
50025
50642
  }
50026
50643
  function validateReadOpts(opts) {
50027
50644
  const channel = requireTargetAlias(opts);
50028
- const limit = parsePositiveInt2("limit", opts.limit);
50645
+ const limit = parsePositiveInt4("limit", opts.limit);
50029
50646
  const before = opts.before?.trim();
50030
50647
  const after = opts.after?.trim();
50031
50648
  return {
@@ -50115,7 +50732,7 @@ function normalizeMemberHandleRef(raw) {
50115
50732
  }
50116
50733
  return handle;
50117
50734
  }
50118
- function parsePositiveInt3(name, raw) {
50735
+ function parsePositiveInt5(name, raw) {
50119
50736
  if (raw === void 0) return void 0;
50120
50737
  const n = Number(raw);
50121
50738
  if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {
@@ -50126,7 +50743,7 @@ function parsePositiveInt3(name, raw) {
50126
50743
  }
50127
50744
  return n;
50128
50745
  }
50129
- function parseNonNegativeInt(name, raw) {
50746
+ function parseNonNegativeInt3(name, raw) {
50130
50747
  if (raw === void 0) return void 0;
50131
50748
  const n = Number(raw);
50132
50749
  if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0) {
@@ -50160,8 +50777,8 @@ function normalizeSearchOpts(opts) {
50160
50777
  message: "--sort relevance requires --query; filter-only search is sorted by recent"
50161
50778
  });
50162
50779
  }
50163
- const limit = parsePositiveInt3("limit", opts.limit);
50164
- const offset = parseNonNegativeInt("offset", opts.offset);
50780
+ const limit = parsePositiveInt5("limit", opts.limit);
50781
+ const offset = parseNonNegativeInt3("offset", opts.offset);
50165
50782
  const sort = opts.sort ?? (query ? void 0 : "recent");
50166
50783
  return {
50167
50784
  ...query ? { query } : {},
@@ -53033,6 +53650,7 @@ registerAgentLoginCommand(agentCmd);
53033
53650
  registerAgentListCommand(agentCmd);
53034
53651
  registerAgentBridgeCommand(agentCmd);
53035
53652
  var channelCmd = program2.command("channel").description("Channel membership and attention operations");
53653
+ registerChannelInfoCommand(channelCmd);
53036
53654
  registerChannelMembersCommand(channelCmd);
53037
53655
  registerChannelCreateCommand(channelCmd);
53038
53656
  registerChannelUpdateCommand(channelCmd);
@@ -53047,10 +53665,14 @@ registerThreadUnfollowCommand(threadCmd);
53047
53665
  var serverCmd = program2.command("server").description("Server / workspace introspection");
53048
53666
  registerServerInfoCommand(serverCmd);
53049
53667
  registerServerUpdateCommand(serverCmd);
53668
+ var userCmd = program2.command("user").description("User and agent introspection");
53669
+ registerUserInfoCommand(userCmd);
53050
53670
  var manualCmd = program2.command("manual").description("Raft Manual for Agents retrieval (canonical operating topics)");
53051
53671
  registerKnowledgeGetCommand(manualCmd);
53672
+ registerKnowledgeSearchCommand(manualCmd);
53052
53673
  var knowledgeCmd = program2.command("knowledge").description("Legacy alias for `raft manual`");
53053
53674
  registerKnowledgeGetCommand(knowledgeCmd);
53675
+ registerKnowledgeSearchCommand(knowledgeCmd);
53054
53676
  var inboxCmd = program2.command("inbox").description("Inbox target summary operations");
53055
53677
  registerInboxCheckCommand(inboxCmd);
53056
53678
  var messageCmd = program2.command("message").description("Message operations");