@botiverse/raft-daemon 0.63.5 → 0.63.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,6 +12,7 @@ import os from "os";
12
12
  import path2 from "path";
13
13
  import { fetch as undiciFetch } from "undici";
14
14
  import { fetch as fetch2 } from "undici";
15
+ import { spawn } from "child_process";
15
16
  import { mkdir, readFile, stat, writeFile } from "fs/promises";
16
17
  import path3 from "path";
17
18
  import { fetch as undiciFetch2 } from "undici";
@@ -949,6 +950,55 @@ function delay(ms) {
949
950
  if (ms <= 0) return Promise.resolve();
950
951
  return new Promise((resolve) => setTimeout(resolve, ms));
951
952
  }
953
+ function canInstallEnterToOpenUrl(input) {
954
+ const tty = input;
955
+ return Boolean(tty?.isTTY === true && typeof tty.on === "function" && typeof tty.off === "function");
956
+ }
957
+ function openUrlInBrowser(url2) {
958
+ const platform = process.platform;
959
+ let command;
960
+ let args;
961
+ if (platform === "darwin") {
962
+ command = "open";
963
+ args = [url2];
964
+ } else if (platform === "win32") {
965
+ command = "cmd";
966
+ args = ["/c", "start", "", url2];
967
+ } else {
968
+ command = "xdg-open";
969
+ args = [url2];
970
+ }
971
+ const child = spawn(command, args, {
972
+ detached: true,
973
+ stdio: "ignore",
974
+ windowsHide: true
975
+ });
976
+ child.on("error", () => {
977
+ });
978
+ child.unref();
979
+ }
980
+ function installEnterToOpenUrl(options) {
981
+ if (!canInstallEnterToOpenUrl(options.input)) return () => {
982
+ };
983
+ const input = options.input;
984
+ const openUrl = options.openUrl ?? openUrlInBrowser;
985
+ let active = true;
986
+ const cleanup = () => {
987
+ if (!active) return;
988
+ active = false;
989
+ input.off("data", onData);
990
+ input.pause?.();
991
+ };
992
+ const onData = (chunk) => {
993
+ const text = Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk);
994
+ if (!text.includes("\n") && !text.includes("\r")) return;
995
+ cleanup();
996
+ openUrl(options.url);
997
+ };
998
+ input.on("data", onData);
999
+ input.resume?.();
1000
+ return cleanup;
1001
+ }
952
1002
  function describeListResult(reason, serverUrl) {
953
1003
  switch (reason) {
954
1004
  case "ok":
@@ -973,15 +1023,25 @@ var agentListCommand = defineCommand(
973
1023
  throw cliError("INVALID_ARG", "--server is required");
974
1024
  }
975
1025
  let userSession;
1026
+ let cleanupEnterToOpen;
976
1027
  try {
977
1028
  userSession = await runDeviceCodeLogin({
978
1029
  serverUrl: options.server,
979
1030
  ...options.clientName ? { clientName: options.clientName } : {},
980
- onUserAction: ({ verificationUri, userCode, expiresInSeconds }) => {
1031
+ onUserAction: ({ verificationUri, verificationUriComplete, userCode, expiresInSeconds }) => {
1032
+ const enterOpensBrowser = canInstallEnterToOpenUrl(ctx.io.stdin);
1033
+ const url2 = verificationUriComplete ?? verificationUri;
981
1034
  ctx.io.stderr.write(
982
- `Open ${verificationUri} in your browser, enter code ${userCode} (expires in ~${Math.max(0, Math.floor(expiresInSeconds / 60))}m).
1035
+ (enterOpensBrowser ? `Press Enter to open the browser authorization URL: ${url2}
1036
+ ` : `Open this browser authorization URL: ${url2}
1037
+ `) + (verificationUriComplete ? ` Code is pre-filled. Approve the login in the browser; this command will continue automatically.
1038
+ ` : ` Enter code ${userCode} and approve the login in the browser; this command will continue automatically.
1039
+ `) + ` Expires in ~${Math.max(0, Math.floor(expiresInSeconds / 60))}m.
983
1040
  `
984
1041
  );
1042
+ if (enterOpensBrowser) {
1043
+ cleanupEnterToOpen = installEnterToOpenUrl({ input: ctx.io.stdin, url: url2 });
1044
+ }
985
1045
  }
986
1046
  });
987
1047
  } catch (err) {
@@ -989,6 +1049,8 @@ var agentListCommand = defineCommand(
989
1049
  throw cliError(err.code, err.message, { cause: err });
990
1050
  }
991
1051
  throw err;
1052
+ } finally {
1053
+ cleanupEnterToOpen?.();
992
1054
  }
993
1055
  const res = await undiciFetch(
994
1056
  `${options.server.replace(/\/+$/, "")}/api/agents/manageable`,
@@ -1078,16 +1140,26 @@ var agentLoginCommand = defineCommand(
1078
1140
  const idempotent = await handleExistingCredential(ctx, options, paths);
1079
1141
  if (idempotent === "handled") return;
1080
1142
  let userSession;
1143
+ let cleanupEnterToOpen;
1081
1144
  try {
1082
1145
  userSession = await runDeviceCodeLogin({
1083
1146
  serverUrl: options.server,
1084
1147
  ...options.clientName ? { clientName: options.clientName } : {},
1085
1148
  onUserAction: (action) => {
1086
- ctx.io.stderr.write(formatVerificationHandoff(action));
1149
+ const enterOpensBrowser = canInstallEnterToOpenUrl(ctx.io.stdin);
1150
+ ctx.io.stderr.write(formatVerificationHandoff(action, { enterOpensBrowser }));
1151
+ if (enterOpensBrowser) {
1152
+ cleanupEnterToOpen = installEnterToOpenUrl({
1153
+ input: ctx.io.stdin,
1154
+ url: action.verificationUriComplete ?? action.verificationUri
1155
+ });
1156
+ }
1087
1157
  }
1088
1158
  });
1089
1159
  } catch (err) {
1090
1160
  throw asCliError(err);
1161
+ } finally {
1162
+ cleanupEnterToOpen?.();
1091
1163
  }
1092
1164
  await mintAndPersist(ctx, options, userSession.accessToken, paths);
1093
1165
  }
@@ -1286,14 +1358,19 @@ Next (if you are the agent): run \`raft manual get raft-cli-overview\`, then use
1286
1358
  `
1287
1359
  );
1288
1360
  }
1289
- function formatVerificationHandoff(action) {
1361
+ function formatVerificationHandoff(action, options) {
1290
1362
  const mins = Math.max(0, Math.floor(action.expiresInSeconds / 60));
1363
+ const url2 = action.verificationUriComplete ?? action.verificationUri;
1364
+ const openLine = options.enterOpensBrowser ? `Press Enter to open the browser authorization URL: ${url2}
1365
+ ` : `Open this browser authorization URL: ${url2}
1366
+ `;
1291
1367
  if (action.verificationUriComplete) {
1292
- return `Open this link to approve (code pre-filled): ${action.verificationUriComplete}
1368
+ return openLine + ` Code is pre-filled. Approve the login in the browser; this command will continue automatically.
1293
1369
  Expires in ~${mins}m.
1294
1370
  `;
1295
1371
  }
1296
- return `Open ${action.verificationUri} in your browser, enter code ${action.userCode} (expires in ~${mins}m).
1372
+ return openLine + ` Enter code ${action.userCode} and approve the login in the browser; this command will continue automatically.
1373
+ Expires in ~${mins}m.
1297
1374
  `;
1298
1375
  }
1299
1376
  function formatStartHandoff(authorization, options, paths) {
@@ -1303,10 +1380,12 @@ function formatStartHandoff(authorization, options, paths) {
1303
1380
  out += `Login started for profile '${paths.profileSlug}'. Ask the user to approve in a browser:
1304
1381
  `;
1305
1382
  if (authorization.verificationUriComplete) {
1306
- out += ` Open this link (code pre-filled): ${authorization.verificationUriComplete}
1383
+ out += ` Browser authorization URL (code pre-filled): ${authorization.verificationUriComplete}
1307
1384
  `;
1308
1385
  } else {
1309
- out += ` Open ${authorization.verificationUri} and enter code ${authorization.userCode}.
1386
+ out += ` Browser authorization URL: ${authorization.verificationUri}
1387
+ `;
1388
+ out += ` Enter code ${authorization.userCode} and approve the login.
1310
1389
  `;
1311
1390
  }
1312
1391
  out += ` Code expires in ~${mins}m.
@@ -1462,6 +1541,68 @@ function makeIsMember(members) {
1462
1541
  const set2 = new Set(members);
1463
1542
  return (value) => typeof value === "string" && set2.has(value);
1464
1543
  }
1544
+ var RUNTIME_PROVIDER_DISPLAY_NAMES = {
1545
+ "anthropic": "Anthropic",
1546
+ "deepseek": "DeepSeek",
1547
+ "fusecode": "FuseCode",
1548
+ "google": "Google",
1549
+ "openai": "OpenAI",
1550
+ "opencode": "OpenCode",
1551
+ "opencode-go": "OpenCode Go",
1552
+ "openrouter": "OpenRouter"
1553
+ };
1554
+ function getRuntimeProviderDisplayName(providerId) {
1555
+ return RUNTIME_PROVIDER_DISPLAY_NAMES[providerId] ?? humanizeRuntimeProviderSegment(providerId);
1556
+ }
1557
+ function formatRuntimeProviderModelLabel(modelId) {
1558
+ const separatorIndex = modelId.indexOf("/");
1559
+ if (separatorIndex <= 0 || separatorIndex === modelId.length - 1) return modelId;
1560
+ const providerId = modelId.slice(0, separatorIndex);
1561
+ const modelName = modelId.slice(separatorIndex + 1);
1562
+ const providerLabel = getRuntimeProviderDisplayName(providerId);
1563
+ const modelParts = modelName.split("/");
1564
+ const modelLabel = humanizeRuntimeProviderSegment(modelParts[modelParts.length - 1] || modelName);
1565
+ if (modelParts.length === 1) return `${modelLabel} \xB7 ${providerLabel}`;
1566
+ const upstreamLabel = modelParts.slice(0, -1).map(getRuntimeProviderDisplayName).join(" / ");
1567
+ return `${modelLabel} \xB7 ${upstreamLabel} via ${providerLabel}`;
1568
+ }
1569
+ function humanizeRuntimeProviderSegment(value) {
1570
+ return value.replace(/\[(\d+)m\]/gi, "-$1m").split(/[-_/]/).filter(Boolean).map(formatRuntimeProviderLabelToken).join(" ");
1571
+ }
1572
+ function formatRuntimeProviderLabelToken(token) {
1573
+ const normalized = token.toLowerCase();
1574
+ const specialCases = {
1575
+ ai: "AI",
1576
+ api: "API",
1577
+ chatgpt: "ChatGPT",
1578
+ claude: "Claude",
1579
+ codestral: "Codestral",
1580
+ deepseek: "DeepSeek",
1581
+ flash: "Flash",
1582
+ free: "Free",
1583
+ gemini: "Gemini",
1584
+ glm: "GLM",
1585
+ gpt: "GPT",
1586
+ hy3: "HY3",
1587
+ kimi: "Kimi",
1588
+ minimax: "MiniMax",
1589
+ nano: "Nano",
1590
+ nemotron: "Nemotron",
1591
+ omni: "Omni",
1592
+ opus: "Opus",
1593
+ pro: "Pro",
1594
+ sonnet: "Sonnet",
1595
+ super: "Super"
1596
+ };
1597
+ if (specialCases[normalized]) return specialCases[normalized];
1598
+ if (normalized === "b" || normalized === "m") return normalized.toUpperCase();
1599
+ if (/^v\d+(\.\d+)?$/.test(normalized)) return normalized.toUpperCase();
1600
+ if (/^\d+m$/i.test(token)) return token.toUpperCase();
1601
+ if (/^\d+[bk]$/i.test(token)) return token.toUpperCase();
1602
+ if (/^m\d+(\.\d+)?$/i.test(token)) return token.toUpperCase();
1603
+ if (/^\d/.test(token)) return token;
1604
+ return normalized.charAt(0).toUpperCase() + normalized.slice(1);
1605
+ }
1465
1606
  var SLOCK_REF_CHANNEL_NAME_PATTERN = String.raw`[\p{L}\p{N}_-]+`;
1466
1607
  var SLOCK_REF_USER_NAME_PATTERN = SLOCK_REF_CHANNEL_NAME_PATTERN;
1467
1608
  var SLOCK_REF_DM_PEER_PATTERN = String.raw`[\w-]+`;
@@ -15259,11 +15400,36 @@ var integrationApproveAgentLoginOperationSchema = external_exports.object({
15259
15400
  scopes: external_exports.array(external_exports.string().trim().min(1).max(120)).max(64),
15260
15401
  draftHint: draftHintSchema
15261
15402
  });
15403
+ var integrationAppDraftFieldsSchema = external_exports.object({
15404
+ name: external_exports.string().trim().min(1).max(120).optional(),
15405
+ description: external_exports.string().trim().max(1e3).optional(),
15406
+ homepageUrl: external_exports.string().trim().max(2e3).optional(),
15407
+ returnUrl: external_exports.string().trim().max(2e3).optional(),
15408
+ agentManifestUrl: external_exports.string().trim().max(2e3).optional()
15409
+ });
15410
+ var integrationRegisterAppOperationSchema = integrationAppDraftFieldsSchema.extend({
15411
+ type: external_exports.literal("integration:register_app"),
15412
+ name: external_exports.string().trim().min(1).max(120),
15413
+ clientKey: external_exports.string().trim().min(1).max(120),
15414
+ returnUrl: external_exports.string().trim().min(1).max(2e3),
15415
+ scopes: external_exports.array(external_exports.string().trim().min(1).max(120)).max(64).default([]),
15416
+ unsafeDemoUrlOverride: external_exports.boolean().optional(),
15417
+ draftHint: draftHintSchema
15418
+ });
15419
+ var integrationUpdateAppRegistrationOperationSchema = integrationAppDraftFieldsSchema.extend({
15420
+ type: external_exports.literal("integration:update_app_registration"),
15421
+ clientKey: external_exports.string().trim().min(1).max(120),
15422
+ scopes: external_exports.array(external_exports.string().trim().min(1).max(120)).max(64).optional(),
15423
+ unsafeDemoUrlOverride: external_exports.boolean().optional(),
15424
+ draftHint: draftHintSchema
15425
+ });
15262
15426
  var actionCardActionSchema = external_exports.discriminatedUnion("type", [
15263
15427
  channelCreateOperationSchema,
15264
15428
  agentCreateOperationSchema,
15265
15429
  channelAddMemberOperationSchema,
15266
- integrationApproveAgentLoginOperationSchema
15430
+ integrationApproveAgentLoginOperationSchema,
15431
+ integrationRegisterAppOperationSchema,
15432
+ integrationUpdateAppRegistrationOperationSchema
15267
15433
  ]);
15268
15434
  function validateActionCardAction(action) {
15269
15435
  if (action.type === "agent:create") {
@@ -15277,6 +15443,12 @@ function validateActionCardAction(action) {
15277
15443
  return "channel:add_member must include at least one human or agent";
15278
15444
  }
15279
15445
  }
15446
+ if (action.type === "integration:update_app_registration") {
15447
+ const hasMetadataPatch = action.name !== void 0 || action.description !== void 0 || action.homepageUrl !== void 0 || action.returnUrl !== void 0 || action.agentManifestUrl !== void 0 || action.scopes !== void 0;
15448
+ if (!hasMetadataPatch) {
15449
+ return "integration:update_app_registration must include at least one field to update";
15450
+ }
15451
+ }
15280
15452
  return null;
15281
15453
  }
15282
15454
  function formatAgentInboxSnapshot(rows) {
@@ -15622,9 +15794,9 @@ var RUNTIME_MODELS = {
15622
15794
  ],
15623
15795
  opencode: [
15624
15796
  { id: "default", label: "Configured Default / Auto", verified: "suggestion_only" },
15625
- { id: "deepseek/deepseek-v4-pro", label: "DeepSeek V4 Pro (OpenCode)", verified: "suggestion_only" },
15626
- { id: "openrouter/anthropic/claude-opus-4.5", label: "Claude Opus 4.5 via OpenRouter", verified: "suggestion_only" },
15627
- { id: "fusecode/opus[1m]", label: "Opus 1M via FuseCode", verified: "suggestion_only" }
15797
+ { id: "deepseek/deepseek-v4-pro", label: formatRuntimeProviderModelLabel("deepseek/deepseek-v4-pro"), verified: "suggestion_only" },
15798
+ { id: "openrouter/anthropic/claude-opus-4.5", label: formatRuntimeProviderModelLabel("openrouter/anthropic/claude-opus-4.5"), verified: "suggestion_only" },
15799
+ { id: "fusecode/opus[1m]", label: formatRuntimeProviderModelLabel("fusecode/opus[1m]"), verified: "suggestion_only" }
15628
15800
  ],
15629
15801
  pi: [
15630
15802
  { id: "default", label: "Configured Default / Auto", verified: "suggestion_only" }
@@ -15658,6 +15830,11 @@ var CONTROLLED_RUNTIME_ENV_KEYS = {
15658
15830
  // this list in sync as new providers are added.
15659
15831
  pi: Object.values(PI_BUILTIN_PROVIDER_ENV_KEYS)
15660
15832
  };
15833
+ var PRO_SEAT_MONTHLY_USD = 10;
15834
+ var PRO_AGENT_SEAT_BLOCK_SIZE = 10;
15835
+ var PRO_AGENT_SEAT_FRACTION = 1 / PRO_AGENT_SEAT_BLOCK_SIZE;
15836
+ var PRO_SEAT_ANNUAL_MONTHLY_USD = 8.8;
15837
+ var PRO_PACK_AGENT_SEATS = PRO_AGENT_SEAT_BLOCK_SIZE;
15661
15838
  var PLAN_CONFIG = {
15662
15839
  free: {
15663
15840
  displayName: "Free",
@@ -15684,9 +15861,9 @@ var PLAN_CONFIG = {
15684
15861
  },
15685
15862
  pro: {
15686
15863
  displayName: "Pro",
15687
- limits: { maxMachines: -1, maxAgents: 10, maxChannels: -1, messageHistoryDays: -1, includedAgents: 10 },
15864
+ limits: { maxMachines: -1, maxAgents: PRO_PACK_AGENT_SEATS, maxChannels: -1, messageHistoryDays: -1, includedAgents: PRO_PACK_AGENT_SEATS },
15688
15865
  comingSoon: false,
15689
- price: 20,
15866
+ price: PRO_SEAT_MONTHLY_USD,
15690
15867
  extraAgentPrice: 0
15691
15868
  }
15692
15869
  };
@@ -15696,8 +15873,8 @@ var DISPLAY_PLAN_CONFIG = {
15696
15873
  displayName: "Pro",
15697
15874
  limits: { maxMachines: -1, maxAgents: -1, maxChannels: -1, messageHistoryDays: -1, includedAgents: -1 },
15698
15875
  comingSoon: false,
15699
- price: 20,
15700
- priceCadence: "/ seat pack / month",
15876
+ price: PRO_SEAT_MONTHLY_USD,
15877
+ priceCadence: "/ seat / month",
15701
15878
  extraAgentPrice: 0,
15702
15879
  displayFeatures: [
15703
15880
  "Everything in Free",
@@ -15707,7 +15884,7 @@ var DISPLAY_PLAN_CONFIG = {
15707
15884
  "More professional features coming soon"
15708
15885
  ],
15709
15886
  displayDescription: "For builders and teams scaling agent collaboration.",
15710
- displayNote: "$17.60 / seat pack / month when billed yearly"
15887
+ displayNote: `$${PRO_SEAT_ANNUAL_MONTHLY_USD.toFixed(2)} / seat / month when billed yearly. Each human uses 1 seat; each agent uses ${PRO_AGENT_SEAT_FRACTION} seat.`
15711
15888
  },
15712
15889
  enterprise: {
15713
15890
  displayName: "Enterprise",
@@ -17033,7 +17210,7 @@ var actionPrepareCommand = defineCommand(
17033
17210
  options: [
17034
17211
  {
17035
17212
  flags: "--target <target>",
17036
- description: "Channel/DM/thread target to post the card. Same format as raft message send: '#channel', 'dm:@peer', '#channel:shortid'"
17213
+ description: "Channel/DM/thread target to post the card. Same format as raft message send: '#channel', 'dm:@peer', '#channel:shortid', 'dm:@peer:shortid'"
17037
17214
  }
17038
17215
  ]
17039
17216
  },
@@ -18849,8 +19026,10 @@ var attachmentUploadCommand = defineCommand(
18849
19026
  form
18850
19027
  );
18851
19028
  if (!res.ok) {
18852
- const code = res.status >= 500 ? "SERVER_5XX" : "UPLOAD_FAILED";
18853
- throw cliError(code, res.error ?? `HTTP ${res.status}`);
19029
+ const code = res.errorCode ?? (res.status >= 500 ? "SERVER_5XX" : "UPLOAD_FAILED");
19030
+ throw cliError(code, res.error ?? `HTTP ${res.status}`, {
19031
+ suggestedNextAction: res.suggestedNextAction ?? void 0
19032
+ });
18854
19033
  }
18855
19034
  const d = res.data;
18856
19035
  writeText(ctx.io, `File uploaded: ${d.filename} (${(d.sizeBytes / 1024).toFixed(1)}KB)
@@ -20226,6 +20405,129 @@ var integrationEnvCommand = defineCommand(
20226
20405
  function registerIntegrationEnvCommand(parent, runtimeOptions = {}) {
20227
20406
  registerCliCommand(parent, integrationEnvCommand, runtimeOptions);
20228
20407
  }
20408
+ function normalizeScopes2(raw) {
20409
+ if (!raw || raw.length === 0) return void 0;
20410
+ const scopes = Array.from(new Set(
20411
+ raw.flatMap((value) => value.split(",")).map((value) => value.trim()).filter(Boolean)
20412
+ )).sort();
20413
+ if (scopes.length === 0) {
20414
+ throw cliError("INVALID_ARG", "--scope must include at least one non-empty scope");
20415
+ }
20416
+ return scopes;
20417
+ }
20418
+ function requiredTrimmed(value, flag) {
20419
+ const trimmed = value?.trim() ?? "";
20420
+ if (!trimmed) throw cliError("INVALID_ARG", `${flag} is required`);
20421
+ return trimmed;
20422
+ }
20423
+ function optionalTrimmed(value) {
20424
+ return value?.trim() || void 0;
20425
+ }
20426
+ function formatAppPrepare(data) {
20427
+ const lines = [
20428
+ `Integration app ${data.mode} card prepared`,
20429
+ `client key: ${data.action.clientKey}`,
20430
+ `card: ${data.actionCardMessageId}`,
20431
+ `target: ${data.target}`
20432
+ ];
20433
+ if (data.action.name) lines.push(`name: ${data.action.name}`);
20434
+ if (data.action.homepageUrl) lines.push(`app URL: ${data.action.homepageUrl}`);
20435
+ if (data.action.returnUrl) lines.push(`redirect URL: ${data.action.returnUrl}`);
20436
+ if (data.action.agentManifestUrl) lines.push(`agent manifest: ${data.action.agentManifestUrl}`);
20437
+ if (data.action.scopes) lines.push(`scopes: ${data.action.scopes.length > 0 ? data.action.scopes.join(", ") : "-"}`);
20438
+ if (data.action.unsafeDemoUrlOverride) lines.push("unsafe demo URL override: requested");
20439
+ lines.push("next: ask a server owner/admin to review and execute the action card");
20440
+ lines.push("secret: not stored in the card; after owner/admin execution, the requester agent receives a private one-time handoff");
20441
+ return lines.join("\n");
20442
+ }
20443
+ async function prepareApp(mode, ctx, opts) {
20444
+ const target = requiredTrimmed(opts.target, "--target");
20445
+ const clientKey = requiredTrimmed(opts.clientKey, "--client-key");
20446
+ const scopes = normalizeScopes2([...opts.scope ?? [], ...opts.scopes ?? []]);
20447
+ const agentContext = ctx.loadAgentContext();
20448
+ const client = ctx.createApiClient(agentContext);
20449
+ const body = {
20450
+ mode,
20451
+ target,
20452
+ clientKey,
20453
+ name: optionalTrimmed(opts.name),
20454
+ description: optionalTrimmed(opts.description),
20455
+ homepageUrl: optionalTrimmed(opts.homepageUrl) ?? optionalTrimmed(opts.appUrl),
20456
+ returnUrl: optionalTrimmed(opts.redirectUrl),
20457
+ agentManifestUrl: optionalTrimmed(opts.agentManifestUrl),
20458
+ scopes,
20459
+ unsafeDemoUrlOverride: opts.unsafeDemoUrlOverride === true
20460
+ };
20461
+ if (mode === "register") {
20462
+ requiredTrimmed(body.name, "--name");
20463
+ requiredTrimmed(body.returnUrl, "--redirect-url");
20464
+ }
20465
+ const res = await client.request(
20466
+ "POST",
20467
+ `/internal/agent/${encodeURIComponent(agentContext.agentId)}/integrations/app/prepare`,
20468
+ body
20469
+ );
20470
+ if (!res.ok || !res.data) {
20471
+ const code = res.status >= 500 ? "SERVER_5XX" : "INTEGRATION_APP_PREPARE_FAILED";
20472
+ throw cliError(code, res.error ?? `HTTP ${res.status}`);
20473
+ }
20474
+ if (opts.json) {
20475
+ writeJson(ctx.io, { ok: true, data: res.data });
20476
+ return;
20477
+ }
20478
+ writeText(ctx.io, `${formatAppPrepare(res.data)}
20479
+ `);
20480
+ }
20481
+ var sharedOptions = [
20482
+ { flags: "--client-key <key>", description: "Stable app client key / OAuth client_id to reserve or update" },
20483
+ { flags: "--name <name>", description: "App display name" },
20484
+ { flags: "--redirect-url <url>", description: "OAuth redirect/callback URL" },
20485
+ { flags: "--app-url <url>", description: "App homepage URL" },
20486
+ { flags: "--homepage-url <url>", description: "App homepage URL (alias-friendly explicit name)" },
20487
+ { flags: "--description <text>", description: "App description" },
20488
+ { flags: "--agent-manifest-url <url>", description: "Optional agent behavior manifest URL" },
20489
+ {
20490
+ flags: "--scope <scope>",
20491
+ description: "Requested/displayed scope; can be repeated or comma-separated",
20492
+ parse: (value, previous = []) => {
20493
+ previous.push(value);
20494
+ return previous;
20495
+ }
20496
+ },
20497
+ {
20498
+ flags: "--scopes <scopes>",
20499
+ description: "Requested/displayed scopes; alias for --scope, comma-separated",
20500
+ parse: (value, previous = []) => {
20501
+ previous.push(value);
20502
+ return previous;
20503
+ }
20504
+ },
20505
+ { flags: "--unsafe-demo-url-override", description: "Explicitly mark localhost/private URL use as an unsafe demo override" },
20506
+ { flags: "--target <target>", description: "Channel/DM/thread target to post the human action card" },
20507
+ { flags: "--json", description: "Emit machine-readable JSON" }
20508
+ ];
20509
+ var integrationAppPrepareRegisterCommand = defineCommand(
20510
+ {
20511
+ name: "register",
20512
+ description: "Prepare a third-party app registration action card for a human owner/admin to commit",
20513
+ options: sharedOptions
20514
+ },
20515
+ async (ctx, opts) => prepareApp("register", ctx, opts)
20516
+ );
20517
+ var integrationAppPrepareUpdateCommand = defineCommand(
20518
+ {
20519
+ name: "update",
20520
+ description: "Prepare a third-party app registration update action card for a human owner/admin to commit",
20521
+ options: sharedOptions
20522
+ },
20523
+ async (ctx, opts) => prepareApp("update", ctx, opts)
20524
+ );
20525
+ function registerIntegrationAppCommands(parent, runtimeOptions = {}) {
20526
+ const appCmd = parent.command("app").description("Third-party app registration preparation");
20527
+ const prepareCmd = appCmd.command("prepare").description("Prepare app registration/update action cards");
20528
+ registerCliCommand(prepareCmd, integrationAppPrepareRegisterCommand, runtimeOptions);
20529
+ registerCliCommand(prepareCmd, integrationAppPrepareUpdateCommand, runtimeOptions);
20530
+ }
20229
20531
  var MODIFY_HINT = "(to modify: snooze/update/cancel; raft reminder --help)";
20230
20532
  function formatReminder(r) {
20231
20533
  const ref = r.msgRef ? ` ref=${r.msgRef}` : "";
@@ -20663,6 +20965,7 @@ var integrationCmd = program.command("integration").description("Third-party ser
20663
20965
  registerIntegrationListCommand(integrationCmd);
20664
20966
  registerIntegrationLoginCommand(integrationCmd);
20665
20967
  registerIntegrationEnvCommand(integrationCmd);
20968
+ registerIntegrationAppCommands(integrationCmd);
20666
20969
  var reminderCmd = program.command("reminder").description("Reminder operations");
20667
20970
  registerReminderScheduleCommand(reminderCmd);
20668
20971
  registerReminderListCommand(reminderCmd);
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  DAEMON_CLI_USAGE,
4
4
  DaemonCore,
5
5
  parseDaemonCliArgs
6
- } from "./chunk-DZ25KV6L.js";
6
+ } from "./chunk-DUWRNQQE.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.63.5",
3
+ "version": "0.63.6",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "raft-daemon": "dist/raft-daemon.js",
@@ -62,6 +62,7 @@
62
62
  "@slock-ai/trace-client": "workspace:*",
63
63
  "@types/node": "^25.5.0",
64
64
  "@types/ws": "^8.18.1",
65
+ "fast-check": "^4.8.0",
65
66
  "tsup": "^8.5.1",
66
67
  "typescript": "^5.9.3"
67
68
  }