nolo-cli 0.96.0-alpha.1 → 0.97.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/{_executeModel-AUQRMRWL.js → _executeModel-JIG7MRXQ.js} +13 -13
  2. package/{agentDeleteCommand-4BAHJRU3.js → agentDeleteCommand-THAZ5GQS.js} +2 -2
  3. package/{agentEmailCommands-QISOY7Y6.js → agentEmailCommands-A7T7AJA4.js} +14 -14
  4. package/{agentListCommands-U46ODMQU.js → agentListCommands-BRZFEJQM.js} +4 -4
  5. package/{agentMachineCommands-EHV2KM2C.js → agentMachineCommands-DM4N5PK3.js} +3 -3
  6. package/{agentRecordCommands-SIPURU2S.js → agentRecordCommands-TTAEMNHB.js} +14 -14
  7. package/{agentRunCommand-K4CLMA6B.js → agentRunCommand-JVSTGVG2.js} +14 -14
  8. package/{agentRunControl-XLGD3UZ5.js → agentRunControl-WCTKX5VL.js} +2 -2
  9. package/{agentRuntimeLocal-O4HPUJA4.js → agentRuntimeLocal-73CVIWBB.js} +2 -2
  10. package/{agentSlice-ZYT2OUR3.js → agentSlice-6X4JL2E3.js} +1 -1
  11. package/{appDeleteCommands-R5BBTKQK.js → appDeleteCommands-S7CK4OYL.js} +2 -2
  12. package/{appDeployCommands-ZJIXOJWD.js → appDeployCommands-U6TMS5GO.js} +2 -2
  13. package/{appDeployStatusCommands-B3R2ZTBF.js → appDeployStatusCommands-DTNQJ3LJ.js} +2 -2
  14. package/{appGetCommands-2AQSOV2A.js → appGetCommands-3SHZEQD5.js} +2 -2
  15. package/{appListCommands-HCIJGZFY.js → appListCommands-E2ZMIUB6.js} +2 -2
  16. package/{chatQueueReduxAdapter-Q5V4YJVI.js → chatQueueReduxAdapter-LAQEZQKE.js} +2 -2
  17. package/{chunk-NTW5GWDM.js → chunk-3VNWWVKB.js} +2 -0
  18. package/{chunk-AFDS2CVM.js → chunk-3WD6RUUJ.js} +2 -2
  19. package/{chunk-EGSKXKR5.js → chunk-54ADB4W7.js} +1 -1
  20. package/{chunk-BZWBEHGD.js → chunk-6FVRQBRR.js} +14 -8
  21. package/{chunk-LLT642J4.js → chunk-7OLPQSMQ.js} +1 -1
  22. package/{chunk-A6G32FNX.js → chunk-ESWUWEFS.js} +3 -3
  23. package/{chunk-ZXKVPF4K.js → chunk-HWIZU4OL.js} +1 -1
  24. package/{chunk-XRWZB6CF.js → chunk-JCIHVIVG.js} +5 -5
  25. package/{chunk-FOWEGIMF.js → chunk-K4YGZD3P.js} +8 -8
  26. package/{chunk-JOHSKZQX.js → chunk-LXF6XQDT.js} +8 -8
  27. package/{chunk-OA6Q2A4I.js → chunk-LZIWMYX4.js} +78 -18
  28. package/{chunk-BGSLKVCP.js → chunk-R2B3MIZA.js} +2 -2
  29. package/{chunk-IAO6JBYW.js → chunk-RG6JBBX5.js} +5 -1
  30. package/{chunk-ZLR5JN3E.js → chunk-SQQVLHMH.js} +3 -3
  31. package/{chunk-DEUUPHOO.js → chunk-TDRTS7QW.js} +1 -1
  32. package/{chunk-MMPXJXHT.js → chunk-TZJJ77KQ.js} +98 -12
  33. package/{chunk-CPH3W5A7.js → chunk-WGR3J4Q6.js} +86 -1
  34. package/{chunk-XOVEWFLK.js → chunk-Y5HW6GM2.js} +2 -2
  35. package/{chunk-3SJQXXGY.js → chunk-YVIV7WT4.js} +84 -9
  36. package/{chunk-4MY4GLIW.js → chunk-ZWUOR654.js} +11 -2
  37. package/{contentThunks-PT23JWJX.js → contentThunks-ATLWNC2D.js} +3 -3
  38. package/{createAgentAutomationAction-N27SYTLU.js → createAgentAutomationAction-QYYWTVUR.js} +3 -3
  39. package/{createDialogAction-XZPLHD5G.js → createDialogAction-7I5VGWCR.js} +4 -4
  40. package/{createPageAction-KHVJQ3CS.js → createPageAction-WNURYCWU.js} +3 -3
  41. package/{dialogCommands-ZUWW5UT6.js → dialogCommands-RILHDRQ5.js} +2 -2
  42. package/{dialogSlice-3YH242HS.js → dialogSlice-W5BYELVR.js} +2 -2
  43. package/{docCreateCommands-Q6FADDSJ.js → docCreateCommands-GSTPU7SG.js} +2 -2
  44. package/{docDeleteCommands-ZKIH54PZ.js → docDeleteCommands-2FC3LSUT.js} +2 -2
  45. package/{docReadCommands-7BZT2QTW.js → docReadCommands-27POBA34.js} +2 -2
  46. package/{docStore-YSZRNUUD.js → docStore-7LAHBFP2.js} +1 -1
  47. package/{docUpdateCommands-WJXWTRL7.js → docUpdateCommands-U4II6VCO.js} +2 -2
  48. package/{handleSendMessageAction-KJO2QDBM.js → handleSendMessageAction-SKMJMVRU.js} +2 -2
  49. package/index.js +46 -46
  50. package/{machineCommands-QC4TD7GJ.js → machineCommands-S2RNYKVJ.js} +14 -14
  51. package/{machineWsRunDispatch-XUOIAXO7.js → machineWsRunDispatch-JC44LBLP.js} +14 -14
  52. package/package.json +1 -1
  53. package/{readlineWorkspace-74TXXSLO.js → readlineWorkspace-VZSBXUH4.js} +15 -15
  54. package/{runAgentClientLoop-37BXJD62.js → runAgentClientLoop-ZYENU7GH.js} +11 -11
  55. package/{spaceCommands-P3ONT6LL.js → spaceCommands-QB3NNEMN.js} +2 -2
  56. package/{streamAgentChatTurn-FGXQXALU.js → streamAgentChatTurn-43GPPQSN.js} +12 -12
  57. package/{tools-R5UF2KZO.js → tools-SX6Y4STZ.js} +8 -8
  58. package/{updateDialogTitleAction-RTADGV7A.js → updateDialogTitleAction-VAKA4ZNY.js} +3 -3
@@ -21,7 +21,7 @@ import {
21
21
  formatStatusRunCard,
22
22
  formatStopRunCard,
23
23
  resolveRunLabel
24
- } from "./chunk-NTW5GWDM.js";
24
+ } from "./chunk-3VNWWVKB.js";
25
25
  import {
26
26
  omitNullishAgentSummaryFields,
27
27
  sortSafeAgentSummaries,
@@ -29,7 +29,7 @@ import {
29
29
  toCompactAgentSummary,
30
30
  toSafeAgentSummary,
31
31
  toUnavailableAgentSummary
32
- } from "./chunk-IAO6JBYW.js";
32
+ } from "./chunk-RG6JBBX5.js";
33
33
  import {
34
34
  getUserDataItemTimestamp,
35
35
  mergeAndDedupUserData
@@ -81,10 +81,10 @@ import {
81
81
  } from "./chunk-VF4K2QE6.js";
82
82
  import {
83
83
  createDocState
84
- } from "./chunk-BGSLKVCP.js";
84
+ } from "./chunk-R2B3MIZA.js";
85
85
  import {
86
86
  createDialogAction
87
- } from "./chunk-AFDS2CVM.js";
87
+ } from "./chunk-3WD6RUUJ.js";
88
88
  import {
89
89
  DEFAULT_COLLAPSED_CATEGORIES,
90
90
  addContentToSpace,
@@ -102,7 +102,7 @@ import {
102
102
  updateContentCategory,
103
103
  updateContentTitle,
104
104
  writeStoredCollapsedCategories
105
- } from "./chunk-ZXKVPF4K.js";
105
+ } from "./chunk-HWIZU4OL.js";
106
106
  import {
107
107
  getCurrentSpaceId,
108
108
  getCurrentSpaceIdRaw,
@@ -124,14 +124,14 @@ import {
124
124
  selectMsgById,
125
125
  uiAskChoiceFunc,
126
126
  uiAskChoiceFunctionSchema
127
- } from "./chunk-FOWEGIMF.js";
127
+ } from "./chunk-K4YGZD3P.js";
128
128
  import {
129
129
  createAgent,
130
130
  deleteServerSyncedCredential,
131
131
  runLlm,
132
132
  streamAgentChatTurn,
133
133
  updateAgent
134
- } from "./chunk-ZLR5JN3E.js";
134
+ } from "./chunk-SQQVLHMH.js";
135
135
  import {
136
136
  getActiveDialogKey,
137
137
  selectCurrentDialogKey,
@@ -3945,7 +3945,7 @@ async function deleteDialogsFunc(args, thunkApi) {
3945
3945
  const deletedDialogIds = [];
3946
3946
  const deletedDialogKeys = [];
3947
3947
  const failures = [];
3948
- const { deleteDialog: deleteDialog2 } = await import("./dialogSlice-3YH242HS.js");
3948
+ const { deleteDialog: deleteDialog2 } = await import("./dialogSlice-W5BYELVR.js");
3949
3949
  for (const target of targets) {
3950
3950
  try {
3951
3951
  await thunkApi.dispatch(deleteDialog2(target.dbKey)).unwrap();
@@ -13027,7 +13027,61 @@ var runAgentBackground = createAsyncThunk("agent/runBackground", async (args, {
13027
13027
  throw lastError ?? new Error("\u4E8B\u4EF6\u6D41\u91CD\u8FDE\u5931\u8D25");
13028
13028
  });
13029
13029
 
13030
+ // packages/ai/tools/agent/credentialFanoutGuard.ts
13031
+ var UNKNOWN_CREDENTIAL_GROUP = "unknown";
13032
+ function normalizeCredentialGroupValue(group) {
13033
+ if (typeof group !== "string") return UNKNOWN_CREDENTIAL_GROUP;
13034
+ const trimmed2 = group.trim();
13035
+ if (!trimmed2) return UNKNOWN_CREDENTIAL_GROUP;
13036
+ if (trimmed2.toLowerCase() === UNKNOWN_CREDENTIAL_GROUP) {
13037
+ return UNKNOWN_CREDENTIAL_GROUP;
13038
+ }
13039
+ return trimmed2;
13040
+ }
13041
+ var describeEntry = (entry) => entry.agentKey ?? entry.runId ?? "(unknown run)";
13042
+ function checkCredentialFanout(args) {
13043
+ const candidateGroup = normalizeCredentialGroupValue(
13044
+ args.candidate.credentialGroup
13045
+ );
13046
+ for (const entry of args.active) {
13047
+ if (entry.runId && args.candidate.runId && entry.runId === args.candidate.runId) {
13048
+ continue;
13049
+ }
13050
+ const entryGroup = normalizeCredentialGroupValue(entry.credentialGroup);
13051
+ if (candidateGroup === UNKNOWN_CREDENTIAL_GROUP || entryGroup === UNKNOWN_CREDENTIAL_GROUP) {
13052
+ if (args.allowUnknownCredential === true) continue;
13053
+ const side = candidateGroup === UNKNOWN_CREDENTIAL_GROUP ? "candidate" : "active";
13054
+ return {
13055
+ allowed: false,
13056
+ reason: "unknown_credential_group",
13057
+ conflict: entry,
13058
+ message: `\u62D2\u7EDD\u5E76\u53D1\u6D3E\u53D1\uFF1A${side === "candidate" ? `\u5019\u9009 agent ${describeEntry(args.candidate)} \u7684 credentialGroup \u672A\u77E5` : `\u5DF2\u6D3B\u8DC3 run ${describeEntry(entry)} \u7684 credentialGroup \u672A\u77E5`}\uFF0C\u65E0\u6CD5\u8BC1\u660E\u5B83\u4E0E\u540C\u6279\u5E76\u53D1 run \u4E0D\u5171\u7528\u4E0A\u6E38\u51ED\u8BC1\u3002\u8BF7\u6539\u4E3A\u4E32\u884C\u6D3E\u53D1\u3001\u6362\u7528 credentialGroup \u660E\u786E\u7684 agent\uFF0C\u6216\u5728\u786E\u8BA4\u98CE\u9669\u540E\u663E\u5F0F\u4F20 allowUnknownCredential: true \u5F3A\u5236\u653E\u884C\u3002`
13059
+ };
13060
+ }
13061
+ if (candidateGroup === entryGroup) {
13062
+ return {
13063
+ allowed: false,
13064
+ reason: "credential_group_conflict",
13065
+ conflict: entry,
13066
+ message: `\u62D2\u7EDD\u5E76\u53D1\u6D3E\u53D1\uFF1A\u5019\u9009 agent ${describeEntry(args.candidate)} \u4E0E\u5DF2\u6D3B\u8DC3 run ${describeEntry(entry)} \u540C\u5C5E credentialGroup "${candidateGroup}"\uFF0C\u540C\u4E00\u51ED\u8BC1\u4E0A\u7981\u6B62\u5E76\u53D1\u6247\u51FA\u3002\u8BF7\u4E32\u884C\u6D3E\u53D1\u6216\u6539\u7528\u5176\u4ED6 credentialGroup \u7684 agent\u3002`
13067
+ };
13068
+ }
13069
+ }
13070
+ return { allowed: true };
13071
+ }
13072
+
13030
13073
  // packages/ai/tools/agent/startAgentRunTool.ts
13074
+ var BATCH_FANOUT_ENTRY_TTL_MS = 30 * 60 * 1e3;
13075
+ var batchFanoutRegistry = /* @__PURE__ */ new Map();
13076
+ function pruneBatchFanoutRegistry(nowMs) {
13077
+ for (const [batchId, entries] of batchFanoutRegistry) {
13078
+ const alive = entries.filter(
13079
+ (e) => nowMs - e.startedAtMs < BATCH_FANOUT_ENTRY_TTL_MS
13080
+ );
13081
+ if (alive.length === 0) batchFanoutRegistry.delete(batchId);
13082
+ else batchFanoutRegistry.set(batchId, alive);
13083
+ }
13084
+ }
13031
13085
  function buildStartAgentRunFunctionSchema(opts) {
13032
13086
  const supportsWait = opts?.supportsWait !== false;
13033
13087
  const wakeEnabled = opts?.wakeEnabled === true;
@@ -13059,7 +13113,16 @@ function buildStartAgentRunFunctionSchema(opts) {
13059
13113
  // 与 server 透传保持不动,探活/烟测仍走 CLI 侧。
13060
13114
  batchId: {
13061
13115
  type: "string",
13062
- description: "\u53EF\u9009\u3002\u6279\u6B21 id\uFF0C\u7528\u4E8E\u628A\u591A\u4E2A\u5E76\u884C run \u5F52\u4E3A\u4E00\u7EC4\uFF0C\u4FBF\u4E8E\u540E\u7EED controlAgentRun(list, batchId=...) \u6309\u6279\u67E5\u8BE2\u3002\u672A\u4F20\u65F6\u81EA\u52A8\u751F\u6210\u4E00\u4E2A\u5E76\u5728\u8FD4\u56DE\u503C\u4E2D\u5E26\u56DE\uFF0C\u8C03\u7528\u65B9\u65E0\u9700\u5148\u521B\u5EFA\u3002"
13116
+ description: "\u53EF\u9009\u3002\u6279\u6B21 id\uFF0C\u7528\u4E8E\u628A\u591A\u4E2A\u5E76\u884C run \u5F52\u4E3A\u4E00\u7EC4\uFF0C\u4FBF\u4E8E\u540E\u7EED controlAgentRun(list, batchId=...) \u6309\u6279\u67E5\u8BE2\u3002\u672A\u4F20\u65F6\u81EA\u52A8\u751F\u6210\u4E00\u4E2A\u5E76\u5728\u8FD4\u56DE\u503C\u4E2D\u5E26\u56DE\uFF0C\u8C03\u7528\u65B9\u65E0\u9700\u5148\u521B\u5EFA\u3002\u540C\u4E00 batchId \u5185\u7684\u5E76\u53D1\u6D3E\u53D1\u4F1A\u505A\u51ED\u8BC1\u7EC4\u9694\u79BB\u68C0\u67E5\uFF1AcredentialGroup \u76F8\u540C\u6216\u672A\u77E5\u7684\u5E76\u53D1 run \u4F1A\u88AB\u62D2\u7EDD\u3002"
13117
+ },
13118
+ credentialGroup: {
13119
+ type: "string",
13120
+ description: "\u53EF\u9009\u3002\u7167\u6284 listAgents \u8FD4\u56DE\u7684 credentialGroup \u5B57\u6BB5\uFF0C\u7528\u4E8E\u540C\u6279\u6B21\u5E76\u53D1\u6247\u51FA\u7684\u51ED\u8BC1\u9694\u79BB\u6821\u9A8C\u3002\u7F3A\u7701/\u7A7A\u503C\u89C6\u4E3A\u300C\u672A\u77E5\u300D\uFF08\u4E0D\u662F\u300C\u72EC\u7ACB\u300D\uFF09\uFF1A\u4E0E\u540C batch \u5185\u4EFB\u4F55\u5176\u4ED6 run \u5E76\u53D1\u90FD\u4F1A\u88AB\u62D2\u7EDD\u3002"
13121
+ },
13122
+ allowUnknownCredential: {
13123
+ type: "boolean",
13124
+ description: "\u53EF\u9009\u3002\u663E\u5F0F\u786E\u8BA4\u300C\u51ED\u8BC1\u5F52\u5C5E\u672A\u77E5\u300D\u7684\u5E76\u53D1\u98CE\u9669\u540E\u5F3A\u5236\u653E\u884C\uFF08\u7B49\u540C\u4E8E CLI \u7684 --force-unknown-credential\uFF09\u3002\u4EC5\u5728\u5DF2\u81EA\u884C\u786E\u8BA4\u4E24\u4FA7\u4E0D\u5171\u7528\u4E0A\u6E38\u51ED\u8BC1\u65F6\u4F7F\u7528\uFF1B\u9ED8\u8BA4 false\uFF0C\u672A\u77E5\u51ED\u8BC1\u5E76\u53D1\u4E00\u5F8B\u62D2\u7EDD\u3002",
13125
+ default: false
13063
13126
  },
13064
13127
  trackTodo: {
13065
13128
  type: "boolean",
@@ -13092,13 +13155,25 @@ async function startAgentRunFunc(args, thunkApi, _context) {
13092
13155
  const { agentKey, task, input, agentName, batchId, wait } = args;
13093
13156
  const resultMode = args.resultMode ?? "full";
13094
13157
  const { dispatch } = thunkApi;
13095
- const effectiveBatchId = typeof batchId === "string" && batchId.trim() ? batchId.trim() : `batch-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-${Math.random().toString(36).slice(2, 8)}`;
13158
+ const explicitBatchId = typeof batchId === "string" && batchId.trim() ? batchId.trim() : void 0;
13159
+ const effectiveBatchId = explicitBatchId ?? `batch-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-${Math.random().toString(36).slice(2, 8)}`;
13096
13160
  if (!agentKey) {
13097
13161
  throw new Error("startAgentRun: \u7F3A\u5C11 agentKey \u53C2\u6570\u3002");
13098
13162
  }
13099
13163
  if (!task || typeof task !== "string") {
13100
13164
  throw new Error("startAgentRun: \u7F3A\u5C11\u6709\u6548\u7684 task \u6587\u672C\u63CF\u8FF0\u3002");
13101
13165
  }
13166
+ if (explicitBatchId) {
13167
+ const nowMs = Date.now();
13168
+ pruneBatchFanoutRegistry(nowMs);
13169
+ const active = batchFanoutRegistry.get(explicitBatchId) ?? [];
13170
+ const verdict = checkCredentialFanout({
13171
+ active,
13172
+ candidate: { agentKey, credentialGroup: args.credentialGroup },
13173
+ allowUnknownCredential: args.allowUnknownCredential === true
13174
+ });
13175
+ if (!verdict.allowed) throw new Error(verdict.message);
13176
+ }
13102
13177
  const content = buildDelegatedTaskContent(task, input);
13103
13178
  const payloadMetrics = calculateDelegatedPayloadMetrics(task, input, content);
13104
13179
  const activeDialogKey = getActiveDialogKey();
@@ -13128,6 +13203,16 @@ async function startAgentRunFunc(args, thunkApi, _context) {
13128
13203
  };
13129
13204
  }
13130
13205
  const runId = bgResult.dialogId;
13206
+ if (explicitBatchId) {
13207
+ const entries = batchFanoutRegistry.get(explicitBatchId) ?? [];
13208
+ entries.push({
13209
+ runId,
13210
+ agentKey,
13211
+ ...typeof args.credentialGroup === "string" && args.credentialGroup.trim() ? { credentialGroup: args.credentialGroup.trim() } : {},
13212
+ startedAtMs: Date.now()
13213
+ });
13214
+ batchFanoutRegistry.set(explicitBatchId, entries);
13215
+ }
13131
13216
  const status = bgResult.status ?? "pending";
13132
13217
  const resolvedName = agentName?.trim() || bgResult.agentName || bgResult.name;
13133
13218
  const identity = { agentName: resolvedName, agentKey, runId };
@@ -14821,7 +14906,7 @@ var executeToolRun = createAsyncThunk(
14821
14906
  if (!executionInput) {
14822
14907
  throw new Error(`ToolRun ${id} has no input to execute with.`);
14823
14908
  }
14824
- const { findToolExecutor: findToolExecutor2 } = await import("./tools-R5UF2KZO.js");
14909
+ const { findToolExecutor: findToolExecutor2 } = await import("./tools-SX6Y4STZ.js");
14825
14910
  const { executor } = findToolExecutor2(run.toolName);
14826
14911
  toolRunStarted({
14827
14912
  id: run.id,
@@ -17328,7 +17413,7 @@ async function updateDocFunc(args, thunkApi) {
17328
17413
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
17329
17414
  };
17330
17415
  await dispatch(write({ data: updatedPageData, customKey: id })).unwrap();
17331
- const { getDocState, applyExternalDocUpdate } = await import("./docStore-YSZRNUUD.js");
17416
+ const { getDocState, applyExternalDocUpdate } = await import("./docStore-7LAHBFP2.js");
17332
17417
  if (getDocState().pageKey === id) {
17333
17418
  applyExternalDocUpdate({
17334
17419
  slateData: finalSlateData,
@@ -19634,6 +19719,7 @@ export {
19634
19719
  rememberMemoryFunctionSchema,
19635
19720
  deleteMemoryFunctionSchema,
19636
19721
  queryMemoryFunctionSchema,
19722
+ checkCredentialFanout,
19637
19723
  buildStartAgentRunFunctionSchema,
19638
19724
  CONTROL_AGENT_RUN_ACTIONS,
19639
19725
  buildControlAgentRunFunctionSchema,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isAgentRunTerminalStatus
3
- } from "./chunk-NTW5GWDM.js";
3
+ } from "./chunk-3VNWWVKB.js";
4
4
  import {
5
5
  isCompiledBinary,
6
6
  resolveCliEntrypointPath
@@ -11,6 +11,60 @@ import { homedir as nodeHomedir } from "node:os";
11
11
  import { dirname, isAbsolute, join, resolve } from "node:path";
12
12
  import * as nodeFs from "node:fs";
13
13
  import { execFileSync as nodeExecFileSync, spawn as nodeSpawn } from "node:child_process";
14
+
15
+ // packages/ai/tools/agent/runFailureClass.ts
16
+ var RATE_LIMIT_PATTERN = /429|rate.?limit|quota|insufficient.?balance|UPSTREAM_402|cooling|冷却/i;
17
+ var PROVIDER_ERROR_PATTERN = /provider|upstream|5\d\d|bad.?gateway|service.?unavailable|overloaded/i;
18
+ var MALFORMED_PATTERN = /MALFORMED_FUNCTION_CALL|malformed|invalid.?function.?call|invalid.?tool.?call/i;
19
+ var STALLED_PATTERN = /stall|no.?progress|repetition|stagnant|无进展|卡死/i;
20
+ var TOOL_ERROR_PATTERN = /tool.?error|tool.?fail|工具/i;
21
+ function classifyRunFailure(input) {
22
+ const status = typeof input.status === "string" ? input.status : "";
23
+ if (status === "done" || status === "killed" || status === "cancelled") {
24
+ return void 0;
25
+ }
26
+ const reason = typeof input.failureReason === "string" ? input.failureReason : "";
27
+ const message = typeof input.errorMessage === "string" ? input.errorMessage : "";
28
+ switch (reason) {
29
+ case "provider_rate_limited":
30
+ return { failureClass: "rate_limited", retryable: true };
31
+ case "provider_error":
32
+ return MALFORMED_PATTERN.test(message) ? { failureClass: "provider_error", retryable: false } : { failureClass: "provider_error", retryable: true };
33
+ case "stalled":
34
+ return { failureClass: "stalled", retryable: false };
35
+ case "tool_error":
36
+ return { failureClass: "tool_error", retryable: false };
37
+ case "config_unresolved":
38
+ return { failureClass: "unknown", retryable: false };
39
+ case "cancelled":
40
+ return void 0;
41
+ default:
42
+ break;
43
+ }
44
+ if (message) {
45
+ if (RATE_LIMIT_PATTERN.test(message)) {
46
+ return { failureClass: "rate_limited", retryable: true };
47
+ }
48
+ if (MALFORMED_PATTERN.test(message)) {
49
+ return { failureClass: "provider_error", retryable: false };
50
+ }
51
+ if (STALLED_PATTERN.test(message)) {
52
+ return { failureClass: "stalled", retryable: false };
53
+ }
54
+ if (TOOL_ERROR_PATTERN.test(message)) {
55
+ return { failureClass: "tool_error", retryable: false };
56
+ }
57
+ if (PROVIDER_ERROR_PATTERN.test(message)) {
58
+ return { failureClass: "provider_error", retryable: true };
59
+ }
60
+ }
61
+ if (status === "failed" || status === "timeout" || status === "orphaned") {
62
+ return { failureClass: "unknown", retryable: false };
63
+ }
64
+ return void 0;
65
+ }
66
+
67
+ // packages/cli/agentRunControl.ts
14
68
  var RUN_TERMINAL_STATUSES = /* @__PURE__ */ new Set([
15
69
  "done",
16
70
  "failed",
@@ -794,6 +848,7 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
794
848
  logPath,
795
849
  queuePath,
796
850
  batchId,
851
+ ...typeof input.credentialGroup === "string" && input.credentialGroup.trim() ? { credentialGroup: input.credentialGroup.trim() } : {},
797
852
  ...typeof input.parentDialogId === "string" && input.parentDialogId.trim() ? { parentDialogId: input.parentDialogId.trim() } : {},
798
853
  ...dodCommands && dodCommands.length > 0 ? { dodCommands } : {},
799
854
  ...spawnHead ? { spawnHead } : {},
@@ -925,6 +980,15 @@ function transitionRunToTerminal(runId, update, deps = {}, options = {}) {
925
980
  } else if (update.status === "killed") {
926
981
  record2.failureReason = "cancelled";
927
982
  }
983
+ const classification = classifyRunFailure({
984
+ status: update.status,
985
+ failureReason: record2.failureReason,
986
+ errorMessage: update.note ?? record2.note
987
+ });
988
+ if (classification) {
989
+ record2.failureClass = classification.failureClass;
990
+ record2.retryable = classification.retryable;
991
+ }
928
992
  const resolvedToolCount = typeof update.toolCallCount === "number" ? update.toolCallCount : record2.activity?.counters?.toolCalls;
929
993
  if (typeof resolvedToolCount === "number") {
930
994
  record2.toolCallCount = resolvedToolCount;
@@ -1044,6 +1108,15 @@ function checkStaleRun(runId, deps = {}) {
1044
1108
  const at = now().toISOString();
1045
1109
  latest.status = "orphaned";
1046
1110
  latest.note = pidReused ? "orphaned: process gone (pid reused by another process)" : "orphaned: process gone without writing terminal status";
1111
+ const orphanClassification = classifyRunFailure({
1112
+ status: "orphaned",
1113
+ failureReason: latest.failureReason,
1114
+ errorMessage: latest.note
1115
+ });
1116
+ if (orphanClassification) {
1117
+ latest.failureClass = orphanClassification.failureClass;
1118
+ latest.retryable = orphanClassification.retryable;
1119
+ }
1047
1120
  latest.endedAt = at;
1048
1121
  latest.reconciledAt = at;
1049
1122
  latest.pid = void 0;
@@ -1259,6 +1332,18 @@ function printStatusOnce(record, deps) {
1259
1332
  }
1260
1333
  if (record.note) deps.output.write(`note: ${record.note}
1261
1334
  `);
1335
+ if (record.failureReason) deps.output.write(`failure: ${record.failureReason}
1336
+ `);
1337
+ if (record.failureClass) {
1338
+ deps.output.write(
1339
+ `class: ${record.failureClass}${typeof record.retryable === "boolean" ? ` (retryable=${record.retryable})` : ""}
1340
+ `
1341
+ );
1342
+ }
1343
+ if (record.credentialGroup) {
1344
+ deps.output.write(`credGroup: ${record.credentialGroup}
1345
+ `);
1346
+ }
1262
1347
  const activitySummary = formatActivitySummary(record.activity);
1263
1348
  if (activitySummary) deps.output.write(`${activitySummary}
1264
1349
  `);
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  toolRegistry
3
- } from "./chunk-MMPXJXHT.js";
3
+ } from "./chunk-TZJJ77KQ.js";
4
4
  import {
5
5
  i18n_default
6
- } from "./chunk-FOWEGIMF.js";
6
+ } from "./chunk-K4YGZD3P.js";
7
7
  import {
8
8
  canonicalizeToolNames
9
9
  } from "./chunk-O6OSWFZQ.js";
@@ -21,6 +21,7 @@ import {
21
21
  commitRunRecordClaim,
22
22
  findRunRecord,
23
23
  gcRunRecords,
24
+ isRunTerminalStatus,
24
25
  popAllQueueEntries,
25
26
  queryRunRecords,
26
27
  releaseRunRecordAck,
@@ -29,7 +30,7 @@ import {
29
30
  terminateRunProcess,
30
31
  transitionRunToTerminal,
31
32
  withQueueLock
32
- } from "./chunk-CPH3W5A7.js";
33
+ } from "./chunk-WGR3J4Q6.js";
33
34
  import {
34
35
  clearCredentialAvailability,
35
36
  markCredentialUnavailable,
@@ -60,7 +61,7 @@ import {
60
61
  import {
61
62
  inlineImageUrlsForCustomProvider,
62
63
  prepareTools
63
- } from "./chunk-XOVEWFLK.js";
64
+ } from "./chunk-Y5HW6GM2.js";
64
65
  import {
65
66
  getServerProviderSecret
66
67
  } from "./chunk-HS7MLR74.js";
@@ -69,6 +70,7 @@ import {
69
70
  CONTROL_AGENT_RUN_ACTIONS,
70
71
  buildControlAgentRunFunctionSchema,
71
72
  buildStartAgentRunFunctionSchema,
73
+ checkCredentialFanout,
72
74
  deleteMemoryFunctionSchema,
73
75
  queryMemoryFunctionSchema,
74
76
  readXPostFunc,
@@ -78,7 +80,7 @@ import {
78
80
  rememberMemoryFunctionSchema,
79
81
  resolveAgentRequiredPackIds,
80
82
  setTodoListFunc
81
- } from "./chunk-MMPXJXHT.js";
83
+ } from "./chunk-TZJJ77KQ.js";
82
84
  import {
83
85
  fetchWithTransientRetry,
84
86
  isTransientFetchError
@@ -94,7 +96,10 @@ import {
94
96
  isAgentRunTerminalStatus,
95
97
  resolveRunLabel,
96
98
  shortRunId
97
- } from "./chunk-NTW5GWDM.js";
99
+ } from "./chunk-3VNWWVKB.js";
100
+ import {
101
+ deriveCredentialGroup
102
+ } from "./chunk-RG6JBBX5.js";
98
103
  import {
99
104
  getModelPricing
100
105
  } from "./chunk-EYAQT56M.js";
@@ -104,14 +109,14 @@ import {
104
109
  prepareTokenUsageData,
105
110
  resolveBuiltinPlatformAgentConfig,
106
111
  runKeyed
107
- } from "./chunk-FOWEGIMF.js";
112
+ } from "./chunk-K4YGZD3P.js";
108
113
  import {
109
114
  BUILTIN_DIALOG_LLM_CHAT_FALLBACK_MODEL,
110
115
  BUILTIN_TITLE_LLM_CONFIG
111
116
  } from "./chunk-MC4XLIJ7.js";
112
117
  import {
113
118
  fetchServerSyncedCredential
114
- } from "./chunk-ZLR5JN3E.js";
119
+ } from "./chunk-SQQVLHMH.js";
115
120
  import {
116
121
  require_date_fns
117
122
  } from "./chunk-M76ECQRD.js";
@@ -165,7 +170,7 @@ import {
165
170
  resolveOpenAiCompatibleProviderConfig,
166
171
  shouldUseGeminiNativeToolRoute,
167
172
  summarizeToolArguments
168
- } from "./chunk-4MY4GLIW.js";
173
+ } from "./chunk-ZWUOR654.js";
169
174
  import {
170
175
  PlatformStreamInterruptedError,
171
176
  buildPlatformChatCompletionRequest,
@@ -11468,6 +11473,12 @@ function buildRunStatusPayload(reconciled, deps, opts = {}) {
11468
11473
  endedAt: reconciled.endedAt ?? null,
11469
11474
  exitCode: reconciled.exitCode ?? null,
11470
11475
  ...reconciled.failureReason ? { failureReason: reconciled.failureReason } : {},
11476
+ // 结构化失败分类 + 可重试性:编排者据此决策,不再肉读 logTail。
11477
+ ...reconciled.failureClass ? { failureClass: reconciled.failureClass } : {},
11478
+ ...typeof reconciled.retryable === "boolean" ? { retryable: reconciled.retryable } : {},
11479
+ // 日志落盘路径始终暴露:stalled/failed 且 dialogId 缺失(如 ephemeral)
11480
+ // 时 logTail 只能靠它读,不能只留在进程内存。
11481
+ ...reconciled.logPath ? { logPath: reconciled.logPath } : {},
11471
11482
  ...typeof reconciled.toolCallCount === "number" ? { toolCallCount: reconciled.toolCallCount } : {},
11472
11483
  ...reconciled.lastAssistantText ? { lastAssistantText: reconciled.lastAssistantText } : {},
11473
11484
  // Non-ephemeral runs expose dialogId so the caller can read the
@@ -11502,6 +11513,39 @@ function buildRunStatusPayload(reconciled, deps, opts = {}) {
11502
11513
  }
11503
11514
  };
11504
11515
  }
11516
+ async function assertCredentialFanoutAllowed(deps, args) {
11517
+ let candidateGroup;
11518
+ if (deps.resolveAgentCredentialGroup) {
11519
+ try {
11520
+ candidateGroup = await deps.resolveAgentCredentialGroup(args.agentKey);
11521
+ } catch {
11522
+ candidateGroup = void 0;
11523
+ }
11524
+ }
11525
+ if (!candidateGroup && typeof args.credentialGroup === "string" && args.credentialGroup.trim()) {
11526
+ candidateGroup = args.credentialGroup.trim();
11527
+ }
11528
+ const { batchId, parentDialogId } = args;
11529
+ if (!batchId && !parentDialogId) return candidateGroup;
11530
+ const active = queryRunRecords({ limit: 500 }, deps).runs.filter((record) => {
11531
+ if (isRunTerminalStatus(record.status)) return false;
11532
+ if (batchId && record.batchId === batchId) return true;
11533
+ if (parentDialogId && record.parentDialogId === parentDialogId) return true;
11534
+ return false;
11535
+ }).map((record) => ({
11536
+ runId: record.runId,
11537
+ agentKey: record.agentKey,
11538
+ credentialGroup: record.credentialGroup
11539
+ }));
11540
+ if (active.length === 0) return candidateGroup;
11541
+ const verdict = checkCredentialFanout({
11542
+ active,
11543
+ candidate: { agentKey: args.agentKey, credentialGroup: candidateGroup },
11544
+ allowUnknownCredential: args.allowUnknownCredential === true
11545
+ });
11546
+ if (!verdict.allowed) throw new Error(verdict.message);
11547
+ return candidateGroup;
11548
+ }
11505
11549
  function createCliStartAgentRunExecutor(deps = {}) {
11506
11550
  return async (call) => {
11507
11551
  const args = parseCallArgs(call);
@@ -11524,6 +11568,14 @@ function createCliStartAgentRunExecutor(deps = {}) {
11524
11568
  ];
11525
11569
  const agentName = typeof args.agentName === "string" && args.agentName.trim() ? args.agentName.trim() : typeof args.name === "string" && args.name.trim() ? args.name.trim() : void 0;
11526
11570
  const batchId = typeof args.batchId === "string" && args.batchId.trim() ? args.batchId.trim() : void 0;
11571
+ const parentDialogId = typeof args.parentDialogId === "string" && args.parentDialogId.trim() ? args.parentDialogId.trim() : void 0;
11572
+ const credentialGroup = await assertCredentialFanoutAllowed(deps, {
11573
+ agentKey,
11574
+ ...batchId ? { batchId } : {},
11575
+ ...parentDialogId ? { parentDialogId } : {},
11576
+ ...typeof args.credentialGroup === "string" && args.credentialGroup.trim() ? { credentialGroup: args.credentialGroup.trim() } : {},
11577
+ allowUnknownCredential: args.allowUnknownCredential === true
11578
+ });
11527
11579
  const dodCommands = Array.isArray(args.dodCommands) ? args.dodCommands.filter((c) => typeof c === "string" && c.trim().length > 0).map((c) => c.trim()) : typeof args.dod === "string" && args.dod.trim().length > 0 ? [args.dod.trim()] : Array.isArray(args.dod) ? args.dod.filter((c) => typeof c === "string" && c.trim().length > 0).map((c) => c.trim()) : void 0;
11528
11580
  const { runId, batchId: resolvedBatchId } = await spawnLocalBackgroundRun(
11529
11581
  {
@@ -11533,7 +11585,8 @@ function createCliStartAgentRunExecutor(deps = {}) {
11533
11585
  agentKey,
11534
11586
  ...agentName ? { agentName } : {},
11535
11587
  ...batchId ? { batchId } : {},
11536
- ...typeof args.parentDialogId === "string" && args.parentDialogId.trim() ? { parentDialogId: args.parentDialogId.trim() } : {},
11588
+ ...credentialGroup ? { credentialGroup } : {},
11589
+ ...parentDialogId ? { parentDialogId } : {},
11537
11590
  ...dodCommands && dodCommands.length > 0 ? { dodCommands } : {},
11538
11591
  cwd: deps.cwd ?? process.cwd(),
11539
11592
  message,
@@ -11619,6 +11672,8 @@ async function spawnContinuationRun(reconciled, userInput, deps) {
11619
11672
  ...agentName ? { agentName } : {},
11620
11673
  ...reconciled.batchId ? { batchId: reconciled.batchId } : {},
11621
11674
  ...reconciled.parentDialogId ? { parentDialogId: reconciled.parentDialogId } : {},
11675
+ // 续跑继承原 run 的凭证组(同一 agent),供并发扇出守卫判定。
11676
+ ...reconciled.credentialGroup ? { credentialGroup: reconciled.credentialGroup } : {},
11622
11677
  cwd: reconciled.cwd ?? deps.cwd ?? process.cwd(),
11623
11678
  message: userInput,
11624
11679
  ...reconciled.ephemeral ? { ephemeral: true } : {},
@@ -12217,7 +12272,8 @@ function buildLocalToolExecutors(args) {
12217
12272
  startAgentRun: createCliStartAgentRunExecutor({
12218
12273
  env: args.env,
12219
12274
  cliEntrypoint: args.cliEntrypoint,
12220
- cwd: args.workspaceRoot
12275
+ cwd: args.workspaceRoot,
12276
+ ...args.resolveAgentCredentialGroup ? { resolveAgentCredentialGroup: args.resolveAgentCredentialGroup } : {}
12221
12277
  }),
12222
12278
  controlAgentRun: createCliControlAgentRunExecutor({
12223
12279
  env: args.env
@@ -13078,6 +13134,23 @@ function createCliLocalRuntimeAdapter(deps) {
13078
13134
  const localToolUsage = /* @__PURE__ */ new Map();
13079
13135
  const buildProviderOpenAiTools = deps.buildProviderOpenAiTools ?? buildOpenAiTools;
13080
13136
  const additionalToolNames = deps.pastedTextStore ? ["readPastedText"] : [];
13137
+ const resolveAgentCredentialGroup = async (agentRef) => {
13138
+ try {
13139
+ const record = await readAgentFromStore({
13140
+ agentRef,
13141
+ store: await getOrCreateSharedStore(deps),
13142
+ userId
13143
+ });
13144
+ if (!record || typeof record !== "object") return void 0;
13145
+ const rec = record;
13146
+ const existing = typeof rec.credentialGroup === "string" && rec.credentialGroup.trim() ? rec.credentialGroup.trim() : void 0;
13147
+ if (existing) return existing;
13148
+ const ref = typeof rec.apiKeyRef === "string" && rec.apiKeyRef.trim() ? rec.apiKeyRef : typeof rec.credentialRef === "string" && rec.credentialRef.trim() ? rec.credentialRef : void 0;
13149
+ return deriveCredentialGroup(ref)?.credentialGroup;
13150
+ } catch {
13151
+ return void 0;
13152
+ }
13153
+ };
13081
13154
  let activeAgentToolNames = [];
13082
13155
  const workspaceRoot = deps.cwd ?? process.cwd();
13083
13156
  let runtimeToolExecutionLimits = {};
@@ -13090,6 +13163,7 @@ function createCliLocalRuntimeAdapter(deps) {
13090
13163
  readXPost: deps.readXPost,
13091
13164
  readXhsProfile: deps.readXhsProfile,
13092
13165
  cliEntrypoint: CLI_ENTRYPOINT,
13166
+ resolveAgentCredentialGroup,
13093
13167
  ...deps.confirmDestructiveAction ? { confirmDestructiveAction: deps.confirmDestructiveAction } : {},
13094
13168
  ...deps.requestUserChoice ? { requestUserChoice: deps.requestUserChoice } : {},
13095
13169
  ...deps.pastedTextStore ? { pastedTextStore: deps.pastedTextStore } : {},
@@ -13167,6 +13241,7 @@ function createCliLocalRuntimeAdapter(deps) {
13167
13241
  readXPost: deps.readXPost,
13168
13242
  readXhsProfile: deps.readXhsProfile,
13169
13243
  cliEntrypoint: CLI_ENTRYPOINT,
13244
+ resolveAgentCredentialGroup,
13170
13245
  ...deps.confirmDestructiveAction ? { confirmDestructiveAction: deps.confirmDestructiveAction } : {},
13171
13246
  ...deps.requestUserChoice ? { requestUserChoice: deps.requestUserChoice } : {},
13172
13247
  ...deps.pastedTextStore ? { pastedTextStore: deps.pastedTextStore } : {},
@@ -38,13 +38,15 @@ import {
38
38
  TOOL_GUIDED_SECTION_ORDER,
39
39
  buildIdentityBlock,
40
40
  buildRuntimeGuidanceBlocks,
41
+ detectDispatchIntent,
42
+ detectDispatchIntentFromMessages,
41
43
  estimateContextTokens,
42
44
  hashStablePrefixContent,
43
45
  normalizeChatCompletionsBodyForProvider,
44
46
  requiresBareImageUrl,
45
47
  resolveToolGuidedSections,
46
48
  toBareImageUrlMessages
47
- } from "./chunk-OA6Q2A4I.js";
49
+ } from "./chunk-LZIWMYX4.js";
48
50
  import {
49
51
  convertMessagesToResponsesInput,
50
52
  extractReasoningFromResponseOutput,
@@ -13529,7 +13531,14 @@ async function runLocalAgentTurn(input) {
13529
13531
  agentConfig.exposedToolNames ?? agentConfig.toolNames ?? []
13530
13532
  );
13531
13533
  const guidanceBlocks = buildRuntimeGuidanceBlocks(agentTools);
13532
- const toolGuidedSections = resolveToolGuidedSections(agentTools);
13534
+ const toolGuidedSections = resolveToolGuidedSections(agentTools, {
13535
+ // 单调锁定:历史里任一 user 消息命中派发关键词、或已出现过
13536
+ // startAgentRun/controlAgentRun 的 tool_calls,后续每轮都保持 true,
13537
+ // 防止 session-scope 的 agentCollaboration 段逐轮翻转击穿前缀缓存。
13538
+ dispatchIntent: detectDispatchIntentFromMessages(history) || detectDispatchIntent(
13539
+ typeof input.input === "string" ? input.input : void 0
13540
+ )
13541
+ });
13533
13542
  const guidanceScopes = [
13534
13543
  ...input.userLanguage?.trim() ? [buildUserResponseLanguageContext({ language: input.userLanguage })] : [],
13535
13544
  guidanceBlocks.startupProtocol,
@@ -7,14 +7,14 @@ import {
7
7
  updateContentPinned,
8
8
  updateContentTitle,
9
9
  uploadAndAddFileToSpace
10
- } from "./chunk-ZXKVPF4K.js";
10
+ } from "./chunk-HWIZU4OL.js";
11
11
  import "./chunk-ZJ7UHBJS.js";
12
- import "./chunk-FOWEGIMF.js";
12
+ import "./chunk-K4YGZD3P.js";
13
13
  import "./chunk-MC4XLIJ7.js";
14
14
  import "./chunk-3BMYXEUW.js";
15
15
  import "./chunk-YYLHWIW6.js";
16
16
  import "./chunk-AGGIDPCZ.js";
17
- import "./chunk-ZLR5JN3E.js";
17
+ import "./chunk-SQQVLHMH.js";
18
18
  import "./chunk-TOP2VXOR.js";
19
19
  import "./chunk-5RGU3J7P.js";
20
20
  import "./chunk-6YTOJY35.js";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  addContentToSpace
3
- } from "./chunk-ZXKVPF4K.js";
3
+ } from "./chunk-HWIZU4OL.js";
4
4
  import "./chunk-ZJ7UHBJS.js";
5
- import "./chunk-FOWEGIMF.js";
5
+ import "./chunk-K4YGZD3P.js";
6
6
  import "./chunk-MC4XLIJ7.js";
7
7
  import "./chunk-3BMYXEUW.js";
8
8
  import "./chunk-YYLHWIW6.js";
9
9
  import "./chunk-AGGIDPCZ.js";
10
- import "./chunk-ZLR5JN3E.js";
10
+ import "./chunk-SQQVLHMH.js";
11
11
  import "./chunk-TOP2VXOR.js";
12
12
  import "./chunk-5RGU3J7P.js";
13
13
  import "./chunk-6YTOJY35.js";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  createDialogAction,
3
3
  isLocalOwnerDialogAgents
4
- } from "./chunk-AFDS2CVM.js";
5
- import "./chunk-ZXKVPF4K.js";
4
+ } from "./chunk-3WD6RUUJ.js";
5
+ import "./chunk-HWIZU4OL.js";
6
6
  import "./chunk-ZJ7UHBJS.js";
7
- import "./chunk-FOWEGIMF.js";
7
+ import "./chunk-K4YGZD3P.js";
8
8
  import "./chunk-MC4XLIJ7.js";
9
9
  import "./chunk-3BMYXEUW.js";
10
10
  import "./chunk-YYLHWIW6.js";
11
11
  import "./chunk-AGGIDPCZ.js";
12
- import "./chunk-ZLR5JN3E.js";
12
+ import "./chunk-SQQVLHMH.js";
13
13
  import "./chunk-TOP2VXOR.js";
14
14
  import "./chunk-5RGU3J7P.js";
15
15
  import "./chunk-6YTOJY35.js";