@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.
package/dist/cli/index.js CHANGED
@@ -28001,6 +28001,7 @@ var CliError = class extends Error {
28001
28001
  code;
28002
28002
  exitCode;
28003
28003
  suggestedNextAction;
28004
+ draftSaved;
28004
28005
  constructor(options) {
28005
28006
  super(options.message);
28006
28007
  this.name = "CliError";
@@ -28008,6 +28009,7 @@ var CliError = class extends Error {
28008
28009
  this.exitCode = options.exitCode ?? 1;
28009
28010
  this.cause = options.cause;
28010
28011
  this.suggestedNextAction = options.suggestedNextAction;
28012
+ this.draftSaved = options.draftSaved;
28011
28013
  }
28012
28014
  };
28013
28015
  var CliExit = class extends Error {
@@ -28034,7 +28036,8 @@ function cliError(code, message, options = {}) {
28034
28036
  message,
28035
28037
  exitCode: options.exitCode,
28036
28038
  cause: options.cause,
28037
- suggestedNextAction: options.suggestedNextAction
28039
+ suggestedNextAction: options.suggestedNextAction,
28040
+ draftSaved: options.draftSaved
28038
28041
  });
28039
28042
  }
28040
28043
  function toCliError(err) {
@@ -28823,6 +28826,18 @@ function defineTraceFields(definitions) {
28823
28826
  }
28824
28827
  return definitions;
28825
28828
  }
28829
+ var TRACE_LIFECYCLE_SHADOW_SIGNAL_SITE_VALUES = [
28830
+ "daemon_ingest",
28831
+ "delivery_ack",
28832
+ "hint_resolution",
28833
+ "lifecycle_plan",
28834
+ "preserve_rebroadcast",
28835
+ "ready_online",
28836
+ "runtime_error",
28837
+ "slock_action_status",
28838
+ "starting_resolve",
28839
+ "synthetic_repair"
28840
+ ];
28826
28841
  var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28827
28842
  { key: "row_kind", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "stable" },
28828
28843
  { key: "trace_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
@@ -28845,10 +28860,13 @@ var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28845
28860
  { key: "route_pattern", fieldClass: "query_axis", placement: "span", valueKind: "route" },
28846
28861
  { key: "caller_kind", fieldClass: "query_axis", placement: "span", valueKind: "closed_enum", enumBinding: "stable" },
28847
28862
  { key: "server_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
28863
+ { key: "channel_id", fieldClass: "query_axis", placement: "span_or_event", valueKind: "identity", highCardinality: true },
28848
28864
  { key: "machine_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
28849
28865
  { key: "agent_id", fieldClass: "query_axis", placement: "span_or_event", valueKind: "identity", highCardinality: true },
28866
+ { key: "job_id", fieldClass: "query_axis", placement: "span_or_event", valueKind: "identity", highCardinality: true },
28850
28867
  { key: "launch_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
28851
28868
  { key: "session_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
28869
+ { key: "outcome", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28852
28870
  { key: "observation_class", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28853
28871
  { key: "action", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28854
28872
  { key: "source", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
@@ -28858,6 +28876,7 @@ var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28858
28876
  { key: "error_class", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28859
28877
  { key: "query_name", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "query_registry" },
28860
28878
  { key: "phase", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
28879
+ { key: "eligibility_subcheck", fieldClass: "query_axis", placement: "event", valueKind: "closed_enum", enumBinding: "pending_457" },
28861
28880
  { key: "hint_source", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
28862
28881
  { key: "resolved_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
28863
28882
  { key: "previous_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
@@ -28867,7 +28886,7 @@ var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28867
28886
  { key: "activity_source", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
28868
28887
  { key: "status_bucket", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
28869
28888
  { key: "shadow_agent_id", fieldClass: "family_query_axis", placement: "event", valueKind: "identity", scope: "family:lifecycle_shadow", highCardinality: true },
28870
- { key: "shadow_signal_site", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
28889
+ { 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 },
28871
28890
  { key: "shadow_observation_class", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
28872
28891
  { key: "shadow_prior_projection", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
28873
28892
  { key: "shadow_projection", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
@@ -28877,6 +28896,8 @@ var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
28877
28896
  { key: "shadow_direction", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
28878
28897
  { key: "shadow_plan_kind", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
28879
28898
  { key: "row_count", fieldClass: "detail", placement: "span_or_event", valueKind: "detail" },
28899
+ { key: "rows_copied", fieldClass: "detail", placement: "span_or_event", valueKind: "numeric" },
28900
+ { key: "batch_index", fieldClass: "detail", placement: "span_or_event", valueKind: "numeric" },
28880
28901
  { key: "retry_count", fieldClass: "detail", placement: "span_or_event", valueKind: "detail" },
28881
28902
  { key: "error_message", fieldClass: "detail", placement: "span_or_event", valueKind: "detail", contentRule: "scrub_and_short_retention" },
28882
28903
  { key: "query_text", fieldClass: "content_safety", placement: "span_or_event", valueKind: "content", contentRule: "scrub_and_short_retention" },
@@ -42927,6 +42948,24 @@ var agentApiKnowledgeGetResponseSchema = passthroughObject({
42927
42948
  contentType: external_exports.string(),
42928
42949
  content: external_exports.string()
42929
42950
  });
42951
+ var agentApiKnowledgeSearchQuerySchema = passthroughObject({
42952
+ query: external_exports.string().trim().min(1),
42953
+ scope: optionalStringSchema,
42954
+ reason: optionalStringSchema,
42955
+ turn_id: optionalStringSchema,
42956
+ trace_id: optionalStringSchema
42957
+ });
42958
+ var agentApiKnowledgeSearchResultSchema = passthroughObject({
42959
+ slug: external_exports.string(),
42960
+ title: external_exports.string(),
42961
+ firstScreen: external_exports.string()
42962
+ });
42963
+ var agentApiKnowledgeSearchResponseSchema = passthroughObject({
42964
+ ok: external_exports.literal(true),
42965
+ query: external_exports.string(),
42966
+ scope: external_exports.string().nullable(),
42967
+ results: external_exports.array(agentApiKnowledgeSearchResultSchema)
42968
+ });
42930
42969
  var agentApiMessageSearchQuerySchema = passthroughObject({
42931
42970
  q: optionalStringSchema,
42932
42971
  channel: optionalStringSchema,
@@ -43378,7 +43417,14 @@ var agentApiSendSentResponseSchema = passthroughObject({
43378
43417
  messageId: external_exports.string(),
43379
43418
  messageSeq: optionalNumberSchema,
43380
43419
  recentUnread: external_exports.array(agentApiMessageEnvelopeSchema).optional(),
43381
- pendingMentionActions: external_exports.array(agentApiMessageEnvelopeSchema).optional()
43420
+ pendingMentionActions: external_exports.array(agentApiMessageEnvelopeSchema).optional(),
43421
+ attention: passthroughObject({
43422
+ driveByJoinedToPost: passthroughObject({
43423
+ reason: optionalStringSchema,
43424
+ muteCommand: optionalStringSchema,
43425
+ stillArrives: optionalStringArraySchema
43426
+ }).optional()
43427
+ }).optional()
43382
43428
  });
43383
43429
  var agentApiSendResponseSchema = external_exports.discriminatedUnion("state", [
43384
43430
  agentApiSendSentResponseSchema,
@@ -43567,6 +43613,16 @@ var agentApiContract = {
43567
43613
  request: { query: agentApiKnowledgeGetQuerySchema },
43568
43614
  response: { body: agentApiKnowledgeGetResponseSchema }
43569
43615
  }),
43616
+ knowledgeSearch: route({
43617
+ key: "knowledgeSearch",
43618
+ method: "GET",
43619
+ path: "/knowledge/search",
43620
+ client: { resource: "knowledge", method: "search" },
43621
+ capability: "knowledge",
43622
+ description: "Search Slock Manual for Agents topics from the current server.",
43623
+ request: { query: agentApiKnowledgeSearchQuerySchema },
43624
+ response: { body: agentApiKnowledgeSearchResponseSchema }
43625
+ }),
43570
43626
  messageSend: route({
43571
43627
  key: "messageSend",
43572
43628
  method: "POST",
@@ -44868,7 +44924,8 @@ var SUPPORTED_TRANSLATION_LANGUAGE_CODES = [
44868
44924
  "es",
44869
44925
  "fr",
44870
44926
  "de",
44871
- "pt-br"
44927
+ "pt-br",
44928
+ "it"
44872
44929
  ];
44873
44930
  var SUPPORTED_TRANSLATION_LANGUAGE_SET = new Set(
44874
44931
  SUPPORTED_TRANSLATION_LANGUAGE_CODES
@@ -45000,6 +45057,15 @@ var SERVER_CAPABILITY_MATRIX = {
45000
45057
  })
45001
45058
  };
45002
45059
 
45060
+ // ../shared/src/tracing/traceFamilyRegistry.ts
45061
+ init_esm_shims();
45062
+
45063
+ // ../shared/src/tracing/stateTransitionTrace.ts
45064
+ init_esm_shims();
45065
+
45066
+ // ../shared/src/tracing/stateViolationTrace.ts
45067
+ init_esm_shims();
45068
+
45003
45069
  // ../shared/src/index.ts
45004
45070
  var BUILTIN_RUNTIME_PROVIDER_ENV_KEYS = PI_BUILTIN_PROVIDER_API_KEY_ENV_KEYS_GENERATED;
45005
45071
  var BUILTIN_RUNTIME_PROVIDERS = Object.entries(BUILTIN_RUNTIME_PROVIDER_ENV_KEYS).map(([id, envKey]) => ({ id, envKey }));
@@ -45442,7 +45508,8 @@ function createAgentApiSurfaceClient(client) {
45442
45508
  read: (query) => requestClientAsApiResponse(agentApi.history.read(query))
45443
45509
  },
45444
45510
  knowledge: {
45445
- get: (query) => requestClientAsApiResponse(agentApi.knowledge.get(query))
45511
+ get: (query) => requestClientAsApiResponse(agentApi.knowledge.get(query)),
45512
+ search: (query) => requestClientAsApiResponse(agentApi.knowledge.search(query))
45446
45513
  },
45447
45514
  tasks: {
45448
45515
  list: (query) => requestClientAsApiResponse(agentApi.tasks.list(query)),
@@ -46193,6 +46260,10 @@ function renderError(io, err) {
46193
46260
  `);
46194
46261
  io.stderr.write(`Code: ${err.code}
46195
46262
  `);
46263
+ if (err.draftSaved !== void 0) {
46264
+ io.stderr.write(`Draft saved: ${err.draftSaved ? "yes" : "no"}
46265
+ `);
46266
+ }
46196
46267
  if (err.suggestedNextAction) {
46197
46268
  io.stderr.write(`Next action: ${err.suggestedNextAction}
46198
46269
  `);
@@ -48557,6 +48628,156 @@ function formatServerInfo(data) {
48557
48628
  }
48558
48629
  return text;
48559
48630
  }
48631
+ function channelRef(name) {
48632
+ return name.startsWith("#") ? name : `#${name}`;
48633
+ }
48634
+ function channelVisibility(channel) {
48635
+ const type = channel.type?.trim();
48636
+ return type === "private" ? "private" : "public";
48637
+ }
48638
+ function channelMuted(channel) {
48639
+ if (typeof channel.muted === "boolean") return channel.muted;
48640
+ if (typeof channel.activityMuted === "boolean") return channel.activityMuted;
48641
+ return void 0;
48642
+ }
48643
+ function channelStatus(channel) {
48644
+ const parts = [
48645
+ channelVisibility(channel),
48646
+ channel.joined ? "joined" : "not joined"
48647
+ ];
48648
+ const muted = channelMuted(channel);
48649
+ if (muted !== void 0) parts.push(muted ? "muted" : "not muted");
48650
+ if (typeof channel.archived === "boolean") parts.push(channel.archived ? "archived" : "not archived");
48651
+ return parts.join(", ");
48652
+ }
48653
+ function formatPageFooter(page) {
48654
+ if (!page) return "";
48655
+ const start = page.total === 0 ? 0 : Math.min(page.offset + 1, page.total);
48656
+ const end = Math.min(page.offset + page.limit, page.total);
48657
+ const lines = [`
48658
+ Showing ${start}-${end} of ${page.total}.`];
48659
+ if (page.nextCommand && end < page.total) {
48660
+ lines.push(`More: ${page.nextCommand}`);
48661
+ }
48662
+ return `${lines.join("\n")}
48663
+ `;
48664
+ }
48665
+ function formatChannelInfo(channel, memberCounts) {
48666
+ const lines = ["## Channel", ""];
48667
+ lines.push(`Channel: ${channelRef(channel.name)}`);
48668
+ if (channel.id) lines.push(`ID: ${channel.id}`);
48669
+ lines.push(`Visibility: ${channelVisibility(channel)}`);
48670
+ lines.push(`Joined: ${channel.joined ? "yes" : "no"}`);
48671
+ const muted = channelMuted(channel);
48672
+ if (muted !== void 0) lines.push(`Muted: ${muted ? "yes" : "no"}`);
48673
+ if (typeof channel.archived === "boolean") lines.push(`Archived: ${channel.archived ? "yes" : "no"}`);
48674
+ lines.push(`Description: ${channel.description?.trim() || "(none)"}`);
48675
+ if (memberCounts) {
48676
+ const agents = memberCounts.agents ?? 0;
48677
+ const humans = memberCounts.humans ?? 0;
48678
+ lines.push(`Members: ${agents + humans} (${agents} agents, ${humans} humans)`);
48679
+ }
48680
+ lines.push("");
48681
+ lines.push(`More: raft channel members "${channelRef(channel.name)}"`);
48682
+ return `${lines.join("\n")}
48683
+ `;
48684
+ }
48685
+ function formatServerSummary(data) {
48686
+ const channels = data.channels ?? [];
48687
+ const agents = data.agents ?? [];
48688
+ const humans = data.humans ?? [];
48689
+ const joined = channels.filter((channel) => channel.joined).length;
48690
+ const lines = [
48691
+ "## Server",
48692
+ "",
48693
+ `Channels: ${channels.length} visible (${joined} joined)`,
48694
+ `Agents: ${agents.length}`,
48695
+ `Humans: ${humans.length}`,
48696
+ "",
48697
+ "Narrow queries:",
48698
+ "- raft server info --channels",
48699
+ "- raft server info --agents",
48700
+ "- raft server info --humans",
48701
+ "- raft channel info <name>",
48702
+ "- raft user info <name>",
48703
+ "",
48704
+ "Full dump: raft server info --full"
48705
+ ];
48706
+ return `${lines.join("\n")}
48707
+ `;
48708
+ }
48709
+ function formatServerChannels(channels, page) {
48710
+ const lines = [
48711
+ "## Server Channels",
48712
+ "",
48713
+ "Private channels are shown only when this agent is a member. Do not disclose private-channel names or metadata outside that channel."
48714
+ ];
48715
+ if (channels.length === 0) {
48716
+ lines.push("(none)");
48717
+ } else {
48718
+ for (const channel of channels) {
48719
+ const description = channel.description?.trim();
48720
+ lines.push(description ? `${channelRef(channel.name)} [${channelStatus(channel)}] \u2014 ${description}` : `${channelRef(channel.name)} [${channelStatus(channel)}]`);
48721
+ }
48722
+ }
48723
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48724
+ }
48725
+ function formatServerAgents(agents, page) {
48726
+ const lines = [
48727
+ "## Server Agents",
48728
+ "",
48729
+ "Role labels show server-level owner/admin authority; no role label means ordinary member."
48730
+ ];
48731
+ if (agents.length === 0) {
48732
+ lines.push("(none)");
48733
+ } else {
48734
+ for (const agent of agents) {
48735
+ const role = roleLabel(agent.role);
48736
+ const status = agentStatusLabel(agent);
48737
+ lines.push(agent.description ? `@${agent.name} (${status})${role} \u2014 ${agent.description}` : `@${agent.name} (${status})${role}`);
48738
+ }
48739
+ }
48740
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48741
+ }
48742
+ function formatServerHumans(humans, page) {
48743
+ const lines = [
48744
+ "## Server Humans",
48745
+ "",
48746
+ "Role labels show server-level owner/admin authority; no role label means ordinary member."
48747
+ ];
48748
+ if (humans.length === 0) {
48749
+ lines.push("(none)");
48750
+ } else {
48751
+ for (const human of humans) {
48752
+ const role = roleLabel(human.role);
48753
+ lines.push(human.description ? `@${human.name}${role} \u2014 ${human.description}` : `@${human.name}${role}`);
48754
+ }
48755
+ }
48756
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48757
+ }
48758
+ function formatUserInfo(user, memberships, page, skippedChannels = 0) {
48759
+ const name = user.value.name;
48760
+ const role = roleLabel(user.value.role);
48761
+ const lines = ["## User", ""];
48762
+ lines.push(`User: @${name}`);
48763
+ lines.push(`Kind: ${user.kind}`);
48764
+ if (user.kind === "agent") lines.push(`Status: ${agentStatusLabel(user.value)}`);
48765
+ if (role) lines.push(`Role: ${role.slice(2, -1)}`);
48766
+ if (user.value.description) lines.push(`Description: ${user.value.description}`);
48767
+ lines.push("");
48768
+ lines.push("### Visible Channel Memberships");
48769
+ if (memberships.length === 0) {
48770
+ lines.push("(none found in inspected visible channels)");
48771
+ } else {
48772
+ for (const channel of memberships) {
48773
+ lines.push(`${channelRef(channel.name)} [${channelStatus(channel)}]`);
48774
+ }
48775
+ }
48776
+ if (skippedChannels > 0) {
48777
+ lines.push(`Skipped ${skippedChannels} visible channel roster checks because the server rejected them.`);
48778
+ }
48779
+ return `${lines.join("\n")}${formatPageFooter(page)}`;
48780
+ }
48560
48781
  function formatChannelMembers(data) {
48561
48782
  let text = "## Channel Members\n\n";
48562
48783
  const ref = data.channel?.ref ?? "(unknown)";
@@ -48626,68 +48847,7 @@ function registerChannelMembersCommand(parent, runtimeOptions) {
48626
48847
  registerCliCommand(parent, channelMembersCommand, runtimeOptions);
48627
48848
  }
48628
48849
 
48629
- // src/commands/channel/create.ts
48630
- init_esm_shims();
48631
- function normalizeChannelName(raw) {
48632
- return (raw ?? "").trim().replace(/^#/, "");
48633
- }
48634
- function formatCreateChannelResult(channel) {
48635
- const target = `#${channel.name}`;
48636
- const visibility = channel.type === "private" ? "private" : "public";
48637
- return `Created ${target} (${visibility}). You are joined and can send messages there.`;
48638
- }
48639
- var channelCreateCommand = defineCommand(
48640
- {
48641
- name: "create",
48642
- description: "Create a public or private channel when this agent has server admin authority",
48643
- options: [
48644
- {
48645
- flags: "--name <name>",
48646
- description: "Channel name, with or without a leading '#'"
48647
- },
48648
- {
48649
- flags: "--description <description>",
48650
- description: "Optional channel description"
48651
- },
48652
- {
48653
- flags: "--private",
48654
- description: "Create a private channel instead of a public channel"
48655
- }
48656
- ]
48657
- },
48658
- async (ctx, opts) => {
48659
- const name = normalizeChannelName(opts.name);
48660
- if (!name) {
48661
- throw new CliError({
48662
- code: "INVALID_ARG",
48663
- message: "--name is required"
48664
- });
48665
- }
48666
- const agentContext = ctx.loadAgentContext();
48667
- const client = ctx.createApiClient(agentContext);
48668
- const res = await client.request(
48669
- "POST",
48670
- `/internal/agent/${encodeURIComponent(agentContext.agentId)}/channels`,
48671
- {
48672
- name,
48673
- description: opts.description,
48674
- visibility: opts.private ? "private" : "public"
48675
- }
48676
- );
48677
- if (!res.ok || !res.data) {
48678
- throw new CliError({
48679
- code: res.status >= 500 ? "SERVER_5XX" : "CREATE_FAILED",
48680
- message: res.error ?? `HTTP ${res.status}`
48681
- });
48682
- }
48683
- writeText(ctx.io, formatCreateChannelResult(res.data) + "\n");
48684
- }
48685
- );
48686
- function registerChannelCreateCommand(parent, runtimeOptions) {
48687
- registerCliCommand(parent, channelCreateCommand, runtimeOptions);
48688
- }
48689
-
48690
- // src/commands/channel/update.ts
48850
+ // src/commands/channel/info.ts
48691
48851
  init_esm_shims();
48692
48852
 
48693
48853
  // src/commands/channel/leave.ts
@@ -48761,7 +48921,123 @@ function registerChannelLeaveCommand(parent, runtimeOptions) {
48761
48921
  registerCliCommand(parent, channelLeaveCommand, runtimeOptions);
48762
48922
  }
48763
48923
 
48924
+ // src/commands/channel/info.ts
48925
+ function normalizeChannelInfoTarget(target) {
48926
+ const input = target?.trim() ?? "";
48927
+ const normalized = input.startsWith("#") ? input : `#${input}`;
48928
+ const name = parseRegularChannelTarget(normalized);
48929
+ if (!name) {
48930
+ throw new CliError({
48931
+ code: "INVALID_TARGET",
48932
+ message: "Target must be a regular channel name, e.g. '#engineering' or 'engineering'. DMs and thread targets are not supported."
48933
+ });
48934
+ }
48935
+ return { input: normalized, name };
48936
+ }
48937
+ var channelInfoCommand = defineCommand(
48938
+ {
48939
+ name: "info",
48940
+ description: "Show narrow channel facts: existence, joined state, description, and member count when visible",
48941
+ arguments: ["<target>"]
48942
+ },
48943
+ async (ctx, target) => {
48944
+ const { input, name } = normalizeChannelInfoTarget(target);
48945
+ const agentContext = ctx.loadAgentContext();
48946
+ const client = ctx.createApiClient(agentContext);
48947
+ const agentApi = createAgentApiSurfaceClient(client);
48948
+ const infoRes = await agentApi.server.info();
48949
+ if (!infoRes.ok) {
48950
+ throw new CliError({
48951
+ code: infoRes.status >= 500 ? "SERVER_5XX" : "INFO_FAILED",
48952
+ message: infoRes.error ?? `HTTP ${infoRes.status}`
48953
+ });
48954
+ }
48955
+ const channel = (infoRes.data?.channels ?? []).find((candidate) => candidate.name === name);
48956
+ if (!channel) {
48957
+ throw new CliError({
48958
+ code: "NOT_FOUND",
48959
+ message: `Channel not found or not visible: ${input}`,
48960
+ suggestedNextAction: "Run `raft server info --channels --query <name>` to inspect visible channels, or ask a channel member to add you if this is private."
48961
+ });
48962
+ }
48963
+ let memberCounts = null;
48964
+ const membersRes = await agentApi.channels.members({ channel: `#${name}` });
48965
+ if (membersRes.ok) {
48966
+ memberCounts = {
48967
+ agents: membersRes.data?.agents?.length ?? 0,
48968
+ humans: membersRes.data?.humans?.length ?? 0
48969
+ };
48970
+ }
48971
+ writeText(ctx.io, formatChannelInfo(channel, memberCounts));
48972
+ }
48973
+ );
48974
+ function registerChannelInfoCommand(parent, runtimeOptions) {
48975
+ registerCliCommand(parent, channelInfoCommand, runtimeOptions);
48976
+ }
48977
+
48978
+ // src/commands/channel/create.ts
48979
+ init_esm_shims();
48980
+ function normalizeChannelName(raw) {
48981
+ return (raw ?? "").trim().replace(/^#/, "");
48982
+ }
48983
+ function formatCreateChannelResult(channel) {
48984
+ const target = `#${channel.name}`;
48985
+ const visibility = channel.type === "private" ? "private" : "public";
48986
+ return `Created ${target} (${visibility}). You are joined and can send messages there.`;
48987
+ }
48988
+ var channelCreateCommand = defineCommand(
48989
+ {
48990
+ name: "create",
48991
+ description: "Create a public or private channel when this agent has server admin authority",
48992
+ options: [
48993
+ {
48994
+ flags: "--name <name>",
48995
+ description: "Channel name, with or without a leading '#'"
48996
+ },
48997
+ {
48998
+ flags: "--description <description>",
48999
+ description: "Optional channel description"
49000
+ },
49001
+ {
49002
+ flags: "--private",
49003
+ description: "Create a private channel instead of a public channel"
49004
+ }
49005
+ ]
49006
+ },
49007
+ async (ctx, opts) => {
49008
+ const name = normalizeChannelName(opts.name);
49009
+ if (!name) {
49010
+ throw new CliError({
49011
+ code: "INVALID_ARG",
49012
+ message: "--name is required"
49013
+ });
49014
+ }
49015
+ const agentContext = ctx.loadAgentContext();
49016
+ const client = ctx.createApiClient(agentContext);
49017
+ const res = await client.request(
49018
+ "POST",
49019
+ `/internal/agent/${encodeURIComponent(agentContext.agentId)}/channels`,
49020
+ {
49021
+ name,
49022
+ description: opts.description,
49023
+ visibility: opts.private ? "private" : "public"
49024
+ }
49025
+ );
49026
+ if (!res.ok || !res.data) {
49027
+ throw new CliError({
49028
+ code: res.status >= 500 ? "SERVER_5XX" : "CREATE_FAILED",
49029
+ message: res.error ?? `HTTP ${res.status}`
49030
+ });
49031
+ }
49032
+ writeText(ctx.io, formatCreateChannelResult(res.data) + "\n");
49033
+ }
49034
+ );
49035
+ function registerChannelCreateCommand(parent, runtimeOptions) {
49036
+ registerCliCommand(parent, channelCreateCommand, runtimeOptions);
49037
+ }
49038
+
48764
49039
  // src/commands/channel/update.ts
49040
+ init_esm_shims();
48765
49041
  function normalizeChannelName2(raw) {
48766
49042
  return (raw ?? "").trim().replace(/^#/, "");
48767
49043
  }
@@ -49034,7 +49310,12 @@ function registerChannelRemoveMemberCommand(parent, runtimeOptions) {
49034
49310
  // src/commands/channel/join.ts
49035
49311
  init_esm_shims();
49036
49312
  function formatJoinChannelResult(target) {
49037
- return `Joined ${target}. You can now send messages there and receive ordinary channel delivery.`;
49313
+ return [
49314
+ `Joined ${target}. You can now send messages there and receive ordinary channel delivery.`,
49315
+ "Still arrives:",
49316
+ "- Personal @mentions still reach you even if you later mute ordinary channel updates.",
49317
+ "- Threads you started or follow stay followed even if you later mute this channel."
49318
+ ].join("\n");
49038
49319
  }
49039
49320
  function formatAlreadyJoined(target) {
49040
49321
  return `Already joined ${target}.`;
@@ -49190,12 +49471,90 @@ function registerChannelUnmuteCommand(parent, runtimeOptions) {
49190
49471
 
49191
49472
  // src/commands/server/info.ts
49192
49473
  init_esm_shims();
49474
+ function parseNonNegativeInt(raw, name, fallback) {
49475
+ if (raw === void 0) return fallback;
49476
+ if (!/^\d+$/.test(raw)) {
49477
+ throw new CliError({
49478
+ code: "INVALID_ARG",
49479
+ message: `${name} must be a non-negative integer`
49480
+ });
49481
+ }
49482
+ return Number(raw);
49483
+ }
49484
+ function parsePositiveInt2(raw, name, fallback) {
49485
+ const value = parseNonNegativeInt(raw, name, fallback);
49486
+ if (value <= 0) {
49487
+ throw new CliError({
49488
+ code: "INVALID_ARG",
49489
+ message: `${name} must be greater than 0`
49490
+ });
49491
+ }
49492
+ return value;
49493
+ }
49494
+ function selectedSections(opts) {
49495
+ const sections = [];
49496
+ if (opts.channels) sections.push("channels");
49497
+ if (opts.agents) sections.push("agents");
49498
+ if (opts.humans) sections.push("humans");
49499
+ return sections;
49500
+ }
49501
+ function hasListModifier(opts) {
49502
+ return Boolean(opts.joined || opts.query !== void 0 || opts.limit !== void 0 || opts.offset !== void 0);
49503
+ }
49504
+ function includesQuery(row, query) {
49505
+ const needle = query?.trim().toLowerCase();
49506
+ if (!needle) return true;
49507
+ const values = Object.values(row).filter((value) => typeof value === "string").map((value) => value.toLowerCase());
49508
+ return values.some((value) => value.includes(needle));
49509
+ }
49510
+ function pageRows(rows, offset, limit) {
49511
+ return rows.slice(offset, offset + limit);
49512
+ }
49513
+ function nextCommand(section, opts, offset, limit, total) {
49514
+ const nextOffset = offset + limit;
49515
+ if (nextOffset >= total) return void 0;
49516
+ const parts = ["raft server info", `--${section}`, `--offset ${nextOffset}`, `--limit ${limit}`];
49517
+ if (opts.query?.trim()) parts.push(`--query ${JSON.stringify(opts.query.trim())}`);
49518
+ if (opts.joined) parts.push("--joined");
49519
+ return parts.join(" ");
49520
+ }
49193
49521
  var serverInfoCommand = defineCommand(
49194
49522
  {
49195
49523
  name: "info",
49196
- description: "List channels, agents, and humans on the current server"
49524
+ description: "Show bounded server facts; use --full for the legacy full inventory",
49525
+ options: [
49526
+ { flags: "--full", description: "Print the full channels, agents, humans, and runtime inventory" },
49527
+ { flags: "--channels", description: "List visible channels only" },
49528
+ { flags: "--agents", description: "List agents only" },
49529
+ { flags: "--humans", description: "List humans only" },
49530
+ { flags: "--joined", description: "With --channels, show only joined channels" },
49531
+ { flags: "--query <text>", description: "Filter the selected list by visible text" },
49532
+ { flags: "--limit <n>", description: "Maximum rows for list output (default: 50)" },
49533
+ { flags: "--offset <n>", description: "Rows to skip for list output (default: 0)" }
49534
+ ]
49197
49535
  },
49198
- async (ctx) => {
49536
+ async (ctx, opts = {}) => {
49537
+ const sections = selectedSections(opts);
49538
+ if (opts.full && sections.length > 0) {
49539
+ throw new CliError({
49540
+ code: "INVALID_ARG",
49541
+ message: "--full cannot be combined with --channels, --agents, or --humans"
49542
+ });
49543
+ }
49544
+ if (sections.length === 0 && hasListModifier(opts)) {
49545
+ throw new CliError({
49546
+ code: "INVALID_ARG",
49547
+ message: "--query, --limit, --offset, and --joined require --channels, --agents, or --humans"
49548
+ });
49549
+ }
49550
+ if (opts.joined && sections.some((section) => section !== "channels")) {
49551
+ throw new CliError({
49552
+ code: "INVALID_ARG",
49553
+ message: "--joined can only be used with --channels"
49554
+ });
49555
+ }
49556
+ const limit = parsePositiveInt2(opts.limit, "--limit", 50);
49557
+ const offset = parseNonNegativeInt(opts.offset, "--offset", 0);
49199
49558
  const agentContext = ctx.loadAgentContext();
49200
49559
  const client = ctx.createApiClient(agentContext);
49201
49560
  const res = await createAgentApiSurfaceClient(client).server.info();
@@ -49206,14 +49565,56 @@ var serverInfoCommand = defineCommand(
49206
49565
  message: res.error ?? `HTTP ${res.status}`
49207
49566
  });
49208
49567
  }
49209
- const data = res.data;
49210
- if (data?.runtimeContext) {
49211
- data.runtimeContext = {
49212
- ...data.runtimeContext,
49213
- workspacePath: data.runtimeContext.workspacePath ?? ctx.env.SLOCK_CURRENT_WORKSPACE_PATH ?? null
49214
- };
49568
+ if (!res.data) {
49569
+ throw new CliError({
49570
+ code: "INVALID_JSON_RESPONSE",
49571
+ message: "Agent API serverInfo returned an empty response body"
49572
+ });
49215
49573
  }
49216
- writeText(ctx.io, formatServerInfo(data));
49574
+ const data = {
49575
+ ...res.data,
49576
+ runtimeContext: {
49577
+ ...res.data.runtimeContext,
49578
+ workspacePath: res.data.runtimeContext.workspacePath ?? ctx.env.SLOCK_CURRENT_WORKSPACE_PATH ?? null
49579
+ }
49580
+ };
49581
+ if (opts.full) {
49582
+ writeText(ctx.io, formatServerInfo(data));
49583
+ return;
49584
+ }
49585
+ if (sections.length === 0) {
49586
+ writeText(ctx.io, formatServerSummary(data));
49587
+ return;
49588
+ }
49589
+ const chunks = [];
49590
+ for (const section of sections) {
49591
+ if (section === "channels") {
49592
+ const rows = (data.channels ?? []).filter((channel) => !opts.joined || channel.joined).filter((channel) => includesQuery(channel, opts.query));
49593
+ chunks.push(formatServerChannels(pageRows(rows, offset, limit), {
49594
+ total: rows.length,
49595
+ offset,
49596
+ limit,
49597
+ nextCommand: nextCommand(section, opts, offset, limit, rows.length)
49598
+ }));
49599
+ } else if (section === "agents") {
49600
+ const rows = (data.agents ?? []).filter((agent) => includesQuery(agent, opts.query));
49601
+ chunks.push(formatServerAgents(pageRows(rows, offset, limit), {
49602
+ total: rows.length,
49603
+ offset,
49604
+ limit,
49605
+ nextCommand: nextCommand(section, opts, offset, limit, rows.length)
49606
+ }));
49607
+ } else {
49608
+ const rows = (data.humans ?? []).filter((human) => includesQuery(human, opts.query));
49609
+ chunks.push(formatServerHumans(pageRows(rows, offset, limit), {
49610
+ total: rows.length,
49611
+ offset,
49612
+ limit,
49613
+ nextCommand: nextCommand(section, opts, offset, limit, rows.length)
49614
+ }));
49615
+ }
49616
+ }
49617
+ writeText(ctx.io, chunks.join("\n"));
49217
49618
  }
49218
49619
  );
49219
49620
  function registerServerInfoCommand(parent, runtimeOptions) {
@@ -49553,6 +49954,100 @@ function registerServerUpdateCommand(parent, runtimeOptions) {
49553
49954
  registerCliCommand(parent, serverUpdateCommand, runtimeOptions);
49554
49955
  }
49555
49956
 
49957
+ // src/commands/user/info.ts
49958
+ init_esm_shims();
49959
+ function parseNonNegativeInt2(raw, name, fallback) {
49960
+ if (raw === void 0) return fallback;
49961
+ if (!/^\d+$/.test(raw)) {
49962
+ throw new CliError({
49963
+ code: "INVALID_ARG",
49964
+ message: `${name} must be a non-negative integer`
49965
+ });
49966
+ }
49967
+ return Number(raw);
49968
+ }
49969
+ function parsePositiveInt3(raw, name, fallback) {
49970
+ const value = parseNonNegativeInt2(raw, name, fallback);
49971
+ if (value <= 0) {
49972
+ throw new CliError({
49973
+ code: "INVALID_ARG",
49974
+ message: `${name} must be greater than 0`
49975
+ });
49976
+ }
49977
+ return value;
49978
+ }
49979
+ function normalizeUserName(target) {
49980
+ const trimmed = target?.trim() ?? "";
49981
+ const name = trimmed.startsWith("@") ? trimmed.slice(1) : trimmed;
49982
+ if (!name) {
49983
+ throw new CliError({
49984
+ code: "INVALID_ARG",
49985
+ message: "user name is required"
49986
+ });
49987
+ }
49988
+ return name;
49989
+ }
49990
+ var userInfoCommand = defineCommand(
49991
+ {
49992
+ name: "info",
49993
+ description: "Show narrow visible facts for a human or agent and its visible channel memberships",
49994
+ arguments: ["<name>"],
49995
+ options: [
49996
+ { flags: "--limit <n>", description: "Maximum visible channels to inspect (default: 50)" },
49997
+ { flags: "--offset <n>", description: "Visible channels to skip before inspection (default: 0)" }
49998
+ ]
49999
+ },
50000
+ async (ctx, target, opts = {}) => {
50001
+ const name = normalizeUserName(target);
50002
+ const limit = parsePositiveInt3(opts.limit, "--limit", 50);
50003
+ const offset = parseNonNegativeInt2(opts.offset, "--offset", 0);
50004
+ const agentContext = ctx.loadAgentContext();
50005
+ const client = ctx.createApiClient(agentContext);
50006
+ const agentApi = createAgentApiSurfaceClient(client);
50007
+ const infoRes = await agentApi.server.info();
50008
+ if (!infoRes.ok) {
50009
+ throw new CliError({
50010
+ code: infoRes.status >= 500 ? "SERVER_5XX" : "INFO_FAILED",
50011
+ message: infoRes.error ?? `HTTP ${infoRes.status}`
50012
+ });
50013
+ }
50014
+ const agent = (infoRes.data?.agents ?? []).find((candidate) => candidate.name === name);
50015
+ const human = (infoRes.data?.humans ?? []).find((candidate) => candidate.name === name);
50016
+ const user = agent ? { kind: "agent", value: agent } : human ? { kind: "human", value: human } : null;
50017
+ if (!user) {
50018
+ throw new CliError({
50019
+ code: "NOT_FOUND",
50020
+ message: `User not found or not visible: @${name}`,
50021
+ suggestedNextAction: "Run `raft server info --agents --query <name>` or `raft server info --humans --query <name>` to inspect visible users."
50022
+ });
50023
+ }
50024
+ const visibleChannels = infoRes.data?.channels ?? [];
50025
+ const inspectedChannels = visibleChannels.slice(offset, offset + limit);
50026
+ const memberships = [];
50027
+ let skippedChannels = 0;
50028
+ for (const channel of inspectedChannels) {
50029
+ const membersRes = await agentApi.channels.members({ channel: `#${channel.name}` });
50030
+ if (!membersRes.ok) {
50031
+ skippedChannels += 1;
50032
+ continue;
50033
+ }
50034
+ const agents = membersRes.data?.agents ?? [];
50035
+ const humans = membersRes.data?.humans ?? [];
50036
+ const found = user.kind === "agent" ? agents.some((candidate) => candidate.name === name) : humans.some((candidate) => candidate.name === name);
50037
+ if (found) memberships.push(channel);
50038
+ }
50039
+ writeText(ctx.io, formatUserInfo(user, memberships, {
50040
+ total: visibleChannels.length,
50041
+ offset,
50042
+ limit,
50043
+ nextCommand: offset + limit < visibleChannels.length ? `raft user info @${name} --offset ${offset + limit} --limit ${limit}` : void 0
50044
+ }, skippedChannels));
50045
+ }
50046
+ );
50047
+ function registerUserInfoCommand(parent, runtimeOptions) {
50048
+ registerCliCommand(parent, userInfoCommand, runtimeOptions);
50049
+ }
50050
+
49556
50051
  // src/commands/knowledge/get.ts
49557
50052
  init_esm_shims();
49558
50053
  function formatKnowledgeStdout(content) {
@@ -49628,6 +50123,91 @@ function registerKnowledgeGetCommand(parent, runtimeOptions) {
49628
50123
  registerCliCommand(parent, knowledgeGetCommand, runtimeOptions);
49629
50124
  }
49630
50125
 
50126
+ // src/commands/knowledge/search.ts
50127
+ init_esm_shims();
50128
+ function formatKnowledgeSearchResults(results) {
50129
+ return results.map((result2, index) => {
50130
+ const firstScreen = result2.firstScreen.trim();
50131
+ const body = firstScreen.split(/\r?\n/).filter(Boolean).map((line) => ` ${line}`).join("\n");
50132
+ return `${index + 1}. ${result2.slug} \u2014 ${result2.title}${body ? `
50133
+ ${body}` : ""}`;
50134
+ }).join("\n\n") + "\n";
50135
+ }
50136
+ function toKnowledgeSearchErrorCode(errorCode2, status) {
50137
+ switch (errorCode2) {
50138
+ case "INVALID_JSON_RESPONSE":
50139
+ case "SCOPE_DENIED":
50140
+ case "knowledge_agent_missing":
50141
+ case "knowledge_internal_error":
50142
+ case "knowledge_not_found":
50143
+ case "knowledge_query_invalid":
50144
+ case "knowledge_reason_invalid":
50145
+ case "knowledge_scope_invalid":
50146
+ case "knowledge_source_invalid":
50147
+ case "knowledge_trace_id_invalid":
50148
+ case "knowledge_turn_id_invalid":
50149
+ case "unsupported_capability":
50150
+ return errorCode2;
50151
+ default:
50152
+ return status >= 500 ? "SERVER_5XX" : "KNOWLEDGE_SEARCH_FAILED";
50153
+ }
50154
+ }
50155
+ var knowledgeSearchCommand = defineCommand(
50156
+ {
50157
+ name: "search",
50158
+ description: "Search Raft Manual for Agents topics from the current server",
50159
+ arguments: ["<keywords>"],
50160
+ options: [
50161
+ {
50162
+ flags: "--scope <scope>",
50163
+ description: "Optional search scope. Currently supports: recipes"
50164
+ },
50165
+ {
50166
+ flags: "--reason <text>",
50167
+ description: "Optional rationale for this search (>=12 chars when provided)"
50168
+ },
50169
+ {
50170
+ flags: "--turn-id <id>",
50171
+ description: "Optional turn id for correlation in the knowledge event"
50172
+ },
50173
+ {
50174
+ flags: "--trace-id <id>",
50175
+ description: "Optional trace id for correlation in the knowledge event"
50176
+ }
50177
+ ],
50178
+ helpAfter: '\nExamples:\n raft manual search "preview before merge" --scope recipes\n raft manual get recipes/technique/preview-env\n'
50179
+ },
50180
+ async (ctx, keywords, opts) => {
50181
+ const agentContext = ctx.loadAgentContext();
50182
+ const client = ctx.createApiClient(agentContext);
50183
+ const res = await createAgentApiSurfaceClient(client).knowledge.search({
50184
+ query: keywords,
50185
+ scope: opts.scope,
50186
+ reason: opts.reason,
50187
+ turn_id: opts.turnId,
50188
+ trace_id: opts.traceId
50189
+ });
50190
+ if (!res.ok) {
50191
+ throw new CliError({
50192
+ code: toKnowledgeSearchErrorCode(res.errorCode, res.status),
50193
+ message: res.error ?? `HTTP ${res.status}`,
50194
+ suggestedNextAction: res.suggestedNextAction ?? (res.errorCode === "knowledge_not_found" ? "Try different keywords, or run `raft manual get index` to browse available topics." : void 0)
50195
+ });
50196
+ }
50197
+ const data = res.data;
50198
+ if (!data || data.ok !== true || !Array.isArray(data.results)) {
50199
+ throw new CliError({
50200
+ code: "KNOWLEDGE_SEARCH_FAILED",
50201
+ message: "Server returned an unexpected response shape"
50202
+ });
50203
+ }
50204
+ writeText(ctx.io, formatKnowledgeSearchResults(data.results));
50205
+ }
50206
+ );
50207
+ function registerKnowledgeSearchCommand(parent, runtimeOptions) {
50208
+ registerCliCommand(parent, knowledgeSearchCommand, runtimeOptions);
50209
+ }
50210
+
49631
50211
  // src/commands/inbox/check.ts
49632
50212
  init_esm_shims();
49633
50213
 
@@ -49689,7 +50269,11 @@ function parseThreadTarget(target) {
49689
50269
  return null;
49690
50270
  }
49691
50271
  function formatUnfollowThreadResult(target) {
49692
- 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.`;
50272
+ return [
50273
+ `Unfollowed ${target}. Ordinary delivery for this thread has stopped.`,
50274
+ "Still arrives: personal @mentions pierce as single messages \u2014 they do NOT re-follow you.",
50275
+ "Posting in this thread re-follows you automatically."
50276
+ ].join("\n");
49693
50277
  }
49694
50278
  var threadUnfollowCommand = defineCommand(
49695
50279
  {
@@ -50342,6 +50926,168 @@ You can also choose not to send anything.
50342
50926
  `
50343
50927
  });
50344
50928
  }
50929
+ function formatDriveByJoinedToPostTip(target, data) {
50930
+ const attention = data.attention?.driveByJoinedToPost;
50931
+ if (!attention) return "";
50932
+ const muteCommand = attention.muteCommand?.trim() || `raft channel mute "${target}"`;
50933
+ const stillArrives = attention.stillArrives?.[0]?.trim() || "@mentions still reach you, and threads you started stay followed.";
50934
+ return [
50935
+ "Tip: you joined this channel to post this message. If you don't need its ordinary updates:",
50936
+ ` ${muteCommand}`,
50937
+ stillArrives
50938
+ ].join("\n");
50939
+ }
50940
+ function markSendFailureDraftSaved(err, draftSaved) {
50941
+ if (err instanceof CliError) {
50942
+ if (err.draftSaved !== void 0) return err;
50943
+ return new CliError({
50944
+ code: err.code,
50945
+ message: err.message,
50946
+ exitCode: err.exitCode,
50947
+ cause: err.cause,
50948
+ suggestedNextAction: err.suggestedNextAction,
50949
+ draftSaved
50950
+ });
50951
+ }
50952
+ const message = err instanceof Error ? err.message : String(err);
50953
+ return new CliError({
50954
+ code: "INTERNAL_BUG",
50955
+ message: `Unexpected error: ${message}`,
50956
+ cause: err,
50957
+ draftSaved
50958
+ });
50959
+ }
50960
+ async function handleMessageSend(ctx, positionalContent, opts, setFailureDraftSaved) {
50961
+ const target = opts.target?.trim() ?? "";
50962
+ if (!target) {
50963
+ throw cliError("INVALID_ARG", "--target is required");
50964
+ }
50965
+ try {
50966
+ rejectArgContent(positionalContent, opts);
50967
+ } catch (err) {
50968
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50969
+ throw err;
50970
+ }
50971
+ try {
50972
+ validateDraftSendFlags(opts);
50973
+ } catch (err) {
50974
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50975
+ throw err;
50976
+ }
50977
+ let content;
50978
+ let outgoingContent = "";
50979
+ let outgoingAttachmentIds = [];
50980
+ let previousDraftReholdCount = 0;
50981
+ let seenUpToSeq;
50982
+ if (opts.sendDraft) {
50983
+ content = await resolveOptionalSendContent(ctx.io.stdin ?? process.stdin);
50984
+ try {
50985
+ rejectSendDraftStdin(content, opts.target);
50986
+ } catch (err) {
50987
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50988
+ throw err;
50989
+ }
50990
+ } else {
50991
+ try {
50992
+ content = await resolveSendContent(ctx.io.stdin ?? process.stdin);
50993
+ } catch (err) {
50994
+ if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50995
+ throw err;
50996
+ }
50997
+ outgoingContent = content;
50998
+ outgoingAttachmentIds = opts.attachmentId && opts.attachmentId.length > 0 ? opts.attachmentId : [];
50999
+ }
51000
+ const agentContext = ctx.loadAgentContext();
51001
+ const client = ctx.createApiClient(agentContext);
51002
+ if (opts.sendDraft) {
51003
+ const savedDraft = getSavedDraft(agentContext.agentId, target);
51004
+ if (!savedDraft) {
51005
+ throw cliError(
51006
+ "SEND_DRAFT_NOT_FOUND",
51007
+ [
51008
+ "No saved draft exists for this target.",
51009
+ "To create or update a draft, send message content normally:",
51010
+ ` raft message send --target "${target}" <<'${MESSAGE_HEREDOC_DELIMITER}'`,
51011
+ " message body",
51012
+ ` ${MESSAGE_HEREDOC_DELIMITER}`
51013
+ ].join("\n")
51014
+ );
51015
+ }
51016
+ outgoingContent = savedDraft.content;
51017
+ outgoingAttachmentIds = savedDraft.attachmentIds;
51018
+ previousDraftReholdCount = savedDraft.reholdCount;
51019
+ seenUpToSeq = savedDraft.seenUpToSeq;
51020
+ setFailureDraftSaved(true);
51021
+ } else {
51022
+ const previousDraft = getSavedDraft(agentContext.agentId, target);
51023
+ previousDraftReholdCount = previousDraft?.reholdCount ?? 0;
51024
+ seenUpToSeq = previousDraft?.seenUpToSeq;
51025
+ }
51026
+ if (seenUpToSeq === void 0) {
51027
+ seenUpToSeq = getConsumedSeq(agentContext.agentId, target);
51028
+ }
51029
+ const body = {
51030
+ target,
51031
+ content: outgoingContent,
51032
+ draftReholdCount: previousDraftReholdCount
51033
+ };
51034
+ if (seenUpToSeq !== void 0) {
51035
+ body.seenUpToSeq = seenUpToSeq;
51036
+ }
51037
+ if (opts.sendDraft) {
51038
+ body.sendDraft = true;
51039
+ if (opts.anyway) body.continueAnyway = true;
51040
+ } else {
51041
+ body.draftReplacedExisting = previousDraftReholdCount > 0;
51042
+ }
51043
+ if (outgoingAttachmentIds.length > 0) {
51044
+ body.attachmentIds = outgoingAttachmentIds;
51045
+ }
51046
+ const agentApi = createAgentApiSurfaceClient(client);
51047
+ const res = await agentApi.messages.send(body);
51048
+ if (!res.ok) {
51049
+ const code = res.status >= 500 ? "SERVER_5XX" : "SEND_FAILED";
51050
+ throw cliError(code, res.error ?? `HTTP ${res.status}`);
51051
+ }
51052
+ const data = res.data;
51053
+ if (!data) {
51054
+ throw cliError("INVALID_JSON_RESPONSE", "Agent API messageSend returned an empty response body");
51055
+ }
51056
+ if (data.state === "held") {
51057
+ if (typeof data.seenUpToSeq === "number" && Number.isFinite(data.seenUpToSeq)) {
51058
+ recordConsumedSeqs(agentContext.agentId, { [target]: data.seenUpToSeq });
51059
+ }
51060
+ setSavedDraft(agentContext.agentId, target, {
51061
+ content: outgoingContent,
51062
+ attachmentIds: outgoingAttachmentIds,
51063
+ savedAt: Date.now(),
51064
+ reholdCount: previousDraftReholdCount + 1,
51065
+ seenUpToSeq: data.seenUpToSeq
51066
+ });
51067
+ writeText(ctx.io, formatHeldSendOutput(target, data));
51068
+ return;
51069
+ }
51070
+ clearSavedDraft(agentContext.agentId, target);
51071
+ const shortId = data.messageId ? data.messageId.slice(0, 8) : null;
51072
+ const replyHint = shortId ? ` (to reply in this message's thread, use target "${target.includes(":") ? target : target + ":" + shortId}")` : "";
51073
+ let unreadSection = "";
51074
+ if (data.recentUnread && data.recentUnread.length > 0) {
51075
+ unreadSection = `
51076
+
51077
+ --- New messages you may have missed ---
51078
+ ${formatMessages(data.recentUnread)}`;
51079
+ }
51080
+ const pendingMentionActions = normalizePendingMentionActions(data);
51081
+ const mentionSection = pendingMentionActions.length > 0 ? `
51082
+
51083
+ ${formatPendingMentionActions(pendingMentionActions, { source: "send" }).trimEnd()}` : "";
51084
+ const driveByTip = formatDriveByJoinedToPostTip(target, data);
51085
+ const driveBySection = driveByTip ? `
51086
+
51087
+ ${driveByTip}` : "";
51088
+ writeText(ctx.io, `Message sent to ${target}. Message ID: ${data.messageId}${replyHint}${driveBySection}${mentionSection}${unreadSection}
51089
+ `);
51090
+ }
50345
51091
  var messageSendCommand = defineCommand(
50346
51092
  {
50347
51093
  name: "send",
@@ -50360,131 +51106,14 @@ var messageSendCommand = defineCommand(
50360
51106
  ]
50361
51107
  },
50362
51108
  async (ctx, positionalContent, opts) => {
50363
- const target = opts.target?.trim() ?? "";
50364
- if (!target) {
50365
- throw cliError("INVALID_ARG", "--target is required");
50366
- }
50367
- try {
50368
- rejectArgContent(positionalContent, opts);
50369
- } catch (err) {
50370
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50371
- throw err;
50372
- }
51109
+ let failureDraftSaved = false;
50373
51110
  try {
50374
- validateDraftSendFlags(opts);
50375
- } catch (err) {
50376
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50377
- throw err;
50378
- }
50379
- let content;
50380
- let outgoingContent = "";
50381
- let outgoingAttachmentIds = [];
50382
- let previousDraftReholdCount = 0;
50383
- let seenUpToSeq;
50384
- if (opts.sendDraft) {
50385
- content = await resolveOptionalSendContent(ctx.io.stdin ?? process.stdin);
50386
- try {
50387
- rejectSendDraftStdin(content, opts.target);
50388
- } catch (err) {
50389
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50390
- throw err;
50391
- }
50392
- } else {
50393
- try {
50394
- content = await resolveSendContent(ctx.io.stdin ?? process.stdin);
50395
- } catch (err) {
50396
- if (err instanceof SendContentError) throw cliError(err.code, err.message, { cause: err });
50397
- throw err;
50398
- }
50399
- outgoingContent = content;
50400
- outgoingAttachmentIds = opts.attachmentId && opts.attachmentId.length > 0 ? opts.attachmentId : [];
50401
- }
50402
- const agentContext = ctx.loadAgentContext();
50403
- const client = ctx.createApiClient(agentContext);
50404
- if (opts.sendDraft) {
50405
- const savedDraft = getSavedDraft(agentContext.agentId, target);
50406
- if (!savedDraft) {
50407
- throw cliError(
50408
- "SEND_DRAFT_NOT_FOUND",
50409
- [
50410
- "No saved draft exists for this target.",
50411
- "To create or update a draft, send message content normally:",
50412
- ` raft message send --target "${target}" <<'${MESSAGE_HEREDOC_DELIMITER}'`,
50413
- " message body",
50414
- ` ${MESSAGE_HEREDOC_DELIMITER}`
50415
- ].join("\n")
50416
- );
50417
- return;
50418
- }
50419
- outgoingContent = savedDraft.content;
50420
- outgoingAttachmentIds = savedDraft.attachmentIds;
50421
- previousDraftReholdCount = savedDraft.reholdCount;
50422
- seenUpToSeq = savedDraft.seenUpToSeq;
50423
- } else {
50424
- const previousDraft = getSavedDraft(agentContext.agentId, target);
50425
- previousDraftReholdCount = previousDraft?.reholdCount ?? 0;
50426
- seenUpToSeq = previousDraft?.seenUpToSeq;
50427
- }
50428
- if (seenUpToSeq === void 0) {
50429
- seenUpToSeq = getConsumedSeq(agentContext.agentId, target);
50430
- }
50431
- const body = {
50432
- target,
50433
- content: outgoingContent,
50434
- draftReholdCount: previousDraftReholdCount
50435
- };
50436
- if (seenUpToSeq !== void 0) {
50437
- body.seenUpToSeq = seenUpToSeq;
50438
- }
50439
- if (opts.sendDraft) {
50440
- body.sendDraft = true;
50441
- if (opts.anyway) body.continueAnyway = true;
50442
- } else {
50443
- body.draftReplacedExisting = previousDraftReholdCount > 0;
50444
- }
50445
- if (outgoingAttachmentIds.length > 0) {
50446
- body.attachmentIds = outgoingAttachmentIds;
50447
- }
50448
- const agentApi = createAgentApiSurfaceClient(client);
50449
- const res = await agentApi.messages.send(body);
50450
- if (!res.ok) {
50451
- const code = res.status >= 500 ? "SERVER_5XX" : "SEND_FAILED";
50452
- throw cliError(code, res.error ?? `HTTP ${res.status}`);
50453
- }
50454
- const data = res.data;
50455
- if (!data) {
50456
- throw cliError("INVALID_JSON_RESPONSE", "Agent API messageSend returned an empty response body");
50457
- }
50458
- if (data.state === "held") {
50459
- if (typeof data.seenUpToSeq === "number" && Number.isFinite(data.seenUpToSeq)) {
50460
- recordConsumedSeqs(agentContext.agentId, { [target]: data.seenUpToSeq });
50461
- }
50462
- setSavedDraft(agentContext.agentId, target, {
50463
- content: outgoingContent,
50464
- attachmentIds: outgoingAttachmentIds,
50465
- savedAt: Date.now(),
50466
- reholdCount: previousDraftReholdCount + 1,
50467
- seenUpToSeq: data.seenUpToSeq
51111
+ await handleMessageSend(ctx, positionalContent, opts, (draftSaved) => {
51112
+ failureDraftSaved = draftSaved;
50468
51113
  });
50469
- writeText(ctx.io, formatHeldSendOutput(target, data));
50470
- return;
50471
- }
50472
- clearSavedDraft(agentContext.agentId, target);
50473
- const shortId = data.messageId ? data.messageId.slice(0, 8) : null;
50474
- const replyHint = shortId ? ` (to reply in this message's thread, use target "${target.includes(":") ? target : target + ":" + shortId}")` : "";
50475
- let unreadSection = "";
50476
- if (data.recentUnread && data.recentUnread.length > 0) {
50477
- unreadSection = `
50478
-
50479
- --- New messages you may have missed ---
50480
- ${formatMessages(data.recentUnread)}`;
51114
+ } catch (err) {
51115
+ throw markSendFailureDraftSaved(err, failureDraftSaved);
50481
51116
  }
50482
- const pendingMentionActions = normalizePendingMentionActions(data);
50483
- const mentionSection = pendingMentionActions.length > 0 ? `
50484
-
50485
- ${formatPendingMentionActions(pendingMentionActions, { source: "send" }).trimEnd()}` : "";
50486
- writeText(ctx.io, `Message sent to ${target}. Message ID: ${data.messageId}${replyHint}${mentionSection}${unreadSection}
50487
- `);
50488
51117
  }
50489
51118
  );
50490
51119
  function registerSendCommand(parent, runtimeOptions = {}) {
@@ -50596,7 +51225,7 @@ function requireTargetAlias(opts) {
50596
51225
  }
50597
51226
 
50598
51227
  // src/commands/message/read.ts
50599
- function parsePositiveInt2(name, raw) {
51228
+ function parsePositiveInt4(name, raw) {
50600
51229
  if (raw === void 0) return void 0;
50601
51230
  const n = Number(raw);
50602
51231
  if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {
@@ -50635,7 +51264,7 @@ function mapReadFailure(res) {
50635
51264
  }
50636
51265
  function validateReadOpts(opts) {
50637
51266
  const channel = requireTargetAlias(opts);
50638
- const limit = parsePositiveInt2("limit", opts.limit);
51267
+ const limit = parsePositiveInt4("limit", opts.limit);
50639
51268
  const before = opts.before?.trim();
50640
51269
  const after = opts.after?.trim();
50641
51270
  return {
@@ -50727,7 +51356,7 @@ function normalizeMemberHandleRef(raw) {
50727
51356
  }
50728
51357
  return handle;
50729
51358
  }
50730
- function parsePositiveInt3(name, raw) {
51359
+ function parsePositiveInt5(name, raw) {
50731
51360
  if (raw === void 0) return void 0;
50732
51361
  const n = Number(raw);
50733
51362
  if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {
@@ -50738,7 +51367,7 @@ function parsePositiveInt3(name, raw) {
50738
51367
  }
50739
51368
  return n;
50740
51369
  }
50741
- function parseNonNegativeInt(name, raw) {
51370
+ function parseNonNegativeInt3(name, raw) {
50742
51371
  if (raw === void 0) return void 0;
50743
51372
  const n = Number(raw);
50744
51373
  if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0) {
@@ -50772,8 +51401,8 @@ function normalizeSearchOpts(opts) {
50772
51401
  message: "--sort relevance requires --query; filter-only search is sorted by recent"
50773
51402
  });
50774
51403
  }
50775
- const limit = parsePositiveInt3("limit", opts.limit);
50776
- const offset = parseNonNegativeInt("offset", opts.offset);
51404
+ const limit = parsePositiveInt5("limit", opts.limit);
51405
+ const offset = parseNonNegativeInt3("offset", opts.offset);
50777
51406
  const sort = opts.sort ?? (query ? void 0 : "recent");
50778
51407
  return {
50779
51408
  ...query ? { query } : {},
@@ -53737,6 +54366,7 @@ registerAgentLoginCommand(agentCmd);
53737
54366
  registerAgentListCommand(agentCmd);
53738
54367
  registerAgentBridgeCommand(agentCmd);
53739
54368
  var channelCmd = program2.command("channel").description("Channel membership and attention operations");
54369
+ registerChannelInfoCommand(channelCmd);
53740
54370
  registerChannelMembersCommand(channelCmd);
53741
54371
  registerChannelCreateCommand(channelCmd);
53742
54372
  registerChannelUpdateCommand(channelCmd);
@@ -53751,10 +54381,14 @@ registerThreadUnfollowCommand(threadCmd);
53751
54381
  var serverCmd = program2.command("server").description("Server / workspace introspection");
53752
54382
  registerServerInfoCommand(serverCmd);
53753
54383
  registerServerUpdateCommand(serverCmd);
54384
+ var userCmd = program2.command("user").description("User and agent introspection");
54385
+ registerUserInfoCommand(userCmd);
53754
54386
  var manualCmd = program2.command("manual").description("Raft Manual for Agents retrieval (canonical operating topics)");
53755
54387
  registerKnowledgeGetCommand(manualCmd);
54388
+ registerKnowledgeSearchCommand(manualCmd);
53756
54389
  var knowledgeCmd = program2.command("knowledge").description("Legacy alias for `raft manual`");
53757
54390
  registerKnowledgeGetCommand(knowledgeCmd);
54391
+ registerKnowledgeSearchCommand(knowledgeCmd);
53758
54392
  var inboxCmd = program2.command("inbox").description("Inbox target summary operations");
53759
54393
  registerInboxCheckCommand(inboxCmd);
53760
54394
  var messageCmd = program2.command("message").description("Message operations");