nolo-cli 0.1.55 → 0.1.56

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.
Files changed (2) hide show
  1. package/index.js +1635 -358
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1306,66 +1306,158 @@ async function connectCliAuthorityBroker(args2) {
1306
1306
  ...defaultCliAuthorityBrokerConnectDeps,
1307
1307
  ...args2.deps
1308
1308
  };
1309
- const client = deps.createClient({
1310
- endpoint: args2.endpoint,
1311
- invoke: createCliAuthorityBrokerSocketInvoker({ endpoint: args2.endpoint })
1312
- });
1313
- async function attachToExistingBroker(attempts) {
1314
- for (let attempt = 0; attempt < attempts; attempt += 1) {
1315
- await deps.sleep(100);
1316
- try {
1317
- await client.open();
1318
- return true;
1319
- } catch (error) {
1320
- if (!isCliAuthorityBrokerUnavailableError(error)) throw error;
1321
- }
1322
- }
1323
- return false;
1324
- }
1325
- try {
1326
- await deps.startBroker({
1309
+ async function connectClient() {
1310
+ const client2 = deps.createClient({
1327
1311
  endpoint: args2.endpoint,
1328
- metadataPath: args2.metadataPath,
1329
- healthPath: args2.healthPath,
1330
- createStore: () => createLevelAuthorityStore(args2.dbPath)
1312
+ invoke: createCliAuthorityBrokerSocketInvoker({ endpoint: args2.endpoint })
1331
1313
  });
1332
- await client.open();
1333
- return client;
1334
- } catch (error) {
1335
- if (!isCliAuthorityLockError(error)) throw error;
1336
- if (await attachToExistingBroker(5)) {
1337
- return client;
1314
+ async function attachToExistingBroker(attempts) {
1315
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
1316
+ await deps.sleep(100);
1317
+ try {
1318
+ await client2.open();
1319
+ return true;
1320
+ } catch (error) {
1321
+ if (!isCliAuthorityBrokerUnavailableError(error)) throw error;
1322
+ }
1323
+ }
1324
+ return false;
1338
1325
  }
1339
- let lastError = error;
1340
- for (let attempt = 0; attempt < 5; attempt += 1) {
1341
- await deps.sleep(100);
1342
- try {
1343
- await deps.startBroker({
1344
- endpoint: args2.endpoint,
1345
- metadataPath: args2.metadataPath,
1346
- healthPath: args2.healthPath,
1347
- createStore: () => createLevelAuthorityStore(args2.dbPath)
1348
- });
1349
- await client.open();
1350
- return client;
1351
- } catch (retryError) {
1352
- lastError = retryError;
1353
- if (isCliAuthorityLockError(retryError)) {
1354
- if (await attachToExistingBroker(2)) {
1355
- return client;
1326
+ try {
1327
+ await deps.startBroker({
1328
+ endpoint: args2.endpoint,
1329
+ metadataPath: args2.metadataPath,
1330
+ healthPath: args2.healthPath,
1331
+ createStore: () => createLevelAuthorityStore(args2.dbPath)
1332
+ });
1333
+ await client2.open();
1334
+ return client2;
1335
+ } catch (error) {
1336
+ if (!isCliAuthorityLockError(error)) throw error;
1337
+ if (await attachToExistingBroker(5)) {
1338
+ return client2;
1339
+ }
1340
+ let lastError = error;
1341
+ for (let attempt = 0; attempt < 5; attempt += 1) {
1342
+ await deps.sleep(100);
1343
+ try {
1344
+ await deps.startBroker({
1345
+ endpoint: args2.endpoint,
1346
+ metadataPath: args2.metadataPath,
1347
+ healthPath: args2.healthPath,
1348
+ createStore: () => createLevelAuthorityStore(args2.dbPath)
1349
+ });
1350
+ await client2.open();
1351
+ return client2;
1352
+ } catch (retryError) {
1353
+ lastError = retryError;
1354
+ if (isCliAuthorityLockError(retryError)) {
1355
+ if (await attachToExistingBroker(2)) {
1356
+ return client2;
1357
+ }
1358
+ continue;
1356
1359
  }
1357
- continue;
1358
- }
1359
- if (isCliAuthorityBrokerUnavailableError(retryError)) {
1360
- continue;
1360
+ if (isCliAuthorityBrokerUnavailableError(retryError)) {
1361
+ continue;
1362
+ }
1363
+ throw retryError;
1361
1364
  }
1362
- throw retryError;
1363
1365
  }
1366
+ throw new Error(`CLI authority broker could not attach or take ownership for ${args2.endpoint}`, {
1367
+ cause: lastError
1368
+ });
1369
+ }
1370
+ }
1371
+ let client = await connectClient();
1372
+ let reconnecting = null;
1373
+ async function reconnect() {
1374
+ reconnecting ??= connectClient();
1375
+ try {
1376
+ client = await reconnecting;
1377
+ return client;
1378
+ } finally {
1379
+ reconnecting = null;
1364
1380
  }
1365
- throw new Error(`CLI authority broker could not attach or take ownership for ${args2.endpoint}`, {
1366
- cause: lastError
1367
- });
1368
1381
  }
1382
+ async function runWithSelfHealing(operation) {
1383
+ try {
1384
+ return await operation(client);
1385
+ } catch (error) {
1386
+ if (!isCliAuthorityBrokerUnavailableError(error)) throw error;
1387
+ const recoveredClient = await reconnect();
1388
+ return operation(recoveredClient);
1389
+ }
1390
+ }
1391
+ return {
1392
+ get location() {
1393
+ return client.location;
1394
+ },
1395
+ get status() {
1396
+ return client.status;
1397
+ },
1398
+ open: () => runWithSelfHealing((activeClient) => activeClient.open()),
1399
+ close: () => runWithSelfHealing((activeClient) => activeClient.close()),
1400
+ get: (key) => runWithSelfHealing((activeClient) => activeClient.get(key)),
1401
+ put: (key, value) => runWithSelfHealing((activeClient) => activeClient.put(key, value)),
1402
+ del: (key) => runWithSelfHealing((activeClient) => activeClient.del(key)),
1403
+ batchWrite: (ops) => runWithSelfHealing((activeClient) => activeClient.batchWrite(ops)),
1404
+ createBatch() {
1405
+ const ops = [];
1406
+ return {
1407
+ put(key, value) {
1408
+ ops.push({ type: "put", key, value });
1409
+ },
1410
+ del(key) {
1411
+ ops.push({ type: "del", key });
1412
+ },
1413
+ write: () => runWithSelfHealing((activeClient) => activeClient.batchWrite(ops))
1414
+ };
1415
+ },
1416
+ iterator(options = {}) {
1417
+ return async function* iterate() {
1418
+ let activeOptions = options;
1419
+ let lastYieldedKey;
1420
+ let skipResumeKey = false;
1421
+ let recovered = false;
1422
+ while (true) {
1423
+ try {
1424
+ for await (const entry of client.iterator(activeOptions)) {
1425
+ if (skipResumeKey && entry[0] === lastYieldedKey) {
1426
+ skipResumeKey = false;
1427
+ continue;
1428
+ }
1429
+ skipResumeKey = false;
1430
+ lastYieldedKey = entry[0];
1431
+ yield entry;
1432
+ }
1433
+ return;
1434
+ } catch (error) {
1435
+ if (recovered || !isCliAuthorityBrokerUnavailableError(error)) {
1436
+ throw error;
1437
+ }
1438
+ recovered = true;
1439
+ await reconnect();
1440
+ if (lastYieldedKey === void 0) {
1441
+ activeOptions = options;
1442
+ continue;
1443
+ }
1444
+ if (options.reverse) {
1445
+ activeOptions = {
1446
+ ...options,
1447
+ lt: lastYieldedKey
1448
+ };
1449
+ continue;
1450
+ }
1451
+ activeOptions = {
1452
+ ...options,
1453
+ gte: lastYieldedKey
1454
+ };
1455
+ skipResumeKey = true;
1456
+ }
1457
+ }
1458
+ }();
1459
+ }
1460
+ };
1369
1461
  }
1370
1462
  async function getDefaultCliLocalRuntimeAuthority(options = {}) {
1371
1463
  const env = options.env ?? process.env;
@@ -1602,7 +1694,6 @@ var init_keys = __esm({
1602
1694
  "packages/share/keys.ts"() {
1603
1695
  "use strict";
1604
1696
  init_keys2();
1605
- init_types();
1606
1697
  init_toTrimmedString();
1607
1698
  init_userId();
1608
1699
  init_helpers();
@@ -5025,9 +5116,9 @@ function buildAgentRuntimeDialogWritePlan(args2) {
5025
5116
  existingDialog: args2.existingDialog,
5026
5117
  messages: args2.input.messages
5027
5118
  }),
5028
- status: "done",
5119
+ status: args2.input.result.error === true ? "failed" : "done",
5029
5120
  triggerType: `${args2.runtimeHost}-local`,
5030
- executionMode: "foreground",
5121
+ executionMode: args2.existingDialog?.executionMode ?? "foreground",
5031
5122
  createdAt: args2.existingDialog?.createdAt ?? nowIso,
5032
5123
  updatedAt: nowIso,
5033
5124
  finishedAt: args2.now,
@@ -8519,7 +8610,53 @@ async function resolveAgentRecordFromHybridStore(args2) {
8519
8610
  }
8520
8611
  return null;
8521
8612
  }
8613
+ function isNonEmptyCredentialValue(value) {
8614
+ if (value == null) return false;
8615
+ if (typeof value === "string") return value.trim().length > 0;
8616
+ if (typeof value === "object") return Object.keys(value).length > 0;
8617
+ return true;
8618
+ }
8619
+ function agentRecordHasConfiguredCredential(record) {
8620
+ if (!record || typeof record !== "object") return false;
8621
+ if (Array.isArray(record)) {
8622
+ return record.some(agentRecordHasConfiguredCredential);
8623
+ }
8624
+ for (const [key, value] of Object.entries(record)) {
8625
+ const normalizedKey = normalizeCredentialFieldName(key);
8626
+ if ((CLI_SECRET_FIELD_NAMES.has(normalizedKey) || CLI_CREDENTIAL_REF_FIELDS.has(normalizedKey)) && isNonEmptyCredentialValue(value)) {
8627
+ return true;
8628
+ }
8629
+ if (typeof value === "object" && value != null && agentRecordHasConfiguredCredential(value)) {
8630
+ return true;
8631
+ }
8632
+ }
8633
+ return false;
8634
+ }
8635
+ function sanitizeAgentRecordForCliOutput(record) {
8636
+ if (record == null || typeof record !== "object") return record;
8637
+ if (Array.isArray(record)) {
8638
+ return record.map((item) => sanitizeAgentRecordForCliOutput(item));
8639
+ }
8640
+ const source = record;
8641
+ const out = {};
8642
+ for (const [key, value] of Object.entries(source)) {
8643
+ const normalizedKey = normalizeCredentialFieldName(key);
8644
+ if (CLI_SECRET_FIELD_NAMES.has(normalizedKey)) continue;
8645
+ if (CLI_CREDENTIAL_REF_FIELDS.has(normalizedKey)) {
8646
+ if (isNonEmptyCredentialValue(value)) out[key] = value;
8647
+ continue;
8648
+ }
8649
+ if (value != null && typeof value === "object") {
8650
+ out[key] = sanitizeAgentRecordForCliOutput(value);
8651
+ continue;
8652
+ }
8653
+ out[key] = value;
8654
+ }
8655
+ return out;
8656
+ }
8522
8657
  function normalizeAgentRecordForOutput(agentKey, authToken, agent) {
8658
+ const credentialConfigured = agentRecordHasConfiguredCredential(agent);
8659
+ const sanitizedRecord = sanitizeAgentRecordForCliOutput(agent);
8523
8660
  return {
8524
8661
  agentKey,
8525
8662
  baseUrl: agent?.serverOrigin ?? null,
@@ -8531,9 +8668,12 @@ function normalizeAgentRecordForOutput(agentKey, authToken, agent) {
8531
8668
  customProviderUrl: agent?.customProviderUrl ?? null,
8532
8669
  tools: agent?.tools ?? [],
8533
8670
  isPublic: agent?.isPublic,
8671
+ credentialConfigured,
8672
+ credentialRef: agent?.credentialRef ?? void 0,
8673
+ apiKeyRef: agent?.apiKeyRef ?? void 0,
8534
8674
  authUserId: parseUserIdFromAuthToken(authToken),
8535
8675
  userId: agent?.userId,
8536
- record: agent
8676
+ record: sanitizedRecord
8537
8677
  };
8538
8678
  }
8539
8679
  function parseAgentUpdateArgs(args2) {
@@ -8709,7 +8849,7 @@ async function buildUpdatedAgentRecord(args2) {
8709
8849
  updates: args2.parsed.updates
8710
8850
  };
8711
8851
  }
8712
- var PROVIDER_COPY_FIELDS;
8852
+ var PROVIDER_COPY_FIELDS, CLI_SECRET_FIELD_NAMES, CLI_CREDENTIAL_REF_FIELDS, normalizeCredentialFieldName;
8713
8853
  var init_agentRecordHelpers = __esm({
8714
8854
  "packages/cli/agentRecordHelpers.ts"() {
8715
8855
  "use strict";
@@ -8732,6 +8872,26 @@ var init_agentRecordHelpers = __esm({
8732
8872
  "inputPrice",
8733
8873
  "outputPrice"
8734
8874
  ];
8875
+ CLI_SECRET_FIELD_NAMES = /* @__PURE__ */ new Set([
8876
+ "apikey",
8877
+ "password",
8878
+ "passwd",
8879
+ "secret",
8880
+ "clientsecret",
8881
+ "accesstoken",
8882
+ "refreshtoken",
8883
+ "sessiontoken",
8884
+ "bearertoken",
8885
+ "authorization",
8886
+ "authheader",
8887
+ "token",
8888
+ "oauthtoken",
8889
+ "idtoken",
8890
+ "credentials",
8891
+ "credential"
8892
+ ]);
8893
+ CLI_CREDENTIAL_REF_FIELDS = /* @__PURE__ */ new Set(["credentialref", "apikeyref"]);
8894
+ normalizeCredentialFieldName = (value) => value.replace(/[^a-z0-9]/gi, "").toLowerCase();
8735
8895
  }
8736
8896
  });
8737
8897
 
@@ -8779,26 +8939,36 @@ function ensureHeavyCliLocalRuntimeModules() {
8779
8939
  ({ fetchAntigravityCloudCodeCompletion } = requireFromAdapter(
8780
8940
  "../../agent-runtime/antigravityCloudCodeProvider.ts"
8781
8941
  ));
8782
- ({ isAntigravityOAuthAgent } = requireFromAdapter("../../agent-runtime/antigravityOAuth.ts"));
8783
- ({ readOAuthCredential: readOAuthCredential2 } = requireFromAdapter("../../agent-runtime/oauthTokenStore.ts"));
8784
- ({ getDefaultCliLocalRuntimeDb: getDefaultCliLocalRuntimeDb3 } = requireFromAdapter("../localRuntimeDb.ts"));
8785
- ({ resolveAgentRuntimeConfigFromRecord: resolveAgentRuntimeConfigFromRecord2 } = requireFromAdapter("./agentConfigResolver.ts"));
8786
- ({ resolveCliOpenAiProviderConfig } = requireFromAdapter("./localProviderResolver.ts"));
8942
+ ({ isAntigravityOAuthAgent } = requireFromAdapter(
8943
+ "../../agent-runtime/antigravityOAuth.ts"
8944
+ ));
8945
+ ({ readOAuthCredential: readOAuthCredential2 } = requireFromAdapter(
8946
+ "../../agent-runtime/oauthTokenStore.ts"
8947
+ ));
8948
+ ({ getDefaultCliLocalRuntimeDb: getDefaultCliLocalRuntimeDb3 } = requireFromAdapter(
8949
+ "../localRuntimeDb.ts"
8950
+ ));
8951
+ ({ resolveAgentRuntimeConfigFromRecord: resolveAgentRuntimeConfigFromRecord2 } = requireFromAdapter(
8952
+ "./agentConfigResolver.ts"
8953
+ ));
8954
+ ({ resolveCliOpenAiProviderConfig } = requireFromAdapter(
8955
+ "./localProviderResolver.ts"
8956
+ ));
8787
8957
  ({ createFileCredentialBroker: createFileCredentialBroker2 } = requireFromAdapter(
8788
8958
  "../../agent-runtime/fileCredentialBroker.ts"
8789
8959
  ));
8790
- ({ createOAuthApiKeyRefResolver } = requireFromAdapter("../oauth/apiKeyRefResolver.ts"));
8791
- ({
8792
- buildLocalDialogWritePlan,
8793
- localDialogMessageRecordToRuntimeMessage
8794
- } = requireFromAdapter("./localDialogRecords.ts"));
8795
- ({
8796
- buildLocalAgentLookupKeys: buildLocalAgentLookupKeys2,
8797
- shouldReadAgentKeyRemotely: shouldReadAgentKeyRemotely2
8798
- } = requireFromAdapter("./localAgentRecords.ts"));
8799
- ({ createCliHybridRecordStore } = requireFromAdapter("./hybridRecordStore.ts"));
8960
+ ({ createOAuthApiKeyRefResolver } = requireFromAdapter(
8961
+ "../oauth/apiKeyRefResolver.ts"
8962
+ ));
8963
+ ({ buildLocalDialogWritePlan, localDialogMessageRecordToRuntimeMessage } = requireFromAdapter("./localDialogRecords.ts"));
8964
+ ({ buildLocalAgentLookupKeys: buildLocalAgentLookupKeys2, shouldReadAgentKeyRemotely: shouldReadAgentKeyRemotely2 } = requireFromAdapter("./localAgentRecords.ts"));
8965
+ ({ createCliHybridRecordStore } = requireFromAdapter(
8966
+ "./hybridRecordStore.ts"
8967
+ ));
8800
8968
  ({ executeLocalToolWithPolicy: executeLocalToolWithPolicy2 } = requireFromAdapter("./localToolPolicy.ts"));
8801
- ({ inferCaptureIntent } = requireFromAdapter("../../ai/policy/runtimePolicy.ts"));
8969
+ ({ inferCaptureIntent } = requireFromAdapter(
8970
+ "../../ai/policy/runtimePolicy.ts"
8971
+ ));
8802
8972
  ({ TOOL_PACKS } = requireFromAdapter("../../ai/tools/toolPacks.ts"));
8803
8973
  ({ prepareTools } = requireFromAdapter("../../ai/tools/prepareTools.ts"));
8804
8974
  ({
@@ -8811,14 +8981,12 @@ function ensureHeavyCliLocalRuntimeModules() {
8811
8981
  defaultExecuteCli = cliExecutor.executeCli;
8812
8982
  CliProviderQuotaError = cliExecutor.CliProviderQuotaError;
8813
8983
  ({ buildCliPrompt } = requireFromAdapter("../../ai/agent/cliPrompt.ts"));
8814
- ({
8815
- readXhsProfileFunc,
8816
- readXhsProfileFunctionSchema
8817
- } = requireFromAdapter("../../ai/tools/readXhsProfileTool.ts"));
8818
- ({
8819
- readXPostFunc,
8820
- readXPostFunctionSchema
8821
- } = requireFromAdapter("../../ai/tools/readXPostTool.ts"));
8984
+ ({ readXhsProfileFunc, readXhsProfileFunctionSchema } = requireFromAdapter(
8985
+ "../../ai/tools/readXhsProfileTool.ts"
8986
+ ));
8987
+ ({ readXPostFunc, readXPostFunctionSchema } = requireFromAdapter(
8988
+ "../../ai/tools/readXPostTool.ts"
8989
+ ));
8822
8990
  ({ ulid: ulid2 } = requireFromAdapter("ulid"));
8823
8991
  }
8824
8992
  function normalizeRuntimeCacheCwd(cwd) {
@@ -8877,7 +9045,8 @@ function parseLocalToolBudgets(env) {
8877
9045
  for (const part of raw.split(",")) {
8878
9046
  const [name, value] = part.split("=").map((item) => item.trim());
8879
9047
  const limit = Number(value);
8880
- if (name && Number.isFinite(limit) && limit >= 0) budgets[name] = Math.floor(limit);
9048
+ if (name && Number.isFinite(limit) && limit >= 0)
9049
+ budgets[name] = Math.floor(limit);
8881
9050
  }
8882
9051
  return budgets;
8883
9052
  }
@@ -8893,7 +9062,9 @@ function assertWithinLocalToolBudget(args2) {
8893
9062
  }
8894
9063
  function isTransientFetchError(error) {
8895
9064
  const message = toErrorMessage(error);
8896
- return /certificate|handshake|network|socket|timed out|timeout|ECONNRESET/i.test(message);
9065
+ return /certificate|handshake|network|socket|timed out|timeout|ECONNRESET/i.test(
9066
+ message
9067
+ );
8897
9068
  }
8898
9069
  async function defaultSleep(ms) {
8899
9070
  await new Promise((resolve8) => setTimeout(resolve8, ms));
@@ -8925,26 +9096,39 @@ async function defaultLoopbackRequest(input2, init) {
8925
9096
  }
8926
9097
  return await new Promise((resolve8, reject) => {
8927
9098
  const requestImpl = target.protocol === "https:" ? httpsRequest : httpRequest;
8928
- const req = requestImpl(target, {
8929
- method: init?.method ?? "GET",
8930
- headers: Object.fromEntries(headers.entries())
8931
- }, (res) => {
8932
- const chunks = [];
8933
- res.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
8934
- res.on("end", () => {
8935
- resolve8(new Response(Buffer.concat(chunks), {
8936
- status: res.statusCode ?? 500,
8937
- headers: res.headers
8938
- }));
8939
- });
8940
- });
9099
+ const req = requestImpl(
9100
+ target,
9101
+ {
9102
+ method: init?.method ?? "GET",
9103
+ headers: Object.fromEntries(headers.entries())
9104
+ },
9105
+ (res) => {
9106
+ const chunks = [];
9107
+ res.on(
9108
+ "data",
9109
+ (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))
9110
+ );
9111
+ res.on("end", () => {
9112
+ resolve8(
9113
+ new Response(Buffer.concat(chunks), {
9114
+ status: res.statusCode ?? 500,
9115
+ headers: res.headers
9116
+ })
9117
+ );
9118
+ });
9119
+ }
9120
+ );
8941
9121
  req.on("error", reject);
8942
- init?.signal?.addEventListener("abort", () => {
8943
- req.destroy(
8944
- init.signal?.reason instanceof Error ? init.signal.reason : new Error("request aborted")
8945
- );
8946
- reject(init.signal?.reason ?? new Error("request aborted"));
8947
- }, { once: true });
9122
+ init?.signal?.addEventListener(
9123
+ "abort",
9124
+ () => {
9125
+ req.destroy(
9126
+ init.signal?.reason instanceof Error ? init.signal.reason : new Error("request aborted")
9127
+ );
9128
+ reject(init.signal?.reason ?? new Error("request aborted"));
9129
+ },
9130
+ { once: true }
9131
+ );
8948
9132
  if (body) req.write(body);
8949
9133
  req.end();
8950
9134
  });
@@ -8962,7 +9146,9 @@ async function fetchWithTransientRetry(fetchImpl, input2, init, options = {}) {
8962
9146
  if (!isTransientFetchError(error)) throw error;
8963
9147
  lastError = error;
8964
9148
  if (attempt < TRANSIENT_FETCH_MAX_ATTEMPTS) {
8965
- await (options.sleep ?? defaultSleep)(transientFetchRetryDelayMs(attempt));
9149
+ await (options.sleep ?? defaultSleep)(
9150
+ transientFetchRetryDelayMs(attempt)
9151
+ );
8966
9152
  }
8967
9153
  }
8968
9154
  }
@@ -9041,8 +9227,11 @@ function summarizeOpenAiToolNames(tools) {
9041
9227
  }, []);
9042
9228
  }
9043
9229
  function addDefaultLightWebToolsForConfiguredAgents(toolNames, agentConfig) {
9044
- const explicitToolNames = Array.isArray(agentConfig?.toolSurface?.explicitToolNames) ? agentConfig.toolSurface.explicitToolNames : agentConfig?.toolNames;
9045
- if (!Array.isArray(explicitToolNames) || explicitToolNames.length === 0) return toolNames;
9230
+ const explicitToolNames = Array.isArray(
9231
+ agentConfig?.toolSurface?.explicitToolNames
9232
+ ) ? agentConfig.toolSurface.explicitToolNames : agentConfig?.toolNames;
9233
+ if (!Array.isArray(explicitToolNames) || explicitToolNames.length === 0)
9234
+ return toolNames;
9046
9235
  const webCapable = explicitToolNames.some(
9047
9236
  (toolName) => toolName === "fetchWebpage" || toolName === "exa_search" || toolName === "firecrawl_scrape" || toolName === "firecrawl_search" || toolName === "read_x_post" || toolName === "read_xhs_profile" || toolName.startsWith("browser_")
9048
9237
  );
@@ -9051,7 +9240,10 @@ function addDefaultLightWebToolsForConfiguredAgents(toolNames, agentConfig) {
9051
9240
  }
9052
9241
  function buildOpenAiTools(args2) {
9053
9242
  const toolset = buildLocalWorkspaceToolsetForEnv(args2);
9243
+ const toolNameSet = new Set(args2.toolNames ?? []);
9244
+ const callAgentTools = toolNameSet.has("callAgent") ? prepareTools(["callAgent"]) : [];
9054
9245
  return [
9246
+ ...callAgentTools,
9055
9247
  ...buildLocalWorkspaceOpenAiTools2({
9056
9248
  toolNames: toolset.toolNames,
9057
9249
  exposeShellTools: toolset.exposeShellTools,
@@ -9061,7 +9253,9 @@ function buildOpenAiTools(args2) {
9061
9253
  readFileParameterVariant: resolveReadFileParameterVariant(args2.env),
9062
9254
  globFilesDescriptionVariant: resolveGlobFilesDescriptionVariant(args2.env),
9063
9255
  globFilesParameterVariant: resolveGlobFilesParameterVariant(args2.env),
9064
- searchFilesDescriptionVariant: resolveSearchFilesDescriptionVariant(args2.env),
9256
+ searchFilesDescriptionVariant: resolveSearchFilesDescriptionVariant(
9257
+ args2.env
9258
+ ),
9065
9259
  searchFilesParameterVariant: resolveSearchFilesParameterVariant(args2.env)
9066
9260
  }),
9067
9261
  ...buildServerPlatformOpenAiTools({ toolNames: args2.toolNames }),
@@ -9084,7 +9278,9 @@ function buildLocalWorkspaceToolsetForEnv(args2) {
9084
9278
  const toolset = buildLocalWorkspaceToolset2({
9085
9279
  declaredToolNames: args2.toolNames,
9086
9280
  exposeShellTools: true,
9087
- useDeclaredToolNamesOnly: shouldUseDeclaredOnlyLocalWorkspaceTools(args2.env)
9281
+ useDeclaredToolNamesOnly: shouldUseDeclaredOnlyLocalWorkspaceTools(
9282
+ args2.env
9283
+ )
9088
9284
  });
9089
9285
  return toolset;
9090
9286
  }
@@ -9093,7 +9289,9 @@ function buildLocalPolicyToolNames(args2) {
9093
9289
  ...buildLocalWorkspacePolicyToolNames2({
9094
9290
  declaredToolNames: args2.toolNames,
9095
9291
  exposeShellTools: true,
9096
- useDeclaredToolNamesOnly: shouldUseDeclaredOnlyLocalWorkspaceTools(args2.env)
9292
+ useDeclaredToolNamesOnly: shouldUseDeclaredOnlyLocalWorkspaceTools(
9293
+ args2.env
9294
+ )
9097
9295
  }),
9098
9296
  ...(() => {
9099
9297
  const extra = [];
@@ -9101,6 +9299,7 @@ function buildLocalPolicyToolNames(args2) {
9101
9299
  for (const name of names) {
9102
9300
  if (name === "read_x_post") extra.push("read_x_post");
9103
9301
  if (name === "read_xhs_profile") extra.push("read_xhs_profile");
9302
+ if (name === "callAgent") extra.push("callAgent");
9104
9303
  if (LOCAL_SERVER_TABLE_TOOL_NAME_SET.has(name)) extra.push(name);
9105
9304
  }
9106
9305
  return extra;
@@ -9113,28 +9312,44 @@ function shouldUseDeclaredOnlyLocalWorkspaceTools(env) {
9113
9312
  return value === "declared-only" || value === "declared";
9114
9313
  }
9115
9314
  function resolveGlobFilesDescriptionVariant(env) {
9116
- return resolveLocalWorkspaceDescriptionVariant(env.NOLO_GLOBFILES_DESCRIPTION_VARIANT);
9315
+ return resolveLocalWorkspaceDescriptionVariant(
9316
+ env.NOLO_GLOBFILES_DESCRIPTION_VARIANT
9317
+ );
9117
9318
  }
9118
9319
  function resolveListFilesDescriptionVariant(env) {
9119
- return resolveLocalWorkspaceDescriptionVariant(env.NOLO_LISTFILES_DESCRIPTION_VARIANT);
9320
+ return resolveLocalWorkspaceDescriptionVariant(
9321
+ env.NOLO_LISTFILES_DESCRIPTION_VARIANT
9322
+ );
9120
9323
  }
9121
9324
  function resolveListFilesParameterVariant(env) {
9122
- return resolveLocalWorkspaceParameterVariant(env.NOLO_LISTFILES_PARAMETER_VARIANT);
9325
+ return resolveLocalWorkspaceParameterVariant(
9326
+ env.NOLO_LISTFILES_PARAMETER_VARIANT
9327
+ );
9123
9328
  }
9124
9329
  function resolveReadFileDescriptionVariant(env) {
9125
- return resolveLocalWorkspaceDescriptionVariant(env.NOLO_READFILE_DESCRIPTION_VARIANT);
9330
+ return resolveLocalWorkspaceDescriptionVariant(
9331
+ env.NOLO_READFILE_DESCRIPTION_VARIANT
9332
+ );
9126
9333
  }
9127
9334
  function resolveReadFileParameterVariant(env) {
9128
- return resolveLocalWorkspaceParameterVariant(env.NOLO_READFILE_PARAMETER_VARIANT);
9335
+ return resolveLocalWorkspaceParameterVariant(
9336
+ env.NOLO_READFILE_PARAMETER_VARIANT
9337
+ );
9129
9338
  }
9130
9339
  function resolveGlobFilesParameterVariant(env) {
9131
- return resolveLocalWorkspaceParameterVariant(env.NOLO_GLOBFILES_PARAMETER_VARIANT);
9340
+ return resolveLocalWorkspaceParameterVariant(
9341
+ env.NOLO_GLOBFILES_PARAMETER_VARIANT
9342
+ );
9132
9343
  }
9133
9344
  function resolveSearchFilesDescriptionVariant(env) {
9134
- return resolveLocalWorkspaceDescriptionVariant(env.NOLO_SEARCHFILES_DESCRIPTION_VARIANT);
9345
+ return resolveLocalWorkspaceDescriptionVariant(
9346
+ env.NOLO_SEARCHFILES_DESCRIPTION_VARIANT
9347
+ );
9135
9348
  }
9136
9349
  function resolveSearchFilesParameterVariant(env) {
9137
- return resolveLocalWorkspaceParameterVariant(env.NOLO_SEARCHFILES_PARAMETER_VARIANT);
9350
+ return resolveLocalWorkspaceParameterVariant(
9351
+ env.NOLO_SEARCHFILES_PARAMETER_VARIANT
9352
+ );
9138
9353
  }
9139
9354
  function resolveLocalWorkspaceDescriptionVariant(value) {
9140
9355
  return value === "brief" || value === "strategy" || value === "workflow" || value === "antiShell" ? value : "strategy";
@@ -9145,17 +9360,23 @@ function resolveLocalWorkspaceParameterVariant(value) {
9145
9360
  function buildServerPlatformOpenAiTools(args2) {
9146
9361
  const toolNameSet = new Set(args2.toolNames ?? []);
9147
9362
  const tableTools = prepareTools(
9148
- Array.from(toolNameSet).filter((name) => LOCAL_SERVER_TABLE_TOOL_NAME_SET.has(name))
9363
+ Array.from(toolNameSet).filter(
9364
+ (name) => LOCAL_SERVER_TABLE_TOOL_NAME_SET.has(name)
9365
+ )
9149
9366
  );
9150
9367
  return [
9151
- ...toolNameSet.has("read_xhs_profile") ? [{
9152
- type: "function",
9153
- function: readXhsProfileFunctionSchema
9154
- }] : [],
9155
- ...toolNameSet.has("read_x_post") ? [{
9156
- type: "function",
9157
- function: readXPostFunctionSchema
9158
- }] : [],
9368
+ ...toolNameSet.has("read_xhs_profile") ? [
9369
+ {
9370
+ type: "function",
9371
+ function: readXhsProfileFunctionSchema
9372
+ }
9373
+ ] : [],
9374
+ ...toolNameSet.has("read_x_post") ? [
9375
+ {
9376
+ type: "function",
9377
+ function: readXPostFunctionSchema
9378
+ }
9379
+ ] : [],
9159
9380
  ...tableTools
9160
9381
  ];
9161
9382
  }
@@ -9199,7 +9420,10 @@ function withResolvedRuntimeToolSurface(agentConfig, env) {
9199
9420
  };
9200
9421
  }
9201
9422
  function resolveRuntimeServerUrl(env) {
9202
- return (env.NOLO_SERVER_URL || env.NOLO_SERVER || env.BASE_URL || "").replace(/\/+$/, "");
9423
+ return (env.NOLO_SERVER_URL || env.NOLO_SERVER || env.BASE_URL || "").replace(
9424
+ /\/+$/,
9425
+ ""
9426
+ );
9203
9427
  }
9204
9428
  function resolveRuntimeAuthToken(env) {
9205
9429
  return env.AUTH_TOKEN || env.AUTH || env.NOLO_MACHINE_API_KEY || "";
@@ -9267,11 +9491,7 @@ function buildLocalParentWakeMessage(args2) {
9267
9491
  `childDialogKey: ${args2.childDialogKey}`,
9268
9492
  `childAgentKey: ${args2.childAgentKey}`,
9269
9493
  "status: done",
9270
- ...args2.childEvidenceSummary ? [
9271
- "",
9272
- "childEvidenceSummary:",
9273
- args2.childEvidenceSummary
9274
- ] : [],
9494
+ ...args2.childEvidenceSummary ? ["", "childEvidenceSummary:", args2.childEvidenceSummary] : [],
9275
9495
  "",
9276
9496
  "Read the childEvidenceSummary and decide the next step yourself. This wake came from a local CLI run, so completion evidence is the synced child dialog, subjectRefs, commits, artifacts, and test output rather than a server-side child process."
9277
9497
  ].join("\n");
@@ -9291,7 +9511,9 @@ async function postRemoteRecord(args2) {
9291
9511
  });
9292
9512
  if (!response.ok) {
9293
9513
  const text = await response.text().catch(() => "");
9294
- throw new Error(`remote dialog evidence write failed: HTTP ${response.status} ${text.slice(0, 500)}`);
9514
+ throw new Error(
9515
+ `remote dialog evidence write failed: HTTP ${response.status} ${text.slice(0, 500)}`
9516
+ );
9295
9517
  }
9296
9518
  }
9297
9519
  async function readRemoteRecord(args2) {
@@ -9311,7 +9533,9 @@ async function readRemoteRecord(args2) {
9311
9533
  async function maybeWakeParentDialogAfterLocalSync(args2) {
9312
9534
  if (args2.input.runtimeContext?.parentWakeOnTerminal !== true) return;
9313
9535
  if (args2.childDialogRecord.parentWake?.terminalNotifiedAt) return;
9314
- const parentDialogId = asOptionalTrimmedString(args2.childDialogRecord.parentDialogId);
9536
+ const parentDialogId = asOptionalTrimmedString(
9537
+ args2.childDialogRecord.parentDialogId
9538
+ );
9315
9539
  if (!parentDialogId) return;
9316
9540
  const parentDialogKey = `dialog-${args2.userId}-${parentDialogId}`;
9317
9541
  const parentDialog = await readRemoteRecord({
@@ -9329,8 +9553,12 @@ async function maybeWakeParentDialogAfterLocalSync(args2) {
9329
9553
  args2.childDialogRecord.subjectRefs,
9330
9554
  [{ kind: "dialog", id: childDialogId, role: "completed-child-dialog" }]
9331
9555
  );
9332
- const allowedChildAgentKeys = normalizeRemoteStringList(args2.input.runtimeContext?.allowedChildAgentKeys);
9333
- const allowedToolNames = normalizeRemoteStringList(args2.input.runtimeContext?.allowedToolNames);
9556
+ const allowedChildAgentKeys = normalizeRemoteStringList(
9557
+ args2.input.runtimeContext?.allowedChildAgentKeys
9558
+ );
9559
+ const allowedToolNames = normalizeRemoteStringList(
9560
+ args2.input.runtimeContext?.allowedToolNames
9561
+ );
9334
9562
  const wakeResponse = await args2.fetchImpl(`${args2.serverUrl}/api/agent/run`, {
9335
9563
  method: "POST",
9336
9564
  headers: {
@@ -9360,7 +9588,9 @@ async function maybeWakeParentDialogAfterLocalSync(args2) {
9360
9588
  });
9361
9589
  if (!wakeResponse.ok) {
9362
9590
  const text = await wakeResponse.text().catch(() => "");
9363
- throw new Error(`parent dialog wake failed: HTTP ${wakeResponse.status} ${text.slice(0, 500)}`);
9591
+ throw new Error(
9592
+ `parent dialog wake failed: HTTP ${wakeResponse.status} ${text.slice(0, 500)}`
9593
+ );
9364
9594
  }
9365
9595
  const notifiedAt = Date.now();
9366
9596
  await postRemoteRecord({
@@ -9410,7 +9640,9 @@ async function syncLocalDialogEvidenceToRemote(args2) {
9410
9640
  })
9411
9641
  )
9412
9642
  );
9413
- const childDialogOp = args2.ops.find((op) => op.type === "put" && !op.key.includes("-msg-"));
9643
+ const childDialogOp = args2.ops.find(
9644
+ (op) => op.type === "put" && !op.key.includes("-msg-")
9645
+ );
9414
9646
  const childDialogRecord = childDialogOp?.value && typeof childDialogOp.value === "object" ? childDialogOp.value : null;
9415
9647
  if (childDialogOp && childDialogRecord) {
9416
9648
  try {
@@ -9425,7 +9657,9 @@ async function syncLocalDialogEvidenceToRemote(args2) {
9425
9657
  });
9426
9658
  } catch (error) {
9427
9659
  args2.output?.write(
9428
- `[nolo] Parent dialog wake failed; synced local child evidence remains queryable: ${toErrorMessage(error)}
9660
+ `[nolo] Parent dialog wake failed; synced local child evidence remains queryable: ${toErrorMessage(
9661
+ error
9662
+ )}
9429
9663
  `
9430
9664
  );
9431
9665
  }
@@ -9436,8 +9670,14 @@ function buildServerPlatformToolExecutors(args2) {
9436
9670
  const postServer = async (path8, body) => {
9437
9671
  const serverUrl = resolveRuntimeServerUrl(args2.env);
9438
9672
  const authToken = resolveRuntimeAuthToken(args2.env);
9439
- if (!serverUrl) throw new Error("server platform tools require NOLO_SERVER_URL, NOLO_SERVER, or BASE_URL.");
9440
- if (!authToken) throw new Error("server platform tools require AUTH_TOKEN or NOLO_MACHINE_API_KEY.");
9673
+ if (!serverUrl)
9674
+ throw new Error(
9675
+ "server platform tools require NOLO_SERVER_URL, NOLO_SERVER, or BASE_URL."
9676
+ );
9677
+ if (!authToken)
9678
+ throw new Error(
9679
+ "server platform tools require AUTH_TOKEN or NOLO_MACHINE_API_KEY."
9680
+ );
9441
9681
  const response = await args2.fetchImpl(`${serverUrl}${path8}`, {
9442
9682
  method: "POST",
9443
9683
  headers: {
@@ -9448,12 +9688,15 @@ function buildServerPlatformToolExecutors(args2) {
9448
9688
  });
9449
9689
  const text = await response.text().catch(() => "");
9450
9690
  if (!response.ok) {
9451
- throw new Error(`server platform tool bridge failed: HTTP ${response.status} ${text.slice(0, 500)}`);
9691
+ throw new Error(
9692
+ `server platform tool bridge failed: HTTP ${response.status} ${text.slice(0, 500)}`
9693
+ );
9452
9694
  }
9453
9695
  return text;
9454
9696
  };
9455
9697
  const guardExplicitTableCapture = (call) => {
9456
- if (inferCaptureIntent(String(call.userInput ?? "")) === "strong") return null;
9698
+ if (inferCaptureIntent(String(call.userInput ?? "")) === "strong")
9699
+ return null;
9457
9700
  return JSON.stringify({
9458
9701
  error: "knowledge_capture_requires_confirmation",
9459
9702
  message: "\u5F53\u524D\u672C\u5730\u8FD0\u884C\u4E0D\u5141\u8BB8\u81EA\u52A8\u5199\u5165\u8868\u683C\u3002\u53EA\u6709\u5F53\u7528\u6237\u5728\u5F53\u524D\u8BF7\u6C42\u91CC\u660E\u786E\u8981\u6C42\u4FDD\u5B58\u3001\u5EFA\u8868\u3001\u5199\u5165 table \u6216\u505A\u6210\u6570\u636E\u96C6\u65F6\uFF0C\u624D\u80FD\u7EE7\u7EED\uFF1B\u5426\u5219\u8BF7\u5148\u8BE2\u95EE\u7528\u6237\u3002",
@@ -9487,6 +9730,231 @@ function buildServerPlatformToolExecutors(args2) {
9487
9730
  );
9488
9731
  return tableExecutors;
9489
9732
  }
9733
+ function buildCliDelegatedAgentInput(task, input2) {
9734
+ if (input2 === void 0 || input2 === null) {
9735
+ return task;
9736
+ }
9737
+ if (typeof input2 === "string") {
9738
+ return `${task}
9739
+
9740
+ --- INPUT (text) ---
9741
+ ${input2}`;
9742
+ }
9743
+ return `${task}
9744
+
9745
+ --- INPUT (json) ---
9746
+ ${JSON.stringify(input2, null, 2)}`;
9747
+ }
9748
+ async function persistCliPendingChildDialog(args2) {
9749
+ const nowIso = new Date(args2.now).toISOString();
9750
+ const dialogKey = `dialog-${args2.userId}-${args2.dialogId}`;
9751
+ const record = {
9752
+ id: args2.dialogId,
9753
+ dbKey: dialogKey,
9754
+ type: "dialog",
9755
+ userId: args2.userId,
9756
+ cybots: [args2.agentKey],
9757
+ primaryAgentKey: args2.agentKey,
9758
+ title: args2.title.slice(0, 80),
9759
+ status: "pending",
9760
+ triggerType: "cli-local",
9761
+ executionMode: args2.background ? "background" : "foreground",
9762
+ createdAt: nowIso,
9763
+ updatedAt: nowIso,
9764
+ ...args2.spaceId ? { spaceId: args2.spaceId } : {},
9765
+ ...args2.parentDialogId ? { parentDialogId: args2.parentDialogId } : {},
9766
+ ...args2.rootDialogId ? { rootDialogId: args2.rootDialogId } : {},
9767
+ localRuntime: {
9768
+ host: "cli",
9769
+ workspaceRoot: args2.workspaceRoot,
9770
+ workspaceKind: "current",
9771
+ workspaceAccess: "inherited"
9772
+ }
9773
+ };
9774
+ await args2.store.batch([{ type: "put", key: dialogKey, value: record }]);
9775
+ }
9776
+ async function persistCliFailedChildDialog(args2) {
9777
+ const dialogKey = `dialog-${args2.userId}-${args2.dialogId}`;
9778
+ const existing = await args2.store.read(dialogKey);
9779
+ const existingRecord = existing && typeof existing === "object" ? existing : {};
9780
+ await args2.store.batch([
9781
+ {
9782
+ type: "put",
9783
+ key: dialogKey,
9784
+ value: {
9785
+ ...existingRecord,
9786
+ id: args2.dialogId,
9787
+ dbKey: dialogKey,
9788
+ status: "failed",
9789
+ errorMessage: args2.errorMessage,
9790
+ updatedAt: new Date(args2.now).toISOString(),
9791
+ finishedAt: args2.now
9792
+ }
9793
+ }
9794
+ ]);
9795
+ }
9796
+ function createCliCallAgentToolExecutor(deps, ctx) {
9797
+ ensureHeavyCliLocalRuntimeModules();
9798
+ const userId = resolveLocalUserId(deps.env);
9799
+ const workspaceRoot = deps.cwd ?? process.cwd();
9800
+ const now = deps.now ?? Date.now;
9801
+ const createId = deps.createId ?? createFallbackId;
9802
+ return async (call) => {
9803
+ const parsed = parseNoloWorkspaceToolArguments2(call.arguments);
9804
+ const agentKey = asTrimmedString(parsed.agentKey);
9805
+ const task = asTrimmedString(parsed.task);
9806
+ if (!agentKey) {
9807
+ return {
9808
+ content: JSON.stringify({ error: "callAgent: agentKey is required" }),
9809
+ metadata: { callAgent: true }
9810
+ };
9811
+ }
9812
+ if (!task) {
9813
+ return {
9814
+ content: JSON.stringify({ error: "callAgent: task is required" }),
9815
+ metadata: { callAgent: true }
9816
+ };
9817
+ }
9818
+ const allowedChildAgentKeys = asTrimmedNonEmptyStringArray(
9819
+ ctx.runtimeContext?.allowedChildAgentKeys
9820
+ );
9821
+ if (allowedChildAgentKeys.length > 0 && !allowedChildAgentKeys.includes(agentKey)) {
9822
+ return {
9823
+ content: JSON.stringify({
9824
+ error: "callAgent: agentKey is not allowed by parent runtimeContext.allowedChildAgentKeys",
9825
+ agentKey,
9826
+ allowedChildAgentKeys
9827
+ }),
9828
+ metadata: { callAgent: true }
9829
+ };
9830
+ }
9831
+ const background = parsed.background === true;
9832
+ const parentDialogId = asOptionalTrimmedString(ctx.dialogId);
9833
+ const parentThreadId = parentDialogId ?? asOptionalTrimmedString(ctx.runtimeContext?.parentThreadId);
9834
+ const rootThreadId = asOptionalTrimmedString(ctx.runtimeContext?.rootThreadId) ?? asOptionalTrimmedString(ctx.runtimeContext?.parentThreadId) ?? parentThreadId;
9835
+ const presentationIntent = background ? "background_handoff" : "inline_result";
9836
+ const threadKind = background ? "background" : "inline";
9837
+ const childRuntimeContext = {
9838
+ ...ctx.runtimeContext ?? {},
9839
+ surface: "cli",
9840
+ entrypoint: "agent-tool:callAgent",
9841
+ threadKind,
9842
+ presentationIntent,
9843
+ ...parentThreadId ? { parentThreadId } : {},
9844
+ ...rootThreadId ? { rootThreadId } : {},
9845
+ workspaceRoot,
9846
+ workspaceKind: "current",
9847
+ workspaceAccess: "inherited"
9848
+ };
9849
+ const childDialogId = createId();
9850
+ const store = await getOrCreateSharedStore(deps);
9851
+ await persistCliPendingChildDialog({
9852
+ store,
9853
+ userId,
9854
+ dialogId: childDialogId,
9855
+ agentKey,
9856
+ title: task,
9857
+ spaceId: ctx.spaceId,
9858
+ parentDialogId,
9859
+ rootDialogId: rootThreadId,
9860
+ workspaceRoot,
9861
+ background,
9862
+ now: now()
9863
+ });
9864
+ const childAdapter = ctx.createChildAdapter({
9865
+ dialogId: childDialogId,
9866
+ spaceId: ctx.spaceId,
9867
+ runtimeContext: childRuntimeContext
9868
+ });
9869
+ const childInputBase = {
9870
+ adapter: childAdapter,
9871
+ agentRef: agentKey,
9872
+ input: buildCliDelegatedAgentInput(task, parsed.input),
9873
+ runtimeContext: childRuntimeContext,
9874
+ spaceId: ctx.spaceId,
9875
+ continueDialogId: childDialogId,
9876
+ parentDialogId
9877
+ };
9878
+ if (background) {
9879
+ void ctx.runChildTurn(childInputBase).catch(async (error) => {
9880
+ const errorMessage = toErrorMessage(error);
9881
+ try {
9882
+ await persistCliFailedChildDialog({
9883
+ store,
9884
+ userId,
9885
+ dialogId: childDialogId,
9886
+ errorMessage,
9887
+ now: now()
9888
+ });
9889
+ } catch (persistError) {
9890
+ deps.output?.write(
9891
+ `[nolo] failed to persist background child failure: ${toErrorMessage(
9892
+ persistError
9893
+ )}
9894
+ `
9895
+ );
9896
+ }
9897
+ });
9898
+ return {
9899
+ content: JSON.stringify({
9900
+ success: true,
9901
+ status: "pending",
9902
+ agentKey,
9903
+ childDialogId,
9904
+ ...parentDialogId ? { parentDialogId } : {}
9905
+ }),
9906
+ metadata: { callAgent: true, background: true, localRuntime: true }
9907
+ };
9908
+ }
9909
+ try {
9910
+ const childResult = await ctx.runChildTurn(childInputBase);
9911
+ return {
9912
+ content: JSON.stringify({
9913
+ success: true,
9914
+ agentKey,
9915
+ dialogId: childDialogId,
9916
+ model: childResult.model ?? null,
9917
+ provider: childResult.provider ?? null,
9918
+ content: childResult.content ?? "",
9919
+ usage: childResult.usage ?? null
9920
+ }),
9921
+ metadata: { callAgent: true, background: false, localRuntime: true }
9922
+ };
9923
+ } catch (error) {
9924
+ const errorMessage = toErrorMessage(error);
9925
+ try {
9926
+ await persistCliFailedChildDialog({
9927
+ store,
9928
+ userId,
9929
+ dialogId: childDialogId,
9930
+ errorMessage,
9931
+ now: now()
9932
+ });
9933
+ } catch (persistError) {
9934
+ deps.output?.write(
9935
+ `[nolo] failed to persist foreground child failure: ${toErrorMessage(
9936
+ persistError
9937
+ )}
9938
+ `
9939
+ );
9940
+ }
9941
+ return {
9942
+ content: JSON.stringify({
9943
+ success: false,
9944
+ agentKey,
9945
+ dialogId: childDialogId,
9946
+ error: errorMessage
9947
+ }),
9948
+ metadata: {
9949
+ callAgent: true,
9950
+ background: false,
9951
+ localRuntime: true,
9952
+ error: true
9953
+ }
9954
+ };
9955
+ }
9956
+ };
9957
+ }
9490
9958
  function buildLocalToolExecutors(args2) {
9491
9959
  return {
9492
9960
  ...createLocalWorkspaceToolExecutors2({
@@ -9573,7 +10041,10 @@ async function readAgentFromStore(args2) {
9573
10041
  const normalizedRef = normalizeAgentHandle(args2.agentRef);
9574
10042
  if (!normalizedRef) return null;
9575
10043
  try {
9576
- const iterator = args2.store.iterator({ gte: "agent-", lte: "agent-\uFFFF" });
10044
+ const iterator = args2.store.iterator({
10045
+ gte: "agent-",
10046
+ lte: "agent-\uFFFF"
10047
+ });
9577
10048
  for await (const [key, record] of iterator) {
9578
10049
  if (!record || typeof record !== "object") continue;
9579
10050
  const handle = normalizeAgentHandle(record.handle);
@@ -9629,7 +10100,9 @@ async function writeDialog(args2) {
9629
10100
  throw error;
9630
10101
  }
9631
10102
  args2.output?.write(
9632
- `[nolo] Remote dialog evidence sync failed; local dialog only: ${toErrorMessage(error)}
10103
+ `[nolo] Remote dialog evidence sync failed; local dialog only: ${toErrorMessage(
10104
+ error
10105
+ )}
9633
10106
  `
9634
10107
  );
9635
10108
  }
@@ -9659,7 +10132,12 @@ function createCliLocalRuntimeAdapter(deps) {
9659
10132
  });
9660
10133
  return {
9661
10134
  host: "cli",
9662
- capabilities: ["leveldb-agent-config", "local-provider", "leveldb-persistence", "local-tools"],
10135
+ capabilities: [
10136
+ "leveldb-agent-config",
10137
+ "local-provider",
10138
+ "leveldb-persistence",
10139
+ "local-tools"
10140
+ ],
9663
10141
  loadAgentConfig: async (agentRef) => {
9664
10142
  const cacheKey = buildPreparedAgentCacheKey({
9665
10143
  userId,
@@ -9830,7 +10308,9 @@ function createCliLocalRuntimeAdapter(deps) {
9830
10308
  });
9831
10309
  if (result.status < 200 || result.status >= 300) {
9832
10310
  const errMsg = result.body && typeof result.body === "object" && result.body.error && typeof result.body.error.message === "string" ? result.body.error.message : JSON.stringify(result.body);
9833
- throw new Error(`local antigravity provider failed: HTTP ${result.status} ${errMsg}`);
10311
+ throw new Error(
10312
+ `local antigravity provider failed: HTTP ${result.status} ${errMsg}`
10313
+ );
9834
10314
  }
9835
10315
  const choice = Array.isArray(result.body.choices) ? result.body.choices[0] : void 0;
9836
10316
  const message = choice?.message ?? {};
@@ -9905,16 +10385,23 @@ function createCliLocalRuntimeAdapter(deps) {
9905
10385
  openAiToolNames: summarizeOpenAiToolNames(tools2),
9906
10386
  stream
9907
10387
  });
9908
- const res = await fetchWithTransientRetry(fetchImpl, request.url, {
9909
- ...request.init
9910
- }, {
9911
- sleep: deps.sleep,
9912
- loopbackRequest
9913
- });
10388
+ const res = await fetchWithTransientRetry(
10389
+ fetchImpl,
10390
+ request.url,
10391
+ {
10392
+ ...request.init
10393
+ },
10394
+ {
10395
+ sleep: deps.sleep,
10396
+ loopbackRequest
10397
+ }
10398
+ );
9914
10399
  if (!res.ok) {
9915
10400
  const raw2 = await res.text().catch(() => "");
9916
10401
  const data2 = parsePlatformChatCompletionData2(raw2);
9917
- throw new Error(`platform provider failed: HTTP ${res.status} ${JSON.stringify(data2)}`);
10402
+ throw new Error(
10403
+ `platform provider failed: HTTP ${res.status} ${JSON.stringify(data2)}`
10404
+ );
9918
10405
  }
9919
10406
  const contentType = res.headers.get("content-type") ?? "";
9920
10407
  const shouldStream = Boolean(stream && options?.onTextDelta) && contentType.includes("text/event-stream");
@@ -10044,7 +10531,9 @@ function createCliLocalRuntimeAdapter(deps) {
10044
10531
  const code = error && typeof error === "object" && typeof error.code === "string" ? error.code : void 0;
10045
10532
  const request = error && typeof error === "object" && error.permissionRequest;
10046
10533
  if (code === "destructive_action_requires_confirmation" && deps.confirmDestructiveAction && request && typeof request === "object") {
10047
- const confirmed = await deps.confirmDestructiveAction(request);
10534
+ const confirmed = await deps.confirmDestructiveAction(
10535
+ request
10536
+ );
10048
10537
  if (confirmed) {
10049
10538
  const result = await executeLocalToolWithPolicy2({
10050
10539
  env: deps.env,
@@ -10083,6 +10572,7 @@ var init_localRuntimeAdapter = __esm({
10083
10572
  init_optionalString();
10084
10573
  init_recordOrEmpty();
10085
10574
  init_stringArray();
10575
+ init_trimmedString();
10086
10576
  init_summarizeEndpoint();
10087
10577
  requireFromAdapter = createRequire(import.meta.url);
10088
10578
  heavyCliLocalRuntimeModulesLoaded = false;
@@ -10092,7 +10582,11 @@ var init_localRuntimeAdapter = __esm({
10092
10582
  BUILTIN_NOLO_AGENT_KEY = NOLO_DEFAULT_AGENT_KEY;
10093
10583
  SOURCE_CLI_DIR = dirname3(fileURLToPath3(import.meta.url));
10094
10584
  CLI_DIR = isCompiledBinary() ? dirname3(process.execPath) : SOURCE_CLI_DIR;
10095
- CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : join5(SOURCE_CLI_DIR, "..", `index${extname2(fileURLToPath3(import.meta.url)) || ".ts"}`);
10585
+ CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : join5(
10586
+ SOURCE_CLI_DIR,
10587
+ "..",
10588
+ `index${extname2(fileURLToPath3(import.meta.url)) || ".ts"}`
10589
+ );
10096
10590
  LOCAL_SERVER_TABLE_TOOL_NAMES = [
10097
10591
  "createTable",
10098
10592
  "addTableRow",
@@ -10100,7 +10594,9 @@ var init_localRuntimeAdapter = __esm({
10100
10594
  "updateTableRow",
10101
10595
  "updateTableRows"
10102
10596
  ];
10103
- LOCAL_SERVER_TABLE_TOOL_NAME_SET = new Set(LOCAL_SERVER_TABLE_TOOL_NAMES);
10597
+ LOCAL_SERVER_TABLE_TOOL_NAME_SET = new Set(
10598
+ LOCAL_SERVER_TABLE_TOOL_NAMES
10599
+ );
10104
10600
  preparedAgentRuntimeCache = /* @__PURE__ */ new Map();
10105
10601
  hybridStoreCache = /* @__PURE__ */ new Map();
10106
10602
  }
@@ -10216,8 +10712,8 @@ async function runAgentUpdateCommand(args2, deps = {}) {
10216
10712
  ok: true,
10217
10713
  agentKey: built.agentKey,
10218
10714
  baseUrl: built.serverUrl,
10219
- updates: built.updates,
10220
- record: built.nextRecord
10715
+ updates: sanitizeAgentRecordForCliOutput(built.updates),
10716
+ record: sanitizeAgentRecordForCliOutput(built.nextRecord)
10221
10717
  }, null, 2));
10222
10718
  output2.write("\n");
10223
10719
  return 0;
@@ -10289,8 +10785,8 @@ async function runAgentCreateCommand(args2, deps = {}) {
10289
10785
  ok: true,
10290
10786
  agentKey: built.agentKey,
10291
10787
  baseUrl: built.serverUrl,
10292
- updates: built.updates,
10293
- record: built.nextRecord
10788
+ updates: sanitizeAgentRecordForCliOutput(built.updates),
10789
+ record: sanitizeAgentRecordForCliOutput(built.nextRecord)
10294
10790
  }, null, 2));
10295
10791
  output2.write("\n");
10296
10792
  return 0;
@@ -10588,35 +11084,59 @@ function isTableRow(line) {
10588
11084
  const cells = splitTableCells(line);
10589
11085
  return cells.length >= 2 && cells.some((cell) => cell.length > 0);
10590
11086
  }
11087
+ function isPipeWrappedTableRow(line) {
11088
+ const trimmed = line.trim();
11089
+ return trimmed.startsWith("|") && trimmed.endsWith("|") && isTableRow(line);
11090
+ }
11091
+ function isCodeFenceLine(line) {
11092
+ return /^\s*```/.test(line);
11093
+ }
11094
+ function tableRowToBullet(line) {
11095
+ const row = splitTableCells(line);
11096
+ const label = row[0] ?? "";
11097
+ const detail = row.slice(1).join(" \u2014 ").trim();
11098
+ return detail ? ` \u2022 ${label} \u2014 ${detail}` : ` \u2022 ${label}`;
11099
+ }
10591
11100
  function convertMarkdownTablesForTerminal(text) {
10592
11101
  const lines = text.split("\n");
10593
11102
  const out = [];
11103
+ let inFence = false;
10594
11104
  for (let index = 0; index < lines.length; index += 1) {
10595
11105
  const line = lines[index] ?? "";
11106
+ if (isCodeFenceLine(line)) {
11107
+ inFence = !inFence;
11108
+ out.push(line);
11109
+ continue;
11110
+ }
11111
+ if (inFence) {
11112
+ out.push(line);
11113
+ continue;
11114
+ }
10596
11115
  const next = lines[index + 1] ?? "";
10597
11116
  if (isTableRow(line) && isTableSeparator(next)) {
10598
- const headers = splitTableCells(line);
10599
11117
  index += 1;
10600
11118
  while (index + 1 < lines.length && isTableRow(lines[index + 1] ?? "") && !isTableSeparator(lines[index + 1] ?? "")) {
10601
11119
  index += 1;
10602
- const row = splitTableCells(lines[index] ?? "");
10603
- const label = row[0] ?? "";
10604
- const detail = row.slice(1).join(" \u2014 ").trim();
10605
- out.push(detail ? ` \u2022 ${label} \u2014 ${detail}` : ` \u2022 ${label}`);
11120
+ out.push(tableRowToBullet(lines[index] ?? ""));
10606
11121
  }
10607
11122
  if (out.length > 0 && out[out.length - 1] !== "") out.push("");
10608
11123
  continue;
10609
11124
  }
11125
+ if (isPipeWrappedTableRow(line)) {
11126
+ if (!isTableSeparator(line)) out.push(tableRowToBullet(line));
11127
+ continue;
11128
+ }
10610
11129
  out.push(line);
10611
11130
  }
10612
11131
  return out.join("\n");
10613
11132
  }
10614
- function polishAssistantStructure(text) {
10615
- return convertMarkdownTablesForTerminal(text).replace(/\r\n/g, "\n").replace(/([^\n])\n(#{1,3} )/g, "$1\n\n$2").replace(/\n{4,}/g, "\n\n\n").trim();
11133
+ function polishAssistantStructure(text, options = {}) {
11134
+ const polished = convertMarkdownTablesForTerminal(text).replace(/\r\n/g, "\n").replace(/([^\n])\n(#{1,3} )/g, "$1\n\n$2").replace(/\n{4,}/g, "\n\n\n");
11135
+ return options.trimEdges === false ? polished : polished.trim();
10616
11136
  }
10617
11137
  function styleInlineMarkdown(line, mode) {
10618
11138
  if (mode === "plain") return line;
10619
- return line.replace(/\*\*(.+?)\*\*/g, `${ANSI.bold}$1${ANSI.reset}`);
11139
+ return line.replace(/`([^`]+)`/g, `${ANSI.cyan}$1${ANSI.reset}`).replace(/\*\*(.+?)\*\*/g, `${ANSI.bold}$1${ANSI.reset}`);
10620
11140
  }
10621
11141
  function styleRichMarkdownLine(line) {
10622
11142
  const heading = line.match(/^(#{1,3})\s+(.+)$/);
@@ -10631,20 +11151,27 @@ function styleRichMarkdownLine(line) {
10631
11151
  }
10632
11152
  return styleInlineMarkdown(line, "rich");
10633
11153
  }
10634
- function formatAssistantDisplay(text, mode = "rich") {
10635
- const polished = polishAssistantStructure(text);
10636
- if (mode === "plain") {
10637
- return polished.split("\n").map((line) => styleInlineMarkdown(line, "plain")).join("\n");
10638
- }
10639
- return polished.split("\n").map((line) => styleRichMarkdownLine(line)).join("\n");
11154
+ function formatAssistantDisplay(text, mode = "rich", options = {}) {
11155
+ const polished = polishAssistantStructure(text, options);
11156
+ let inFence = false;
11157
+ return polished.split("\n").map((line) => {
11158
+ if (isCodeFenceLine(line)) {
11159
+ inFence = !inFence;
11160
+ return mode === "plain" ? line : `${ANSI.dim}${line}${ANSI.reset}`;
11161
+ }
11162
+ if (inFence) return line;
11163
+ if (mode === "plain") return styleInlineMarkdown(line, "plain");
11164
+ return styleRichMarkdownLine(line);
11165
+ }).join("\n");
10640
11166
  }
10641
11167
  function emitFormattedAssistantBlock(write, text, renderMode, trailingNewline = false) {
10642
11168
  if (!text) return;
10643
- write(formatAssistantDisplay(text, renderMode));
11169
+ write(formatAssistantDisplay(text, renderMode, { trimEdges: false }));
10644
11170
  if (trailingNewline) write("\n");
10645
11171
  }
10646
11172
  function createRenderAwareStreamWriter(args2) {
10647
11173
  let buffer = "";
11174
+ let inFence = false;
10648
11175
  const flushCompleteBlocks = () => {
10649
11176
  if (args2.renderMode === "plain") {
10650
11177
  if (!buffer) return;
@@ -10655,23 +11182,41 @@ function createRenderAwareStreamWriter(args2) {
10655
11182
  while (buffer.includes("\n")) {
10656
11183
  const lines = buffer.split("\n");
10657
11184
  if (lines.length < 2) break;
10658
- if (isTableRow(lines[0] ?? "") && isTableSeparator(lines[1] ?? "")) {
10659
- let end = 2;
10660
- while (end < lines.length && isTableRow(lines[end] ?? "") && !isTableSeparator(lines[end] ?? "")) {
10661
- end += 1;
10662
- }
10663
- const tableComplete = end < lines.length || buffer.endsWith("\n");
10664
- if (!tableComplete) break;
10665
- emitFormattedAssistantBlock(
10666
- args2.write,
10667
- lines.slice(0, end).join("\n"),
10668
- args2.renderMode,
10669
- true
10670
- );
10671
- buffer = lines.slice(end).join("\n");
11185
+ const firstLine = lines[0] ?? "";
11186
+ if (isCodeFenceLine(firstLine)) {
11187
+ inFence = !inFence;
11188
+ args2.write(`${ANSI.dim}${firstLine}${ANSI.reset}
11189
+ `);
11190
+ buffer = lines.slice(1).join("\n");
11191
+ continue;
11192
+ }
11193
+ if (inFence) {
11194
+ args2.write(`${firstLine}
11195
+ `);
11196
+ buffer = lines.slice(1).join("\n");
10672
11197
  continue;
10673
11198
  }
10674
- emitFormattedAssistantBlock(args2.write, lines[0] ?? "", args2.renderMode, true);
11199
+ if (isTableRow(firstLine)) {
11200
+ const nextLineComplete = lines.length > 2;
11201
+ if (!nextLineComplete) break;
11202
+ if (isTableSeparator(lines[1] ?? "")) {
11203
+ let end = 2;
11204
+ while (end < lines.length && isTableRow(lines[end] ?? "") && !isTableSeparator(lines[end] ?? "")) {
11205
+ end += 1;
11206
+ }
11207
+ const tableComplete = end < lines.length - 1;
11208
+ if (!tableComplete) break;
11209
+ emitFormattedAssistantBlock(
11210
+ args2.write,
11211
+ lines.slice(0, end).join("\n"),
11212
+ args2.renderMode,
11213
+ true
11214
+ );
11215
+ buffer = lines.slice(end).join("\n");
11216
+ continue;
11217
+ }
11218
+ }
11219
+ emitFormattedAssistantBlock(args2.write, firstLine, args2.renderMode, true);
10675
11220
  buffer = lines.slice(1).join("\n");
10676
11221
  }
10677
11222
  };
@@ -10689,6 +11234,8 @@ function createRenderAwareStreamWriter(args2) {
10689
11234
  if (!buffer) return;
10690
11235
  if (args2.renderMode === "plain") {
10691
11236
  args2.write(buffer);
11237
+ } else if (inFence) {
11238
+ args2.write(buffer);
10692
11239
  } else {
10693
11240
  emitFormattedAssistantBlock(args2.write, buffer, args2.renderMode);
10694
11241
  }
@@ -11307,6 +11854,7 @@ var init_gatewayHttpStatus = __esm({
11307
11854
  });
11308
11855
 
11309
11856
  // packages/cli/client/agentRun.ts
11857
+ import { ulid as ulid3 } from "ulid";
11310
11858
  async function loadRunLocalAgentTurn() {
11311
11859
  const { runLocalAgentTurn: runLocalAgentTurn2 } = await Promise.resolve().then(() => (init_agentRuntimeLocal(), agentRuntimeLocal_exports));
11312
11860
  return runLocalAgentTurn2;
@@ -11322,7 +11870,9 @@ function formatElapsed(totalSeconds) {
11322
11870
  }
11323
11871
  function findServerPlatformTools(toolNames) {
11324
11872
  if (!Array.isArray(toolNames)) return [];
11325
- return toolNames.filter((toolName) => SERVER_PLATFORM_TOOL_NAMES.has(toolName));
11873
+ return toolNames.filter(
11874
+ (toolName) => SERVER_PLATFORM_TOOL_NAMES.has(toolName)
11875
+ );
11326
11876
  }
11327
11877
  function resolveServerPlatformToolNames(agentConfig) {
11328
11878
  return findServerPlatformTools([
@@ -11333,7 +11883,9 @@ function resolveServerPlatformToolNames(agentConfig) {
11333
11883
  function isKnownServerPlatformAgent(options) {
11334
11884
  if (KNOWN_SERVER_PLATFORM_AGENT_KEYS.has(options.agentKey)) return true;
11335
11885
  const normalizedKey = normalizeAgentHandle(options.agentKey);
11336
- return Boolean(normalizedKey && KNOWN_SERVER_PLATFORM_AGENT_ALIASES.has(normalizedKey));
11886
+ return Boolean(
11887
+ normalizedKey && KNOWN_SERVER_PLATFORM_AGENT_ALIASES.has(normalizedKey)
11888
+ );
11337
11889
  }
11338
11890
  function shouldShowUsage(env) {
11339
11891
  return env.NOLO_DEBUG === "1" || env.NOLO_SHOW_USAGE === "1";
@@ -11344,7 +11896,8 @@ async function resolveCurrentMachineId(options) {
11344
11896
  function resolveRequestedRuntimeMode(options) {
11345
11897
  const envMode = options.env.NOLO_RUNTIME_MODE;
11346
11898
  if (options.runtimeMode) return options.runtimeMode;
11347
- if (envMode === "local" || envMode === "server" || envMode === "auto") return envMode;
11899
+ if (envMode === "local" || envMode === "server" || envMode === "auto")
11900
+ return envMode;
11348
11901
  return "auto";
11349
11902
  }
11350
11903
  function buildDefaultLocalRuntimeAdapter(options) {
@@ -11357,7 +11910,9 @@ function buildDefaultLocalRuntimeAdapter(options) {
11357
11910
  });
11358
11911
  }
11359
11912
  function resolveLocalRuntimeAdapter(options) {
11360
- return options.localRuntimeAdapter || options.localRuntimeAdapterFactory?.(options.env, { cwd: options.localRuntimeCwd }) || buildDefaultLocalRuntimeAdapter(options);
11913
+ return options.localRuntimeAdapter || options.localRuntimeAdapterFactory?.(options.env, {
11914
+ cwd: options.localRuntimeCwd
11915
+ }) || buildDefaultLocalRuntimeAdapter(options);
11361
11916
  }
11362
11917
  async function shouldSkipAutoLocalForServerPlatformTools(options) {
11363
11918
  if (isBuiltinNoloAgentRef(options.agentKey)) return false;
@@ -11492,7 +12047,8 @@ function formatToolJsonEvent(event) {
11492
12047
  `;
11493
12048
  }
11494
12049
  function shouldAttemptAutoLocal(options) {
11495
- if (options.localRuntimeAdapter || options.localRuntimeAdapterFactory) return true;
12050
+ if (options.localRuntimeAdapter || options.localRuntimeAdapterFactory)
12051
+ return true;
11496
12052
  if (options.env.NOLO_DISABLE_CLI_WORKSPACE_TOOLS !== "1" && isBuiltinNoloAgentRef(options.agentKey) && resolveAuthToken2(options.env)) {
11497
12053
  return true;
11498
12054
  }
@@ -11505,7 +12061,8 @@ function shouldAttemptAutoLocal(options) {
11505
12061
  }
11506
12062
  function formatUsage(usage2, dialogId) {
11507
12063
  const parts = [];
11508
- if (typeof dialogId === "string" && dialogId) parts.push(`dialog=${dialogId}`);
12064
+ if (typeof dialogId === "string" && dialogId)
12065
+ parts.push(`dialog=${dialogId}`);
11509
12066
  const input2 = usage2?.input_tokens ?? usage2?.prompt_tokens ?? 0;
11510
12067
  const output2 = usage2?.output_tokens ?? usage2?.completion_tokens ?? 0;
11511
12068
  if (input2 || output2) parts.push(`tokens=${input2}+${output2}`);
@@ -11535,19 +12092,23 @@ async function readAgentRunFailureMetadata(res) {
11535
12092
  };
11536
12093
  }
11537
12094
  async function runHttpAgentTurn(options, authToken) {
11538
- const spinner = new Spinner(options.output, `${options.agentName} -> working`);
12095
+ const spinner = new Spinner(
12096
+ options.output,
12097
+ `${options.agentName} -> working`
12098
+ );
11539
12099
  spinner.start();
11540
12100
  const fetchImpl = options.fetchImpl ?? fetch;
11541
12101
  const subjectRefs = buildSubjectRefs(options);
11542
- const allowedChildAgentKeys = options.allowedChildAgentKeys?.filter((key) => key.trim());
11543
- const allowedToolNames = options.allowedToolNames?.filter((name) => name.trim());
12102
+ const allowedChildAgentKeys = options.allowedChildAgentKeys?.filter(
12103
+ (key) => key.trim()
12104
+ );
12105
+ const allowedToolNames = options.allowedToolNames?.filter(
12106
+ (name) => name.trim()
12107
+ );
11544
12108
  const shouldStream = !options.noStream && !options.background;
11545
12109
  const buildRequestBody = (stream) => JSON.stringify({
11546
12110
  agentKey: options.agentKey,
11547
- userInput: buildUserInputContent(
11548
- options.message,
11549
- options.imageUrls
11550
- ),
12111
+ userInput: buildUserInputContent(options.message, options.imageUrls),
11551
12112
  runtimeContext: {
11552
12113
  surface: "cli",
11553
12114
  host: "terminal",
@@ -11683,12 +12244,78 @@ async function refreshMissingLocalAgentConfig(options) {
11683
12244
  return Boolean(agentConfig);
11684
12245
  }
11685
12246
  async function runLocalAgentTurnForCli(options, settings) {
11686
- const adapter = resolveLocalRuntimeAdapter(options);
11687
- if (!adapter) {
11688
- options.output.write("[nolo] Local runtime was requested but no local runtime adapter is available.\n");
12247
+ const baseAdapter = resolveLocalRuntimeAdapter(options);
12248
+ if (!baseAdapter) {
12249
+ options.output.write(
12250
+ "[nolo] Local runtime was requested but no local runtime adapter is available.\n"
12251
+ );
11689
12252
  return { exitCode: 1 };
11690
12253
  }
11691
- const spinner = new Spinner(options.output, `${options.agentName} -> working locally`);
12254
+ const subjectRefs = buildSubjectRefs(options);
12255
+ const allowedChildAgentKeys = options.allowedChildAgentKeys?.filter(
12256
+ (key) => key.trim()
12257
+ );
12258
+ const allowedToolNames = options.allowedToolNames?.filter(
12259
+ (name) => name.trim()
12260
+ );
12261
+ const runtimeContext2 = subjectRefs || allowedChildAgentKeys?.length || allowedToolNames?.length || options.parentWakeOnTerminal ? {
12262
+ ...subjectRefs ? { subjectRefs } : {},
12263
+ ...allowedChildAgentKeys?.length ? { allowedChildAgentKeys } : {},
12264
+ ...allowedToolNames?.length ? { allowedToolNames } : {},
12265
+ ...options.parentWakeOnTerminal ? { parentWakeOnTerminal: true } : {},
12266
+ ...options.parentDialogId ? { parentThreadId: options.parentDialogId } : {}
12267
+ } : void 0;
12268
+ const currentDialogId = options.continueDialogId ?? ulid3();
12269
+ const runChildTurn = async (input2) => {
12270
+ const { runLocalAgentTurn: runLocalAgentTurn2 } = await Promise.resolve().then(() => (init_agentRuntimeLocal(), agentRuntimeLocal_exports));
12271
+ return runLocalAgentTurn2(input2);
12272
+ };
12273
+ const createFreshChildBaseAdapter = () => options.localRuntimeAdapterFactory?.(options.env, {
12274
+ cwd: options.localRuntimeCwd
12275
+ }) ?? buildDefaultLocalRuntimeAdapter(options);
12276
+ const withLocalDelegation = (args2) => {
12277
+ let adapter2;
12278
+ const callAgentExecutor = createCliCallAgentToolExecutor(
12279
+ {
12280
+ env: options.env,
12281
+ fetchImpl: options.fetchImpl,
12282
+ cwd: options.localRuntimeCwd,
12283
+ output: options.output
12284
+ },
12285
+ {
12286
+ createChildAdapter: (child) => withLocalDelegation({
12287
+ base: createFreshChildBaseAdapter(),
12288
+ dialogId: child.dialogId,
12289
+ spaceId: child.spaceId,
12290
+ runtimeContext: child.runtimeContext
12291
+ }),
12292
+ runChildTurn,
12293
+ dialogId: args2.dialogId,
12294
+ spaceId: args2.spaceId,
12295
+ runtimeContext: args2.runtimeContext
12296
+ }
12297
+ );
12298
+ adapter2 = {
12299
+ ...args2.base,
12300
+ executeTool: async (call) => {
12301
+ if (call.name === "callAgent") {
12302
+ return callAgentExecutor(call);
12303
+ }
12304
+ return args2.base.executeTool(call);
12305
+ }
12306
+ };
12307
+ return adapter2;
12308
+ };
12309
+ const adapter = withLocalDelegation({
12310
+ base: baseAdapter,
12311
+ dialogId: currentDialogId,
12312
+ spaceId: options.spaceId,
12313
+ runtimeContext: runtimeContext2
12314
+ });
12315
+ const spinner = new Spinner(
12316
+ options.output,
12317
+ `${options.agentName} -> working locally`
12318
+ );
11692
12319
  spinner.start();
11693
12320
  try {
11694
12321
  const toolDisplayMode = resolveToolDisplayMode(options.env);
@@ -11707,32 +12334,19 @@ async function runLocalAgentTurnForCli(options, settings) {
11707
12334
  (chunk) => renderWriter.push(chunk),
11708
12335
  thinkingMode
11709
12336
  );
11710
- const subjectRefs = buildSubjectRefs(options);
11711
- const allowedChildAgentKeys = options.allowedChildAgentKeys?.filter((key) => key.trim());
11712
- const allowedToolNames = options.allowedToolNames?.filter((name) => name.trim());
11713
12337
  const runLocalAgentTurn2 = await loadRunLocalAgentTurn();
11714
12338
  const result = await runLocalAgentTurn2({
11715
12339
  adapter,
11716
12340
  agentRef: options.agentKey,
11717
- input: buildUserInputContent(
11718
- options.message,
11719
- options.imageUrls
11720
- ),
11721
- continueDialogId: options.continueDialogId,
12341
+ input: buildUserInputContent(options.message, options.imageUrls),
12342
+ continueDialogId: currentDialogId,
11722
12343
  spaceId: options.spaceId,
11723
12344
  category: options.category,
11724
12345
  inheritedFromDialogKey: options.inheritedFromDialogKey,
11725
12346
  parentDialogId: options.parentDialogId,
11726
12347
  background: options.background,
11727
12348
  noStream: options.noStream,
11728
- ...subjectRefs || allowedChildAgentKeys?.length || allowedToolNames?.length ? {
11729
- runtimeContext: {
11730
- ...subjectRefs ? { subjectRefs } : {},
11731
- ...allowedChildAgentKeys?.length ? { allowedChildAgentKeys } : {},
11732
- ...allowedToolNames?.length ? { allowedToolNames } : {},
11733
- ...options.parentWakeOnTerminal ? { parentWakeOnTerminal: true } : {}
11734
- }
11735
- } : {},
12349
+ ...runtimeContext2 ? { runtimeContext: runtimeContext2 } : {},
11736
12350
  ...typeof options.timeoutMs === "number" ? { timeoutMs: options.timeoutMs } : {},
11737
12351
  ...options.actionGateHandler ? { onActionGate: options.actionGateHandler } : {},
11738
12352
  ...options.onLoopEvent ? { onLoopEvent: options.onLoopEvent } : {},
@@ -11764,7 +12378,10 @@ ${options.agentName} > `);
11764
12378
  renderWriter.flush();
11765
12379
  options.output.write("\n");
11766
12380
  } else {
11767
- const content = formatAssistantResponseForCli(result.content.trim(), options);
12381
+ const content = formatAssistantResponseForCli(
12382
+ result.content.trim(),
12383
+ options
12384
+ );
11768
12385
  if (content) {
11769
12386
  options.output.write(`
11770
12387
  ${options.agentName} > ${content}
@@ -11794,7 +12411,9 @@ ${options.agentName} > (no text response)
11794
12411
  async function readStreamingAgentRun(options, res) {
11795
12412
  const reader = res.body?.getReader();
11796
12413
  if (!reader) {
11797
- options.output.write("[nolo] Agent stream response did not include a readable body.\n");
12414
+ options.output.write(
12415
+ "[nolo] Agent stream response did not include a readable body.\n"
12416
+ );
11798
12417
  return { exitCode: 1 };
11799
12418
  }
11800
12419
  const decoder = new TextDecoder();
@@ -11827,7 +12446,9 @@ ${options.agentName} > `);
11827
12446
  dialogId = payload.dialogId;
11828
12447
  }
11829
12448
  if (payload?.error || payload?.type === "error") {
11830
- throw new Error(String(payload.error || payload.message || "Agent stream failed"));
12449
+ throw new Error(
12450
+ String(payload.error || payload.message || "Agent stream failed")
12451
+ );
11831
12452
  }
11832
12453
  if (payload?.type === "done") {
11833
12454
  usage2 = payload.usage;
@@ -11868,7 +12489,9 @@ ${options.agentName} > `);
11868
12489
  [nolo] Agent stream transport interrupted after dialog ${dialogId} was created: ${message}
11869
12490
  `
11870
12491
  );
11871
- options.output.write("[nolo] The agent run may still finish on the server; read the dialog before retrying.\n");
12492
+ options.output.write(
12493
+ "[nolo] The agent run may still finish on the server; read the dialog before retrying.\n"
12494
+ );
11872
12495
  return { exitCode: 0, dialogId, streamInterrupted: true };
11873
12496
  }
11874
12497
  options.output.write(`
@@ -11888,7 +12511,8 @@ ${options.agentName} > (no text response)
11888
12511
  options.output.write("\n");
11889
12512
  }
11890
12513
  const usageText = formatUsage(usage2, dialogId);
11891
- if (usageText && shouldShowUsage(options.env)) options.output.write(`${usageText}
12514
+ if (usageText && shouldShowUsage(options.env))
12515
+ options.output.write(`${usageText}
11892
12516
  `);
11893
12517
  return {
11894
12518
  exitCode: 0,
@@ -11905,7 +12529,9 @@ async function runAgentTurn(options) {
11905
12529
  if (runtimeMode === "auto" && shouldAttemptAutoLocal(options)) {
11906
12530
  const skipLocal = await shouldSkipAutoLocalForServerPlatformTools(options);
11907
12531
  if (!skipLocal) {
11908
- const localResult = await runLocalAgentTurnForCli(options, { reportFailure: false });
12532
+ const localResult = await runLocalAgentTurnForCli(options, {
12533
+ reportFailure: false
12534
+ });
11909
12535
  if (localResult.exitCode === 0) {
11910
12536
  return {
11911
12537
  exitCode: localResult.exitCode,
@@ -13673,19 +14299,19 @@ import { homedir as nodeHomedir } from "node:os";
13673
14299
  import { join as join10 } from "node:path";
13674
14300
  import * as nodeFs from "node:fs";
13675
14301
  import { spawn as nodeSpawn } from "node:child_process";
13676
- function resolveNoloHome2(env, homedir11 = nodeHomedir) {
14302
+ function resolveNoloHome2(env, homedir10 = nodeHomedir) {
13677
14303
  const fromEnv = env?.NOLO_HOME;
13678
14304
  if (typeof fromEnv === "string" && fromEnv.length > 0) return fromEnv;
13679
- return join10(homedir11(), ".nolo");
14305
+ return join10(homedir10(), ".nolo");
13680
14306
  }
13681
- function resolveRunsDir(env, homedir11 = nodeHomedir) {
13682
- return join10(resolveNoloHome2(env, homedir11), "runs");
14307
+ function resolveRunsDir(env, homedir10 = nodeHomedir) {
14308
+ return join10(resolveNoloHome2(env, homedir10), "runs");
13683
14309
  }
13684
- function resolveRunRecordPath(runId, env, homedir11 = nodeHomedir) {
13685
- return join10(resolveRunsDir(env, homedir11), `${runId}.json`);
14310
+ function resolveRunRecordPath(runId, env, homedir10 = nodeHomedir) {
14311
+ return join10(resolveRunsDir(env, homedir10), `${runId}.json`);
13686
14312
  }
13687
- function resolveRunLogPath(runId, env, homedir11 = nodeHomedir) {
13688
- return join10(resolveRunsDir(env, homedir11), `${runId}.log`);
14313
+ function resolveRunLogPath(runId, env, homedir10 = nodeHomedir) {
14314
+ return join10(resolveRunsDir(env, homedir10), `${runId}.log`);
13689
14315
  }
13690
14316
  function defaultGenerateRunId() {
13691
14317
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
@@ -13693,13 +14319,13 @@ function defaultGenerateRunId() {
13693
14319
  return `run-${timestamp}-${random}`;
13694
14320
  }
13695
14321
  function writeRunRecord(record, deps = {}) {
13696
- const fs5 = deps.fs ?? nodeFs;
14322
+ const fs6 = deps.fs ?? nodeFs;
13697
14323
  const path8 = resolveRunRecordPath(record.runId, deps.env, deps.homedir);
13698
- fs5.mkdirSync(resolveRunsDir(deps.env, deps.homedir), { recursive: true });
13699
- fs5.writeFileSync(path8, JSON.stringify(record, null, 2));
14324
+ fs6.mkdirSync(resolveRunsDir(deps.env, deps.homedir), { recursive: true });
14325
+ fs6.writeFileSync(path8, JSON.stringify(record, null, 2));
13700
14326
  }
13701
14327
  function createRunActivityTracker(runId, deps = {}, options = {}) {
13702
- const fs5 = deps.fs ?? nodeFs;
14328
+ const fs6 = deps.fs ?? nodeFs;
13703
14329
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
13704
14330
  const minWriteIntervalMs = options.minWriteIntervalMs ?? DEFAULT_ACTIVITY_WRITE_INTERVAL_MS;
13705
14331
  let lastEventAt = now().toISOString();
@@ -13773,20 +14399,20 @@ function createRunActivityTracker(runId, deps = {}, options = {}) {
13773
14399
  return { onLoopEvent, getActivity, flush, dispose };
13774
14400
  }
13775
14401
  function readRunRecord(runId, deps = {}) {
13776
- const fs5 = deps.fs ?? nodeFs;
14402
+ const fs6 = deps.fs ?? nodeFs;
13777
14403
  const path8 = resolveRunRecordPath(runId, deps.env, deps.homedir);
13778
14404
  try {
13779
- return JSON.parse(fs5.readFileSync(path8, "utf8"));
14405
+ return JSON.parse(fs6.readFileSync(path8, "utf8"));
13780
14406
  } catch {
13781
14407
  return null;
13782
14408
  }
13783
14409
  }
13784
14410
  function listRunRecords(deps = {}) {
13785
- const fs5 = deps.fs ?? nodeFs;
14411
+ const fs6 = deps.fs ?? nodeFs;
13786
14412
  const dir = resolveRunsDir(deps.env, deps.homedir);
13787
14413
  let entries = [];
13788
14414
  try {
13789
- entries = fs5.readdirSync(dir);
14415
+ entries = fs6.readdirSync(dir);
13790
14416
  } catch {
13791
14417
  return [];
13792
14418
  }
@@ -13832,16 +14458,16 @@ function buildAgentRunChildCommand(options) {
13832
14458
  }
13833
14459
  async function spawnLocalBackgroundRun(input2, deps = {}) {
13834
14460
  const env = deps.env ?? process.env;
13835
- const homedir11 = deps.homedir ?? nodeHomedir;
13836
- const fs5 = deps.fs ?? nodeFs;
14461
+ const homedir10 = deps.homedir ?? nodeHomedir;
14462
+ const fs6 = deps.fs ?? nodeFs;
13837
14463
  const spawn5 = deps.spawn ?? nodeSpawn;
13838
14464
  const generateRunId = deps.generateRunId ?? defaultGenerateRunId;
13839
14465
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
13840
14466
  const runId = generateRunId();
13841
- const logPath = resolveRunLogPath(runId, env, homedir11);
13842
- const recordPath = resolveRunRecordPath(runId, env, homedir11);
13843
- const runsDir = resolveRunsDir(env, homedir11);
13844
- fs5.mkdirSync(runsDir, { recursive: true });
14467
+ const logPath = resolveRunLogPath(runId, env, homedir10);
14468
+ const recordPath = resolveRunRecordPath(runId, env, homedir10);
14469
+ const runsDir = resolveRunsDir(env, homedir10);
14470
+ fs6.mkdirSync(runsDir, { recursive: true });
13845
14471
  const record = {
13846
14472
  runId,
13847
14473
  agentKey: input2.agentKey,
@@ -13852,7 +14478,7 @@ async function spawnLocalBackgroundRun(input2, deps = {}) {
13852
14478
  status: "running",
13853
14479
  logPath
13854
14480
  };
13855
- fs5.writeFileSync(recordPath, JSON.stringify(record, null, 2));
14481
+ fs6.writeFileSync(recordPath, JSON.stringify(record, null, 2));
13856
14482
  const { execPath, childArgs } = buildAgentRunChildCommand({
13857
14483
  rawArgs: input2.rawArgs,
13858
14484
  commandPath: input2.commandPath,
@@ -13863,7 +14489,7 @@ async function spawnLocalBackgroundRun(input2, deps = {}) {
13863
14489
  NOLO_AGENT_RUN_CHILD: "1",
13864
14490
  NOLO_AGENT_RUN_ID: runId
13865
14491
  };
13866
- const logFd = fs5.openSync(logPath, "a");
14492
+ const logFd = fs6.openSync(logPath, "a");
13867
14493
  const proc = spawn5(execPath, childArgs, {
13868
14494
  cwd: input2.cwd,
13869
14495
  env: childEnv,
@@ -13873,7 +14499,7 @@ async function spawnLocalBackgroundRun(input2, deps = {}) {
13873
14499
  proc.unref();
13874
14500
  if (typeof proc.pid === "number") {
13875
14501
  record.pid = proc.pid;
13876
- fs5.writeFileSync(recordPath, JSON.stringify(record, null, 2));
14502
+ fs6.writeFileSync(recordPath, JSON.stringify(record, null, 2));
13877
14503
  }
13878
14504
  return { runId, pid: proc.pid, logPath };
13879
14505
  }
@@ -13926,9 +14552,9 @@ function formatDuration(startedAt, endedAt) {
13926
14552
  return `${seconds}s`;
13927
14553
  }
13928
14554
  function readLastLogLines(logPath, count, deps) {
13929
- const fs5 = deps.fs ?? nodeFs;
14555
+ const fs6 = deps.fs ?? nodeFs;
13930
14556
  try {
13931
- const content = fs5.readFileSync(logPath, "utf8");
14557
+ const content = fs6.readFileSync(logPath, "utf8");
13932
14558
  const lines = content.split("\n");
13933
14559
  if (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
13934
14560
  return lines.slice(-count);
@@ -13937,9 +14563,9 @@ function readLastLogLines(logPath, count, deps) {
13937
14563
  }
13938
14564
  }
13939
14565
  function readLogContent(logPath, tailCount, deps) {
13940
- const fs5 = deps.fs ?? nodeFs;
14566
+ const fs6 = deps.fs ?? nodeFs;
13941
14567
  try {
13942
- const content = fs5.readFileSync(logPath, "utf8");
14568
+ const content = fs6.readFileSync(logPath, "utf8");
13943
14569
  if (typeof tailCount === "number" && tailCount > 0) {
13944
14570
  const lines = content.split("\n");
13945
14571
  if (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
@@ -14206,8 +14832,8 @@ async function runAgentLogsCommand(args2, deps) {
14206
14832
  `);
14207
14833
  return 1;
14208
14834
  }
14209
- const fs5 = deps.fs ?? nodeFs;
14210
- if (!fs5.existsSync(record.logPath)) {
14835
+ const fs6 = deps.fs ?? nodeFs;
14836
+ if (!fs6.existsSync(record.logPath)) {
14211
14837
  deps.output.write(`Log not found: ${record.logPath}
14212
14838
  `);
14213
14839
  return 1;
@@ -14750,7 +15376,6 @@ __export(agentRunCommand_exports, {
14750
15376
  resolveWorkflowReference: () => resolveWorkflowReference,
14751
15377
  runAgentRunCommand: () => runAgentRunCommand
14752
15378
  });
14753
- import { homedir as homedir6 } from "node:os";
14754
15379
  function resolvePositiveMs(value, fallback) {
14755
15380
  return parsePositiveFiniteNumberOrFallback(value, fallback);
14756
15381
  }
@@ -14923,7 +15548,7 @@ async function runAgentRunCommand(args2, deps) {
14923
15548
  }
14924
15549
  let localRuntimeCwd = parsed.cwd;
14925
15550
  if (!localRuntimeCwd && parsed.runtimeMode === "local") {
14926
- localRuntimeCwd = homedir6();
15551
+ localRuntimeCwd = process.cwd();
14927
15552
  }
14928
15553
  const runEnv = buildLocalRunEnv({
14929
15554
  env,
@@ -14936,7 +15561,7 @@ async function runAgentRunCommand(args2, deps) {
14936
15561
  commandPath: deps.commandPath,
14937
15562
  cliEntrypointPath: deps.cliEntrypointPath,
14938
15563
  agentKey,
14939
- cwd: parsed.cwd,
15564
+ cwd: localRuntimeCwd,
14940
15565
  msgFile: readFlagValue(args2, "--msg-file"),
14941
15566
  timeoutMs: parsed.timeoutMs,
14942
15567
  output: output2
@@ -15455,12 +16080,14 @@ function buildCompanionKeys(rawId, userId) {
15455
16080
  }
15456
16081
  function normalizeListedAgent(record) {
15457
16082
  const privateKey = typeof record?.dbKey === "string" ? record.dbKey : "";
15458
- if (privateKey.startsWith("cybot-")) return null;
15459
16083
  const explicitId = typeof record?.id === "string" && record.id ? record.id : void 0;
15460
16084
  const ownerUserId = typeof record?.userId === "string" ? record.userId : "";
15461
16085
  const rawId = explicitId || (ownerUserId && privateKey.startsWith(`agent-${ownerUserId}-`) ? privateKey.slice(`agent-${ownerUserId}-`.length) : parseAgentRecordId(privateKey, explicitId));
15462
16086
  if (!privateKey || !rawId || !ownerUserId) return null;
15463
16087
  const keys = buildCompanionKeys(rawId, ownerUserId);
16088
+ const credentialConfigured = agentRecordHasConfiguredCredential(record);
16089
+ const credentialRef = typeof record?.credentialRef === "string" && record.credentialRef ? record.credentialRef : void 0;
16090
+ const apiKeyRef = typeof record?.apiKeyRef === "string" && record.apiKeyRef ? record.apiKeyRef : void 0;
15464
16091
  return {
15465
16092
  id: rawId,
15466
16093
  privateKey,
@@ -15471,7 +16098,10 @@ function normalizeListedAgent(record) {
15471
16098
  isPublicFlag: !!record?.isPublic,
15472
16099
  publicRecordExists: false,
15473
16100
  type: typeof record?.type === "string" ? record.type : null,
15474
- tools: Array.isArray(record?.tools) ? record.tools.filter((tool) => typeof tool === "string") : []
16101
+ tools: Array.isArray(record?.tools) ? record.tools.filter((tool) => typeof tool === "string") : [],
16102
+ credentialConfigured,
16103
+ credentialRef,
16104
+ apiKeyRef
15475
16105
  };
15476
16106
  }
15477
16107
  function sortListedAgents(agents) {
@@ -15486,8 +16116,7 @@ function parseAgentListArgs(args2) {
15486
16116
  return {
15487
16117
  wantJson: args2.includes("--json"),
15488
16118
  publicOnly: args2.includes("--public-only"),
15489
- idsOnly: args2.includes("--ids-only"),
15490
- includeLegacy: args2.includes("--include-legacy")
16119
+ idsOnly: args2.includes("--ids-only")
15491
16120
  };
15492
16121
  }
15493
16122
  async function listLocalCachedAgents(args2) {
@@ -15576,6 +16205,7 @@ var init_agentListHelpers = __esm({
15576
16205
  "packages/cli/agentListHelpers.ts"() {
15577
16206
  "use strict";
15578
16207
  init_globalRecordOperations();
16208
+ init_agentRecordHelpers();
15579
16209
  }
15580
16210
  });
15581
16211
 
@@ -15632,7 +16262,7 @@ __export(agentListCommands_exports, {
15632
16262
  async function runAgentListCommand(args2, deps = {}) {
15633
16263
  const env = deps.env ?? process.env;
15634
16264
  const output2 = deps.output ?? process.stdout;
15635
- const { wantJson, publicOnly, idsOnly, includeLegacy } = parseAgentListArgs(args2);
16265
+ const { wantJson, publicOnly, idsOnly } = parseAgentListArgs(args2);
15636
16266
  const spaceInput = readOption2(args2, "--space") ?? readOption2(args2, "--space-id");
15637
16267
  const authToken = resolveAuthToken(args2, env);
15638
16268
  if (!authToken) {
@@ -15657,7 +16287,6 @@ async function runAgentListCommand(args2, deps = {}) {
15657
16287
  authToken,
15658
16288
  fallbackFetchImpl,
15659
16289
  fetchImpl,
15660
- includeLegacy,
15661
16290
  serverUrls,
15662
16291
  userId
15663
16292
  });
@@ -15674,7 +16303,6 @@ async function runAgentListCommand(args2, deps = {}) {
15674
16303
  authToken,
15675
16304
  fallbackFetchImpl,
15676
16305
  fetchImpl,
15677
- includeLegacy,
15678
16306
  serverUrl,
15679
16307
  userId,
15680
16308
  queryUserRecords,
@@ -15683,9 +16311,7 @@ async function runAgentListCommand(args2, deps = {}) {
15683
16311
  source = "remote-cache";
15684
16312
  }
15685
16313
  }
15686
- if (!includeLegacy) {
15687
- agents = agents.filter((agent) => agent.privateKey.startsWith("agent-"));
15688
- }
16314
+ agents = agents.filter((agent) => agent.privateKey.startsWith("agent-"));
15689
16315
  let resolvedSpaceId = null;
15690
16316
  if (spaceInput) {
15691
16317
  const { spaceId, spaceKey } = buildSpaceLookup(spaceInput);
@@ -15760,6 +16386,7 @@ async function runAgentListCommand(args2, deps = {}) {
15760
16386
  for (const agent of agents) {
15761
16387
  const status = agent.publicRecordExists ? "public" : "private";
15762
16388
  const flagMismatch = agent.isPublicFlag !== agent.publicRecordExists ? ` flag=${agent.isPublicFlag}` : "";
16389
+ const credentialLine = agent.credentialConfigured ? `credentialConfigured=true${agent.credentialRef ? ` credentialRef=${agent.credentialRef}` : ""}${agent.apiKeyRef ? ` apiKeyRef=${agent.apiKeyRef}` : ""}` : "credentialConfigured=false";
15763
16390
  output2.write(
15764
16391
  [
15765
16392
  `
@@ -15770,7 +16397,8 @@ async function runAgentListCommand(args2, deps = {}) {
15770
16397
  `updatedAt=${agent.updatedAt ?? "-"}`,
15771
16398
  `privateKey=${agent.privateKey}`,
15772
16399
  `publicKey=${agent.publicKey}${flagMismatch}`,
15773
- `tools=${agent.tools.join(", ") || "-"}`
16400
+ `tools=${agent.tools.join(", ") || "-"}`,
16401
+ credentialLine
15774
16402
  ].join("\n")
15775
16403
  );
15776
16404
  output2.write("\n");
@@ -17133,7 +17761,7 @@ import {
17133
17761
  unlinkSync as unlinkSync2,
17134
17762
  writeFileSync as writeFileSync6
17135
17763
  } from "node:fs";
17136
- import { homedir as homedir7 } from "node:os";
17764
+ import { homedir as homedir6 } from "node:os";
17137
17765
  import { basename, dirname as dirname6, join as join12 } from "node:path";
17138
17766
  function readChatgptWebImageLocalJobMeta(payload) {
17139
17767
  if (!isRecord(payload)) return null;
@@ -17274,7 +17902,7 @@ async function runChatgptWebImageLocalJob(input2, deps = {}) {
17274
17902
  if (!prompt) {
17275
17903
  throw new Error("\u7F3A\u5C11\u751F\u56FE prompt\uFF08payload.meta.prompt \u5FC5\u586B\uFF09");
17276
17904
  }
17277
- const home = (deps.homedir ?? homedir7)();
17905
+ const home = (deps.homedir ?? homedir6)();
17278
17906
  const lockPath = deps.lockPath ?? defaultLockPath(home);
17279
17907
  const outDir = deps.outDir ?? defaultOutDir(home);
17280
17908
  const release2 = acquireChatgptWebImageLock(lockPath);
@@ -19912,7 +20540,7 @@ var init_dialogCommands = __esm({
19912
20540
 
19913
20541
  // packages/cli/docPageHelpers.ts
19914
20542
  import { readFileSync as readFileSync10 } from "node:fs";
19915
- import { ulid as ulid3 } from "ulid";
20543
+ import { ulid as ulid4 } from "ulid";
19916
20544
  function getCliArg(args2, flag) {
19917
20545
  const idx = args2.indexOf(flag);
19918
20546
  return idx !== -1 ? args2[idx + 1] : void 0;
@@ -19931,7 +20559,7 @@ function textToSlate(text) {
19931
20559
  }));
19932
20560
  }
19933
20561
  function createPageId() {
19934
- return ulid3();
20562
+ return ulid4();
19935
20563
  }
19936
20564
  function buildPageKey(userId, pageId) {
19937
20565
  return `page-${userId}-${pageId}`;
@@ -20976,7 +21604,9 @@ var init_docDeleteCommands = __esm({
20976
21604
  // packages/cli/memoryCommands.ts
20977
21605
  var memoryCommands_exports = {};
20978
21606
  __export(memoryCommands_exports, {
20979
- runMemoryDeleteCommand: () => runMemoryDeleteCommand
21607
+ runMemoryDeleteCommand: () => runMemoryDeleteCommand,
21608
+ runMemoryListCommand: () => runMemoryListCommand,
21609
+ runMemoryRememberCommand: () => runMemoryRememberCommand
20980
21610
  });
20981
21611
  function hasFlag4(args2, flag) {
20982
21612
  return args2.includes(flag);
@@ -21182,7 +21812,232 @@ async function runMemoryDeleteCommand(args2, deps = {}) {
21182
21812
  return 1;
21183
21813
  }
21184
21814
  }
21185
- var VALUE_FLAGS2;
21815
+ function printMemoryListUsage(output2) {
21816
+ output2.write(`Usage:
21817
+ nolo memory list [--limit 50] [--kind episodic] [--subject-type agent]
21818
+ nolo memory list --subject-type agent --subject <subjectId> --json
21819
+
21820
+ Options:
21821
+ --limit <n> Page size (1-200, default 50).
21822
+ --cursor <cursor> Continue from a previous page's nextCursor.
21823
+ --kind <kind> Filter episodic / semantic / procedural.
21824
+ --subject-type <type> Filter user / agent / space / project / system.
21825
+ --subject <subjectId> Filter subjectId (requires --subject-type).
21826
+ --json Print machine-readable JSON.
21827
+ --server <url> Prefer this server and include known Nolo peers.
21828
+ --token <jwt> Override AUTH_TOKEN.
21829
+
21830
+ Listing is scoped to the authenticated user's memories.
21831
+ `);
21832
+ }
21833
+ function buildListBody(args2) {
21834
+ const body = {};
21835
+ const limit = readLimit(args2);
21836
+ if (typeof limit === "number") body.limit = limit;
21837
+ const cursor = readOption2(args2, "--cursor")?.trim();
21838
+ if (cursor) body.cursor = cursor;
21839
+ const kind = readOption2(args2, "--kind")?.trim();
21840
+ if (kind) body.kind = kind;
21841
+ const subjectType = readOption2(args2, "--subject-type")?.trim();
21842
+ if (subjectType) body.subjectType = subjectType;
21843
+ const subjectId = (readOption2(args2, "--subject") ?? readOption2(args2, "--subject-id"))?.trim();
21844
+ if (subjectId) body.subjectId = subjectId;
21845
+ return body;
21846
+ }
21847
+ function parseMemoryResponse(text) {
21848
+ if (!text) return { result: null, errorMessage: void 0 };
21849
+ try {
21850
+ const parsed = JSON.parse(text);
21851
+ if (typeof parsed === "object" && parsed !== null && "error" in parsed) {
21852
+ const err = parsed.error;
21853
+ const message = typeof err === "object" && err !== null && "message" in err ? String(err.message ?? "") : "";
21854
+ return { result: parsed, errorMessage: message || parsed.message };
21855
+ }
21856
+ return { result: parsed, errorMessage: void 0 };
21857
+ } catch {
21858
+ return { result: { raw: text }, errorMessage: void 0 };
21859
+ }
21860
+ }
21861
+ async function postMemoryList(args2) {
21862
+ const res = await args2.fetchImpl(`${args2.serverUrl}/api/memory/list`, {
21863
+ method: "POST",
21864
+ headers: {
21865
+ Authorization: `Bearer ${args2.authToken}`,
21866
+ "Content-Type": "application/json"
21867
+ },
21868
+ body: JSON.stringify(args2.body)
21869
+ });
21870
+ const text = await res.text();
21871
+ const parsed = parseMemoryResponse(text);
21872
+ if (!res.ok) {
21873
+ throw new Error(parsed.errorMessage ?? `HTTP ${res.status}`);
21874
+ }
21875
+ if (parsed.errorMessage) {
21876
+ throw new Error(parsed.errorMessage);
21877
+ }
21878
+ return parsed.result;
21879
+ }
21880
+ function renderMemoryItem(item) {
21881
+ if (typeof item !== "object" || item === null) return String(item);
21882
+ const record = item;
21883
+ const parts = [];
21884
+ if (record.id) parts.push(record.id);
21885
+ if (record.kind) parts.push(`kind=${record.kind}`);
21886
+ if (record.subjectType) parts.push(`subject=${record.subjectType}${record.subjectId ? `:${record.subjectId}` : ""}`);
21887
+ if (record.scope) parts.push(`scope=${record.scope}`);
21888
+ const content = record.content ? record.content.length > 80 ? `${record.content.slice(0, 80)}\u2026` : record.content : "";
21889
+ return [parts.join(" "), content].filter(Boolean).join("\n ");
21890
+ }
21891
+ async function runMemoryListCommand(args2, deps = {}) {
21892
+ const env = deps.env ?? process.env;
21893
+ const output2 = deps.output ?? process.stdout;
21894
+ if (hasFlag4(args2, "--help") || hasFlag4(args2, "-h")) {
21895
+ printMemoryListUsage(output2);
21896
+ return 0;
21897
+ }
21898
+ try {
21899
+ assertNoUnknownFlags(args2);
21900
+ const authToken = resolveAuthToken(args2, env);
21901
+ if (!authToken) {
21902
+ output2.write("[nolo] memory list requires an auth token. Run `nolo login` or set AUTH_TOKEN.\n");
21903
+ return 1;
21904
+ }
21905
+ const body = buildListBody(args2);
21906
+ const wantJson = hasFlag4(args2, "--json");
21907
+ const fetchImpl = deps.fetchImpl ?? fetch;
21908
+ const serverUrl = resolveServerUrl(args2, env);
21909
+ const serverUrls = resolveServerCandidates(args2, env, serverUrl);
21910
+ const target = serverUrls[0] ?? serverUrl;
21911
+ try {
21912
+ const result = await postMemoryList({ authToken, body, fetchImpl, serverUrl: target });
21913
+ const items = Array.isArray(result.items) ? result.items : [];
21914
+ if (wantJson) {
21915
+ output2.write(`${JSON.stringify({ items, nextCursor: result.nextCursor, truncated: result.truncated }, null, 2)}
21916
+ `);
21917
+ } else {
21918
+ output2.write(`${target}: ${items.length} memor${items.length === 1 ? "y" : "ies"}
21919
+ `);
21920
+ for (const item of items) {
21921
+ output2.write(` ${renderMemoryItem(item)}
21922
+ `);
21923
+ }
21924
+ if (result.nextCursor) {
21925
+ output2.write(`nextCursor: ${result.nextCursor}
21926
+ `);
21927
+ }
21928
+ if (result.truncated) {
21929
+ output2.write("truncated: true (more entries may exist; page with --cursor)\n");
21930
+ }
21931
+ }
21932
+ return 0;
21933
+ } catch (error) {
21934
+ output2.write(`[nolo] memory list failed: ${toErrorMessage(error)}
21935
+ `);
21936
+ return 1;
21937
+ }
21938
+ } catch (error) {
21939
+ output2.write(`[nolo] memory list failed: ${toErrorMessage(error)}
21940
+ `);
21941
+ return 1;
21942
+ }
21943
+ }
21944
+ function printMemoryRememberUsage(output2) {
21945
+ output2.write(`Usage:
21946
+ nolo memory remember --content "\u7528\u6237\u504F\u597D\u5148\u770B\u7ED3\u8BBA" --kind semantic
21947
+ nolo memory remember --content "..." --kind episodic --scope auto --dialog-id <id>
21948
+
21949
+ Options:
21950
+ --content <text> The memory text to store (required).
21951
+ --kind <kind> episodic / semantic / procedural (required).
21952
+ --scope <scope> auto / user / space (default auto).
21953
+ --dialog-id <id> Attach to a dialog.
21954
+ --space <spaceId> Store under a space (requires space membership).
21955
+ --json Print machine-readable JSON.
21956
+ --server <url> Prefer this server and include known Nolo peers.
21957
+ --token <jwt> Override AUTH_TOKEN.
21958
+ `);
21959
+ }
21960
+ function buildRememberBody(args2) {
21961
+ const content = readOption2(args2, "--content")?.trim();
21962
+ const kind = readOption2(args2, "--kind")?.trim();
21963
+ const scope = readOption2(args2, "--scope")?.trim();
21964
+ const dialogId = readOption2(args2, "--dialog-id")?.trim();
21965
+ const spaceId = readOption2(args2, "--space")?.trim();
21966
+ return { content, kind, scope, dialogId, spaceId };
21967
+ }
21968
+ async function postMemoryRemember(args2) {
21969
+ const res = await args2.fetchImpl(`${args2.serverUrl}/api/memory/remember`, {
21970
+ method: "POST",
21971
+ headers: {
21972
+ Authorization: `Bearer ${args2.authToken}`,
21973
+ "Content-Type": "application/json"
21974
+ },
21975
+ body: JSON.stringify(args2.body)
21976
+ });
21977
+ const text = await res.text();
21978
+ const parsed = parseMemoryResponse(text);
21979
+ if (!res.ok) {
21980
+ throw new Error(parsed.errorMessage ?? `HTTP ${res.status}`);
21981
+ }
21982
+ if (parsed.errorMessage) {
21983
+ throw new Error(parsed.errorMessage);
21984
+ }
21985
+ return parsed.result;
21986
+ }
21987
+ async function runMemoryRememberCommand(args2, deps = {}) {
21988
+ const env = deps.env ?? process.env;
21989
+ const output2 = deps.output ?? process.stdout;
21990
+ if (hasFlag4(args2, "--help") || hasFlag4(args2, "-h")) {
21991
+ printMemoryRememberUsage(output2);
21992
+ return 0;
21993
+ }
21994
+ try {
21995
+ assertNoUnknownFlags(args2);
21996
+ const authToken = resolveAuthToken(args2, env);
21997
+ if (!authToken) {
21998
+ output2.write("[nolo] memory remember requires an auth token. Run `nolo login` or set AUTH_TOKEN.\n");
21999
+ return 1;
22000
+ }
22001
+ const { content, kind, scope, dialogId, spaceId } = buildRememberBody(args2);
22002
+ if (!content) {
22003
+ output2.write("[nolo] memory remember requires --content <text>; use --help for examples.\n");
22004
+ return 1;
22005
+ }
22006
+ if (!kind || !REMEMBER_KINDS.has(kind)) {
22007
+ output2.write("[nolo] memory remember requires --kind <episodic|semantic|procedural>.\n");
22008
+ return 1;
22009
+ }
22010
+ const normalizedScope = scope && REMEMBER_SCOPES.has(scope) ? scope : "auto";
22011
+ const body = { content, kind, scope: normalizedScope };
22012
+ if (dialogId) body.dialogId = dialogId;
22013
+ if (spaceId) body.spaceId = spaceId;
22014
+ const wantJson = hasFlag4(args2, "--json");
22015
+ const fetchImpl = deps.fetchImpl ?? fetch;
22016
+ const serverUrl = resolveServerUrl(args2, env);
22017
+ const serverUrls = resolveServerCandidates(args2, env, serverUrl);
22018
+ const target = serverUrls[0] ?? serverUrl;
22019
+ try {
22020
+ const result = await postMemoryRemember({ authToken, body, fetchImpl, serverUrl: target });
22021
+ if (wantJson) {
22022
+ output2.write(`${JSON.stringify(result, null, 2)}
22023
+ `);
22024
+ } else {
22025
+ output2.write(`${target}: remembered ${kind}
22026
+ `);
22027
+ }
22028
+ return 0;
22029
+ } catch (error) {
22030
+ output2.write(`[nolo] memory remember failed: ${toErrorMessage(error)}
22031
+ `);
22032
+ return 1;
22033
+ }
22034
+ } catch (error) {
22035
+ output2.write(`[nolo] memory remember failed: ${toErrorMessage(error)}
22036
+ `);
22037
+ return 1;
22038
+ }
22039
+ }
22040
+ var VALUE_FLAGS2, REMEMBER_KINDS, REMEMBER_SCOPES;
21186
22041
  var init_memoryCommands = __esm({
21187
22042
  "packages/cli/memoryCommands.ts"() {
21188
22043
  "use strict";
@@ -21190,14 +22045,19 @@ var init_memoryCommands = __esm({
21190
22045
  init_optionalString();
21191
22046
  init_cliEnvHelpers();
21192
22047
  VALUE_FLAGS2 = /* @__PURE__ */ new Set([
22048
+ "--content",
22049
+ "--cursor",
22050
+ "--dialog-id",
21193
22051
  "--facet",
21194
22052
  "--id",
21195
22053
  "--ids",
21196
22054
  "--kind",
21197
22055
  "--limit",
21198
22056
  "--pattern-prefix",
22057
+ "--scope",
21199
22058
  "--server",
21200
22059
  "--server-url",
22060
+ "--space",
21201
22061
  "--source-dialog",
21202
22062
  "--subject",
21203
22063
  "--subject-id",
@@ -21205,6 +22065,8 @@ var init_memoryCommands = __esm({
21205
22065
  "--tag",
21206
22066
  "--token"
21207
22067
  ]);
22068
+ REMEMBER_KINDS = /* @__PURE__ */ new Set(["episodic", "semantic", "procedural"]);
22069
+ REMEMBER_SCOPES = /* @__PURE__ */ new Set(["auto", "user", "space"]);
21208
22070
  }
21209
22071
  });
21210
22072
 
@@ -21452,7 +22314,7 @@ __export(spaceCommands_exports, {
21452
22314
  runSpaceInviteCommand: () => runSpaceInviteCommand,
21453
22315
  runSpaceUploadCommand: () => runSpaceUploadCommand
21454
22316
  });
21455
- import { ulid as ulid4 } from "ulid";
22317
+ import { ulid as ulid5 } from "ulid";
21456
22318
  import { readFileSync as readFileSync11 } from "node:fs";
21457
22319
  import { basename as basename2, extname as extname4 } from "node:path";
21458
22320
  function hasHelpArg2(args2) {
@@ -21548,7 +22410,7 @@ async function runSpaceCreateCommand(args2, deps) {
21548
22410
  const { authToken, userId } = requireTokenUser2(args2, deps.env);
21549
22411
  const serverUrl = resolveServerUrl(args2, deps.env);
21550
22412
  const fetchImpl = deps.fetchImpl ?? fetch;
21551
- const spaceId = normalizeSpaceId(readOption2(args2, "--id") ?? ulid4());
22413
+ const spaceId = normalizeSpaceId(readOption2(args2, "--id") ?? ulid5());
21552
22414
  const now = Date.now();
21553
22415
  const nowISO = new Date(now).toISOString();
21554
22416
  const visibilityRaw = readOption2(args2, "--visibility");
@@ -21763,7 +22625,7 @@ async function runSpaceUploadCommand(args2, deps) {
21763
22625
  });
21764
22626
  const formData = new FormData();
21765
22627
  formData.append("file", new Blob([fileContent], { type: mimeType }), uploadName);
21766
- const fileId = ulid4();
22628
+ const fileId = ulid5();
21767
22629
  const fileDbKey = `file-${userId}-${fileId}`;
21768
22630
  formData.append("metadata", JSON.stringify({
21769
22631
  id: fileId,
@@ -22581,9 +23443,9 @@ var init_noloServerUrl = __esm({
22581
23443
  // packages/cli/client/profileConfig.ts
22582
23444
  import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
22583
23445
  import { dirname as dirname7, join as join13 } from "node:path";
22584
- import { homedir as homedir8 } from "node:os";
23446
+ import { homedir as homedir7 } from "node:os";
22585
23447
  function getDefaultProfileConfigPath() {
22586
- return join13(homedir8(), ".nolo", "config.json");
23448
+ return join13(homedir7(), ".nolo", "config.json");
22587
23449
  }
22588
23450
  function loadProfileConfig(path8 = getDefaultProfileConfigPath()) {
22589
23451
  if (!existsSync11(path8)) return null;
@@ -23611,7 +24473,7 @@ var init_heartbeatLoop = __esm({
23611
24473
  // packages/cli/machineDaemonCommands.ts
23612
24474
  import { spawn as spawn4 } from "node:child_process";
23613
24475
  import { existsSync as existsSync12, mkdirSync as mkdirSync7, openSync, readFileSync as readFileSync13, readdirSync as readdirSync2, realpathSync } from "node:fs";
23614
- import { homedir as homedir9 } from "node:os";
24476
+ import { homedir as homedir8 } from "node:os";
23615
24477
  import { dirname as dirname8, isAbsolute as isAbsolute2, join as join14, relative as relative2, resolve as resolve6 } from "node:path";
23616
24478
  import { fileURLToPath as fileURLToPath4 } from "node:url";
23617
24479
  function readJsonFile(path8) {
@@ -23718,7 +24580,7 @@ async function checkConnectorWorkspaceLinks(cwd, output2, validateWorkspaceLinks
23718
24580
  return false;
23719
24581
  }
23720
24582
  function resolveDaemonLogPath(env) {
23721
- return env.NOLO_CONNECT_LOG || join14(homedir9(), ".nolo", "logs", "connector.log");
24583
+ return env.NOLO_CONNECT_LOG || join14(homedir8(), ".nolo", "logs", "connector.log");
23722
24584
  }
23723
24585
  function buildDaemonCommand(cliEntrypointPath) {
23724
24586
  const execPath = process.execPath;
@@ -24322,9 +25184,87 @@ var init_machineCommands = __esm({
24322
25184
  }
24323
25185
  });
24324
25186
 
25187
+ // packages/cli/cliAuthorityBrokerHealth.ts
25188
+ import fs5 from "node:fs/promises";
25189
+ function asBrokerHealthRecord(value) {
25190
+ return typeof value === "object" && value !== null ? value : {};
25191
+ }
25192
+ async function probeCliAuthorityBrokerHealth(args2) {
25193
+ const deps = {
25194
+ ...defaultCliAuthorityBrokerHealthDeps,
25195
+ ...args2.deps
25196
+ };
25197
+ let metadata;
25198
+ let health;
25199
+ try {
25200
+ [metadata, health] = await Promise.all([
25201
+ deps.readJson(args2.metadataPath).then(asBrokerHealthRecord),
25202
+ deps.readJson(args2.healthPath).then(asBrokerHealthRecord)
25203
+ ]);
25204
+ } catch (error) {
25205
+ return {
25206
+ ok: false,
25207
+ error: `authority broker health artifacts are unavailable: ${toErrorMessage(error)}`
25208
+ };
25209
+ }
25210
+ if (health.ok !== true) {
25211
+ return { ok: false, error: "authority broker health artifact is not ok" };
25212
+ }
25213
+ if (typeof metadata.endpoint !== "string" || metadata.endpoint !== args2.endpoint || health.endpoint !== args2.endpoint) {
25214
+ return { ok: false, error: "authority broker endpoint metadata does not match" };
25215
+ }
25216
+ if (typeof metadata.pid !== "number" || !Number.isInteger(metadata.pid) || metadata.pid <= 0 || health.pid !== metadata.pid) {
25217
+ return { ok: false, error: "authority broker pid metadata is invalid" };
25218
+ }
25219
+ if (!deps.isPidAlive(metadata.pid)) {
25220
+ return {
25221
+ ok: false,
25222
+ error: `authority broker metadata pid ${metadata.pid} is not alive`
25223
+ };
25224
+ }
25225
+ try {
25226
+ await deps.openEndpoint(args2.endpoint);
25227
+ } catch (error) {
25228
+ return {
25229
+ ok: false,
25230
+ error: `authority broker endpoint is unreachable: ${toErrorMessage(error)}`
25231
+ };
25232
+ }
25233
+ return { ok: true };
25234
+ }
25235
+ var defaultCliAuthorityBrokerHealthDeps;
25236
+ var init_cliAuthorityBrokerHealth = __esm({
25237
+ "packages/cli/cliAuthorityBrokerHealth.ts"() {
25238
+ "use strict";
25239
+ init_errorMessage();
25240
+ init_cliAuthorityBrokerClient();
25241
+ defaultCliAuthorityBrokerHealthDeps = {
25242
+ async readJson(filePath) {
25243
+ return JSON.parse(await fs5.readFile(filePath, "utf8"));
25244
+ },
25245
+ isPidAlive(pid) {
25246
+ try {
25247
+ process.kill(pid, 0);
25248
+ return true;
25249
+ } catch (error) {
25250
+ return error.code === "EPERM";
25251
+ }
25252
+ },
25253
+ async openEndpoint(endpoint) {
25254
+ const client = createCliAuthorityBrokerClient({
25255
+ endpoint,
25256
+ invoke: createCliAuthorityBrokerSocketInvoker({ endpoint })
25257
+ });
25258
+ await client.open();
25259
+ }
25260
+ };
25261
+ }
25262
+ });
25263
+
24325
25264
  // packages/cli/runtimeDoctorCommands.ts
24326
25265
  var runtimeDoctorCommands_exports = {};
24327
25266
  __export(runtimeDoctorCommands_exports, {
25267
+ defaultLocalRuntimeProbe: () => defaultLocalRuntimeProbe,
24328
25268
  runDoctorRuntimeCommand: () => runDoctorRuntimeCommand
24329
25269
  });
24330
25270
  function detectLocalAgentConfig(env) {
@@ -24347,7 +25287,7 @@ function detectProviderLabel(env) {
24347
25287
  if (env.GEMINI_API_KEY) return "google via env GEMINI_API_KEY";
24348
25288
  return "missing";
24349
25289
  }
24350
- async function defaultLocalRuntimeProbe(env) {
25290
+ async function defaultLocalRuntimeProbe(env, deps = {}) {
24351
25291
  const { resolveCliLocalRuntimeDbPath: resolveCliLocalRuntimeDbPath3 } = await Promise.resolve().then(() => (init_localRuntimeDb(), localRuntimeDb_exports));
24352
25292
  const dbPath = resolveCliLocalRuntimeDbPath3({ env });
24353
25293
  const authorityDriver = resolveCliAuthorityStoreDriver({ env });
@@ -24356,8 +25296,28 @@ async function defaultLocalRuntimeProbe(env) {
24356
25296
  const authorityHealthPath = resolveCliAuthorityBrokerHealthPath({ transport: "tcp", env });
24357
25297
  const agentKey = readLocalAgentKey(env);
24358
25298
  try {
24359
- const { getDefaultCliLocalRuntimeDb: getDefaultCliLocalRuntimeDb4 } = await Promise.resolve().then(() => (init_localRuntimeDb(), localRuntimeDb_exports));
24360
- const db = await getDefaultCliLocalRuntimeDb4({ env });
25299
+ const db = deps.getDb ? await deps.getDb() : await Promise.resolve().then(() => (init_localRuntimeDb(), localRuntimeDb_exports)).then(
25300
+ ({ getDefaultCliLocalRuntimeDb: getDefaultCliLocalRuntimeDb4 }) => getDefaultCliLocalRuntimeDb4({ env })
25301
+ );
25302
+ const authorityHealth = await (deps.probeAuthorityHealth ?? probeCliAuthorityBrokerHealth)({
25303
+ endpoint: authorityEndpoint,
25304
+ metadataPath: authorityMetadataPath,
25305
+ healthPath: authorityHealthPath
25306
+ });
25307
+ if (!authorityHealth.ok) {
25308
+ return {
25309
+ ok: true,
25310
+ dbPath,
25311
+ authorityDriver,
25312
+ authorityEndpoint,
25313
+ authorityMetadataPath,
25314
+ authorityHealthPath,
25315
+ authorityHealthy: false,
25316
+ authorityError: authorityHealth.error,
25317
+ agentFound: false,
25318
+ ...agentKey ? { agentKey } : {}
25319
+ };
25320
+ }
24361
25321
  if (!agentKey) {
24362
25322
  return {
24363
25323
  ok: true,
@@ -24366,6 +25326,7 @@ async function defaultLocalRuntimeProbe(env) {
24366
25326
  authorityEndpoint,
24367
25327
  authorityMetadataPath,
24368
25328
  authorityHealthPath,
25329
+ authorityHealthy: true,
24369
25330
  agentFound: false
24370
25331
  };
24371
25332
  }
@@ -24378,6 +25339,7 @@ async function defaultLocalRuntimeProbe(env) {
24378
25339
  authorityEndpoint,
24379
25340
  authorityMetadataPath,
24380
25341
  authorityHealthPath,
25342
+ authorityHealthy: true,
24381
25343
  agentFound: record != null,
24382
25344
  agentKey
24383
25345
  };
@@ -24389,11 +25351,13 @@ async function defaultLocalRuntimeProbe(env) {
24389
25351
  authorityEndpoint,
24390
25352
  authorityMetadataPath,
24391
25353
  authorityHealthPath,
25354
+ authorityHealthy: true,
24392
25355
  agentFound: false,
24393
25356
  agentKey
24394
25357
  };
24395
25358
  }
24396
25359
  } catch (error) {
25360
+ const errorMessage = toErrorMessage(error);
24397
25361
  return {
24398
25362
  ok: false,
24399
25363
  dbPath,
@@ -24401,9 +25365,11 @@ async function defaultLocalRuntimeProbe(env) {
24401
25365
  authorityEndpoint,
24402
25366
  authorityMetadataPath,
24403
25367
  authorityHealthPath,
25368
+ authorityHealthy: false,
25369
+ authorityError: errorMessage,
24404
25370
  agentFound: false,
24405
25371
  ...agentKey ? { agentKey } : {},
24406
- error: toErrorMessage(error)
25372
+ error: errorMessage
24407
25373
  };
24408
25374
  }
24409
25375
  }
@@ -24417,6 +25383,7 @@ async function runDoctorRuntimeCommand(args2, deps = {}) {
24417
25383
  const hasLocalProvider = detectLocalProvider(env);
24418
25384
  const missingLocalCapabilities = [
24419
25385
  ...localProbe.ok ? [] : ["leveldb"],
25386
+ ...localProbe.authorityHealthy === false ? ["authority-broker"] : [],
24420
25387
  ...hasLocalAgentConfig ? [] : ["agent-config"],
24421
25388
  ...hasLocalProvider ? [] : ["provider"]
24422
25389
  ];
@@ -24453,6 +25420,14 @@ async function runDoctorRuntimeCommand(args2, deps = {}) {
24453
25420
  }
24454
25421
  if (localProbe.authorityHealthPath) {
24455
25422
  output2.write(`Authority health: ${localProbe.authorityHealthPath}
25423
+ `);
25424
+ }
25425
+ output2.write(
25426
+ `Authority broker: ${localProbe.authorityHealthy === true ? "healthy" : localProbe.authorityHealthy === false ? "unhealthy" : "unknown"}
25427
+ `
25428
+ );
25429
+ if (localProbe.authorityHealthy === false && localProbe.authorityError) {
25430
+ output2.write(`Authority error: ${localProbe.authorityError}
24456
25431
  `);
24457
25432
  }
24458
25433
  if (!localProbe.ok && localProbe.error) {
@@ -24488,6 +25463,7 @@ var init_runtimeDoctorCommands = __esm({
24488
25463
  init_runtimeDecision();
24489
25464
  init_cliAuthorityStoreDriver();
24490
25465
  init_cliEnvHelpers();
25466
+ init_cliAuthorityBrokerHealth();
24491
25467
  }
24492
25468
  });
24493
25469
 
@@ -24773,7 +25749,9 @@ __export(tableCommands_exports, {
24773
25749
  runTableDeleteRowCommand: () => runTableDeleteRowCommand,
24774
25750
  runTableDeleteRowsCommand: () => runTableDeleteRowsCommand,
24775
25751
  runTableListCommand: () => runTableListCommand,
25752
+ runTablePurgeRowsCommand: () => runTablePurgeRowsCommand,
24776
25753
  runTableQueryCommand: () => runTableQueryCommand,
25754
+ runTableRemoveRowFieldsCommand: () => runTableRemoveRowFieldsCommand,
24777
25755
  runTableUpdateRowCommand: () => runTableUpdateRowCommand,
24778
25756
  runTableUpdateRowsCommand: () => runTableUpdateRowsCommand
24779
25757
  });
@@ -25636,6 +26614,124 @@ async function postTableJson(deps, ctx, path8, body) {
25636
26614
  }
25637
26615
  return { ok: true, payload };
25638
26616
  }
26617
+ function parseNonEmptyStringArray(flag, raw) {
26618
+ let parsed;
26619
+ try {
26620
+ parsed = JSON.parse(raw);
26621
+ } catch (error) {
26622
+ throw new Error(`${flag} must be valid JSON: ${toErrorMessage(error)}`);
26623
+ }
26624
+ if (!Array.isArray(parsed) || parsed.length === 0 || !parsed.every((value) => typeof value === "string" && value.trim().length > 0)) {
26625
+ throw new Error(`${flag} must be a non-empty JSON array of strings.`);
26626
+ }
26627
+ return [...new Set(parsed.map((value) => value.trim()))];
26628
+ }
26629
+ function readAffectedCount(payload) {
26630
+ if (!isRecord(payload)) return 0;
26631
+ const direct = asOptionalFiniteNumber(payload.affectedCount);
26632
+ if (direct !== void 0) return direct;
26633
+ if (isRecord(payload.rawData)) {
26634
+ return asOptionalFiniteNumber(payload.rawData.affectedCount) ?? 0;
26635
+ }
26636
+ return 0;
26637
+ }
26638
+ async function runExactTableMaintenanceCommand(input2) {
26639
+ const env = input2.deps.env ?? process.env;
26640
+ const output2 = input2.deps.output ?? process.stdout;
26641
+ if (hasFlag7(input2.args, "--help") || hasFlag7(input2.args, "-h")) {
26642
+ output2.write(input2.usage);
26643
+ return 0;
26644
+ }
26645
+ const tableDbKey = readOption5(input2.args, "--table").trim();
26646
+ if (!tableDbKey || !tableDbKey.startsWith("meta-")) {
26647
+ output2.write(`[nolo] table ${input2.action} failed: --table must be an exact table dbKey beginning with "meta-".
26648
+ ${input2.usage}`);
26649
+ return 1;
26650
+ }
26651
+ const authToken = resolveAuthToken5(input2.args, env);
26652
+ if (!authToken) {
26653
+ output2.write(`[nolo] table ${input2.action} failed: AUTH_TOKEN is required.
26654
+ `);
26655
+ return 1;
26656
+ }
26657
+ const rowDbKeysRaw = readOption5(input2.args, "--row-dbkeys");
26658
+ if (!rowDbKeysRaw) {
26659
+ output2.write(`[nolo] table ${input2.action} failed: --row-dbkeys is required.
26660
+ ${input2.usage}`);
26661
+ return 1;
26662
+ }
26663
+ let rowDbKeys;
26664
+ let fields;
26665
+ try {
26666
+ rowDbKeys = parseNonEmptyStringArray("--row-dbkeys", rowDbKeysRaw);
26667
+ if (!rowDbKeys.every((dbKey) => dbKey.startsWith("row-"))) {
26668
+ throw new Error(
26669
+ '--row-dbkeys must contain exact row dbKeys beginning with "row-".'
26670
+ );
26671
+ }
26672
+ if (input2.requireFields) {
26673
+ const fieldsRaw = readOption5(input2.args, "--fields");
26674
+ if (!fieldsRaw) {
26675
+ output2.write(`[nolo] table ${input2.action} failed: --fields is required.
26676
+ ${input2.usage}`);
26677
+ return 1;
26678
+ }
26679
+ fields = parseNonEmptyStringArray("--fields", fieldsRaw);
26680
+ }
26681
+ } catch (error) {
26682
+ output2.write(`[nolo] table ${input2.action} failed: ${toErrorMessage(error)}
26683
+ ${input2.usage}`);
26684
+ return 1;
26685
+ }
26686
+ const execute = hasFlag7(input2.args, "--yes");
26687
+ const body = {
26688
+ tableDbKey,
26689
+ rowDbKeys,
26690
+ ...fields ? { fields } : {},
26691
+ dryRun: !execute,
26692
+ ...execute ? { confirmTableDbKey: tableDbKey } : {}
26693
+ };
26694
+ const result = await postTableJson(
26695
+ input2.deps,
26696
+ { authToken, serverUrl: resolveServerUrl4(input2.args, env) },
26697
+ input2.path,
26698
+ body
26699
+ );
26700
+ if (!result.ok) {
26701
+ output2.write(`[nolo] table ${input2.action} failed: ${result.message}
26702
+ `);
26703
+ return 1;
26704
+ }
26705
+ if (hasFlag7(input2.args, "--json") || readOption5(input2.args, "--output") === "json") {
26706
+ output2.write(`${JSON.stringify(result.payload)}
26707
+ `);
26708
+ return 0;
26709
+ }
26710
+ const status = execute ? "EXECUTED" : "DRY RUN";
26711
+ output2.write(`[nolo] table ${input2.action} ${status}: affectedCount=${readAffectedCount(result.payload)}
26712
+ `);
26713
+ return 0;
26714
+ }
26715
+ async function runTablePurgeRowsCommand(args2, deps = {}) {
26716
+ return runExactTableMaintenanceCommand({
26717
+ args: args2,
26718
+ deps,
26719
+ action: "purge-rows",
26720
+ path: "/api/table/purge-rows",
26721
+ usage: TABLE_PURGE_ROWS_USAGE,
26722
+ requireFields: false
26723
+ });
26724
+ }
26725
+ async function runTableRemoveRowFieldsCommand(args2, deps = {}) {
26726
+ return runExactTableMaintenanceCommand({
26727
+ args: args2,
26728
+ deps,
26729
+ action: "remove-row-fields",
26730
+ path: "/api/table/remove-row-fields",
26731
+ usage: TABLE_REMOVE_ROW_FIELDS_USAGE,
26732
+ requireFields: true
26733
+ });
26734
+ }
25639
26735
  async function runTableAddColumnCommand(args2, deps = {}) {
25640
26736
  const env = deps.env ?? process.env;
25641
26737
  const output2 = deps.output ?? process.stdout;
@@ -25870,7 +26966,7 @@ ${TABLE_DELETE_ROW_USAGE}`);
25870
26966
  `);
25871
26967
  return 0;
25872
26968
  }
25873
- var MULTI_SERVER_FETCH_LIMIT, DELETE_ROWS_QUERY_PAGE_SIZE, DEFAULT_TABLE_LIST_LIMIT, DEFAULT_TABLE_QUERY_LIMIT, UNBOUNDED_CLIENT_CAP, TABLE_ADD_COLUMN_USAGE, TABLE_ADD_ROW_USAGE, TABLE_ADD_ROWS_USAGE, TABLE_UPDATE_ROW_USAGE, TABLE_UPDATE_ROWS_USAGE, TABLE_DELETE_ROW_USAGE;
26969
+ var MULTI_SERVER_FETCH_LIMIT, DELETE_ROWS_QUERY_PAGE_SIZE, DEFAULT_TABLE_LIST_LIMIT, DEFAULT_TABLE_QUERY_LIMIT, UNBOUNDED_CLIENT_CAP, TABLE_ADD_COLUMN_USAGE, TABLE_ADD_ROW_USAGE, TABLE_ADD_ROWS_USAGE, TABLE_UPDATE_ROW_USAGE, TABLE_UPDATE_ROWS_USAGE, TABLE_DELETE_ROW_USAGE, TABLE_PURGE_ROWS_USAGE, TABLE_REMOVE_ROW_FIELDS_USAGE;
25874
26970
  var init_tableCommands = __esm({
25875
26971
  "packages/cli/tableCommands.ts"() {
25876
26972
  "use strict";
@@ -25896,6 +26992,8 @@ var init_tableCommands = __esm({
25896
26992
  TABLE_UPDATE_ROW_USAGE = "Usage:\n nolo table update-row --table <tableId|metaKey> --row <rowId|rowDbKey> --changes <json-object>\n\n";
25897
26993
  TABLE_UPDATE_ROWS_USAGE = "Usage:\n nolo table update-rows --table <tableId|metaKey> --updates <non-empty-json-array>\n\n";
25898
26994
  TABLE_DELETE_ROW_USAGE = "Usage:\n nolo table delete-row --table <tableId|metaKey> --row <rowId|rowDbKey>\n\n";
26995
+ TABLE_PURGE_ROWS_USAGE = "Usage:\n nolo table purge-rows --table <exact-meta-dbKey> --row-dbkeys <non-empty-json-array> [--yes] [--json]\n\n";
26996
+ TABLE_REMOVE_ROW_FIELDS_USAGE = "Usage:\n nolo table remove-row-fields --table <exact-meta-dbKey> --row-dbkeys <non-empty-json-array> --fields <non-empty-json-array> [--yes] [--json]\n\n";
25899
26997
  }
25900
26998
  });
25901
26999
 
@@ -25922,7 +27020,7 @@ var init_prefix = __esm({
25922
27020
  });
25923
27021
 
25924
27022
  // packages/cli/client/compactDialog.ts
25925
- import { ulid as ulid5 } from "ulid";
27023
+ import { ulid as ulid6 } from "ulid";
25926
27024
  function parseTokenUserId(token) {
25927
27025
  try {
25928
27026
  const parts = token.split(".");
@@ -25947,7 +27045,7 @@ async function readDialogRecord(fetchImpl, serverUrl, authToken, dialogKey) {
25947
27045
  return data;
25948
27046
  }
25949
27047
  function buildForkedDialogRecord(current, userId) {
25950
- const newId = ulid5();
27048
+ const newId = ulid6();
25951
27049
  const dbKey = `dialog-${userId}-${newId}`;
25952
27050
  const now = (/* @__PURE__ */ new Date()).toISOString();
25953
27051
  const carried = {};
@@ -26103,15 +27201,23 @@ function renderSelectDialog(args2) {
26103
27201
  }
26104
27202
  return lines.join("\n");
26105
27203
  }
26106
- function countRenderedLines(text) {
26107
- return text.split("\n").length;
27204
+ function outputIsTty(output2) {
27205
+ return typeof output2 === "object" && output2 !== null && "isTTY" in output2 && Boolean(output2.isTTY);
26108
27206
  }
26109
27207
  function clearRenderedLines(output2, lineCount) {
26110
- if (!output2.isTTY || lineCount <= 0) return;
27208
+ if (!outputIsTty(output2) || lineCount <= 0) return;
26111
27209
  for (let index = 0; index < lineCount; index += 1) {
26112
27210
  output2.write("\x1B[1A\x1B[2K");
26113
27211
  }
26114
27212
  }
27213
+ function clearAnchoredLines(output2, bottomRow, lineCount) {
27214
+ if (!outputIsTty(output2) || lineCount <= 0) return;
27215
+ for (let index = 0; index < lineCount; index += 1) {
27216
+ const row = bottomRow - index;
27217
+ if (row < 1) break;
27218
+ output2.write(`\x1B[${row};1H\x1B[2K`);
27219
+ }
27220
+ }
26115
27221
  function isArrowUp(sequence) {
26116
27222
  return sequence === CSI_ARROW_UP || sequence === CSI_ARROW_UP_APP;
26117
27223
  }
@@ -26155,35 +27261,30 @@ function createRawKeyReader(input2) {
26155
27261
  buffer = "";
26156
27262
  return sequence;
26157
27263
  };
26158
- return () => new Promise((resolve8) => {
26159
- const finalize = (sequence) => {
26160
- cleanup();
26161
- resolve8(sequence ?? null);
26162
- };
26163
- const onReadable = () => {
26164
- while (true) {
26165
- const chunk = input2.read();
26166
- if (chunk == null) break;
26167
- buffer += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
26168
- const parsed = tryParseSequence();
26169
- if (parsed === void 0) return;
26170
- finalize(parsed);
26171
- return;
26172
- }
26173
- };
26174
- const cleanup = () => {
26175
- input2.off("readable", onReadable);
26176
- };
26177
- onReadable();
26178
- if (buffer) {
26179
- const parsed = tryParseSequence();
26180
- if (parsed !== void 0) {
26181
- finalize(parsed);
26182
- return;
26183
- }
26184
- }
26185
- input2.on("readable", onReadable);
27264
+ let waiter = null;
27265
+ const tryDeliver = () => {
27266
+ if (!waiter || !buffer) return;
27267
+ const parsed = tryParseSequence();
27268
+ if (parsed === void 0) return;
27269
+ const resolve8 = waiter;
27270
+ waiter = null;
27271
+ resolve8(parsed);
27272
+ };
27273
+ const onData = (chunk) => {
27274
+ buffer += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
27275
+ tryDeliver();
27276
+ };
27277
+ input2.on("data", onData);
27278
+ input2.resume?.();
27279
+ const reader = () => new Promise((resolve8) => {
27280
+ waiter = resolve8;
27281
+ tryDeliver();
26186
27282
  });
27283
+ reader.dispose = () => {
27284
+ waiter = null;
27285
+ input2.off("data", onData);
27286
+ };
27287
+ return reader;
26187
27288
  }
26188
27289
  function drainInputBuffer(input2) {
26189
27290
  if (typeof input2.read !== "function") return;
@@ -26203,8 +27304,9 @@ async function runSelectDialog(args2) {
26203
27304
  const input2 = args2.input ?? process.stdin;
26204
27305
  const readKey = args2.readKey ?? createRawKeyReader(input2);
26205
27306
  const wasRaw = Boolean(input2.isTTY && input2.isRaw);
26206
- const wasPaused = typeof input2.isPaused === "function" ? input2.isPaused() : false;
26207
27307
  let renderedLineCount = 0;
27308
+ const bottomAnchored = Boolean(args2.bottomAnchored && args2.bottomRow && args2.bottomRow > 0);
27309
+ const bottomRow = args2.bottomRow ?? 0;
26208
27310
  const paint = () => {
26209
27311
  const frame = renderSelectDialog({
26210
27312
  items,
@@ -26212,22 +27314,34 @@ async function runSelectDialog(args2) {
26212
27314
  title: args2.title,
26213
27315
  maxVisible: args2.maxVisible
26214
27316
  });
26215
- if (output2.isTTY && typeof output2.write === "function") {
27317
+ const lines = frame.split("\n");
27318
+ const lineCount = lines.length;
27319
+ const canPosition = outputIsTty(output2) && typeof output2.write === "function";
27320
+ if (bottomAnchored && canPosition) {
27321
+ clearAnchoredLines(output2, bottomRow, renderedLineCount);
27322
+ for (let i = 0; i < lines.length; i += 1) {
27323
+ const row = bottomRow - (lines.length - 1 - i);
27324
+ if (row < 1) break;
27325
+ output2.write(`\x1B[${row};1H\x1B[2K${lines[i]}`);
27326
+ }
27327
+ renderedLineCount = lineCount;
27328
+ return;
27329
+ }
27330
+ if (canPosition) {
26216
27331
  clearRenderedLines(output2, renderedLineCount);
26217
27332
  output2.write(`${frame}
26218
27333
  `);
26219
- renderedLineCount = countRenderedLines(frame);
27334
+ renderedLineCount = lineCount;
26220
27335
  return;
26221
27336
  }
26222
27337
  if (typeof output2.write === "function") {
26223
27338
  output2.write(`${frame}
26224
27339
  `);
26225
27340
  }
26226
- renderedLineCount = countRenderedLines(frame);
27341
+ renderedLineCount = lineCount;
26227
27342
  };
26228
- if (input2.isTTY) {
26229
- if (!wasRaw) input2.setRawMode(true);
26230
- if (!wasPaused) input2.pause();
27343
+ if (input2.isTTY && !wasRaw) {
27344
+ input2.setRawMode(true);
26231
27345
  }
26232
27346
  paint();
26233
27347
  try {
@@ -26254,11 +27368,15 @@ async function runSelectDialog(args2) {
26254
27368
  }
26255
27369
  }
26256
27370
  } finally {
27371
+ readKey.dispose?.();
26257
27372
  if (input2.isTTY) {
26258
27373
  drainInputBuffer(input2);
26259
27374
  if (!wasRaw) input2.setRawMode(false);
26260
- if (!wasPaused) input2.resume();
26261
- clearRenderedLines(output2, renderedLineCount);
27375
+ if (bottomAnchored) {
27376
+ clearAnchoredLines(output2, bottomRow, renderedLineCount);
27377
+ } else {
27378
+ clearRenderedLines(output2, renderedLineCount);
27379
+ }
26262
27380
  renderedLineCount = 0;
26263
27381
  }
26264
27382
  }
@@ -26368,7 +27486,6 @@ async function loadAgentCatalog(args2) {
26368
27486
  authToken,
26369
27487
  fallbackFetchImpl,
26370
27488
  fetchImpl,
26371
- includeLegacy: false,
26372
27489
  serverUrls,
26373
27490
  userId
26374
27491
  });
@@ -26384,7 +27501,6 @@ async function loadAgentCatalog(args2) {
26384
27501
  authToken,
26385
27502
  fallbackFetchImpl,
26386
27503
  fetchImpl,
26387
- includeLegacy: false,
26388
27504
  serverUrl,
26389
27505
  userId,
26390
27506
  queryUserRecords,
@@ -26468,7 +27584,7 @@ function formatAgentSwitchMessage(args2) {
26468
27584
  async function runAgentPicker(args2) {
26469
27585
  const output2 = args2.output ?? process.stdout;
26470
27586
  const input2 = args2.input ?? process.stdin;
26471
- const interactive = args2.interactive ?? Boolean(input2.isTTY && output2.isTTY);
27587
+ const interactive = args2.interactive ?? ("isTTY" in input2 && Boolean(input2.isTTY) && "isTTY" in output2 && Boolean(output2.isTTY));
26472
27588
  const entries = await loadAgentCatalog({
26473
27589
  env: args2.env,
26474
27590
  currentKey: args2.currentKey,
@@ -26493,7 +27609,9 @@ async function runAgentPicker(args2) {
26493
27609
  title: void 0,
26494
27610
  input: input2,
26495
27611
  output: output2,
26496
- readKey: args2.readKey
27612
+ readKey: args2.readKey,
27613
+ bottomAnchored: args2.bottomAnchored,
27614
+ bottomRow: args2.bottomRow
26497
27615
  });
26498
27616
  if (result.kind === "cancelled") {
26499
27617
  return { kind: "cancelled", entries };
@@ -26530,7 +27648,7 @@ var init_agentPicker = __esm({
26530
27648
  // packages/cli/tui/pasteImage.ts
26531
27649
  import { existsSync as existsSync14 } from "node:fs";
26532
27650
  import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
26533
- import { homedir as homedir10 } from "node:os";
27651
+ import { homedir as homedir9 } from "node:os";
26534
27652
  import { isAbsolute as isAbsolute3, resolve as resolve7 } from "node:path";
26535
27653
  function extnameOf(path8) {
26536
27654
  const slash = Math.max(path8.lastIndexOf("/"), path8.lastIndexOf("\\"));
@@ -26546,9 +27664,9 @@ function basenameOf(path8) {
26546
27664
  function resolveImageSource(rawPath, cwd) {
26547
27665
  let candidate = rawPath.trim();
26548
27666
  if (!candidate) return candidate;
26549
- if (candidate === "~") return homedir10();
27667
+ if (candidate === "~") return homedir9();
26550
27668
  if (candidate.startsWith("~/") || candidate.startsWith("~\\")) {
26551
- return homedir10() + candidate.slice(1);
27669
+ return homedir9() + candidate.slice(1);
26552
27670
  }
26553
27671
  if (isAbsolute3(candidate)) return candidate;
26554
27672
  return resolve7(cwd, candidate);
@@ -27394,7 +28512,8 @@ __export(readlineWorkspace_exports, {
27394
28512
  takeDisplayWidth: () => takeDisplayWidth,
27395
28513
  truncateAnsi: () => truncateAnsi,
27396
28514
  visibleWidth: () => visibleWidth,
27397
- wrapTextToLines: () => wrapTextToLines
28515
+ wrapTextToLines: () => wrapTextToLines,
28516
+ wrapTranscriptLine: () => wrapTranscriptLine
27398
28517
  });
27399
28518
  import { createInterface as createInterface2 } from "node:readline";
27400
28519
  import { stdin as defaultInput, stdout as defaultOutput } from "node:process";
@@ -27438,33 +28557,54 @@ function stripAnsi(text) {
27438
28557
  return text.replace(ANSI_ESCAPE_REGEX, "");
27439
28558
  }
27440
28559
  function applyTerminalOutputToText(existing, chunk) {
27441
- const cleaned = stripAnsi(chunk);
27442
- if (!cleaned) return existing;
28560
+ if (!chunk) return existing;
27443
28561
  let text = existing;
27444
- for (const ch of cleaned) {
28562
+ let index = 0;
28563
+ while (index < chunk.length) {
28564
+ if (chunk[index] === "\x1B") {
28565
+ const sgr = SGR_SEQUENCE_REGEX.exec(chunk.slice(index));
28566
+ if (sgr) {
28567
+ text += sgr[0];
28568
+ index += sgr[0].length;
28569
+ continue;
28570
+ }
28571
+ const csi = chunk.slice(index).match(/^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/);
28572
+ if (csi) {
28573
+ index += csi[0].length;
28574
+ continue;
28575
+ }
28576
+ index += 1;
28577
+ continue;
28578
+ }
28579
+ const ch = chunk[index];
27445
28580
  if (ch === "\r") {
27446
28581
  const lastNl = text.lastIndexOf("\n");
27447
28582
  text = lastNl === -1 ? "" : text.slice(0, lastNl + 1);
28583
+ index += 1;
27448
28584
  continue;
27449
28585
  }
27450
28586
  if (ch === "\n") {
27451
28587
  text += "\n";
28588
+ index += 1;
27452
28589
  continue;
27453
28590
  }
27454
28591
  if (ch === "\b") {
27455
- if (text.length > 0 && text[text.length - 1] !== "\n") {
27456
- text = text.slice(0, -1);
28592
+ const trailing = TRAILING_SGR_REGEX.exec(text);
28593
+ const sgrTail = trailing ? trailing[0] : "";
28594
+ const head = sgrTail ? text.slice(0, -sgrTail.length) : text;
28595
+ if (head.length > 0 && head[head.length - 1] !== "\n") {
28596
+ text = head.slice(0, -1) + sgrTail;
27457
28597
  }
28598
+ index += 1;
27458
28599
  continue;
27459
28600
  }
27460
28601
  const code = ch.charCodeAt(0);
27461
- if (code < 32 && ch !== " ") {
27462
- continue;
27463
- }
27464
- if (code === 127) {
28602
+ if (code < 32 && ch !== " " || code === 127) {
28603
+ index += 1;
27465
28604
  continue;
27466
28605
  }
27467
28606
  text += ch;
28607
+ index += 1;
27468
28608
  }
27469
28609
  return text;
27470
28610
  }
@@ -27738,12 +28878,98 @@ function takeDisplayWidth(text, width) {
27738
28878
  return { prefix: text.slice(0, index), rest: text.slice(index) };
27739
28879
  }
27740
28880
  function padOrTruncateToWidth(text, width) {
27741
- const textWidth = displayWidth(text);
28881
+ const textWidth = visibleWidth(text);
27742
28882
  if (textWidth > width) {
27743
- return takeDisplayWidth(text, width).prefix;
28883
+ return truncateAnsi(text, width);
27744
28884
  }
27745
28885
  return `${text}${" ".repeat(width - textWidth)}`;
27746
28886
  }
28887
+ function tokenizeAnsiLine(line) {
28888
+ const tokens = [];
28889
+ let index = 0;
28890
+ while (index < line.length) {
28891
+ if (line[index] === "\x1B") {
28892
+ const sgr = SGR_SEQUENCE_REGEX.exec(line.slice(index));
28893
+ if (sgr) {
28894
+ tokens.push({ kind: "sgr", value: sgr[0], width: 0 });
28895
+ index += sgr[0].length;
28896
+ continue;
28897
+ }
28898
+ }
28899
+ const codePoint = line.codePointAt(index) ?? 0;
28900
+ const value = String.fromCodePoint(codePoint);
28901
+ tokens.push({ kind: "char", value, width: displayWidth(value) });
28902
+ index += value.length;
28903
+ }
28904
+ return tokens;
28905
+ }
28906
+ function wrapTranscriptLine(line, columns) {
28907
+ if (line === "") return [""];
28908
+ const tokens = tokenizeAnsiLine(line);
28909
+ const result = [];
28910
+ let activeStyles = [];
28911
+ const applyStyleToken = (value) => {
28912
+ if (SGR_RESET_REGEX.test(value)) {
28913
+ activeStyles = [];
28914
+ } else {
28915
+ activeStyles.push(value);
28916
+ }
28917
+ };
28918
+ let start = 0;
28919
+ while (start < tokens.length) {
28920
+ if (tokens.slice(start).every((token) => token.kind === "sgr")) {
28921
+ if (result.length > 0) break;
28922
+ }
28923
+ const openingStyles = [...activeStyles];
28924
+ let width = 0;
28925
+ let end = start;
28926
+ let lastBreak = -1;
28927
+ while (end < tokens.length) {
28928
+ const token = tokens[end];
28929
+ if (token.kind === "sgr") {
28930
+ end += 1;
28931
+ continue;
28932
+ }
28933
+ if (width + token.width > columns && width > 0) break;
28934
+ width += token.width;
28935
+ end += 1;
28936
+ if (token.value === " " || token.value === " ") {
28937
+ lastBreak = end;
28938
+ }
28939
+ }
28940
+ let segmentEnd = end;
28941
+ if (end < tokens.length && lastBreak > start) {
28942
+ const overflowToken = tokens[end];
28943
+ if (overflowToken.kind === "char" && overflowToken.value !== " " && overflowToken.width === 1) {
28944
+ segmentEnd = lastBreak;
28945
+ }
28946
+ }
28947
+ if (segmentEnd === start) segmentEnd = start + 1;
28948
+ let segment = "";
28949
+ let sawStyle = openingStyles.length > 0;
28950
+ for (let i = start; i < segmentEnd; i += 1) {
28951
+ const token = tokens[i];
28952
+ segment += token.value;
28953
+ if (token.kind === "sgr") {
28954
+ sawStyle = true;
28955
+ applyStyleToken(token.value);
28956
+ }
28957
+ }
28958
+ const prefix = openingStyles.join("");
28959
+ const needsReset = (sawStyle || activeStyles.length > 0) && !segment.endsWith("\x1B[0m");
28960
+ result.push(`${prefix}${segment}${needsReset ? "\x1B[0m" : ""}`);
28961
+ start = segmentEnd;
28962
+ while (start < tokens.length) {
28963
+ const token = tokens[start];
28964
+ if (token.kind === "char" && token.value === " ") {
28965
+ start += 1;
28966
+ continue;
28967
+ }
28968
+ break;
28969
+ }
28970
+ }
28971
+ return result.length > 0 ? result : [""];
28972
+ }
27747
28973
  function wrapTextToLines(text, columns) {
27748
28974
  const result = [];
27749
28975
  for (const logicalLine of text.split("\n")) {
@@ -27777,8 +29003,10 @@ function buildHistoryLines(history, contentWidth) {
27777
29003
  }
27778
29004
  }
27779
29005
  const wrapped = [];
27780
- for (const line of lines) {
27781
- wrapped.push(...wrapTextToLines(line, contentWidth));
29006
+ for (const entry of lines) {
29007
+ for (const logicalLine of entry.split("\n")) {
29008
+ wrapped.push(...wrapTranscriptLine(logicalLine, contentWidth));
29009
+ }
27782
29010
  }
27783
29011
  return wrapped;
27784
29012
  }
@@ -27800,6 +29028,13 @@ function renderScrollbarRow(rowIndex, visibleHeight, totalLines, scrollTop) {
27800
29028
  return "\u2502";
27801
29029
  }
27802
29030
  function parseScrollAction(sequence) {
29031
+ const mouse = SGR_MOUSE_REGEX.exec(sequence);
29032
+ if (mouse) {
29033
+ const button = Number(mouse[1]);
29034
+ if ((button & 64) === 0) return null;
29035
+ if ((button & 2) !== 0) return null;
29036
+ return (button & 1) !== 0 ? "wheel-down" : "wheel-up";
29037
+ }
27803
29038
  switch (sequence) {
27804
29039
  case "\x1B[5~":
27805
29040
  return "page-up";
@@ -27848,6 +29083,13 @@ function applyScrollAction(history, action, output2, inputLines) {
27848
29083
  history.scrollTop + Math.floor(visibleHeight / 2)
27849
29084
  );
27850
29085
  break;
29086
+ case "wheel-up":
29087
+ history.scrollTop = Math.max(0, history.scrollTop - WHEEL_SCROLL_LINES);
29088
+ break;
29089
+ case "wheel-down":
29090
+ history.scrollTop = Math.min(maxScrollTop, history.scrollTop + WHEEL_SCROLL_LINES);
29091
+ if (history.scrollTop >= maxScrollTop) history.followBottom = true;
29092
+ break;
27851
29093
  case "top":
27852
29094
  history.scrollTop = 0;
27853
29095
  break;
@@ -27894,6 +29136,8 @@ function createFixedInput(output2, config) {
27894
29136
  const saveCursor = () => write("\x1B7");
27895
29137
  const restoreCursor = () => write("\x1B8");
27896
29138
  const resetScrollRegion = () => write("\x1B[r");
29139
+ const enableMouse = () => write("\x1B[?1006h\x1B[?1000h");
29140
+ const disableMouse = () => write("\x1B[?1000l\x1B[?1006l");
27897
29141
  const renderInputArea = (buffer) => {
27898
29142
  const colorEnabled = resolveCliColorEnabled();
27899
29143
  const cols = Math.max(1, getColumns());
@@ -27951,7 +29195,7 @@ function createFixedInput(output2, config) {
27951
29195
  write("\x1B[J");
27952
29196
  write(text);
27953
29197
  const cursorLine = startRow + cursorRow;
27954
- write(`\x1B[${cursorLine};${cursorCol + 1}G`);
29198
+ write(`\x1B[${cursorLine};${cursorCol + 1}H`);
27955
29199
  };
27956
29200
  if (!isTTY) return createNoopFixedInput();
27957
29201
  return {
@@ -27959,6 +29203,7 @@ function createFixedInput(output2, config) {
27959
29203
  init() {
27960
29204
  saveCursor();
27961
29205
  setScrollRegion(inputLines);
29206
+ enableMouse();
27962
29207
  },
27963
29208
  enterOutputMode(_submittedText) {
27964
29209
  repaintAt("");
@@ -27971,10 +29216,12 @@ function createFixedInput(output2, config) {
27971
29216
  repaintAt(buffer);
27972
29217
  },
27973
29218
  pause() {
29219
+ disableMouse();
27974
29220
  resetScrollRegion();
27975
29221
  },
27976
29222
  resumeFromSubprocess() {
27977
29223
  setScrollRegion(inputLines);
29224
+ enableMouse();
27978
29225
  const scrollBottom = Math.max(1, getRows() - inputLines);
27979
29226
  write(`\x1B[${scrollBottom};1H
27980
29227
  `);
@@ -27982,8 +29229,10 @@ function createFixedInput(output2, config) {
27982
29229
  resumeFromDialog() {
27983
29230
  saveCursor();
27984
29231
  setScrollRegion(inputLines);
29232
+ enableMouse();
27985
29233
  },
27986
29234
  disable() {
29235
+ disableMouse();
27987
29236
  resetScrollRegion();
27988
29237
  const rows = getRows();
27989
29238
  write(`\x1B[${rows};1H\x1B[2K\x1B[${Math.max(1, rows - 1)};1H`);
@@ -28195,13 +29444,18 @@ async function startTuiWorkspace(options) {
28195
29444
  }
28196
29445
  }
28197
29446
  if (result.action?.type === "pick-agent") {
29447
+ const pickerInputLines = fixedInput.getInputLines();
29448
+ const ttyRows = typeof output2 === "object" && output2 !== null && "rows" in output2 && typeof output2.rows === "number" ? output2.rows : 24;
29449
+ const bottomRow = Math.max(1, ttyRows - pickerInputLines);
28198
29450
  fixedInput.pause();
28199
29451
  try {
28200
29452
  const pickResult = await runAgentPicker({
28201
29453
  currentKey: state.agentKey,
28202
29454
  env: options.env ?? process.env,
28203
29455
  input: input2,
28204
- output: output2
29456
+ output: output2,
29457
+ bottomAnchored: true,
29458
+ bottomRow
28205
29459
  });
28206
29460
  if (pickResult.kind === "list") {
28207
29461
  output2.write(`${pickResult.output}
@@ -28459,7 +29713,7 @@ ${renderStatusLine(state)}
28459
29713
  rl.close();
28460
29714
  }
28461
29715
  }
28462
- var MAX_TUI_HISTORY_TURNS, ANSI_ESCAPE_REGEX;
29716
+ var MAX_TUI_HISTORY_TURNS, ANSI_ESCAPE_REGEX, SGR_SEQUENCE_REGEX, TRAILING_SGR_REGEX, SGR_RESET_REGEX, SGR_MOUSE_REGEX, WHEEL_SCROLL_LINES;
28463
29717
  var init_readlineWorkspace = __esm({
28464
29718
  "packages/cli/tui/readlineWorkspace.ts"() {
28465
29719
  "use strict";
@@ -28478,6 +29732,11 @@ var init_readlineWorkspace = __esm({
28478
29732
  init_i18n();
28479
29733
  MAX_TUI_HISTORY_TURNS = 500;
28480
29734
  ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
29735
+ SGR_SEQUENCE_REGEX = /^\x1b\[[0-9;]*m/;
29736
+ TRAILING_SGR_REGEX = /(?:\x1b\[[0-9;]*m)+$/;
29737
+ SGR_RESET_REGEX = /^\x1b\[0?m$/;
29738
+ SGR_MOUSE_REGEX = /^\x1b\[<(\d+);\d+;\d+[Mm]$/;
29739
+ WHEEL_SCROLL_LINES = 3;
28481
29740
  }
28482
29741
  });
28483
29742
 
@@ -29162,6 +30421,14 @@ function getDocInternalCommandEntries() {
29162
30421
  // packages/cli/memoryInternalCommandEntries.ts
29163
30422
  function getMemoryInternalCommandEntries() {
29164
30423
  return [
30424
+ createEnvCommand(["memory", "list"], "List long-term memories by filter", async (args2, deps) => {
30425
+ const { runMemoryListCommand: runMemoryListCommand2 } = await Promise.resolve().then(() => (init_memoryCommands(), memoryCommands_exports));
30426
+ return runMemoryListCommand2(args2, deps);
30427
+ }),
30428
+ createEnvCommand(["memory", "remember"], "Store a long-term memory", async (args2, deps) => {
30429
+ const { runMemoryRememberCommand: runMemoryRememberCommand2 } = await Promise.resolve().then(() => (init_memoryCommands(), memoryCommands_exports));
30430
+ return runMemoryRememberCommand2(args2, deps);
30431
+ }),
29165
30432
  createEnvCommand(["memory", "delete"], "Delete long-term memories by filter", async (args2, deps) => {
29166
30433
  const { runMemoryDeleteCommand: runMemoryDeleteCommand2 } = await Promise.resolve().then(() => (init_memoryCommands(), memoryCommands_exports));
29167
30434
  return runMemoryDeleteCommand2(args2, deps);
@@ -29303,6 +30570,8 @@ function renderTableHelpText() {
29303
30570
  " nolo table update-rows --table <tableId|metaKey> --updates <json-array>",
29304
30571
  " nolo table delete-row --table <tableId|metaKey> --row <rowId|rowDbKey>",
29305
30572
  " nolo table delete-rows --table <tableId|metaKey> (--row-ids <json-array> | --row-dbkeys <json-array> | --filters <json-object>)",
30573
+ " nolo table purge-rows --table <exact-meta-dbKey> --row-dbkeys <json-array> [--yes] [--json]",
30574
+ " nolo table remove-row-fields --table <exact-meta-dbKey> --row-dbkeys <json-array> --fields <json-array> [--yes] [--json]",
29306
30575
  "",
29307
30576
  "Examples:",
29308
30577
  ` nolo table query --table meta-0e95801d90-01KWSK4Q4TESXQ06SW39JN2TTJ --columns '["title","status","owner","priority","codeStatus"]' --no-base-fields --output items`,
@@ -29328,6 +30597,14 @@ function getTableInternalCommandEntries() {
29328
30597
  const { runTableDeleteRowsCommand: runTableDeleteRowsCommand2 } = await Promise.resolve().then(() => (init_tableCommands(), tableCommands_exports));
29329
30598
  return runTableDeleteRowsCommand2(args2);
29330
30599
  }),
30600
+ createEnvCommand(["table", "purge-rows"], "Permanently purge table rows", async (args2, deps) => {
30601
+ const { runTablePurgeRowsCommand: runTablePurgeRowsCommand2 } = await Promise.resolve().then(() => (init_tableCommands(), tableCommands_exports));
30602
+ return runTablePurgeRowsCommand2(args2, deps);
30603
+ }),
30604
+ createEnvCommand(["table", "remove-row-fields"], "Remove fields from table rows", async (args2, deps) => {
30605
+ const { runTableRemoveRowFieldsCommand: runTableRemoveRowFieldsCommand2 } = await Promise.resolve().then(() => (init_tableCommands(), tableCommands_exports));
30606
+ return runTableRemoveRowFieldsCommand2(args2, deps);
30607
+ }),
29331
30608
  createEnvCommand(["table", "add-column"], "Add a table column", async (args2, deps) => {
29332
30609
  const { runTableAddColumnCommand: runTableAddColumnCommand2 } = await Promise.resolve().then(() => (init_tableCommands(), tableCommands_exports));
29333
30610
  return runTableAddColumnCommand2(args2, deps);