nolo-cli 0.103.0-alpha.2 → 0.104.0-alpha.2

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 (54) hide show
  1. package/{_executeModel-3UCNJCQA.js → _executeModel-4W7C3ACS.js} +10 -10
  2. package/{agentDeleteCommand-2YAHAZFJ.js → agentDeleteCommand-YB3S2LPY.js} +1 -1
  3. package/{agentEmailCommands-WLYF3JRS.js → agentEmailCommands-AQZVMNLR.js} +10 -10
  4. package/{agentListCommands-JP7S7PT2.js → agentListCommands-3GWH4E4G.js} +3 -62
  5. package/{agentMachineCommands-HNGAR5GI.js → agentMachineCommands-R5AVYYN3.js} +2 -2
  6. package/{agentRecordCommands-SXFPW3DL.js → agentRecordCommands-JY4IWSSQ.js} +10 -10
  7. package/{agentRunCommand-JIQ4HY4D.js → agentRunCommand-7VTYZY3Q.js} +11 -10
  8. package/{agentRuntimeLocal-VXZSDIGT.js → agentRuntimeLocal-FRUE5P2V.js} +5 -1
  9. package/{agentSlice-SICQBMCM.js → agentSlice-6LBOYNKN.js} +1 -1
  10. package/{appDeleteCommands-32MHLR4L.js → appDeleteCommands-JPWTSFID.js} +1 -1
  11. package/{appDeployCommands-WCQOUSOB.js → appDeployCommands-YCVY2UYO.js} +1 -1
  12. package/{appDeployStatusCommands-6QKB7DYN.js → appDeployStatusCommands-JMCEIKTI.js} +1 -1
  13. package/{appGetCommands-SFAPP5PB.js → appGetCommands-EXWT3QAE.js} +1 -1
  14. package/{appListCommands-EKUBDRUO.js → appListCommands-PKRLSWRE.js} +1 -1
  15. package/{chatQueueReduxAdapter-HHMUDNXL.js → chatQueueReduxAdapter-WFROMKD3.js} +2 -2
  16. package/{chunk-XS5SWEDQ.js → chunk-2J5Y72GY.js} +1 -1
  17. package/{chunk-DNUUJ45N.js → chunk-3ZW5ZJMM.js} +2 -2
  18. package/{chunk-OZGZPSEG.js → chunk-A6FMKU7M.js} +1 -1
  19. package/chunk-BMQ2MJUK.js +153 -0
  20. package/{chunk-RSONHHPE.js → chunk-DJWMIXDZ.js} +2 -2
  21. package/{chunk-IONPPCL5.js → chunk-EEGDMATE.js} +65 -0
  22. package/{chunk-XVZ22N6C.js → chunk-FQUHIG5X.js} +8 -8
  23. package/{chunk-TQBHNYVR.js → chunk-H66KLASO.js} +8 -8
  24. package/{chunk-6VFARHZW.js → chunk-LC43IGO4.js} +291 -130
  25. package/{chunk-AGVEIAQA.js → chunk-NXUYQBDZ.js} +5 -5
  26. package/{chunk-LW4VFPAY.js → chunk-O7EBSHZR.js} +48 -8
  27. package/{chunk-F2RNI7ZR.js → chunk-RJ4QOQDA.js} +13 -5
  28. package/{chunk-CUQEXCAU.js → chunk-S6JLBH6Z.js} +1 -1
  29. package/{chunk-3WLK2JQ5.js → chunk-U3JZVWIB.js} +3 -3
  30. package/{chunk-4EG4QFTK.js → chunk-VLI5LVL5.js} +3 -3
  31. package/{chunk-B3TVQ6PI.js → chunk-W324THOB.js} +2 -2
  32. package/{chunk-3N3W7KBB.js → chunk-YY7I6GQ3.js} +3 -3
  33. package/{contentThunks-S4S7QPSO.js → contentThunks-LXOZUD2Y.js} +3 -3
  34. package/{createAgentAutomationAction-ODGL2YGP.js → createAgentAutomationAction-M5NDEIC6.js} +3 -3
  35. package/{createDialogAction-GFKRXTK4.js → createDialogAction-TDFOINOY.js} +4 -4
  36. package/{createPageAction-FBV3OWX7.js → createPageAction-WY5ZKP2M.js} +3 -3
  37. package/{dialogCommands-5J56DFWN.js → dialogCommands-YVMHDEOX.js} +1 -1
  38. package/{dialogSlice-LEO27SQG.js → dialogSlice-HSGREZGA.js} +2 -2
  39. package/{docCreateCommands-KYI2DC2U.js → docCreateCommands-7UTWDYJU.js} +1 -1
  40. package/{docDeleteCommands-67REUSRY.js → docDeleteCommands-GG6BJ4PS.js} +1 -1
  41. package/{docReadCommands-HOSVSBDJ.js → docReadCommands-QHMQVSLP.js} +1 -1
  42. package/{docStore-MNX5MHA5.js → docStore-IIS36NGG.js} +1 -1
  43. package/{docUpdateCommands-EMGCSMXY.js → docUpdateCommands-QPL6IVUK.js} +1 -1
  44. package/{handleSendMessageAction-YB6KQFJS.js → handleSendMessageAction-FEHCWMN2.js} +6 -48
  45. package/index.js +41 -41
  46. package/{machineCommands-7GVQCUAK.js → machineCommands-7DEUPY32.js} +10 -10
  47. package/{machineWsRunDispatch-XA7TD7Z7.js → machineWsRunDispatch-D2NHL3P7.js} +10 -10
  48. package/package.json +1 -1
  49. package/{readlineWorkspace-WA7JNI6J.js → readlineWorkspace-JP2AOALW.js} +26 -18
  50. package/{runAgentClientLoop-JGFQ6KIR.js → runAgentClientLoop-UY76PPZM.js} +8 -8
  51. package/{spaceCommands-NKJVJCQQ.js → spaceCommands-BMXKR7H6.js} +1 -1
  52. package/{streamAgentChatTurn-XLFZ66UC.js → streamAgentChatTurn-3YVIO4KE.js} +9 -9
  53. package/{tools-NF5AB34X.js → tools-Q6IBBG33.js} +6 -6
  54. package/{updateDialogTitleAction-6MBTD4UE.js → updateDialogTitleAction-GF5T3VMK.js} +3 -3
@@ -18,6 +18,70 @@ import {
18
18
  publicAgentKey
19
19
  } from "./chunk-M2EJHDJP.js";
20
20
 
21
+ // packages/ai/agent/quotaSnapshot.ts
22
+ function findTightestQuotaWindow(quota, now = Date.now()) {
23
+ if (!quota || !Array.isArray(quota.windows) || quota.windows.length === 0) {
24
+ return void 0;
25
+ }
26
+ let best;
27
+ let bestScore = -Infinity;
28
+ for (const w of quota.windows) {
29
+ let score = 0;
30
+ if (typeof w.utilization === "number" && w.utilization >= 0) {
31
+ score = 500 + Math.min(w.utilization, 1) * 500;
32
+ } else if (typeof w.remaining === "number" && typeof w.limit === "number" && w.limit > 0) {
33
+ const util = Math.max(0, 1 - w.remaining / w.limit);
34
+ score = 500 + util * 500;
35
+ } else if (typeof w.resetAt === "number" && w.resetAt > now) {
36
+ score = 200;
37
+ } else if (typeof w.remaining === "number") {
38
+ score = 100;
39
+ }
40
+ if (score > bestScore) {
41
+ bestScore = score;
42
+ best = w;
43
+ }
44
+ }
45
+ return best ?? quota.windows[0];
46
+ }
47
+ function formatQuotaSummary(quota, now = Date.now(), options) {
48
+ const tightest = findTightestQuotaWindow(quota, now);
49
+ if (!tightest) return void 0;
50
+ const compact = options?.compact === true;
51
+ const parts = [];
52
+ if (typeof tightest.utilization === "number") {
53
+ const pct = Math.round(tightest.utilization * 100);
54
+ parts.push(`${pct}%\u5DF2\u7528`);
55
+ } else if (typeof tightest.remaining === "number") {
56
+ if (typeof tightest.limit === "number") {
57
+ parts.push(`${tightest.remaining}/${tightest.limit}${tightest.unit ? ` ${tightest.unit}` : ""}`);
58
+ } else {
59
+ parts.push(`\u4F59${tightest.remaining}${tightest.unit ? ` ${tightest.unit}` : ""}`);
60
+ }
61
+ }
62
+ if (compact) return parts.length > 0 ? parts[0] : void 0;
63
+ if (tightest.scope && tightest.scope !== "user" && tightest.scope !== "project" && tightest.scope !== tightest.unit) {
64
+ parts.push(tightest.scope);
65
+ }
66
+ if (typeof tightest.resetAt === "number" && tightest.resetAt > now) {
67
+ const diffSec = Math.round((tightest.resetAt - now) / 1e3);
68
+ if (diffSec < 60) {
69
+ parts.push(`${diffSec}s\u540E\u91CD\u7F6E`);
70
+ } else if (diffSec < 3600) {
71
+ parts.push(`${Math.round(diffSec / 60)}m\u540E\u91CD\u7F6E`);
72
+ } else if (diffSec < 86400) {
73
+ const hours = (diffSec / 3600).toFixed(1).replace(/\.0$/, "");
74
+ parts.push(`${hours}h\u540E\u91CD\u7F6E`);
75
+ } else {
76
+ const days = (diffSec / 86400).toFixed(1).replace(/\.0$/, "");
77
+ parts.push(`${days}d\u540E\u91CD\u7F6E`);
78
+ }
79
+ }
80
+ if (parts.length === 0) return void 0;
81
+ if (parts.length === 1 && parts[0] === tightest.scope) return void 0;
82
+ return parts.join(" \xB7 ");
83
+ }
84
+
21
85
  // packages/cli/agentListHelpers.ts
22
86
  function parseAgentRecordId(privateKey, explicitId) {
23
87
  if (explicitId) return explicitId;
@@ -239,6 +303,7 @@ async function decorateAgentsWithPublicStatusAcrossServers(args) {
239
303
  }
240
304
 
241
305
  export {
306
+ formatQuotaSummary,
242
307
  normalizeListedAgent,
243
308
  toSafeListedAgentSummary,
244
309
  parseAgentListArgs,
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-AGGIDPCZ.js";
15
15
  import {
16
16
  runLlm
17
- } from "./chunk-3N3W7KBB.js";
17
+ } from "./chunk-YY7I6GQ3.js";
18
18
  import {
19
19
  cleanupCliSessionForDialog
20
20
  } from "./chunk-TOP2VXOR.js";
@@ -19371,7 +19371,7 @@ var messageSlice = createSliceWithThunks({
19371
19371
  runtimeOptions: args.runtimeOptions
19372
19372
  });
19373
19373
  if (agentKeyToUse) {
19374
- const { streamAgentChatTurn } = await import("./agentSlice-SICQBMCM.js");
19374
+ const { streamAgentChatTurn } = await import("./agentSlice-6LBOYNKN.js");
19375
19375
  await dispatch(
19376
19376
  streamAgentChatTurn({
19377
19377
  agentKey: agentKeyToUse,
@@ -20507,7 +20507,7 @@ var deleteDialogThunk = async (payload, thunkApi) => {
20507
20507
  }
20508
20508
  if (isCurrentDialog) {
20509
20509
  await thunkApi.dispatch(resetMsgs());
20510
- const { clearPendingAttachments: clearPendingAttachments2 } = await import("./dialogSlice-LEO27SQG.js");
20510
+ const { clearPendingAttachments: clearPendingAttachments2 } = await import("./dialogSlice-HSGREZGA.js");
20511
20511
  dispatch(clearPendingAttachments2());
20512
20512
  }
20513
20513
  return { dialogKey, isCurrentDialog, attachmentPlan };
@@ -20515,15 +20515,15 @@ var deleteDialogThunk = async (payload, thunkApi) => {
20515
20515
 
20516
20516
  // packages/chat/dialog/dialogSlice.ts
20517
20517
  var runCreateDialogAction = async (args, thunkApi) => {
20518
- const { createDialogAction } = await import("./createDialogAction-GFKRXTK4.js");
20518
+ const { createDialogAction } = await import("./createDialogAction-TDFOINOY.js");
20519
20519
  return createDialogAction(args, thunkApi);
20520
20520
  };
20521
20521
  var runCreateAgentAutomationAction = async (args, thunkApi) => {
20522
- const { createAgentAutomationAction } = await import("./createAgentAutomationAction-ODGL2YGP.js");
20522
+ const { createAgentAutomationAction } = await import("./createAgentAutomationAction-M5NDEIC6.js");
20523
20523
  return createAgentAutomationAction(args, thunkApi);
20524
20524
  };
20525
20525
  var runUpdateDialogTitleAction = async (args, thunkApi) => {
20526
- const { updateDialogTitleAction } = await import("./updateDialogTitleAction-6MBTD4UE.js");
20526
+ const { updateDialogTitleAction } = await import("./updateDialogTitleAction-GF5T3VMK.js");
20527
20527
  return updateDialogTitleAction(args, thunkApi);
20528
20528
  };
20529
20529
  var runAddDialogAgentAction = async (args, thunkApi) => {
@@ -20547,7 +20547,7 @@ var runSetDialogExtraReferencesAction = async (args, thunkApi) => {
20547
20547
  return setDialogExtraReferencesAction(args, thunkApi);
20548
20548
  };
20549
20549
  var runHandleSendMessageAction = async (args, thunkApi) => {
20550
- const { handleSendMessageAction } = await import("./handleSendMessageAction-YB6KQFJS.js");
20550
+ const { handleSendMessageAction } = await import("./handleSendMessageAction-FEHCWMN2.js");
20551
20551
  return handleSendMessageAction(args, thunkApi);
20552
20552
  };
20553
20553
  function clearDialogState() {
@@ -20560,7 +20560,7 @@ var createPageAndAddReference = createAsyncThunk(
20560
20560
  async (payload, { dispatch, getState, rejectWithValue }) => {
20561
20561
  const { slateData, jsonData, title, type, fileId, groupId, dialogKey } = payload;
20562
20562
  try {
20563
- const { createDocState } = await import("./docStore-MNX5MHA5.js");
20563
+ const { createDocState } = await import("./docStore-IIS36NGG.js");
20564
20564
  const pageKey = await createDocState(
20565
20565
  { slateData, title },
20566
20566
  { dispatch, getState }
@@ -81,10 +81,10 @@ import {
81
81
  } from "./chunk-VF4K2QE6.js";
82
82
  import {
83
83
  createDocState
84
- } from "./chunk-B3TVQ6PI.js";
84
+ } from "./chunk-W324THOB.js";
85
85
  import {
86
86
  createDialogAction
87
- } from "./chunk-DNUUJ45N.js";
87
+ } from "./chunk-3ZW5ZJMM.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-OZGZPSEG.js";
105
+ } from "./chunk-A6FMKU7M.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-XVZ22N6C.js";
127
+ } from "./chunk-FQUHIG5X.js";
128
128
  import {
129
129
  createAgent,
130
130
  deleteServerSyncedCredential,
131
131
  runLlm,
132
132
  streamAgentChatTurn,
133
133
  updateAgent
134
- } from "./chunk-3N3W7KBB.js";
134
+ } from "./chunk-YY7I6GQ3.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-LEO27SQG.js");
3948
+ const { deleteDialog: deleteDialog2 } = await import("./dialogSlice-HSGREZGA.js");
3949
3949
  for (const target of targets) {
3950
3950
  try {
3951
3951
  await thunkApi.dispatch(deleteDialog2(target.dbKey)).unwrap();
@@ -14906,7 +14906,7 @@ var executeToolRun = createAsyncThunk(
14906
14906
  if (!executionInput) {
14907
14907
  throw new Error(`ToolRun ${id} has no input to execute with.`);
14908
14908
  }
14909
- const { findToolExecutor: findToolExecutor2 } = await import("./tools-NF5AB34X.js");
14909
+ const { findToolExecutor: findToolExecutor2 } = await import("./tools-Q6IBBG33.js");
14910
14910
  const { executor } = findToolExecutor2(run.toolName);
14911
14911
  toolRunStarted({
14912
14912
  id: run.id,
@@ -17413,7 +17413,7 @@ async function updateDocFunc(args, thunkApi) {
17413
17413
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
17414
17414
  };
17415
17415
  await dispatch(write({ data: updatedPageData, customKey: id })).unwrap();
17416
- const { getDocState, applyExternalDocUpdate } = await import("./docStore-MNX5MHA5.js");
17416
+ const { getDocState, applyExternalDocUpdate } = await import("./docStore-IIS36NGG.js");
17417
17417
  if (getDocState().pageKey === id) {
17418
17418
  applyExternalDocUpdate({
17419
17419
  slateData: finalSlateData,
@@ -64,6 +64,7 @@ import {
64
64
  applyToolSurfaceConstraints,
65
65
  buildDialogReadEnvelope,
66
66
  buildNoloWorkspaceCommandArgs,
67
+ buildNoloWorkspaceOpenAiTools,
67
68
  createStreamingDialogReadProjector,
68
69
  noloPositiveIntegerString,
69
70
  noloStringArg,
@@ -15652,132 +15653,6 @@ async function evaluateCapabilityPolicy(capability, normalizedInput, ctx) {
15652
15653
  }
15653
15654
  }
15654
15655
 
15655
- // packages/agent-runtime/localToolPolicy.ts
15656
- var NEVER_LOCAL_TOOLS = /* @__PURE__ */ new Set([
15657
- "deleteSpaces",
15658
- "updateAgent",
15659
- "updateSelf",
15660
- "createAgent"
15661
- ]);
15662
- var DEFAULT_LOCAL_TOOLS = /* @__PURE__ */ new Set([
15663
- "readFile",
15664
- "writeFile",
15665
- "editFile",
15666
- "globFiles",
15667
- "execShell",
15668
- "launchProcess",
15669
- "listProcesses",
15670
- // ProcessTask follow-up tools. Same tier as listProcesses: they observe/stop
15671
- // tasks the agent itself already spawned, so their blast radius is strictly
15672
- // narrower than launchProcess (which is default-enabled). Model-facing
15673
- // follow-ups are taskWait/taskStop only — lifecycle history (taskLogs) stays
15674
- // runtime-internal.
15675
- "taskWait",
15676
- "taskStop",
15677
- // Scheduling tools: forking/observing sub-agents is a declared capability
15678
- // of capable agents, and the blast radius is strictly narrower than
15679
- // execShell (already default-enabled). Requiring an env allowlist for these
15680
- // while execShell is open by default inverted the risk model and forced every
15681
- // new local user to hand-edit .env files before sub-agent tasks worked.
15682
- "startAgentRun",
15683
- "controlAgentRun"
15684
- ]);
15685
- function parseToolAllowlist(value) {
15686
- return (value ?? "").split(",").flatMap((item) => {
15687
- const trimmed = item.trim();
15688
- return trimmed ? [trimmed] : [];
15689
- });
15690
- }
15691
- function normalizeLocalToolName(toolName) {
15692
- return canonicalizeToolName(
15693
- String(toolName ?? "").replace(/^functions\./, "").trim()
15694
- );
15695
- }
15696
- function isRestrictedLocalToolMode(env) {
15697
- return env.NOLO_LOCAL_TOOL_MODE === "restricted";
15698
- }
15699
- function resolveLocalToolPolicy(args2) {
15700
- const toolName = normalizeLocalToolName(args2.toolName);
15701
- const restrictedMode = isRestrictedLocalToolMode(args2.env);
15702
- if (!toolName) {
15703
- return {
15704
- allowed: false,
15705
- toolName,
15706
- reason: "Tool name is required."
15707
- };
15708
- }
15709
- if (NEVER_LOCAL_TOOLS.has(toolName)) {
15710
- return {
15711
- allowed: false,
15712
- toolName,
15713
- reason: `${toolName} is blocked by the local runtime safety policy.`
15714
- };
15715
- }
15716
- const allowedByEnv = new Set(parseToolAllowlist(args2.env.NOLO_LOCAL_ALLOWED_TOOLS));
15717
- const agentTools = new Set(
15718
- (args2.agentToolNames ?? []).flatMap((item) => {
15719
- const normalized = normalizeLocalToolName(item);
15720
- return normalized ? [normalized] : [];
15721
- })
15722
- );
15723
- if (!restrictedMode && agentTools.has(toolName)) {
15724
- return { allowed: true, toolName };
15725
- }
15726
- if (DEFAULT_LOCAL_TOOLS.has(toolName) && agentTools.has(toolName)) {
15727
- return { allowed: true, toolName };
15728
- }
15729
- if (allowedByEnv.has(toolName) && agentTools.has(toolName)) {
15730
- return { allowed: true, toolName };
15731
- }
15732
- return {
15733
- allowed: false,
15734
- toolName,
15735
- reason: `${toolName} is not enabled for local runtime runs. The agent must declare the tool in its manifest; in restricted mode (NOLO_LOCAL_TOOL_MODE=restricted) non-default tools also require adding to NOLO_LOCAL_ALLOWED_TOOLS (e.g. NOLO_LOCAL_ALLOWED_TOOLS=someCustomTool) and restarting the session so the env var loads.`
15736
- };
15737
- }
15738
- async function executeLocalToolWithPolicy(args2) {
15739
- if (args2.runToolNames !== void 0 && !args2.runToolNames.includes(normalizeLocalToolName(args2.call.name))) {
15740
- throw new Error(`${args2.call.name} is outside the final run tool surface.`);
15741
- }
15742
- const decision = resolveLocalToolPolicy({
15743
- env: args2.env,
15744
- agentToolNames: args2.agentToolNames,
15745
- toolName: args2.call.name
15746
- });
15747
- if (!decision.allowed) throw new Error(decision.reason);
15748
- const executor = args2.executors?.[decision.toolName];
15749
- if (!executor) {
15750
- throw new Error(`${decision.toolName} is allowed by policy but no local executor is registered.`);
15751
- }
15752
- const opts = {
15753
- ...args2.abortSignal ? { abortSignal: args2.abortSignal } : {},
15754
- ...args2.detachMs !== void 0 ? { detachMs: args2.detachMs } : {},
15755
- ...args2.confirmed !== void 0 ? { confirmed: args2.confirmed } : {},
15756
- ...args2.enableDestructiveShellGuard !== void 0 ? { enableDestructiveShellGuard: args2.enableDestructiveShellGuard } : {},
15757
- ...args2.confirmDestructiveAction ? { confirmDestructiveAction: args2.confirmDestructiveAction } : {},
15758
- ...args2.blockDestructiveWithoutConfirmation !== void 0 ? { blockDestructiveWithoutConfirmation: args2.blockDestructiveWithoutConfirmation } : {}
15759
- };
15760
- if (decision.toolName === "execShell") {
15761
- let parsedInput = args2.call.arguments;
15762
- if (typeof parsedInput === "string") {
15763
- try {
15764
- parsedInput = JSON.parse(parsedInput);
15765
- } catch {
15766
- parsedInput = { command: parsedInput };
15767
- }
15768
- }
15769
- await evaluateExecShellDestructiveGuard(parsedInput, opts);
15770
- opts.confirmed = true;
15771
- }
15772
- return executor(
15773
- {
15774
- ...args2.call,
15775
- name: decision.toolName
15776
- },
15777
- opts
15778
- );
15779
- }
15780
-
15781
15656
  // packages/agent-runtime/localWorkspaceTools.ts
15782
15657
  import { existsSync as existsSync3 } from "node:fs";
15783
15658
  import { createHash as createHash3 } from "node:crypto";
@@ -19312,6 +19187,290 @@ function createLocalWorkspaceToolExecutors(args2) {
19312
19187
  };
19313
19188
  }
19314
19189
 
19190
+ // packages/agent-runtime/toolArgumentGate.ts
19191
+ var FIELD_ALIAS_GROUPS = [
19192
+ // localWorkspaceTools.ts:336 导出常量(readFile/writeFile/editFile/globFiles)
19193
+ PATH_FIELD_ALIASES,
19194
+ // localWorkspaceTools.ts:339-340 导出常量(editFile)
19195
+ OLD_TEXT_FIELD_ALIASES,
19196
+ NEW_TEXT_FIELD_ALIASES,
19197
+ // localWorkspaceTools.ts:733 `args.cmd || args.command`(launchProcess);
19198
+ // launchProcess 的 required ["command"] 见 localWorkspaceToolDefs.ts:283。
19199
+ // 注:execShell 的 schema 无 required(command 在 executor 层强制,
19200
+ // capabilities/execShellCapability.ts:42 声明 cmd 兼容字段),本组对它不产生拦截。
19201
+ ["command", "cmd"],
19202
+ // localWorkspaceTools.ts:698-699 `args.pattern ?? args.glob`(globFiles)
19203
+ ["pattern", "glob"],
19204
+ // noloWorkspaceTools.ts:492 `args.dialog ?? args.dialogId ?? args.id`(readDialog)
19205
+ ["dialog", "dialogId", "id"],
19206
+ // noloWorkspaceTools.ts:545 `args.agent ?? args.agentKey ?? args.id`(readAgent)
19207
+ ["agent", "agentKey", "id"],
19208
+ // noloWorkspaceTools.ts:552 `args.space ?? args.spaceId ?? args.id`(readSpace)
19209
+ ["space", "spaceId", "id"],
19210
+ // noloWorkspaceTools.ts:561/567 `args.doc ?? args.docKey ?? args.pageKey ?? args.key`
19211
+ // (readDoc / readSkillDoc)
19212
+ ["doc", "docKey", "pageKey", "key"],
19213
+ // noloWorkspaceTools.node.ts:238 `parsed.name ?? parsed.skillName ?? parsed.skill`(loadSkill)
19214
+ ["name", "skillName", "skill"],
19215
+ // noloWorkspaceTools.ts:593 `args.table ?? args.tableId ?? args.metaKey`(queryTableRows)
19216
+ ["table", "tableId", "metaKey"]
19217
+ ];
19218
+ var TYPE_MATCHERS = {
19219
+ string: (value) => typeof value === "string",
19220
+ // 数字字符串视为可接受:executor 普遍 Number()/clamp 宽松处理,拦截会误报。
19221
+ number: (value) => typeof value === "number" || typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value)),
19222
+ integer: (value) => typeof value === "number" || typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value)),
19223
+ boolean: (value) => typeof value === "boolean" || value === "true" || value === "false",
19224
+ object: (value) => typeof value === "object" && value !== null && !Array.isArray(value),
19225
+ array: (value) => Array.isArray(value)
19226
+ };
19227
+ function describeValueType(value) {
19228
+ if (value === null) return "null";
19229
+ if (Array.isArray(value)) return "array";
19230
+ return typeof value;
19231
+ }
19232
+ function isAliasSatisfied(args2, field) {
19233
+ for (const group of FIELD_ALIAS_GROUPS) {
19234
+ if (!group.includes(field)) continue;
19235
+ if (group.some((alias) => args2[alias] !== void 0)) return true;
19236
+ }
19237
+ return false;
19238
+ }
19239
+ function readRequiredFields(parameters) {
19240
+ const required = parameters.required;
19241
+ if (!Array.isArray(required)) return [];
19242
+ return required.filter((field) => typeof field === "string");
19243
+ }
19244
+ function readProperties(parameters) {
19245
+ const properties = parameters.properties;
19246
+ if (!properties || typeof properties !== "object" || Array.isArray(properties)) {
19247
+ return {};
19248
+ }
19249
+ return properties;
19250
+ }
19251
+ function validateToolArguments(args2) {
19252
+ const { toolName, rawArguments, parameters } = args2;
19253
+ if (!parameters || typeof parameters !== "object" || Array.isArray(parameters)) {
19254
+ return { ok: true, args: {} };
19255
+ }
19256
+ const schema = parameters;
19257
+ const requiredFields = readRequiredFields(schema);
19258
+ const properties = readProperties(schema);
19259
+ if (requiredFields.length === 0 && Object.keys(properties).length === 0) {
19260
+ return { ok: true, args: {} };
19261
+ }
19262
+ const raw = typeof rawArguments === "string" ? rawArguments.trim() : "";
19263
+ let record = {};
19264
+ if (raw !== "") {
19265
+ let parsed;
19266
+ try {
19267
+ parsed = JSON.parse(raw);
19268
+ } catch {
19269
+ return { ok: true, args: {} };
19270
+ }
19271
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
19272
+ return { ok: true, args: {} };
19273
+ }
19274
+ record = parsed;
19275
+ }
19276
+ for (const field of requiredFields) {
19277
+ if (record[field] !== void 0) continue;
19278
+ if (isAliasSatisfied(record, field)) continue;
19279
+ return {
19280
+ ok: false,
19281
+ message: `${toolName} \u53C2\u6570\u6821\u9A8C\u5931\u8D25\uFF1A\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570 "${field}"\u3002\u8BF7\u8865\u4E0A\u540E\u91CD\u65B0\u8C03\u7528 ${toolName}\u3002`
19282
+ };
19283
+ }
19284
+ for (const [field, spec] of Object.entries(properties)) {
19285
+ const value = record[field];
19286
+ if (value === void 0 || value === null) continue;
19287
+ if (!spec || typeof spec !== "object" || Array.isArray(spec)) continue;
19288
+ const declared = spec.type;
19289
+ if (typeof declared !== "string") continue;
19290
+ const matcher = TYPE_MATCHERS[declared];
19291
+ if (!matcher) continue;
19292
+ if (!matcher(value)) {
19293
+ return {
19294
+ ok: false,
19295
+ message: `${toolName} \u53C2\u6570\u6821\u9A8C\u5931\u8D25\uFF1A\u53C2\u6570 "${field}" \u5E94\u4E3A ${declared}\uFF0C\u5B9E\u9645\u6536\u5230 ${describeValueType(value)}\u3002\u8BF7\u4FEE\u6B63\u540E\u91CD\u65B0\u8C03\u7528 ${toolName}\u3002`
19296
+ };
19297
+ }
19298
+ }
19299
+ return { ok: true, args: record };
19300
+ }
19301
+ function buildToolParametersIndex(tools) {
19302
+ const index = /* @__PURE__ */ new Map();
19303
+ for (const tool of tools) {
19304
+ if (!tool || typeof tool !== "object") continue;
19305
+ const fn3 = tool.function;
19306
+ if (!fn3 || typeof fn3 !== "object") continue;
19307
+ const name = fn3.name;
19308
+ const parameters = fn3.parameters;
19309
+ if (typeof name === "string" && name && parameters !== void 0) {
19310
+ index.set(name, parameters);
19311
+ }
19312
+ }
19313
+ return index;
19314
+ }
19315
+ var cachedAgentRuntimeIndex = null;
19316
+ function getAgentRuntimeToolParametersIndex() {
19317
+ if (cachedAgentRuntimeIndex) return cachedAgentRuntimeIndex;
19318
+ const index = /* @__PURE__ */ new Map();
19319
+ try {
19320
+ const workspaceTools = buildLocalWorkspaceOpenAiTools({
19321
+ toolNames: [...WORKSPACE_TOOL_NAMES],
19322
+ exposeShellTools: true
19323
+ });
19324
+ for (const [name, parameters] of buildToolParametersIndex(workspaceTools)) {
19325
+ index.set(name, parameters);
19326
+ }
19327
+ const noloTools = buildNoloWorkspaceOpenAiTools({
19328
+ toolNames: [...NOLO_WORKSPACE_TOOL_NAMES]
19329
+ });
19330
+ for (const [name, parameters] of buildToolParametersIndex(noloTools)) {
19331
+ index.set(name, parameters);
19332
+ }
19333
+ } catch {
19334
+ }
19335
+ cachedAgentRuntimeIndex = index;
19336
+ return index;
19337
+ }
19338
+
19339
+ // packages/agent-runtime/localToolPolicy.ts
19340
+ var NEVER_LOCAL_TOOLS = /* @__PURE__ */ new Set([
19341
+ "deleteSpaces",
19342
+ "updateAgent",
19343
+ "updateSelf",
19344
+ "createAgent"
19345
+ ]);
19346
+ var DEFAULT_LOCAL_TOOLS = /* @__PURE__ */ new Set([
19347
+ "readFile",
19348
+ "writeFile",
19349
+ "editFile",
19350
+ "globFiles",
19351
+ "execShell",
19352
+ "launchProcess",
19353
+ "listProcesses",
19354
+ // ProcessTask follow-up tools. Same tier as listProcesses: they observe/stop
19355
+ // tasks the agent itself already spawned, so their blast radius is strictly
19356
+ // narrower than launchProcess (which is default-enabled). Model-facing
19357
+ // follow-ups are taskWait/taskStop only — lifecycle history (taskLogs) stays
19358
+ // runtime-internal.
19359
+ "taskWait",
19360
+ "taskStop",
19361
+ // Scheduling tools: forking/observing sub-agents is a declared capability
19362
+ // of capable agents, and the blast radius is strictly narrower than
19363
+ // execShell (already default-enabled). Requiring an env allowlist for these
19364
+ // while execShell is open by default inverted the risk model and forced every
19365
+ // new local user to hand-edit .env files before sub-agent tasks worked.
19366
+ "startAgentRun",
19367
+ "controlAgentRun"
19368
+ ]);
19369
+ function parseToolAllowlist(value) {
19370
+ return (value ?? "").split(",").flatMap((item) => {
19371
+ const trimmed = item.trim();
19372
+ return trimmed ? [trimmed] : [];
19373
+ });
19374
+ }
19375
+ function normalizeLocalToolName(toolName) {
19376
+ return canonicalizeToolName(
19377
+ String(toolName ?? "").replace(/^functions\./, "").trim()
19378
+ );
19379
+ }
19380
+ function isRestrictedLocalToolMode(env) {
19381
+ return env.NOLO_LOCAL_TOOL_MODE === "restricted";
19382
+ }
19383
+ function resolveLocalToolPolicy(args2) {
19384
+ const toolName = normalizeLocalToolName(args2.toolName);
19385
+ const restrictedMode = isRestrictedLocalToolMode(args2.env);
19386
+ if (!toolName) {
19387
+ return {
19388
+ allowed: false,
19389
+ toolName,
19390
+ reason: "Tool name is required."
19391
+ };
19392
+ }
19393
+ if (NEVER_LOCAL_TOOLS.has(toolName)) {
19394
+ return {
19395
+ allowed: false,
19396
+ toolName,
19397
+ reason: `${toolName} is blocked by the local runtime safety policy.`
19398
+ };
19399
+ }
19400
+ const allowedByEnv = new Set(parseToolAllowlist(args2.env.NOLO_LOCAL_ALLOWED_TOOLS));
19401
+ const agentTools = new Set(
19402
+ (args2.agentToolNames ?? []).flatMap((item) => {
19403
+ const normalized = normalizeLocalToolName(item);
19404
+ return normalized ? [normalized] : [];
19405
+ })
19406
+ );
19407
+ if (!restrictedMode && agentTools.has(toolName)) {
19408
+ return { allowed: true, toolName };
19409
+ }
19410
+ if (DEFAULT_LOCAL_TOOLS.has(toolName) && agentTools.has(toolName)) {
19411
+ return { allowed: true, toolName };
19412
+ }
19413
+ if (allowedByEnv.has(toolName) && agentTools.has(toolName)) {
19414
+ return { allowed: true, toolName };
19415
+ }
19416
+ return {
19417
+ allowed: false,
19418
+ toolName,
19419
+ reason: `${toolName} is not enabled for local runtime runs. The agent must declare the tool in its manifest; in restricted mode (NOLO_LOCAL_TOOL_MODE=restricted) non-default tools also require adding to NOLO_LOCAL_ALLOWED_TOOLS (e.g. NOLO_LOCAL_ALLOWED_TOOLS=someCustomTool) and restarting the session so the env var loads.`
19420
+ };
19421
+ }
19422
+ async function executeLocalToolWithPolicy(args2) {
19423
+ if (args2.runToolNames !== void 0 && !args2.runToolNames.includes(normalizeLocalToolName(args2.call.name))) {
19424
+ throw new Error(`${args2.call.name} is outside the final run tool surface.`);
19425
+ }
19426
+ const decision = resolveLocalToolPolicy({
19427
+ env: args2.env,
19428
+ agentToolNames: args2.agentToolNames,
19429
+ toolName: args2.call.name
19430
+ });
19431
+ if (!decision.allowed) throw new Error(decision.reason);
19432
+ const executor = args2.executors?.[decision.toolName];
19433
+ if (!executor) {
19434
+ throw new Error(`${decision.toolName} is allowed by policy but no local executor is registered.`);
19435
+ }
19436
+ const parametersSchema = args2.toolParametersIndex?.get(decision.toolName);
19437
+ if (parametersSchema !== void 0) {
19438
+ const gate = validateToolArguments({
19439
+ toolName: decision.toolName,
19440
+ rawArguments: args2.call.arguments,
19441
+ parameters: parametersSchema
19442
+ });
19443
+ if (!gate.ok) throw new Error(gate.message);
19444
+ }
19445
+ const opts = {
19446
+ ...args2.abortSignal ? { abortSignal: args2.abortSignal } : {},
19447
+ ...args2.detachMs !== void 0 ? { detachMs: args2.detachMs } : {},
19448
+ ...args2.confirmed !== void 0 ? { confirmed: args2.confirmed } : {},
19449
+ ...args2.enableDestructiveShellGuard !== void 0 ? { enableDestructiveShellGuard: args2.enableDestructiveShellGuard } : {},
19450
+ ...args2.confirmDestructiveAction ? { confirmDestructiveAction: args2.confirmDestructiveAction } : {},
19451
+ ...args2.blockDestructiveWithoutConfirmation !== void 0 ? { blockDestructiveWithoutConfirmation: args2.blockDestructiveWithoutConfirmation } : {}
19452
+ };
19453
+ if (decision.toolName === "execShell") {
19454
+ let parsedInput = args2.call.arguments;
19455
+ if (typeof parsedInput === "string") {
19456
+ try {
19457
+ parsedInput = JSON.parse(parsedInput);
19458
+ } catch {
19459
+ parsedInput = { command: parsedInput };
19460
+ }
19461
+ }
19462
+ await evaluateExecShellDestructiveGuard(parsedInput, opts);
19463
+ opts.confirmed = true;
19464
+ }
19465
+ return executor(
19466
+ {
19467
+ ...args2.call,
19468
+ name: decision.toolName
19469
+ },
19470
+ opts
19471
+ );
19472
+ }
19473
+
19315
19474
  // packages/cli/client/localDialogRecords.ts
19316
19475
  var localDialogMessageRecordToRuntimeMessage = dialogMessageRecordToAgentRuntimeMessage;
19317
19476
  function buildLocalDialogWritePlan(args2) {
@@ -20016,7 +20175,7 @@ function buildGeminiGenerateContentRequest(args2) {
20016
20175
  const toolsResult = convertOpenAiToolsToGemini(args2.tools);
20017
20176
  if (toolsResult) {
20018
20177
  request3.tools = toolsResult;
20019
- request3.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
20178
+ request3.toolConfig = { functionCallingConfig: { mode: "AUTO" } };
20020
20179
  }
20021
20180
  const generationConfig = {};
20022
20181
  if (typeof args2.maxTokens === "number" && args2.maxTokens > 0) {
@@ -20065,7 +20224,7 @@ function buildCloudCodeAssistPayload(args2) {
20065
20224
  );
20066
20225
  if (tools) {
20067
20226
  request3.tools = tools;
20068
- request3.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
20227
+ request3.toolConfig = { functionCallingConfig: { mode: "AUTO" } };
20069
20228
  }
20070
20229
  const generationConfig = {};
20071
20230
  if (profile?.maxOutputTokens) {
@@ -20792,8 +20951,6 @@ export {
20792
20951
  createHybridRecordStore,
20793
20952
  isDestructiveShellCommand,
20794
20953
  evaluateShellCommandPolicy,
20795
- resolveLocalToolPolicy,
20796
- executeLocalToolWithPolicy,
20797
20954
  filterRetainedLedgerRecords,
20798
20955
  isLineRangeCovered,
20799
20956
  getProcessRegistry,
@@ -20804,6 +20961,10 @@ export {
20804
20961
  internalSearchWorkspace,
20805
20962
  internalListWorkspaceEntries,
20806
20963
  createLocalWorkspaceToolExecutors,
20964
+ buildToolParametersIndex,
20965
+ getAgentRuntimeToolParametersIndex,
20966
+ resolveLocalToolPolicy,
20967
+ executeLocalToolWithPolicy,
20807
20968
  localDialogMessageRecordToRuntimeMessage,
20808
20969
  buildLocalDialogWritePlan,
20809
20970
  buildNoloWorkspaceCliToolExecutors,