@poolzin/pool-bot 2026.2.23 → 2026.2.25

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 (235) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/acp/client.js +207 -18
  3. package/dist/acp/secret-file.js +22 -0
  4. package/dist/agents/agent-scope.js +10 -0
  5. package/dist/agents/bash-process-registry.test-helpers.js +29 -0
  6. package/dist/agents/bash-tools.exec-approval-request.js +20 -0
  7. package/dist/agents/bash-tools.exec-host-gateway.js +230 -0
  8. package/dist/agents/bash-tools.exec-host-node.js +235 -0
  9. package/dist/agents/bash-tools.exec-types.js +1 -0
  10. package/dist/agents/bash-tools.process.js +224 -218
  11. package/dist/agents/content-blocks.js +16 -0
  12. package/dist/agents/model-fallback.js +96 -101
  13. package/dist/agents/models-config.providers.js +299 -182
  14. package/dist/agents/pi-embedded-payloads.js +1 -0
  15. package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +34 -0
  16. package/dist/agents/skills.test-helpers.js +13 -0
  17. package/dist/agents/stable-stringify.js +12 -0
  18. package/dist/agents/subagent-registry.mocks.shared.js +12 -0
  19. package/dist/agents/test-helpers/assistant-message-fixtures.js +29 -0
  20. package/dist/agents/test-helpers/pi-tools-sandbox-context.js +27 -0
  21. package/dist/agents/tool-policy-shared.js +108 -0
  22. package/dist/agents/tools/browser-tool.js +160 -54
  23. package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
  24. package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
  25. package/dist/agents/tools/image-tool.js +214 -99
  26. package/dist/agents/tools/sessions-history-tool.js +140 -108
  27. package/dist/agents/workspace.js +222 -46
  28. package/dist/auto-reply/commands-registry.js +15 -18
  29. package/dist/auto-reply/fallback-state.js +114 -0
  30. package/dist/auto-reply/model-runtime.js +68 -0
  31. package/dist/auto-reply/reply/agent-runner-execution.js +36 -4
  32. package/dist/auto-reply/reply/agent-runner.js +165 -39
  33. package/dist/auto-reply/reply/commands-setunset-standard.js +13 -0
  34. package/dist/browser/config.js +26 -0
  35. package/dist/browser/navigation-guard.js +31 -0
  36. package/dist/browser/routes/agent.act.js +431 -424
  37. package/dist/browser/routes/agent.shared.js +47 -3
  38. package/dist/browser/routes/agent.snapshot.js +122 -116
  39. package/dist/browser/routes/agent.storage.js +303 -297
  40. package/dist/browser/routes/tabs.js +154 -100
  41. package/dist/browser/server-lifecycle.js +37 -0
  42. package/dist/build-info.json +3 -3
  43. package/dist/channels/allow-from.js +25 -0
  44. package/dist/channels/plugins/account-action-gate.js +13 -0
  45. package/dist/channels/plugins/message-actions.js +10 -0
  46. package/dist/channels/telegram/api.js +18 -0
  47. package/dist/cli/argv.js +84 -21
  48. package/dist/cli/banner.js +2 -1
  49. package/dist/cli/exec-approvals-cli.js +92 -124
  50. package/dist/cli/memory-cli.js +158 -61
  51. package/dist/cli/nodes-cli/register.push.js +63 -0
  52. package/dist/cli/nodes-media-utils.js +21 -0
  53. package/dist/cli/plugins-cli.js +245 -61
  54. package/dist/cli/program/build-program.js +3 -1
  55. package/dist/cli/program/command-registry.js +223 -136
  56. package/dist/cli/program/help.js +43 -12
  57. package/dist/cli/route.js +1 -1
  58. package/dist/cli/test-runtime-capture.js +24 -0
  59. package/dist/commands/agent.js +163 -87
  60. package/dist/commands/channels.mock-harness.js +23 -0
  61. package/dist/commands/daemon-install-runtime-warning.js +11 -0
  62. package/dist/commands/onboard-helpers.js +4 -4
  63. package/dist/commands/sessions.test-helpers.js +61 -0
  64. package/dist/compat/legacy-names.js +2 -2
  65. package/dist/config/commands.js +3 -0
  66. package/dist/config/config.js +1 -1
  67. package/dist/config/env-substitution.js +62 -34
  68. package/dist/config/env-vars.js +9 -0
  69. package/dist/config/io.js +571 -171
  70. package/dist/config/merge-patch.js +50 -4
  71. package/dist/config/redact-snapshot.js +404 -76
  72. package/dist/config/schema.js +58 -570
  73. package/dist/config/validation.js +140 -85
  74. package/dist/config/zod-schema.hooks.js +40 -11
  75. package/dist/config/zod-schema.installs.js +20 -0
  76. package/dist/config/zod-schema.js +8 -7
  77. package/dist/control-ui/assets/{index-HRr1grwl.js → index-Dvkl4Xlx.js} +2 -1
  78. package/dist/control-ui/assets/{index-HRr1grwl.js.map → index-Dvkl4Xlx.js.map} +1 -1
  79. package/dist/control-ui/index.html +1 -1
  80. package/dist/daemon/cmd-argv.js +21 -0
  81. package/dist/daemon/cmd-set.js +58 -0
  82. package/dist/daemon/service-types.js +1 -0
  83. package/dist/discord/monitor/exec-approvals.js +357 -162
  84. package/dist/gateway/auth.js +38 -3
  85. package/dist/gateway/call.js +149 -68
  86. package/dist/gateway/canvas-capability.js +75 -0
  87. package/dist/gateway/control-plane-audit.js +28 -0
  88. package/dist/gateway/control-plane-rate-limit.js +53 -0
  89. package/dist/gateway/events.js +1 -0
  90. package/dist/gateway/hooks.js +109 -54
  91. package/dist/gateway/http-common.js +22 -0
  92. package/dist/gateway/method-scopes.js +169 -0
  93. package/dist/gateway/net.js +23 -0
  94. package/dist/gateway/openresponses-http.js +120 -110
  95. package/dist/gateway/probe-auth.js +2 -0
  96. package/dist/gateway/protocol/index.js +3 -2
  97. package/dist/gateway/protocol/schema/protocol-schemas.js +2 -0
  98. package/dist/gateway/protocol/schema/push.js +18 -0
  99. package/dist/gateway/protocol/schema.js +1 -0
  100. package/dist/gateway/server-http.js +236 -52
  101. package/dist/gateway/server-methods/agent.js +162 -24
  102. package/dist/gateway/server-methods/chat.js +461 -130
  103. package/dist/gateway/server-methods/config.js +193 -150
  104. package/dist/gateway/server-methods/nodes.helpers.js +12 -0
  105. package/dist/gateway/server-methods/nodes.js +251 -69
  106. package/dist/gateway/server-methods/push.js +53 -0
  107. package/dist/gateway/server-reload-handlers.js +2 -3
  108. package/dist/gateway/server-runtime-config.js +5 -0
  109. package/dist/gateway/server-runtime-state.js +2 -0
  110. package/dist/gateway/server-ws-runtime.js +1 -0
  111. package/dist/gateway/server.impl.js +296 -139
  112. package/dist/gateway/session-preview.test-helpers.js +11 -0
  113. package/dist/gateway/startup-auth.js +126 -0
  114. package/dist/gateway/test-helpers.agent-results.js +15 -0
  115. package/dist/gateway/test-helpers.mocks.js +37 -14
  116. package/dist/gateway/test-helpers.server.js +161 -77
  117. package/dist/hooks/bundled/session-memory/handler.js +165 -34
  118. package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
  119. package/dist/infra/archive-path.js +49 -0
  120. package/dist/infra/device-pairing.js +148 -167
  121. package/dist/infra/exec-approvals-allowlist.js +19 -70
  122. package/dist/infra/exec-approvals-analysis.js +44 -17
  123. package/dist/infra/exec-safe-bin-policy.js +269 -0
  124. package/dist/infra/fixed-window-rate-limit.js +33 -0
  125. package/dist/infra/git-root.js +61 -0
  126. package/dist/infra/heartbeat-active-hours.js +2 -2
  127. package/dist/infra/heartbeat-reason.js +40 -0
  128. package/dist/infra/heartbeat-runner.js +72 -32
  129. package/dist/infra/install-source-utils.js +91 -7
  130. package/dist/infra/node-pairing.js +50 -105
  131. package/dist/infra/npm-integrity.js +45 -0
  132. package/dist/infra/npm-pack-install.js +40 -0
  133. package/dist/infra/outbound/channel-adapters.js +20 -7
  134. package/dist/infra/outbound/message-action-runner.js +107 -327
  135. package/dist/infra/outbound/message.js +59 -36
  136. package/dist/infra/outbound/outbound-policy.js +52 -25
  137. package/dist/infra/outbound/outbound-send-service.js +58 -71
  138. package/dist/infra/pairing-files.js +10 -0
  139. package/dist/infra/plain-object.js +9 -0
  140. package/dist/infra/push-apns.js +365 -0
  141. package/dist/infra/restart-sentinel.js +16 -1
  142. package/dist/infra/restart.js +229 -26
  143. package/dist/infra/scp-host.js +54 -0
  144. package/dist/infra/update-startup.js +86 -9
  145. package/dist/media/inbound-path-policy.js +114 -0
  146. package/dist/media/input-files.js +16 -0
  147. package/dist/memory/test-manager.js +8 -0
  148. package/dist/plugin-sdk/temp-path.js +47 -0
  149. package/dist/plugins/discovery.js +217 -23
  150. package/dist/plugins/hook-runner-global.js +16 -0
  151. package/dist/plugins/loader.js +192 -26
  152. package/dist/plugins/logger.js +8 -0
  153. package/dist/plugins/manifest-registry.js +3 -0
  154. package/dist/plugins/path-safety.js +34 -0
  155. package/dist/plugins/registry.js +5 -2
  156. package/dist/plugins/runtime/index.js +271 -206
  157. package/dist/providers/github-copilot-models.js +4 -1
  158. package/dist/security/audit-channel.js +8 -19
  159. package/dist/security/audit-extra.async.js +354 -182
  160. package/dist/security/audit-extra.js +11 -1
  161. package/dist/security/audit-extra.sync.js +340 -33
  162. package/dist/security/audit-fs.js +31 -13
  163. package/dist/security/audit.js +145 -371
  164. package/dist/security/dm-policy-shared.js +24 -0
  165. package/dist/security/external-content.js +20 -8
  166. package/dist/security/fix.js +49 -85
  167. package/dist/security/scan-paths.js +20 -0
  168. package/dist/security/secret-equal.js +3 -7
  169. package/dist/security/windows-acl.js +30 -15
  170. package/dist/shared/node-list-parse.js +13 -0
  171. package/dist/shared/operator-scope-compat.js +37 -0
  172. package/dist/shared/text-chunking.js +29 -0
  173. package/dist/slack/blocks.test-helpers.js +31 -0
  174. package/dist/slack/monitor/mrkdwn.js +8 -0
  175. package/dist/telegram/bot-message-dispatch.js +366 -164
  176. package/dist/telegram/draft-stream.js +30 -7
  177. package/dist/telegram/reasoning-lane-coordinator.js +128 -0
  178. package/dist/terminal/prompt-select-styled.js +9 -0
  179. package/dist/test-utils/command-runner.js +6 -0
  180. package/dist/test-utils/internal-hook-event-payload.js +10 -0
  181. package/dist/test-utils/model-auth-mock.js +12 -0
  182. package/dist/test-utils/provider-usage-fetch.js +14 -0
  183. package/dist/test-utils/temp-home.js +33 -0
  184. package/dist/tui/components/chat-log.js +9 -0
  185. package/dist/tui/tui-command-handlers.js +36 -27
  186. package/dist/tui/tui-event-handlers.js +122 -32
  187. package/dist/tui/tui.js +181 -45
  188. package/dist/utils/mask-api-key.js +10 -0
  189. package/dist/utils/run-with-concurrency.js +39 -0
  190. package/dist/web/media.js +4 -0
  191. package/docs/tools/slash-commands.md +5 -1
  192. package/extensions/bluebubbles/package.json +1 -1
  193. package/extensions/copilot-proxy/package.json +1 -1
  194. package/extensions/diagnostics-otel/package.json +1 -1
  195. package/extensions/discord/package.json +1 -1
  196. package/extensions/feishu/package.json +1 -1
  197. package/extensions/feishu/src/external-keys.ts +19 -0
  198. package/extensions/google-antigravity-auth/package.json +1 -1
  199. package/extensions/google-gemini-cli-auth/package.json +1 -1
  200. package/extensions/googlechat/package.json +1 -1
  201. package/extensions/imessage/package.json +1 -1
  202. package/extensions/irc/package.json +1 -1
  203. package/extensions/line/package.json +1 -1
  204. package/extensions/llm-task/package.json +1 -1
  205. package/extensions/lobster/package.json +1 -1
  206. package/extensions/lobster/src/windows-spawn.ts +193 -0
  207. package/extensions/matrix/CHANGELOG.md +5 -0
  208. package/extensions/matrix/package.json +1 -1
  209. package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
  210. package/extensions/mattermost/package.json +1 -1
  211. package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
  212. package/extensions/memory-core/package.json +1 -1
  213. package/extensions/memory-lancedb/package.json +1 -1
  214. package/extensions/minimax-portal-auth/package.json +1 -1
  215. package/extensions/msteams/CHANGELOG.md +5 -0
  216. package/extensions/msteams/package.json +1 -1
  217. package/extensions/nextcloud-talk/package.json +1 -1
  218. package/extensions/nostr/CHANGELOG.md +5 -0
  219. package/extensions/nostr/package.json +1 -1
  220. package/extensions/open-prose/package.json +1 -1
  221. package/extensions/openai-codex-auth/package.json +1 -1
  222. package/extensions/signal/package.json +1 -1
  223. package/extensions/slack/package.json +1 -1
  224. package/extensions/telegram/package.json +1 -1
  225. package/extensions/tlon/package.json +1 -1
  226. package/extensions/twitch/CHANGELOG.md +5 -0
  227. package/extensions/twitch/package.json +1 -1
  228. package/extensions/voice-call/CHANGELOG.md +5 -0
  229. package/extensions/voice-call/package.json +1 -1
  230. package/extensions/whatsapp/package.json +1 -1
  231. package/extensions/zalo/CHANGELOG.md +5 -0
  232. package/extensions/zalo/package.json +1 -1
  233. package/extensions/zalouser/CHANGELOG.md +5 -0
  234. package/extensions/zalouser/package.json +1 -1
  235. package/package.json +1 -1
@@ -2,44 +2,102 @@ import { Type } from "@sinclair/typebox";
2
2
  import { loadConfig } from "../../config/config.js";
3
3
  import { callGateway } from "../../gateway/call.js";
4
4
  import { capArrayByJsonBytes } from "../../gateway/session-utils.fs.js";
5
- import { isSubagentSessionKey, resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
6
5
  import { truncateUtf16Safe } from "../../utils.js";
7
6
  import { jsonResult, readStringParam } from "./common.js";
8
- import { createAgentToAgentPolicy, resolveSessionReference, resolveMainSessionAlias, resolveInternalSessionKey, stripToolMessages, } from "./sessions-helpers.js";
7
+ import { createSessionVisibilityGuard, createAgentToAgentPolicy, isRequesterSpawnedSessionVisible, resolveEffectiveSessionToolsVisibility, resolveSessionReference, resolveSandboxedSessionToolContext, stripToolMessages, } from "./sessions-helpers.js";
9
8
  const SessionsHistoryToolSchema = Type.Object({
10
9
  sessionKey: Type.String(),
11
10
  limit: Type.Optional(Type.Number({ minimum: 1 })),
12
11
  includeTools: Type.Optional(Type.Boolean()),
13
12
  });
14
- /** Hard cap on the serialized JSON size of the returned messages array. */
15
- const SESSIONS_HISTORY_MAX_BYTES = 512 * 1024;
16
- /** Per-block text truncation limit (in UTF-16 chars). */
17
- const SESSIONS_HISTORY_TEXT_MAX_CHARS = 32_000;
18
- function truncateHistoryText(text, maxChars) {
19
- if (text.length <= maxChars)
20
- return text;
21
- return `${truncateUtf16Safe(text, maxChars)}…(truncated)`;
13
+ const SESSIONS_HISTORY_MAX_BYTES = 80 * 1024;
14
+ const SESSIONS_HISTORY_TEXT_MAX_CHARS = 4000;
15
+ // sandbox policy handling is shared with sessions-list-tool via sessions-helpers.ts
16
+ function truncateHistoryText(text) {
17
+ if (text.length <= SESSIONS_HISTORY_TEXT_MAX_CHARS) {
18
+ return { text, truncated: false };
19
+ }
20
+ const cut = truncateUtf16Safe(text, SESSIONS_HISTORY_TEXT_MAX_CHARS);
21
+ return { text: `${cut}\n…(truncated)…`, truncated: true };
22
22
  }
23
23
  function sanitizeHistoryContentBlock(block) {
24
- if (!block || typeof block !== "object")
25
- return block;
26
- const rec = block;
27
- if (typeof rec.text === "string") {
28
- return { ...rec, text: truncateHistoryText(rec.text, SESSIONS_HISTORY_TEXT_MAX_CHARS) };
24
+ if (!block || typeof block !== "object") {
25
+ return { block, truncated: false };
26
+ }
27
+ const entry = { ...block };
28
+ let truncated = false;
29
+ const type = typeof entry.type === "string" ? entry.type : "";
30
+ if (typeof entry.text === "string") {
31
+ const res = truncateHistoryText(entry.text);
32
+ entry.text = res.text;
33
+ truncated ||= res.truncated;
34
+ }
35
+ if (type === "thinking") {
36
+ if (typeof entry.thinking === "string") {
37
+ const res = truncateHistoryText(entry.thinking);
38
+ entry.thinking = res.text;
39
+ truncated ||= res.truncated;
40
+ }
41
+ // The encrypted signature can be extremely large and is not useful for history recall.
42
+ if ("thinkingSignature" in entry) {
43
+ delete entry.thinkingSignature;
44
+ truncated = true;
45
+ }
29
46
  }
30
- return block;
47
+ if (typeof entry.partialJson === "string") {
48
+ const res = truncateHistoryText(entry.partialJson);
49
+ entry.partialJson = res.text;
50
+ truncated ||= res.truncated;
51
+ }
52
+ if (type === "image") {
53
+ const data = typeof entry.data === "string" ? entry.data : undefined;
54
+ const bytes = data ? data.length : undefined;
55
+ if ("data" in entry) {
56
+ delete entry.data;
57
+ truncated = true;
58
+ }
59
+ entry.omitted = true;
60
+ if (bytes !== undefined) {
61
+ entry.bytes = bytes;
62
+ }
63
+ }
64
+ return { block: entry, truncated };
31
65
  }
32
- function sanitizeHistoryMessage(msg) {
33
- if (!msg || typeof msg !== "object")
34
- return msg;
35
- const rec = msg;
36
- if (typeof rec.content === "string") {
37
- return { ...rec, content: truncateHistoryText(rec.content, SESSIONS_HISTORY_TEXT_MAX_CHARS) };
66
+ function sanitizeHistoryMessage(message) {
67
+ if (!message || typeof message !== "object") {
68
+ return { message, truncated: false };
69
+ }
70
+ const entry = { ...message };
71
+ let truncated = false;
72
+ // Tool result details often contain very large nested payloads.
73
+ if ("details" in entry) {
74
+ delete entry.details;
75
+ truncated = true;
38
76
  }
39
- if (Array.isArray(rec.content)) {
40
- return { ...rec, content: rec.content.map(sanitizeHistoryContentBlock) };
77
+ if ("usage" in entry) {
78
+ delete entry.usage;
79
+ truncated = true;
41
80
  }
42
- return msg;
81
+ if ("cost" in entry) {
82
+ delete entry.cost;
83
+ truncated = true;
84
+ }
85
+ if (typeof entry.content === "string") {
86
+ const res = truncateHistoryText(entry.content);
87
+ entry.content = res.text;
88
+ truncated ||= res.truncated;
89
+ }
90
+ else if (Array.isArray(entry.content)) {
91
+ const updated = entry.content.map((block) => sanitizeHistoryContentBlock(block));
92
+ entry.content = updated.map((item) => item.block);
93
+ truncated ||= updated.some((item) => item.truncated);
94
+ }
95
+ if (typeof entry.text === "string") {
96
+ const res = truncateHistoryText(entry.text);
97
+ entry.text = res.text;
98
+ truncated ||= res.truncated;
99
+ }
100
+ return { message: entry, truncated };
43
101
  }
44
102
  function jsonUtf8Bytes(value) {
45
103
  try {
@@ -49,45 +107,23 @@ function jsonUtf8Bytes(value) {
49
107
  return Buffer.byteLength(String(value), "utf8");
50
108
  }
51
109
  }
52
- function enforceSessionsHistoryHardCap(messages) {
53
- const sanitized = messages.map(sanitizeHistoryMessage);
54
- const { items, bytes } = capArrayByJsonBytes(sanitized, SESSIONS_HISTORY_MAX_BYTES);
55
- const droppedMessages = sanitized.length - items.length;
56
- // Count how many messages had content truncated by comparing original vs sanitized text.
57
- let contentTruncated = 0;
58
- for (let i = 0; i < messages.length; i++) {
59
- if (jsonUtf8Bytes(messages[i]) !== jsonUtf8Bytes(sanitized[i])) {
60
- contentTruncated++;
61
- }
62
- }
63
- return {
64
- messages: items,
65
- truncated: droppedMessages > 0 || contentTruncated > 0,
66
- droppedMessages,
67
- contentTruncated,
68
- bytes,
69
- };
70
- }
71
- function resolveSandboxSessionToolsVisibility(cfg) {
72
- return cfg.agents?.defaults?.sandbox?.sessionToolsVisibility ?? "spawned";
73
- }
74
- async function isSpawnedSessionAllowed(params) {
75
- try {
76
- const list = (await callGateway({
77
- method: "sessions.list",
78
- params: {
79
- includeGlobal: false,
80
- includeUnknown: false,
81
- limit: 500,
82
- spawnedBy: params.requesterSessionKey,
83
- },
84
- }));
85
- const sessions = Array.isArray(list?.sessions) ? list.sessions : [];
86
- return sessions.some((entry) => entry?.key === params.targetSessionKey);
110
+ function enforceSessionsHistoryHardCap(params) {
111
+ if (params.bytes <= params.maxBytes) {
112
+ return { items: params.items, bytes: params.bytes, hardCapped: false };
87
113
  }
88
- catch {
89
- return false;
114
+ const last = params.items.at(-1);
115
+ const lastOnly = last ? [last] : [];
116
+ const lastBytes = jsonUtf8Bytes(lastOnly);
117
+ if (lastBytes <= params.maxBytes) {
118
+ return { items: lastOnly, bytes: lastBytes, hardCapped: true };
90
119
  }
120
+ const placeholder = [
121
+ {
122
+ role: "assistant",
123
+ content: "[sessions_history omitted: message too large]",
124
+ },
125
+ ];
126
+ return { items: placeholder, bytes: jsonUtf8Bytes(placeholder), hardCapped: true };
91
127
  }
92
128
  export function createSessionsHistoryTool(opts) {
93
129
  return {
@@ -101,24 +137,16 @@ export function createSessionsHistoryTool(opts) {
101
137
  required: true,
102
138
  });
103
139
  const cfg = loadConfig();
104
- const { mainKey, alias } = resolveMainSessionAlias(cfg);
105
- const visibility = resolveSandboxSessionToolsVisibility(cfg);
106
- const requesterInternalKey = typeof opts?.agentSessionKey === "string" && opts.agentSessionKey.trim()
107
- ? resolveInternalSessionKey({
108
- key: opts.agentSessionKey,
109
- alias,
110
- mainKey,
111
- })
112
- : undefined;
113
- const restrictToSpawned = opts?.sandboxed === true &&
114
- visibility === "spawned" &&
115
- !!requesterInternalKey &&
116
- !isSubagentSessionKey(requesterInternalKey);
140
+ const { mainKey, alias, effectiveRequesterKey, restrictToSpawned } = resolveSandboxedSessionToolContext({
141
+ cfg,
142
+ agentSessionKey: opts?.agentSessionKey,
143
+ sandboxed: opts?.sandboxed,
144
+ });
117
145
  const resolvedSession = await resolveSessionReference({
118
146
  sessionKey: sessionKeyParam,
119
147
  alias,
120
148
  mainKey,
121
- requesterInternalKey,
149
+ requesterInternalKey: effectiveRequesterKey,
122
150
  restrictToSpawned,
123
151
  });
124
152
  if (!resolvedSession.ok) {
@@ -128,9 +156,9 @@ export function createSessionsHistoryTool(opts) {
128
156
  const resolvedKey = resolvedSession.key;
129
157
  const displayKey = resolvedSession.displayKey;
130
158
  const resolvedViaSessionId = resolvedSession.resolvedViaSessionId;
131
- if (restrictToSpawned && !resolvedViaSessionId) {
132
- const ok = await isSpawnedSessionAllowed({
133
- requesterSessionKey: requesterInternalKey,
159
+ if (restrictToSpawned && !resolvedViaSessionId && resolvedKey !== effectiveRequesterKey) {
160
+ const ok = await isRequesterSpawnedSessionVisible({
161
+ requesterSessionKey: effectiveRequesterKey,
134
162
  targetSessionKey: resolvedKey,
135
163
  });
136
164
  if (!ok) {
@@ -141,45 +169,49 @@ export function createSessionsHistoryTool(opts) {
141
169
  }
142
170
  }
143
171
  const a2aPolicy = createAgentToAgentPolicy(cfg);
144
- const requesterAgentId = resolveAgentIdFromSessionKey(requesterInternalKey);
145
- const targetAgentId = resolveAgentIdFromSessionKey(resolvedKey);
146
- const isCrossAgent = requesterAgentId !== targetAgentId;
147
- if (isCrossAgent) {
148
- if (!a2aPolicy.enabled) {
149
- return jsonResult({
150
- status: "forbidden",
151
- error: "Agent-to-agent history is disabled. Set tools.agentToAgent.enabled=true to allow cross-agent access.",
152
- });
153
- }
154
- if (!a2aPolicy.isAllowed(requesterAgentId, targetAgentId)) {
155
- return jsonResult({
156
- status: "forbidden",
157
- error: "Agent-to-agent history denied by tools.agentToAgent.allow.",
158
- });
159
- }
172
+ const visibility = resolveEffectiveSessionToolsVisibility({
173
+ cfg,
174
+ sandboxed: opts?.sandboxed === true,
175
+ });
176
+ const visibilityGuard = await createSessionVisibilityGuard({
177
+ action: "history",
178
+ requesterSessionKey: effectiveRequesterKey,
179
+ visibility,
180
+ a2aPolicy,
181
+ });
182
+ const access = visibilityGuard.check(resolvedKey);
183
+ if (!access.allowed) {
184
+ return jsonResult({
185
+ status: access.status,
186
+ error: access.error,
187
+ });
160
188
  }
161
189
  const limit = typeof params.limit === "number" && Number.isFinite(params.limit)
162
190
  ? Math.max(1, Math.floor(params.limit))
163
191
  : undefined;
164
192
  const includeTools = Boolean(params.includeTools);
165
- const result = (await callGateway({
193
+ const result = await callGateway({
166
194
  method: "chat.history",
167
195
  params: { sessionKey: resolvedKey, limit },
168
- }));
196
+ });
169
197
  const rawMessages = Array.isArray(result?.messages) ? result.messages : [];
170
- const messages = includeTools ? rawMessages : stripToolMessages(rawMessages);
171
- const capped = enforceSessionsHistoryHardCap(messages);
198
+ const selectedMessages = includeTools ? rawMessages : stripToolMessages(rawMessages);
199
+ const sanitizedMessages = selectedMessages.map((message) => sanitizeHistoryMessage(message));
200
+ const contentTruncated = sanitizedMessages.some((entry) => entry.truncated);
201
+ const cappedMessages = capArrayByJsonBytes(sanitizedMessages.map((entry) => entry.message), SESSIONS_HISTORY_MAX_BYTES);
202
+ const droppedMessages = cappedMessages.items.length < selectedMessages.length;
203
+ const hardened = enforceSessionsHistoryHardCap({
204
+ items: cappedMessages.items,
205
+ bytes: cappedMessages.bytes,
206
+ maxBytes: SESSIONS_HISTORY_MAX_BYTES,
207
+ });
172
208
  return jsonResult({
173
209
  sessionKey: displayKey,
174
- messages: capped.messages,
175
- ...(capped.truncated
176
- ? {
177
- truncated: true,
178
- droppedMessages: capped.droppedMessages,
179
- contentTruncated: capped.contentTruncated,
180
- bytes: capped.bytes,
181
- }
182
- : {}),
210
+ messages: hardened.items,
211
+ truncated: droppedMessages || contentTruncated || hardened.hardCapped,
212
+ droppedMessages: droppedMessages || hardened.hardCapped,
213
+ contentTruncated,
214
+ bytes: hardened.bytes,
183
215
  });
184
216
  },
185
217
  };