@botiverse/raft-daemon 0.72.12 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1359,6 +1359,71 @@ function randomHex(length) {
1359
1359
  }
1360
1360
 
1361
1361
  // ../shared/src/tracing/eventRows.ts
1362
+ var TRACE_EVENT_ROW_V2_PROJECTION_COLUMNS = [
1363
+ ["row_kind", "string"],
1364
+ ["service_name", "string"],
1365
+ ["deployment_environment", "string"],
1366
+ ["service_version", "string"],
1367
+ ["service_revision", "string"],
1368
+ ["service_instance_id", "string"],
1369
+ ["deployment_instance_source", "string"],
1370
+ ["deployment_identity_state", "string"],
1371
+ ["ecs_task_id", "string"],
1372
+ ["ecs_task_family", "string"],
1373
+ ["ecs_task_revision", "string"],
1374
+ ["trace_id", "string"],
1375
+ ["span_id", "string"],
1376
+ ["parent_span_id", "string"],
1377
+ ["span_name", "string"],
1378
+ ["span_kind", "string"],
1379
+ ["span_surface", "string"],
1380
+ ["span_status", "string"],
1381
+ ["span_start_time_ms", "int"],
1382
+ ["span_end_time_ms", "int"],
1383
+ ["event_name", "string"],
1384
+ ["event_kind", "string"],
1385
+ ["event_time", "timestamp"],
1386
+ ["event_time_ms", "int"],
1387
+ ["event_index", "int"],
1388
+ ["server_id", "string"],
1389
+ ["machine_id", "string"],
1390
+ ["agent_id", "string"],
1391
+ ["launch_id", "string"],
1392
+ ["session_id", "string"],
1393
+ ["request_id", "string"],
1394
+ ["route_pattern", "string"],
1395
+ ["caller_kind", "string"],
1396
+ ["outcome", "string"],
1397
+ ["reason", "string"],
1398
+ ["source", "string"],
1399
+ ["authority", "string"],
1400
+ ["activity_write_site", "string"],
1401
+ ["activity_source", "string"],
1402
+ ["hint_source", "string"],
1403
+ ["resolved_activity", "string"],
1404
+ ["previous_activity", "string"],
1405
+ ["next_activity", "string"],
1406
+ ["repair_kind", "string"],
1407
+ ["action", "string"],
1408
+ ["error_class", "string"],
1409
+ ["status_bucket", "string"],
1410
+ ["shadow_agent_id", "string"],
1411
+ ["shadow_signal_site", "string"],
1412
+ ["shadow_observation_class", "string"],
1413
+ ["shadow_prior_projection", "string"],
1414
+ ["shadow_projection", "string"],
1415
+ ["shadow_legacy_outcome", "string"],
1416
+ ["shadow_action", "string"],
1417
+ ["shadow_reason", "string"],
1418
+ ["shadow_direction", "string"],
1419
+ ["shadow_plan_kind", "string"]
1420
+ ];
1421
+ var TRACE_EVENT_ROW_V2_INGEST_STATEMENT = [
1422
+ "SELECT",
1423
+ TRACE_EVENT_ROW_V2_PROJECTION_COLUMNS.map(([column, type]) => `$0["${column}"]::${type} AS ${column}`).join(", "),
1424
+ "INSERT INTO raft.trace_events_v2",
1425
+ `(${TRACE_EVENT_ROW_V2_PROJECTION_COLUMNS.map(([column]) => column).join(", ")})`
1426
+ ].join(" ");
1362
1427
  var PROMOTED_IDENTITY_ATTRS = [
1363
1428
  "server_id",
1364
1429
  "machine_id",
@@ -2020,7 +2085,7 @@ var integrationAppDraftFieldsSchema = z.object({
2020
2085
  var integrationRegisterAppOperationSchema = integrationAppDraftFieldsSchema.extend({
2021
2086
  type: z.literal("integration:register_app"),
2022
2087
  name: z.string().trim().min(1).max(120),
2023
- clientKey: z.string().trim().min(1).max(120),
2088
+ clientKey: z.string().trim().min(1).max(120).optional(),
2024
2089
  returnUrl: z.string().trim().min(1).max(2e3),
2025
2090
  scopes: z.array(z.string().trim().min(1).max(120)).max(64).default([]),
2026
2091
  unsafeDemoUrlOverride: z.boolean().optional(),
@@ -2440,10 +2505,8 @@ var agentApiIntegrationLoginBodySchema = passthroughObject({
2440
2505
  scopes: optionalStringArraySchema,
2441
2506
  target: optionalStringSchema
2442
2507
  });
2443
- var agentApiIntegrationAppPrepareBodySchema = passthroughObject({
2444
- mode: z3.enum(["register", "update"]),
2508
+ var agentApiIntegrationAppPrepareCommonBodyShape = {
2445
2509
  target: z3.string().trim().min(1),
2446
- clientKey: z3.string().trim().min(1),
2447
2510
  name: optionalStringSchema,
2448
2511
  description: optionalStringSchema,
2449
2512
  homepageUrl: optionalStringSchema,
@@ -2452,7 +2515,19 @@ var agentApiIntegrationAppPrepareBodySchema = passthroughObject({
2452
2515
  scopes: optionalStringArraySchema,
2453
2516
  unsafeDemoUrlOverride: optionalBooleanSchema,
2454
2517
  draftHint: optionalStringSchema
2455
- });
2518
+ };
2519
+ var agentApiIntegrationAppPrepareBodySchema = z3.discriminatedUnion("mode", [
2520
+ passthroughObject({
2521
+ mode: z3.literal("register"),
2522
+ ...agentApiIntegrationAppPrepareCommonBodyShape,
2523
+ clientKey: optionalStringSchema
2524
+ }),
2525
+ passthroughObject({
2526
+ mode: z3.literal("update"),
2527
+ ...agentApiIntegrationAppPrepareCommonBodyShape,
2528
+ clientKey: z3.string().trim().min(1)
2529
+ })
2530
+ ]);
2456
2531
  var agentApiIntegrationAppRotateSecretBodySchema = passthroughObject({
2457
2532
  clientKey: z3.string().trim().min(1)
2458
2533
  });
@@ -3595,6 +3670,12 @@ function currentTimeMs() {
3595
3670
  function currentDate() {
3596
3671
  return new Date(currentTimeMs());
3597
3672
  }
3673
+ function setClockTimeout(fn, ms) {
3674
+ return setTimeout(fn, ms);
3675
+ }
3676
+ function clearClockTimeout(timeout) {
3677
+ clearTimeout(timeout);
3678
+ }
3598
3679
 
3599
3680
  // ../shared/src/agentInbox.ts
3600
3681
  function formatAgentInboxDelta(rows, options = {}) {
@@ -5092,8 +5173,31 @@ If a tool or error output contains credential-shaped strings, redact them to \`s
5092
5173
 
5093
5174
  **Profile credential resolution is strict.** When invoked as \`--profile <slug>\` (any entry command) or with \`RAFT_PROFILE=<slug>\` (\`SLOCK_PROFILE\` is a deprecation alias; setting both to different values fails closed), the CLI resolves credentials from \`$RAFT_PROFILE_DIR\` \u2192 \`$RAFT_HOME/profiles/<slug>\` (falling back to \`$SLOCK_PROFILE_DIR\`/\`$SLOCK_HOME\`) \u2192 \`$HOME/.slock/profiles/<slug>\` in that order. It does **not** fall back to a different profile's credential, to an ambient user-level token, or to environment-leaked secrets \u2014 if your designated profile credential is missing or unreadable, the CLI fails closed rather than authenticating as someone else.`;
5094
5175
  }
5095
- function buildSendingMessagesSection() {
5176
+ function buildSendingMessagesSection(shell) {
5096
5177
  const D = MESSAGE_HEREDOC_DELIMITER;
5178
+ if (shell === "powershell") {
5179
+ return `### Sending messages
5180
+
5181
+ - **Reply to a channel**: pipe a PowerShell here-string into \`raft message send --target "#channel-name"\`
5182
+ - **Reply to a DM**: pipe a PowerShell here-string into \`raft message send --target dm:@peer-name\`
5183
+ - **Reply in a thread**: pipe a PowerShell here-string into \`raft message send --target "#channel:shortid"\`
5184
+ - **Start a NEW DM**: pipe a PowerShell here-string into \`raft message send --target dm:@person-name\`
5185
+
5186
+ Message content is always read from stdin. On Windows PowerShell, use a single-quoted here-string so quotes, backticks, dollar variables, and newlines stay literal:
5187
+ \`\`\`powershell
5188
+ @'
5189
+ Long message with "quotes", $vars, \`backticks\`, and code blocks.
5190
+ '@ | raft message send --target "#channel-name"
5191
+ \`\`\`
5192
+
5193
+ The closing \`'@\` must start at the beginning of its line. Do not use Bash heredoc syntax (\`<<\`) in PowerShell.
5194
+
5195
+ If Slock says a message was not sent and was saved as a draft, choose one path:
5196
+ - To update the draft, pipe the revised here-string into a normal \`raft message send --target <target>\` command.
5197
+ - To send the current draft unchanged, use \`raft message send --send-draft --target <target>\` with no stdin. Do not use \`--send-draft\` when changing content.
5198
+
5199
+ **IMPORTANT**: To reply to any message, always reuse the exact \`target\` from the received message. This ensures your reply goes to the right place \u2014 whether it's a channel, DM, or thread.`;
5200
+ }
5097
5201
  return `### Sending messages
5098
5202
 
5099
5203
  - **Reply to a channel**: \`raft message send --target "#channel-name" <<'${D}'\` followed by the message body and \`${D}\`
@@ -5124,25 +5228,26 @@ When a reminder already exists, prefer \`raft reminder snooze\` to push it later
5124
5228
  Use \`raft reminder schedule\` rather than runtime-native wake or cron tools such as ScheduleWakeup or CronCreate for user-visible reminders, so reminders stay author-owned, persistent, observable, snoozable, updatable, and cancelable in Slock.
5125
5229
  Create agent reminders only after resolving the anchor message from the current conversation and passing its msgId explicitly; if no anchor can be resolved, consider posting a status update in the relevant thread so the intent is visible, then revisit when context is available.`;
5126
5230
  }
5127
- function buildThreadsSection() {
5231
+ function buildThreadsSection(shell) {
5128
5232
  const D = MESSAGE_HEREDOC_DELIMITER;
5233
+ const startThreadInstruction = shell === "powershell" ? 'pipe a PowerShell single-quoted here-string into `raft message send --target "#general:00000000"`' : `reply with \`raft message send --target "#general:00000000" <<'${D}'\` followed by the message body and \`${D}\``;
5129
5234
  return `### Threads
5130
5235
 
5131
5236
  Threads are sub-conversations attached to a specific message. They let you discuss a topic without cluttering the main channel.
5132
5237
 
5133
5238
  - **Thread targets** have a colon and short ID suffix: \`#general:00000000\` (thread in #general) or \`dm:@richard:11111111\` (thread in a DM).
5134
5239
  - When you receive a message from a thread (the target has a \`:shortid\` suffix), **always reply using that same target** to keep the conversation in the thread.
5135
- - **Start a new thread**: Use the \`msg=\` field from the header as the thread suffix. For example, if you see \`[target=#general msg=00000000 ...]\`, reply with \`raft message send --target "#general:00000000" <<'${D}'\` followed by the message body and \`${D}\`. The thread will be auto-created if it doesn't exist yet. Example IDs like \`00000000\` are placeholders; real message IDs come from received messages.
5240
+ - **Start a new thread**: Use the \`msg=\` field from the header as the thread suffix. For example, if you see \`[target=#general msg=00000000 ...]\`, ${startThreadInstruction}. The thread will be auto-created if it doesn't exist yet. Example IDs like \`00000000\` are placeholders; real message IDs come from received messages.
5136
5241
  - When you send a message, the response includes the message ID. You can use it to start a thread on your own message.
5137
5242
  - You can read thread history: \`raft message read --target "#general:00000000"\`
5138
- - You can stop receiving ordinary delivery for a thread with \`raft thread unfollow --target "#general:00000000"\`. Only do this when your work in that thread is clearly complete or no longer relevant.
5243
+ - Unfollowing a thread removes its follow record and stops its ordinary delivery while the parent channel is unmuted: \`raft thread unfollow --target "#general:00000000"\`. A parent channel mute already suppresses ordinary delivery from its threads, so do not unfollow solely to mute the parent channel. Only unfollow when your work in that thread is clearly complete or no longer relevant.
5139
5244
  - Threads cannot be nested \u2014 you cannot start a thread inside a thread.`;
5140
5245
  }
5141
5246
  function buildDiscoverySection() {
5142
5247
  return `### Discovering people and channels
5143
5248
 
5144
5249
  Call \`raft server info\` to see all channels in this server, which ones you have joined, other agents, and humans.
5145
- Visible public channels may appear even when \`joined=false\`. In that state you can still inspect them with \`raft message read\` and \`raft channel members\`, but you cannot send messages there or receive ordinary channel delivery until you join with \`raft channel join --target "#channel-name"\`. Private channels require a human with access to add you. To leave a regular channel you have joined, use \`raft channel leave --target "#channel-name"\`. To mute ordinary Activity delivery without leaving a regular channel, use \`raft channel mute --target "#channel-name"\`; personal @mentions and DMs still pierce (a task pierces only when it personally @mentions you), and thread following is separate. To reverse that setting, use \`raft channel unmute --target "#channel-name"\`. To stop following a thread without leaving its parent channel, use \`raft thread unfollow --target "#channel-name:shortid"\`.
5250
+ Visible public channels may appear even when \`joined=false\`. In that state you can still inspect them with \`raft message read\` and \`raft channel members\`, but you cannot send messages there or receive ordinary channel delivery until you join with \`raft channel join --target "#channel-name"\`. Private channels require a human with access to add you. To leave a regular channel you have joined, use \`raft channel leave --target "#channel-name"\`. To mute ordinary Activity delivery from a regular channel and its threads without leaving, use \`raft channel mute --target "#channel-name"\`; personal @mentions and DMs still pierce (a task pierces only when it personally @mentions you), while existing thread follow records remain. To reverse that setting, use \`raft channel unmute --target "#channel-name"\`. To remove a thread's follow record without leaving its parent channel, use \`raft thread unfollow --target "#channel-name:shortid"\`.
5146
5251
  Private channels are membership-gated. If \`raft server info\` shows a channel as private, treat its name, members, and content as private to that channel; do not disclose that information in other channels, DMs, summaries, or task reports unless a human explicitly asks within an authorized context. In \`raft channel members\`, human role labels such as owner/admin show server-level authority; no role label means ordinary member.`;
5147
5252
  }
5148
5253
  function buildChannelAwarenessSection() {
@@ -5329,12 +5434,13 @@ Your context will be periodically compressed to stay within limits. When this ha
5329
5434
  - Keep MEMORY.md complete enough that context compression preserves: which channel is about what, what tasks are in progress, what the user has asked for, and what other agents are doing.`;
5330
5435
  }
5331
5436
  function buildSlockCliGuideSections(options) {
5437
+ const shell = options.shell ?? "posix";
5332
5438
  return {
5333
5439
  communication: buildCommunicationSection(options.audience),
5334
5440
  credentialHygiene: buildCredentialHygieneSection(),
5335
- sendingMessages: buildSendingMessagesSection(),
5441
+ sendingMessages: buildSendingMessagesSection(shell),
5336
5442
  reminders: buildRemindersSection(),
5337
- threads: buildThreadsSection(),
5443
+ threads: buildThreadsSection(shell),
5338
5444
  discovery: buildDiscoverySection(),
5339
5445
  channelAwareness: buildChannelAwarenessSection(),
5340
5446
  readingHistory: buildReadingHistorySection(),
@@ -5384,6 +5490,7 @@ function buildPrompt(config, opts) {
5384
5490
  handle: config.name,
5385
5491
  displayName: config.displayName || config.name
5386
5492
  },
5493
+ shell: opts.commandShell,
5387
5494
  taskClaimCmd
5388
5495
  });
5389
5496
  const checkCmd = "`raft message check`";
@@ -6677,6 +6784,32 @@ async function handleProxyRequest(req, res) {
6677
6784
  const method = req.method ?? "GET";
6678
6785
  const correlationId = randomBytes(8).toString("hex");
6679
6786
  let target;
6787
+ const inboundTraceparent = firstRequestHeader(req.headers.traceparent);
6788
+ const parent = parseTraceparent(inboundTraceparent);
6789
+ const traceContextState = parent ? "continued" : inboundTraceparent ? "malformed" : "new_root";
6790
+ let localPathname = "unknown";
6791
+ try {
6792
+ localPathname = new URL2(req.url ?? "/", "http://agent-proxy.local").pathname;
6793
+ } catch {
6794
+ }
6795
+ const proxySpan = registration.tracer.startSpan("daemon.agent_proxy.request", {
6796
+ parent,
6797
+ surface: "daemon",
6798
+ kind: "client",
6799
+ attrs: {
6800
+ route_family: routeFamilyForPath(localPathname),
6801
+ method: normalizedProxyMethod(method),
6802
+ trace_context_state: traceContextState,
6803
+ proxy_launch_id_present: registration.launchId !== null,
6804
+ correlation_id: correlationId
6805
+ }
6806
+ });
6807
+ let proxySpanStatus = "error";
6808
+ let proxySpanEndAttrs = {
6809
+ outcome: "proxy_failure",
6810
+ normalized_code: "transport_failure",
6811
+ response_started: false
6812
+ };
6680
6813
  try {
6681
6814
  target = new URL2(req.url ?? "/", registration.serverUrl);
6682
6815
  const headers = new Headers();
@@ -6697,6 +6830,7 @@ async function handleProxyRequest(req, res) {
6697
6830
  headers.set("X-Agent-Id", registration.agentId);
6698
6831
  headers.set("X-Slock-Client", "cli");
6699
6832
  headers.set("X-Slock-Agent-Active-Capabilities", registration.activeCapabilities);
6833
+ headers.set("traceparent", formatTraceparent(proxySpan.context));
6700
6834
  let body;
6701
6835
  let rawBodyBuffer;
6702
6836
  if (method !== "GET" && method !== "HEAD") {
@@ -6711,6 +6845,12 @@ async function handleProxyRequest(req, res) {
6711
6845
  if (method === "GET" && target.pathname === "/internal/agent-api/inbox") {
6712
6846
  const localInbox = localAgentApiInboxResponse(registration);
6713
6847
  if (localInbox) {
6848
+ proxySpanStatus = "ok";
6849
+ proxySpanEndAttrs = {
6850
+ outcome: "local_response",
6851
+ local_response_kind: "inbox",
6852
+ http_status: localInbox.status
6853
+ };
6714
6854
  res.writeHead(localInbox.status, { "content-type": "application/json" });
6715
6855
  res.end(JSON.stringify(localInbox.body));
6716
6856
  return;
@@ -6719,6 +6859,12 @@ async function handleProxyRequest(req, res) {
6719
6859
  if (method === "GET" && target.pathname === "/internal/agent-api/events") {
6720
6860
  const localEvents = localAgentApiEventsResponse(registration, target);
6721
6861
  if (localEvents) {
6862
+ proxySpanStatus = "ok";
6863
+ proxySpanEndAttrs = {
6864
+ outcome: "local_response",
6865
+ local_response_kind: "events",
6866
+ http_status: localEvents.status
6867
+ };
6722
6868
  res.writeHead(localEvents.status, { "content-type": "application/json" });
6723
6869
  res.end(JSON.stringify(localEvents.body));
6724
6870
  return;
@@ -6728,6 +6874,12 @@ async function handleProxyRequest(req, res) {
6728
6874
  const rawBody = rawBodyBuffer?.toString("utf8") ?? "";
6729
6875
  const prepared = await prepareAgentApiSideEffectForward(registration, headers, rawBody, sideEffectAction);
6730
6876
  if (prepared.localResponse) {
6877
+ proxySpanStatus = "ok";
6878
+ proxySpanEndAttrs = {
6879
+ outcome: "local_response",
6880
+ local_response_kind: "freshness_hold",
6881
+ http_status: 200
6882
+ };
6731
6883
  const responseText = JSON.stringify(prepared.localResponse);
6732
6884
  res.writeHead(200, { "content-type": "application/json" });
6733
6885
  res.end(responseText);
@@ -6750,10 +6902,23 @@ async function handleProxyRequest(req, res) {
6750
6902
  );
6751
6903
  if (upstream.status >= 500) {
6752
6904
  const transportError = transportNormalizedErrorForHttpStatus(target, upstream.status, registration.launchId);
6905
+ proxySpanStatus = "error";
6906
+ proxySpanEndAttrs = {
6907
+ outcome: "upstream_5xx",
6908
+ http_status: upstream.status,
6909
+ normalized_code: transportError.normalizedCode,
6910
+ response_started: transportError.responseStarted
6911
+ };
6753
6912
  logger.warn(
6754
6913
  `[Agent Credential Proxy] upstream returned HTTP ${upstream.status} (agent=${registration.agentId}, launch=${registration.launchId ?? "none"}, correlation=${correlationId}, method=${method}, path=${target.pathname}, route_family=${transportError.routeFamily}, target_host_class=${transportError.targetHostClass})`
6755
6914
  );
6756
6915
  registration.inboxCoordinator?.recordTransportNormalizedError?.(transportError);
6916
+ } else {
6917
+ proxySpanStatus = "ok";
6918
+ proxySpanEndAttrs = {
6919
+ outcome: "upstream_response",
6920
+ http_status: upstream.status
6921
+ };
6757
6922
  }
6758
6923
  if (shouldBufferJsonResponse(upstream, target.pathname, registration)) {
6759
6924
  const responseText = await upstream.text();
@@ -6785,8 +6950,28 @@ async function handleProxyRequest(req, res) {
6785
6950
  );
6786
6951
  registration.inboxCoordinator?.recordProxyFailure?.(failure);
6787
6952
  registration.inboxCoordinator?.recordTransportNormalizedError?.(transportError);
6953
+ proxySpanStatus = "error";
6954
+ proxySpanEndAttrs = {
6955
+ outcome: "proxy_failure",
6956
+ normalized_code: transportError.normalizedCode,
6957
+ response_started: transportError.responseStarted,
6958
+ ...transportError.upstreamStatus === void 0 ? {} : { http_status: transportError.upstreamStatus }
6959
+ };
6788
6960
  writeProxyFailureResponse(res, failure);
6961
+ } finally {
6962
+ proxySpan.end(proxySpanStatus, { attrs: proxySpanEndAttrs });
6963
+ }
6964
+ }
6965
+ function firstRequestHeader(value) {
6966
+ if (typeof value === "string") return value;
6967
+ return value?.[0];
6968
+ }
6969
+ function normalizedProxyMethod(method) {
6970
+ const normalized = method.toUpperCase();
6971
+ if (normalized === "GET" || normalized === "POST" || normalized === "PUT" || normalized === "PATCH" || normalized === "DELETE" || normalized === "HEAD" || normalized === "OPTIONS") {
6972
+ return normalized;
6789
6973
  }
6974
+ return "OTHER";
6790
6975
  }
6791
6976
  function writeProxyFailureResponse(res, failure) {
6792
6977
  if (res.writableEnded) return;
@@ -7087,7 +7272,12 @@ async function loadRecentTargetMessages(registration, headers, target) {
7087
7272
  const historyHeaders = new Headers(headers);
7088
7273
  historyHeaders.delete("content-length");
7089
7274
  historyHeaders.delete("content-type");
7090
- const res = await fetch(historyUrl, { method: "GET", headers: historyHeaders });
7275
+ const res = await daemonFetch(
7276
+ historyUrl,
7277
+ { method: "GET", headers: historyHeaders },
7278
+ process.env,
7279
+ { isolationKey: AGENT_CREDENTIAL_PROXY_FETCH_ISOLATION_KEY }
7280
+ );
7091
7281
  if (!res.ok) return [];
7092
7282
  const parsed = await res.json().catch(() => null);
7093
7283
  return Array.isArray(parsed?.messages) ? normalizeInboxVisibleMessages(parsed.messages, target) : [];
@@ -7203,7 +7393,8 @@ async function registerAgentCredentialProxy(input) {
7203
7393
  agentId: input.agentId,
7204
7394
  launchId: input.launchId ?? null,
7205
7395
  activeCapabilities: input.activeCapabilities,
7206
- inboxCoordinator: input.inboxCoordinator
7396
+ inboxCoordinator: input.inboxCoordinator,
7397
+ tracer: input.tracer ?? noopTracer
7207
7398
  });
7208
7399
  return {
7209
7400
  proxyUrl: server.proxyUrl,
@@ -7462,7 +7653,8 @@ async function prepareCliTransport(ctx, extraEnv = {}, platform = process.platfo
7462
7653
  serverUrl: ctx.config.serverUrl,
7463
7654
  apiKey: agentCredentialKey,
7464
7655
  activeCapabilities: DEFAULT_ACTIVE_CAPABILITIES,
7465
- inboxCoordinator: ctx.agentCredentialProxyInboxCoordinator
7656
+ inboxCoordinator: ctx.agentCredentialProxyInboxCoordinator,
7657
+ tracer: ctx.tracer
7466
7658
  });
7467
7659
  const launchPart = buildCliTransportLaunchPart(ctx.launchId);
7468
7660
  const proxyTokenDir = path2.join(slockHome, "agent-proxy-tokens", safePathPart(ctx.agentId));
@@ -8053,6 +8245,7 @@ var WINDOWS_ENVIRONMENT_SCRIPT = [
8053
8245
  " $result | ConvertTo-Json -Compress -Depth 3",
8054
8246
  "}"
8055
8247
  ].join(" ");
8248
+ var WINDOWS_COMMAND_RESOLVE_TIMEOUT_MS = 1e3;
8056
8249
  function normalizeProcessEnv(value) {
8057
8250
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
8058
8251
  const env = {};
@@ -8161,7 +8354,8 @@ function resolveCommandOnWindows(command, env, execFileSyncFn, existsSyncFn) {
8161
8354
  command
8162
8355
  ], {
8163
8356
  stdio: ["ignore", "pipe", "ignore"],
8164
- env
8357
+ env,
8358
+ timeout: WINDOWS_COMMAND_RESOLVE_TIMEOUT_MS
8165
8359
  }));
8166
8360
  const resolved = output.trim().split(/\r?\n/)[0];
8167
8361
  if (!resolved) return null;
@@ -11772,7 +11966,6 @@ import { mkdirSync as mkdirSync3, readdirSync as readdirSync3 } from "fs";
11772
11966
  import path12 from "path";
11773
11967
  import {
11774
11968
  AuthStorage,
11775
- createBashTool,
11776
11969
  createAgentSessionFromServices,
11777
11970
  createAgentSessionServices,
11778
11971
  getAgentDir,
@@ -11780,6 +11973,126 @@ import {
11780
11973
  SettingsManager,
11781
11974
  VERSION as PI_SDK_VERSION
11782
11975
  } from "@earendil-works/pi-coding-agent";
11976
+
11977
+ // src/drivers/piCommandTool.ts
11978
+ import { spawn as spawn9 } from "child_process";
11979
+ import {
11980
+ createBashTool
11981
+ } from "@earendil-works/pi-coding-agent";
11982
+ var POWERSHELL_STDIN_LOADER = [
11983
+ "$raftReader = [System.IO.StreamReader]::new([Console]::OpenStandardInput(), [System.Text.Encoding]::ASCII, $false)",
11984
+ "try { $raftEncodedScript = $raftReader.ReadToEnd() } finally { $raftReader.Dispose() }",
11985
+ "$raftScript = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($raftEncodedScript))",
11986
+ "& ([ScriptBlock]::Create($raftScript))"
11987
+ ].join("\r\n");
11988
+ var POWERSHELL_ARGS = [
11989
+ "-NoLogo",
11990
+ "-NoProfile",
11991
+ "-NonInteractive",
11992
+ "-ExecutionPolicy",
11993
+ "Bypass",
11994
+ "-Command",
11995
+ POWERSHELL_STDIN_LOADER
11996
+ ];
11997
+ var MAX_TIMEOUT_SECONDS = 2147483647 / 1e3;
11998
+ function killWindowsProcessTree(pid) {
11999
+ const killer = spawn9("taskkill.exe", ["/F", "/T", "/PID", String(pid)], {
12000
+ detached: true,
12001
+ stdio: "ignore",
12002
+ windowsHide: true
12003
+ });
12004
+ killer.unref();
12005
+ }
12006
+ function buildPiPowerShellScript(command) {
12007
+ return [
12008
+ "$ErrorActionPreference = 'Stop'",
12009
+ "$utf8NoBom = New-Object System.Text.UTF8Encoding($false)",
12010
+ "[Console]::OutputEncoding = $utf8NoBom",
12011
+ "$OutputEncoding = $utf8NoBom",
12012
+ "$global:LASTEXITCODE = 0",
12013
+ "& {",
12014
+ command,
12015
+ "}",
12016
+ "$raftCommandSucceeded = $?",
12017
+ "$raftNativeExitCode = $global:LASTEXITCODE",
12018
+ "if ($raftNativeExitCode -ne 0) { exit $raftNativeExitCode }",
12019
+ "if (-not $raftCommandSucceeded) { exit 1 }",
12020
+ "exit 0",
12021
+ ""
12022
+ ].join("\r\n");
12023
+ }
12024
+ function createPiPowerShellOperations(deps = {}) {
12025
+ const spawnProcess = deps.spawn ?? spawn9;
12026
+ const killProcessTree = deps.killProcessTree ?? killWindowsProcessTree;
12027
+ return {
12028
+ exec: async (command, cwd, { onData, signal, timeout, env }) => {
12029
+ if (signal?.aborted) throw new Error("aborted");
12030
+ if (timeout !== void 0 && (!Number.isFinite(timeout) || timeout <= 0 || timeout > MAX_TIMEOUT_SECONDS)) {
12031
+ throw new Error(
12032
+ `Invalid timeout: must be between 0 and ${MAX_TIMEOUT_SECONDS} seconds`
12033
+ );
12034
+ }
12035
+ const child = spawnProcess("powershell.exe", [...POWERSHELL_ARGS], {
12036
+ cwd,
12037
+ env,
12038
+ stdio: ["pipe", "pipe", "pipe"],
12039
+ windowsHide: true
12040
+ });
12041
+ child.stdout.on("data", onData);
12042
+ child.stderr.on("data", onData);
12043
+ child.stdin.on("error", () => void 0);
12044
+ child.stdin.end(
12045
+ Buffer.from(buildPiPowerShellScript(command), "utf16le").toString(
12046
+ "base64"
12047
+ )
12048
+ );
12049
+ let timedOut = false;
12050
+ const terminate = () => {
12051
+ if (child.pid) killProcessTree(child.pid);
12052
+ };
12053
+ const timeoutHandle = timeout === void 0 ? void 0 : setClockTimeout(() => {
12054
+ timedOut = true;
12055
+ terminate();
12056
+ }, timeout * 1e3);
12057
+ const onAbort = () => terminate();
12058
+ signal?.addEventListener("abort", onAbort, { once: true });
12059
+ if (signal?.aborted) terminate();
12060
+ try {
12061
+ const exitCode = await new Promise((resolve, reject) => {
12062
+ child.once("error", reject);
12063
+ child.once("close", resolve);
12064
+ });
12065
+ if (signal?.aborted) throw new Error("aborted");
12066
+ if (timedOut) throw new Error(`timeout:${timeout}`);
12067
+ return { exitCode };
12068
+ } finally {
12069
+ if (timeoutHandle) clearClockTimeout(timeoutHandle);
12070
+ signal?.removeEventListener("abort", onAbort);
12071
+ }
12072
+ }
12073
+ };
12074
+ }
12075
+ function createPiCommandTool(cwd, toolSpawnEnv, deps = {}) {
12076
+ const platform = deps.platform ?? process.platform;
12077
+ const tool = createBashTool(cwd, {
12078
+ ...platform === "win32" ? { operations: createPiPowerShellOperations(deps) } : {},
12079
+ spawnHook: (spawnContext) => ({
12080
+ ...spawnContext,
12081
+ env: {
12082
+ ...spawnContext.env,
12083
+ ...toolSpawnEnv
12084
+ }
12085
+ })
12086
+ });
12087
+ if (platform !== "win32") return tool;
12088
+ return {
12089
+ ...tool,
12090
+ label: "PowerShell",
12091
+ description: "Execute a Windows PowerShell 5.1 command in the current working directory. Use PowerShell syntax, not Bash syntax. Standard output and standard error are returned."
12092
+ };
12093
+ }
12094
+
12095
+ // src/drivers/pi.ts
11783
12096
  var PI_SESSION_DIR = ".pi-sessions";
11784
12097
  var BUILTIN_SESSION_DIR = ".builtin-sessions";
11785
12098
  var BUILTIN_AGENT_DIR = ".builtin-runtime";
@@ -11888,8 +12201,12 @@ async function withProcessEnvPatch(patch, fn, opts = {}) {
11888
12201
  }
11889
12202
  });
11890
12203
  }
11891
- function resolvePiModelFromRegistry(modelId, modelRegistry) {
12204
+ function resolvePiModelFromRegistry(modelId, modelRegistry, runtimeConfig) {
11892
12205
  if (!modelId || modelId === "default") return void 0;
12206
+ if (runtimeConfig.runtime === "builtin" && runtimeConfig.provider.kind === "gateway" && runtimeConfig.model.kind === "custom") {
12207
+ const provider2 = runtimeConfig.provider.providerId === "openai-compatible" ? "openai" : "anthropic";
12208
+ return modelRegistry.find(provider2, runtimeConfig.model.name);
12209
+ }
11893
12210
  const [provider, ...modelParts] = modelId.split("/");
11894
12211
  if (provider && modelParts.length > 0) {
11895
12212
  return modelRegistry.find(provider, modelParts.join("/"));
@@ -12221,7 +12538,7 @@ async function createPiAgentSessionForContext(ctx, sessionId, opts = {}) {
12221
12538
  agent_dir_source: opts.agentDirSource ?? (spawnEnv.PI_CODING_AGENT_DIR ? "spawn_env" : "default"),
12222
12539
  ...launchTraceEvidenceAttrs
12223
12540
  });
12224
- const model = resolvePiModelFromRegistry(launchRuntimeFields.model, services.modelRegistry);
12541
+ const model = resolvePiModelFromRegistry(launchRuntimeFields.model, services.modelRegistry, runtimeConfig);
12225
12542
  const resolvedModel = formatPiModelLogId(model);
12226
12543
  traceSpan?.addEvent(`${traceEventPrefix}.model_resolved`, {
12227
12544
  available_models_count: services.modelRegistry.getAvailable().length,
@@ -12277,15 +12594,7 @@ async function createPiAgentSessionForContext(ctx, sessionId, opts = {}) {
12277
12594
  model,
12278
12595
  thinkingLevel: launchRuntimeFields.reasoningEffort,
12279
12596
  customTools: [
12280
- createBashTool(ctx.workingDirectory, {
12281
- spawnHook: (spawnContext) => ({
12282
- ...spawnContext,
12283
- env: {
12284
- ...spawnContext.env,
12285
- ...toolSpawnEnv
12286
- }
12287
- })
12288
- })
12597
+ createPiCommandTool(ctx.workingDirectory, toolSpawnEnv)
12289
12598
  ]
12290
12599
  }), { removeFirst: providerEnvScope });
12291
12600
  traceSpan?.addEvent(`${traceEventPrefix}.started`, {
@@ -12596,13 +12905,15 @@ var PiDriver = class {
12596
12905
  return null;
12597
12906
  }
12598
12907
  buildSystemPrompt(config, _agentId) {
12908
+ const windowsPowerShell = process.platform === "win32";
12599
12909
  return buildCliTransportSystemPrompt(config, {
12600
- extraCriticalRules: [],
12910
+ extraCriticalRules: windowsPowerShell ? ["- Pi's `bash` tool is a compatibility name on Windows: it executes native Windows PowerShell 5.1. Use PowerShell syntax and never Bash heredocs or Unix-only commands."] : [],
12601
12911
  postStartupNotes: [
12602
12912
  "**Pi runtime note:** Slock keeps Pi running as a persistent SDK session. While you are working, Slock may send inbox-count notifications into the current turn; call `raft message check` at natural breakpoints."
12603
12913
  ],
12604
12914
  includeStdinNotificationSection: true,
12605
- messageNotificationStyle: "direct"
12915
+ messageNotificationStyle: "direct",
12916
+ commandShell: windowsPowerShell ? "powershell" : "posix"
12606
12917
  });
12607
12918
  }
12608
12919
  };
@@ -12638,13 +12949,15 @@ var BuiltInDriver = class extends PiDriver {
12638
12949
  }));
12639
12950
  }
12640
12951
  buildSystemPrompt(config, _agentId) {
12952
+ const windowsPowerShell = process.platform === "win32";
12641
12953
  return buildCliTransportSystemPrompt(config, {
12642
- extraCriticalRules: [],
12954
+ extraCriticalRules: windowsPowerShell ? ["- This runtime's `bash` tool is a compatibility name on Windows: it executes native Windows PowerShell 5.1. Use PowerShell syntax and never Bash heredocs or Unix-only commands."] : [],
12643
12955
  postStartupNotes: [
12644
12956
  "**Built-in runtime note:** Slock keeps this runtime in an isolated SDK session. While you are working, Slock may send inbox-count notifications into the current turn; call `raft message check` at natural breakpoints."
12645
12957
  ],
12646
12958
  includeStdinNotificationSection: true,
12647
- messageNotificationStyle: "direct"
12959
+ messageNotificationStyle: "direct",
12960
+ commandShell: windowsPowerShell ? "powershell" : "posix"
12648
12961
  });
12649
12962
  }
12650
12963
  };
@@ -21902,6 +22215,10 @@ var systemClock = {
21902
22215
  clearTimeout: (timer) => clearTimeout(timer)
21903
22216
  };
21904
22217
  var INBOUND_WATCHDOG_MS = 7e4;
22218
+ var LEGACY_MACHINE_KEY_MIGRATED_REASON = "legacy_machine_key_migrated";
22219
+ function isTerminalMigratedKeyRejection(statusCode, reason) {
22220
+ return statusCode === 401 && reason === LEGACY_MACHINE_KEY_MIGRATED_REASON;
22221
+ }
21905
22222
  function normalizeHandshakeReason(value) {
21906
22223
  const raw = Array.isArray(value) ? value[0] : value;
21907
22224
  if (typeof raw !== "string") return null;
@@ -22078,6 +22395,17 @@ var DaemonConnection = class {
22078
22395
  slock_reason_present: Boolean(reason),
22079
22396
  slock_reason: reason
22080
22397
  }, "error");
22398
+ if (isTerminalMigratedKeyRejection(statusCode, reason)) {
22399
+ this.shouldConnect = false;
22400
+ logger.error(
22401
+ '[Daemon] This legacy machine key was already migrated to Raft Computer. Reconnects are stopped because this key cannot authenticate again.\nStop and disable this legacy raft-daemon process. In Raft, open this offline Computer and choose "raft-computer: command not found? Install or re-run setup" to copy the install and setup commands for this server.'
22402
+ );
22403
+ this.trace("daemon.connection.reconnect_stopped", {
22404
+ status_code: statusCode,
22405
+ slock_reason: reason,
22406
+ terminal: true
22407
+ }, "error");
22408
+ }
22081
22409
  this.options.onHandshakeRejected?.({ statusCode, reason });
22082
22410
  response.resume();
22083
22411
  try {
@@ -24670,6 +24998,22 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
24670
24998
  },
24671
24999
  endAttrs: ["outcome", "ackSeq", "deliveryId", "error_class", "pending_count"]
24672
25000
  },
25001
+ "daemon.agent_proxy.request": {
25002
+ spanAttrs: [
25003
+ "route_family",
25004
+ "method",
25005
+ "trace_context_state",
25006
+ "proxy_launch_id_present",
25007
+ "correlation_id"
25008
+ ],
25009
+ endAttrs: [
25010
+ "outcome",
25011
+ "local_response_kind",
25012
+ "http_status",
25013
+ "normalized_code",
25014
+ "response_started"
25015
+ ]
25016
+ },
24673
25017
  "daemon.runtime_profile.control.received": {
24674
25018
  spanAttrs: ["agentId", "control_kind", "key_present", "launchId"],
24675
25019
  endAttrs: ["outcome", "error_class"]
@@ -24905,7 +25249,7 @@ function resolveSlockCliPathOrEmpty(moduleUrl = import.meta.url) {
24905
25249
  }
24906
25250
  async function runBundledSlockCli(argv) {
24907
25251
  process.argv = [process.execPath, "slock", ...argv];
24908
- await import("./dist-ME3NQ5JP.js");
25252
+ await import("./dist-YLMDSQ55.js");
24909
25253
  }
24910
25254
  function detectRuntimes(tracer = noopTracer) {
24911
25255
  const ids = [];
@@ -26321,6 +26665,11 @@ var DaemonCore = class {
26321
26665
  });
26322
26666
  }
26323
26667
  handleConnect() {
26668
+ try {
26669
+ this.options.lifecycleHooks?.onConnect?.();
26670
+ } catch (err) {
26671
+ logger.warn(`[Daemon] Connection lifecycle hook failed: ${err instanceof Error ? err.message : String(err)}`);
26672
+ }
26324
26673
  if (!this.opencliWrappersRegenerated) {
26325
26674
  this.opencliWrappersRegenerated = true;
26326
26675
  try {
@@ -26413,7 +26762,6 @@ var DaemonCore = class {
26413
26762
  for (const agentId of agentsForSnapshot) {
26414
26763
  this.connection.send({ type: "reminder.snapshot.request", agentId });
26415
26764
  }
26416
- this.options.lifecycleHooks?.onConnect?.();
26417
26765
  }
26418
26766
  handleDisconnect() {
26419
26767
  logger.warn("[Daemon] Lost connection \u2014 agents continue running locally");
package/dist/cli/index.js CHANGED
@@ -28774,6 +28774,71 @@ function randomHex(length) {
28774
28774
 
28775
28775
  // ../shared/src/tracing/eventRows.ts
28776
28776
  init_esm_shims();
28777
+ var TRACE_EVENT_ROW_V2_PROJECTION_COLUMNS = [
28778
+ ["row_kind", "string"],
28779
+ ["service_name", "string"],
28780
+ ["deployment_environment", "string"],
28781
+ ["service_version", "string"],
28782
+ ["service_revision", "string"],
28783
+ ["service_instance_id", "string"],
28784
+ ["deployment_instance_source", "string"],
28785
+ ["deployment_identity_state", "string"],
28786
+ ["ecs_task_id", "string"],
28787
+ ["ecs_task_family", "string"],
28788
+ ["ecs_task_revision", "string"],
28789
+ ["trace_id", "string"],
28790
+ ["span_id", "string"],
28791
+ ["parent_span_id", "string"],
28792
+ ["span_name", "string"],
28793
+ ["span_kind", "string"],
28794
+ ["span_surface", "string"],
28795
+ ["span_status", "string"],
28796
+ ["span_start_time_ms", "int"],
28797
+ ["span_end_time_ms", "int"],
28798
+ ["event_name", "string"],
28799
+ ["event_kind", "string"],
28800
+ ["event_time", "timestamp"],
28801
+ ["event_time_ms", "int"],
28802
+ ["event_index", "int"],
28803
+ ["server_id", "string"],
28804
+ ["machine_id", "string"],
28805
+ ["agent_id", "string"],
28806
+ ["launch_id", "string"],
28807
+ ["session_id", "string"],
28808
+ ["request_id", "string"],
28809
+ ["route_pattern", "string"],
28810
+ ["caller_kind", "string"],
28811
+ ["outcome", "string"],
28812
+ ["reason", "string"],
28813
+ ["source", "string"],
28814
+ ["authority", "string"],
28815
+ ["activity_write_site", "string"],
28816
+ ["activity_source", "string"],
28817
+ ["hint_source", "string"],
28818
+ ["resolved_activity", "string"],
28819
+ ["previous_activity", "string"],
28820
+ ["next_activity", "string"],
28821
+ ["repair_kind", "string"],
28822
+ ["action", "string"],
28823
+ ["error_class", "string"],
28824
+ ["status_bucket", "string"],
28825
+ ["shadow_agent_id", "string"],
28826
+ ["shadow_signal_site", "string"],
28827
+ ["shadow_observation_class", "string"],
28828
+ ["shadow_prior_projection", "string"],
28829
+ ["shadow_projection", "string"],
28830
+ ["shadow_legacy_outcome", "string"],
28831
+ ["shadow_action", "string"],
28832
+ ["shadow_reason", "string"],
28833
+ ["shadow_direction", "string"],
28834
+ ["shadow_plan_kind", "string"]
28835
+ ];
28836
+ var TRACE_EVENT_ROW_V2_INGEST_STATEMENT = [
28837
+ "SELECT",
28838
+ TRACE_EVENT_ROW_V2_PROJECTION_COLUMNS.map(([column, type]) => `$0["${column}"]::${type} AS ${column}`).join(", "),
28839
+ "INSERT INTO raft.trace_events_v2",
28840
+ `(${TRACE_EVENT_ROW_V2_PROJECTION_COLUMNS.map(([column]) => column).join(", ")})`
28841
+ ].join(" ");
28777
28842
  var PROMOTED_IDENTITY_ATTRS = [
28778
28843
  "server_id",
28779
28844
  "machine_id",
@@ -42899,7 +42964,7 @@ var integrationAppDraftFieldsSchema = external_exports.object({
42899
42964
  var integrationRegisterAppOperationSchema = integrationAppDraftFieldsSchema.extend({
42900
42965
  type: external_exports.literal("integration:register_app"),
42901
42966
  name: external_exports.string().trim().min(1).max(120),
42902
- clientKey: external_exports.string().trim().min(1).max(120),
42967
+ clientKey: external_exports.string().trim().min(1).max(120).optional(),
42903
42968
  returnUrl: external_exports.string().trim().min(1).max(2e3),
42904
42969
  scopes: external_exports.array(external_exports.string().trim().min(1).max(120)).max(64).default([]),
42905
42970
  unsafeDemoUrlOverride: external_exports.boolean().optional(),
@@ -43343,10 +43408,8 @@ var agentApiIntegrationLoginBodySchema = passthroughObject({
43343
43408
  scopes: optionalStringArraySchema,
43344
43409
  target: optionalStringSchema
43345
43410
  });
43346
- var agentApiIntegrationAppPrepareBodySchema = passthroughObject({
43347
- mode: external_exports.enum(["register", "update"]),
43411
+ var agentApiIntegrationAppPrepareCommonBodyShape = {
43348
43412
  target: external_exports.string().trim().min(1),
43349
- clientKey: external_exports.string().trim().min(1),
43350
43413
  name: optionalStringSchema,
43351
43414
  description: optionalStringSchema,
43352
43415
  homepageUrl: optionalStringSchema,
@@ -43355,7 +43418,19 @@ var agentApiIntegrationAppPrepareBodySchema = passthroughObject({
43355
43418
  scopes: optionalStringArraySchema,
43356
43419
  unsafeDemoUrlOverride: optionalBooleanSchema,
43357
43420
  draftHint: optionalStringSchema
43358
- });
43421
+ };
43422
+ var agentApiIntegrationAppPrepareBodySchema = external_exports.discriminatedUnion("mode", [
43423
+ passthroughObject({
43424
+ mode: external_exports.literal("register"),
43425
+ ...agentApiIntegrationAppPrepareCommonBodyShape,
43426
+ clientKey: optionalStringSchema
43427
+ }),
43428
+ passthroughObject({
43429
+ mode: external_exports.literal("update"),
43430
+ ...agentApiIntegrationAppPrepareCommonBodyShape,
43431
+ clientKey: external_exports.string().trim().min(1)
43432
+ })
43433
+ ]);
43359
43434
  var agentApiIntegrationAppRotateSecretBodySchema = passthroughObject({
43360
43435
  clientKey: external_exports.string().trim().min(1)
43361
43436
  });
@@ -45404,6 +45479,9 @@ init_esm_shims();
45404
45479
  // ../shared/src/sync-core/testing.ts
45405
45480
  init_esm_shims();
45406
45481
 
45482
+ // ../shared/src/onboardingStateMachineContract.ts
45483
+ init_esm_shims();
45484
+
45407
45485
  // ../shared/src/testing/failpoints.ts
45408
45486
  init_esm_shims();
45409
45487
  var NoopFailpointRegistry = class {
@@ -51525,6 +51603,7 @@ function formatPendingMentionActions(actions, opts = {}) {
51525
51603
  const lines = opts.source === "send" ? [
51526
51604
  "Undelivered mentions",
51527
51605
  "Message was sent, but these @mentions were not delivered:",
51606
+ "For a literal name rather than a recipient, wrap the @handle in inline or fenced code.",
51528
51607
  ""
51529
51608
  ] : ["Pending mention actions", ""];
51530
51609
  for (const action of actions) {
@@ -51538,7 +51617,7 @@ function formatPendingMentionActions(actions, opts = {}) {
51538
51617
  lines.push(" recovery commands:");
51539
51618
  lines.push(...commands);
51540
51619
  if (commands.some((command) => command.includes(" mention notify "))) {
51541
- lines.push(" note: notify can still report dropped; check the command result before assuming delivery.");
51620
+ lines.push(" note: notify exits nonzero unless the target queue accepts the delivery.");
51542
51621
  }
51543
51622
  }
51544
51623
  }
@@ -51917,12 +51996,19 @@ ${driveByTip}` : "";
51917
51996
  if (pendingMentionActions.length > 0) {
51918
51997
  writeUndeliveredMentionWarning(ctx.io, pendingMentionActions.length);
51919
51998
  }
51999
+ const mentionDeliveryError = pendingMentionActions.length > 0 ? cliError(
52000
+ "MENTION_DELIVERY_FAILED",
52001
+ `Message ${data.messageId} was sent, but ${pendingMentionActions.length} @mention${pendingMentionActions.length === 1 ? " was" : "s were"} not delivered.`,
52002
+ { suggestedNextAction: "Run `raft mention pending` and complete or explicitly resolve every pending mention action." }
52003
+ ) : null;
51920
52004
  if (opts.json) {
51921
52005
  writeJson(ctx.io, data);
52006
+ if (mentionDeliveryError) throw mentionDeliveryError;
51922
52007
  return;
51923
52008
  }
51924
52009
  writeText(ctx.io, `${sentStatusLine}${replyHint}${driveBySection}${mentionSection}${unreadSection}
51925
52010
  `);
52011
+ if (mentionDeliveryError) throw mentionDeliveryError;
51926
52012
  }
51927
52013
  var messageSendCommand = defineCommand(
51928
52014
  {
@@ -53122,6 +53208,17 @@ init_esm_shims();
53122
53208
 
53123
53209
  // src/commands/mention/execute.ts
53124
53210
  init_esm_shims();
53211
+ function resultSucceeded(action, status) {
53212
+ return action === "notify" ? status === "queued" : status === "delivered";
53213
+ }
53214
+ function formatFailedMentionActions(action, requestedIds, results) {
53215
+ const returnedIds = new Set(results.map((result2) => result2.resolutionId));
53216
+ const failures = results.filter((result2) => !resultSucceeded(action, result2.status)).map((result2) => `${result2.resolutionId}: ${result2.status}${result2.reason ? ` (${result2.reason})` : ""}`);
53217
+ for (const id of requestedIds) {
53218
+ if (!returnedIds.has(id)) failures.push(`${id}: missing_result`);
53219
+ }
53220
+ return failures.length > 0 ? failures.join(", ") : null;
53221
+ }
53125
53222
  function normalizeResolutionIds(rawIds) {
53126
53223
  const ids = (rawIds ?? []).map((id) => id.trim()).filter(Boolean);
53127
53224
  if (ids.length === 0) {
@@ -53149,6 +53246,13 @@ function buildMentionExecuteCommand(action) {
53149
53246
  throw cliError(res.status >= 500 ? "SERVER_5XX" : "MENTION_ACTION_FAILED", res.error ?? `HTTP ${res.status}`);
53150
53247
  }
53151
53248
  const results = normalizeMentionActionResults(res.data);
53249
+ const failure3 = formatFailedMentionActions(action, ids, results);
53250
+ if (failure3) {
53251
+ throw cliError(
53252
+ "MENTION_ACTION_FAILED",
53253
+ `Mention ${action} did not complete for every requested target: ${failure3}`
53254
+ );
53255
+ }
53152
53256
  if (opts.json) {
53153
53257
  writeJson(ctx.io, { ok: true, action, results });
53154
53258
  return;
@@ -54731,7 +54835,7 @@ function optionalTrimmed(value) {
54731
54835
  function formatAppPrepare(data) {
54732
54836
  const lines = [
54733
54837
  `Integration app ${data.mode} card prepared`,
54734
- `client key: ${data.action.clientKey}`,
54838
+ `client key: ${data.action.clientKey ?? "auto-generated on commit"}`,
54735
54839
  `card: ${data.actionCardMessageId}`,
54736
54840
  `target: ${data.target}`
54737
54841
  ];
@@ -54749,14 +54853,11 @@ function formatAppPrepare(data) {
54749
54853
  }
54750
54854
  async function prepareApp(mode, ctx, opts) {
54751
54855
  const target = requiredTrimmed(opts.target, "--target");
54752
- const clientKey = requiredTrimmed(opts.clientKey, "--client-key");
54753
54856
  const scopes = normalizeScopes3([...opts.scope ?? [], ...opts.scopes ?? []]);
54754
54857
  const agentContext = ctx.loadAgentContext();
54755
54858
  const client = ctx.createApiClient(agentContext);
54756
- const body = {
54757
- mode,
54859
+ const commonBody = {
54758
54860
  target,
54759
- clientKey,
54760
54861
  name: optionalTrimmed(opts.name),
54761
54862
  description: optionalTrimmed(opts.description),
54762
54863
  homepageUrl: optionalTrimmed(opts.homepageUrl) ?? optionalTrimmed(opts.appUrl),
@@ -54765,7 +54866,8 @@ async function prepareApp(mode, ctx, opts) {
54765
54866
  scopes,
54766
54867
  unsafeDemoUrlOverride: opts.unsafeDemoUrlOverride === true
54767
54868
  };
54768
- if (mode === "register") {
54869
+ const body = mode === "update" ? { ...commonBody, mode: "update", clientKey: requiredTrimmed(opts.clientKey, "--client-key") } : { ...commonBody, mode: "register", clientKey: optionalTrimmed(opts.clientKey) };
54870
+ if (body.mode === "register") {
54769
54871
  requiredTrimmed(body.name, "--name");
54770
54872
  requiredTrimmed(body.returnUrl, "--redirect-url");
54771
54873
  }
@@ -54944,7 +55046,7 @@ var integrationAppPrepareRecoverOwnerCommand = defineCommand(
54944
55046
  async (ctx, opts) => prepareRecoverOwner(ctx, opts)
54945
55047
  );
54946
55048
  var sharedOptions = [
54947
- { flags: "--client-key <key>", description: "Stable app client key / OAuth client_id to reserve or update" },
55049
+ { flags: "--client-key <key>", description: "Stable app client key / OAuth client_id to reserve or update; register defaults to server-generated" },
54948
55050
  { flags: "--name <name>", description: "App display name" },
54949
55051
  { flags: "--redirect-url <url>", description: "OAuth redirect/callback URL" },
54950
55052
  { flags: "--app-url <url>", description: "App homepage URL" },
package/dist/core.js CHANGED
@@ -36,7 +36,7 @@ import {
36
36
  stageAgentMigrationObjectStoreBundle,
37
37
  subscribeDaemonLogs,
38
38
  verifyAgentMigrationAdoptPlan
39
- } from "./chunk-LHJUHF42.js";
39
+ } from "./chunk-BK46OPUN.js";
40
40
  export {
41
41
  AGENT_MIGRATION_BUNDLE_SCHEMA_VERSION,
42
42
  AGENT_MIGRATION_CONTROL_SEAM_ENV,
@@ -28522,6 +28522,71 @@ function randomHex(length) {
28522
28522
  return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
28523
28523
  }
28524
28524
  init_esm_shims();
28525
+ var TRACE_EVENT_ROW_V2_PROJECTION_COLUMNS = [
28526
+ ["row_kind", "string"],
28527
+ ["service_name", "string"],
28528
+ ["deployment_environment", "string"],
28529
+ ["service_version", "string"],
28530
+ ["service_revision", "string"],
28531
+ ["service_instance_id", "string"],
28532
+ ["deployment_instance_source", "string"],
28533
+ ["deployment_identity_state", "string"],
28534
+ ["ecs_task_id", "string"],
28535
+ ["ecs_task_family", "string"],
28536
+ ["ecs_task_revision", "string"],
28537
+ ["trace_id", "string"],
28538
+ ["span_id", "string"],
28539
+ ["parent_span_id", "string"],
28540
+ ["span_name", "string"],
28541
+ ["span_kind", "string"],
28542
+ ["span_surface", "string"],
28543
+ ["span_status", "string"],
28544
+ ["span_start_time_ms", "int"],
28545
+ ["span_end_time_ms", "int"],
28546
+ ["event_name", "string"],
28547
+ ["event_kind", "string"],
28548
+ ["event_time", "timestamp"],
28549
+ ["event_time_ms", "int"],
28550
+ ["event_index", "int"],
28551
+ ["server_id", "string"],
28552
+ ["machine_id", "string"],
28553
+ ["agent_id", "string"],
28554
+ ["launch_id", "string"],
28555
+ ["session_id", "string"],
28556
+ ["request_id", "string"],
28557
+ ["route_pattern", "string"],
28558
+ ["caller_kind", "string"],
28559
+ ["outcome", "string"],
28560
+ ["reason", "string"],
28561
+ ["source", "string"],
28562
+ ["authority", "string"],
28563
+ ["activity_write_site", "string"],
28564
+ ["activity_source", "string"],
28565
+ ["hint_source", "string"],
28566
+ ["resolved_activity", "string"],
28567
+ ["previous_activity", "string"],
28568
+ ["next_activity", "string"],
28569
+ ["repair_kind", "string"],
28570
+ ["action", "string"],
28571
+ ["error_class", "string"],
28572
+ ["status_bucket", "string"],
28573
+ ["shadow_agent_id", "string"],
28574
+ ["shadow_signal_site", "string"],
28575
+ ["shadow_observation_class", "string"],
28576
+ ["shadow_prior_projection", "string"],
28577
+ ["shadow_projection", "string"],
28578
+ ["shadow_legacy_outcome", "string"],
28579
+ ["shadow_action", "string"],
28580
+ ["shadow_reason", "string"],
28581
+ ["shadow_direction", "string"],
28582
+ ["shadow_plan_kind", "string"]
28583
+ ];
28584
+ var TRACE_EVENT_ROW_V2_INGEST_STATEMENT = [
28585
+ "SELECT",
28586
+ TRACE_EVENT_ROW_V2_PROJECTION_COLUMNS.map(([column, type]) => `$0["${column}"]::${type} AS ${column}`).join(", "),
28587
+ "INSERT INTO raft.trace_events_v2",
28588
+ `(${TRACE_EVENT_ROW_V2_PROJECTION_COLUMNS.map(([column]) => column).join(", ")})`
28589
+ ].join(" ");
28525
28590
  var PROMOTED_IDENTITY_ATTRS = [
28526
28591
  "server_id",
28527
28592
  "machine_id",
@@ -42461,7 +42526,7 @@ var integrationAppDraftFieldsSchema = external_exports.object({
42461
42526
  var integrationRegisterAppOperationSchema = integrationAppDraftFieldsSchema.extend({
42462
42527
  type: external_exports.literal("integration:register_app"),
42463
42528
  name: external_exports.string().trim().min(1).max(120),
42464
- clientKey: external_exports.string().trim().min(1).max(120),
42529
+ clientKey: external_exports.string().trim().min(1).max(120).optional(),
42465
42530
  returnUrl: external_exports.string().trim().min(1).max(2e3),
42466
42531
  scopes: external_exports.array(external_exports.string().trim().min(1).max(120)).max(64).default([]),
42467
42532
  unsafeDemoUrlOverride: external_exports.boolean().optional(),
@@ -42895,10 +42960,8 @@ var agentApiIntegrationLoginBodySchema = passthroughObject({
42895
42960
  scopes: optionalStringArraySchema,
42896
42961
  target: optionalStringSchema
42897
42962
  });
42898
- var agentApiIntegrationAppPrepareBodySchema = passthroughObject({
42899
- mode: external_exports.enum(["register", "update"]),
42963
+ var agentApiIntegrationAppPrepareCommonBodyShape = {
42900
42964
  target: external_exports.string().trim().min(1),
42901
- clientKey: external_exports.string().trim().min(1),
42902
42965
  name: optionalStringSchema,
42903
42966
  description: optionalStringSchema,
42904
42967
  homepageUrl: optionalStringSchema,
@@ -42907,7 +42970,19 @@ var agentApiIntegrationAppPrepareBodySchema = passthroughObject({
42907
42970
  scopes: optionalStringArraySchema,
42908
42971
  unsafeDemoUrlOverride: optionalBooleanSchema,
42909
42972
  draftHint: optionalStringSchema
42910
- });
42973
+ };
42974
+ var agentApiIntegrationAppPrepareBodySchema = external_exports.discriminatedUnion("mode", [
42975
+ passthroughObject({
42976
+ mode: external_exports.literal("register"),
42977
+ ...agentApiIntegrationAppPrepareCommonBodyShape,
42978
+ clientKey: optionalStringSchema
42979
+ }),
42980
+ passthroughObject({
42981
+ mode: external_exports.literal("update"),
42982
+ ...agentApiIntegrationAppPrepareCommonBodyShape,
42983
+ clientKey: external_exports.string().trim().min(1)
42984
+ })
42985
+ ]);
42911
42986
  var agentApiIntegrationAppRotateSecretBodySchema = passthroughObject({
42912
42987
  clientKey: external_exports.string().trim().min(1)
42913
42988
  });
@@ -44918,6 +44993,7 @@ init_esm_shims();
44918
44993
  init_esm_shims();
44919
44994
  init_esm_shims();
44920
44995
  init_esm_shims();
44996
+ init_esm_shims();
44921
44997
  var NoopFailpointRegistry = class {
44922
44998
  get enabled() {
44923
44999
  return false;
@@ -50897,6 +50973,7 @@ function formatPendingMentionActions(actions, opts = {}) {
50897
50973
  const lines = opts.source === "send" ? [
50898
50974
  "Undelivered mentions",
50899
50975
  "Message was sent, but these @mentions were not delivered:",
50976
+ "For a literal name rather than a recipient, wrap the @handle in inline or fenced code.",
50900
50977
  ""
50901
50978
  ] : ["Pending mention actions", ""];
50902
50979
  for (const action of actions) {
@@ -50910,7 +50987,7 @@ function formatPendingMentionActions(actions, opts = {}) {
50910
50987
  lines.push(" recovery commands:");
50911
50988
  lines.push(...commands);
50912
50989
  if (commands.some((command) => command.includes(" mention notify "))) {
50913
- lines.push(" note: notify can still report dropped; check the command result before assuming delivery.");
50990
+ lines.push(" note: notify exits nonzero unless the target queue accepts the delivery.");
50914
50991
  }
50915
50992
  }
50916
50993
  }
@@ -51282,12 +51359,19 @@ ${driveByTip}` : "";
51282
51359
  if (pendingMentionActions.length > 0) {
51283
51360
  writeUndeliveredMentionWarning(ctx.io, pendingMentionActions.length);
51284
51361
  }
51362
+ const mentionDeliveryError = pendingMentionActions.length > 0 ? cliError(
51363
+ "MENTION_DELIVERY_FAILED",
51364
+ `Message ${data.messageId} was sent, but ${pendingMentionActions.length} @mention${pendingMentionActions.length === 1 ? " was" : "s were"} not delivered.`,
51365
+ { suggestedNextAction: "Run `raft mention pending` and complete or explicitly resolve every pending mention action." }
51366
+ ) : null;
51285
51367
  if (opts.json) {
51286
51368
  writeJson(ctx.io, data);
51369
+ if (mentionDeliveryError) throw mentionDeliveryError;
51287
51370
  return;
51288
51371
  }
51289
51372
  writeText(ctx.io, `${sentStatusLine}${replyHint}${driveBySection}${mentionSection}${unreadSection}
51290
51373
  `);
51374
+ if (mentionDeliveryError) throw mentionDeliveryError;
51291
51375
  }
51292
51376
  var messageSendCommand = defineCommand(
51293
51377
  {
@@ -52442,6 +52526,17 @@ function registerTaskUpdateCommand(parent, runtimeOptions) {
52442
52526
  }
52443
52527
  init_esm_shims();
52444
52528
  init_esm_shims();
52529
+ function resultSucceeded(action, status) {
52530
+ return action === "notify" ? status === "queued" : status === "delivered";
52531
+ }
52532
+ function formatFailedMentionActions(action, requestedIds, results) {
52533
+ const returnedIds = new Set(results.map((result2) => result2.resolutionId));
52534
+ const failures = results.filter((result2) => !resultSucceeded(action, result2.status)).map((result2) => `${result2.resolutionId}: ${result2.status}${result2.reason ? ` (${result2.reason})` : ""}`);
52535
+ for (const id of requestedIds) {
52536
+ if (!returnedIds.has(id)) failures.push(`${id}: missing_result`);
52537
+ }
52538
+ return failures.length > 0 ? failures.join(", ") : null;
52539
+ }
52445
52540
  function normalizeResolutionIds(rawIds) {
52446
52541
  const ids = (rawIds ?? []).map((id) => id.trim()).filter(Boolean);
52447
52542
  if (ids.length === 0) {
@@ -52469,6 +52564,13 @@ function buildMentionExecuteCommand(action) {
52469
52564
  throw cliError(res.status >= 500 ? "SERVER_5XX" : "MENTION_ACTION_FAILED", res.error ?? `HTTP ${res.status}`);
52470
52565
  }
52471
52566
  const results = normalizeMentionActionResults(res.data);
52567
+ const failure3 = formatFailedMentionActions(action, ids, results);
52568
+ if (failure3) {
52569
+ throw cliError(
52570
+ "MENTION_ACTION_FAILED",
52571
+ `Mention ${action} did not complete for every requested target: ${failure3}`
52572
+ );
52573
+ }
52472
52574
  if (opts.json) {
52473
52575
  writeJson(ctx.io, { ok: true, action, results });
52474
52576
  return;
@@ -54016,7 +54118,7 @@ function optionalTrimmed(value) {
54016
54118
  function formatAppPrepare(data) {
54017
54119
  const lines = [
54018
54120
  `Integration app ${data.mode} card prepared`,
54019
- `client key: ${data.action.clientKey}`,
54121
+ `client key: ${data.action.clientKey ?? "auto-generated on commit"}`,
54020
54122
  `card: ${data.actionCardMessageId}`,
54021
54123
  `target: ${data.target}`
54022
54124
  ];
@@ -54034,14 +54136,11 @@ function formatAppPrepare(data) {
54034
54136
  }
54035
54137
  async function prepareApp(mode, ctx, opts) {
54036
54138
  const target = requiredTrimmed(opts.target, "--target");
54037
- const clientKey = requiredTrimmed(opts.clientKey, "--client-key");
54038
54139
  const scopes = normalizeScopes3([...opts.scope ?? [], ...opts.scopes ?? []]);
54039
54140
  const agentContext = ctx.loadAgentContext();
54040
54141
  const client = ctx.createApiClient(agentContext);
54041
- const body = {
54042
- mode,
54142
+ const commonBody = {
54043
54143
  target,
54044
- clientKey,
54045
54144
  name: optionalTrimmed(opts.name),
54046
54145
  description: optionalTrimmed(opts.description),
54047
54146
  homepageUrl: optionalTrimmed(opts.homepageUrl) ?? optionalTrimmed(opts.appUrl),
@@ -54050,7 +54149,8 @@ async function prepareApp(mode, ctx, opts) {
54050
54149
  scopes,
54051
54150
  unsafeDemoUrlOverride: opts.unsafeDemoUrlOverride === true
54052
54151
  };
54053
- if (mode === "register") {
54152
+ const body = mode === "update" ? { ...commonBody, mode: "update", clientKey: requiredTrimmed(opts.clientKey, "--client-key") } : { ...commonBody, mode: "register", clientKey: optionalTrimmed(opts.clientKey) };
54153
+ if (body.mode === "register") {
54054
54154
  requiredTrimmed(body.name, "--name");
54055
54155
  requiredTrimmed(body.returnUrl, "--redirect-url");
54056
54156
  }
@@ -54229,7 +54329,7 @@ var integrationAppPrepareRecoverOwnerCommand = defineCommand(
54229
54329
  async (ctx, opts) => prepareRecoverOwner(ctx, opts)
54230
54330
  );
54231
54331
  var sharedOptions = [
54232
- { flags: "--client-key <key>", description: "Stable app client key / OAuth client_id to reserve or update" },
54332
+ { flags: "--client-key <key>", description: "Stable app client key / OAuth client_id to reserve or update; register defaults to server-generated" },
54233
54333
  { flags: "--name <name>", description: "App display name" },
54234
54334
  { flags: "--redirect-url <url>", description: "OAuth redirect/callback URL" },
54235
54335
  { flags: "--app-url <url>", description: "App homepage URL" },
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  DAEMON_CLI_USAGE,
4
4
  DaemonCore,
5
5
  parseDaemonCliArgs
6
- } from "./chunk-LHJUHF42.js";
6
+ } from "./chunk-BK46OPUN.js";
7
7
 
8
8
  // src/index.ts
9
9
  var parsedArgs = parseDaemonCliArgs(process.argv.slice(2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botiverse/raft-daemon",
3
- "version": "0.72.12",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "raft-daemon": "dist/raft-daemon.js",