blun-king-cli 9.1.536 → 9.1.561

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 (129) hide show
  1. package/LIESMICH.txt +13 -869
  2. package/README.md +41 -833
  3. package/bin/assistant-message-offload-policy.cjs +3 -1
  4. package/bin/compaction-transaction-policy.cjs +122 -0
  5. package/bin/context-performance-policy.cjs +2 -5
  6. package/bin/context-pressure-policy.cjs +20 -0
  7. package/bin/cron-run-output.cjs +45 -0
  8. package/bin/cron-run-store.cjs +145 -0
  9. package/bin/default-model-output-budget-policy.cjs +28 -0
  10. package/bin/durable-task-resume-policy.cjs +130 -0
  11. package/bin/durable-task-resume-runtime.cjs +117 -0
  12. package/bin/durable-task-resume-store.cjs +88 -0
  13. package/bin/editable-tool-approval-policy.cjs +540 -0
  14. package/bin/editable-tool-approval-runtime.cjs +99 -0
  15. package/bin/file-observation-policy.cjs +133 -0
  16. package/bin/html-to-research-markdown.cjs +146 -0
  17. package/bin/launcher-runtime.js +0 -1
  18. package/bin/micro-compaction-policy.cjs +64 -0
  19. package/bin/mnemo-connect-heartbeat.cjs +1 -3
  20. package/bin/programmatic-tool-runtime.mjs +330 -4
  21. package/bin/read-continuation-policy.cjs +36 -5
  22. package/bin/retry-checkpoint-policy.cjs +13 -0
  23. package/bin/scoped-cron-run-policy.cjs +358 -0
  24. package/bin/session-checkpoint-policy.cjs +25 -0
  25. package/bin/startup-preferences.cjs +4 -3
  26. package/bin/structured-agent-swarm-output.cjs +325 -0
  27. package/bin/subagent-context-fork-policy.cjs +155 -0
  28. package/bin/subagent-skill-policy.cjs +204 -0
  29. package/bin/telegram-approval-relay.cjs +2 -1
  30. package/bin/tool-file-persistence.cjs +141 -0
  31. package/bin/tool-result-offload-policy.cjs +25 -33
  32. package/bin/turn-thinking-policy.cjs +2 -26
  33. package/bin/update-notice.js +30 -18
  34. package/bin/user-message-offload-policy.cjs +3 -1
  35. package/blun.mjs +1564 -640
  36. package/codebase-index/README.md +12 -0
  37. package/codebase-index/codebase_index.py +129 -18
  38. package/package.json +23 -58
  39. package/telegram-plugin/bin/telegram-mnemo-capture.cjs +1 -3
  40. package/telegram-plugin/bin/telegram-typing-keepalive.cjs +89 -0
  41. package/telegram-plugin/dist/bridge.mjs +8 -1
  42. package/CHANGELOG.md +0 -321
  43. package/agent-spine-plugin/CHANGELOG.md +0 -406
  44. package/agent-spine-plugin/CONTRIBUTING.md +0 -52
  45. package/agent-spine-plugin/README.md +0 -344
  46. package/agent-spine-plugin/SECURITY.md +0 -47
  47. package/agent-spine-plugin/docs/acceptance.md +0 -61
  48. package/agent-spine-plugin/docs/architecture.md +0 -183
  49. package/agent-spine-plugin/docs/attention.md +0 -121
  50. package/agent-spine-plugin/docs/automatic-continuity.md +0 -79
  51. package/agent-spine-plugin/docs/channel-runtime.md +0 -92
  52. package/agent-spine-plugin/docs/coordination.md +0 -138
  53. package/agent-spine-plugin/docs/feed-transport.md +0 -99
  54. package/agent-spine-plugin/docs/gateway-runtime.md +0 -116
  55. package/agent-spine-plugin/docs/harness-reference.md +0 -45
  56. package/agent-spine-plugin/docs/host-integration.md +0 -129
  57. package/agent-spine-plugin/docs/https-transport.md +0 -116
  58. package/agent-spine-plugin/docs/learning.md +0 -133
  59. package/agent-spine-plugin/docs/object-transport.md +0 -93
  60. package/agent-spine-plugin/docs/peer-transport.md +0 -88
  61. package/agent-spine-plugin/docs/preflight-recall.md +0 -69
  62. package/agent-spine-plugin/docs/preservation-contract.md +0 -53
  63. package/agent-spine-plugin/docs/quality-gates.md +0 -50
  64. package/agent-spine-plugin/docs/relationships.md +0 -73
  65. package/agent-spine-plugin/docs/releasing.md +0 -83
  66. package/agent-spine-plugin/docs/roadmap.md +0 -307
  67. package/agent-spine-plugin/docs/selfstarter.md +0 -88
  68. package/agent-spine-plugin/docs/session-briefing.md +0 -74
  69. package/agent-spine-plugin/docs/shared-memory.md +0 -259
  70. package/agent-spine-plugin/docs/source-roots.md +0 -86
  71. package/agent-spine-plugin/docs/sqlite-transport.md +0 -76
  72. package/agent-spine-plugin/scripts/check-hosts.js +0 -195
  73. package/agent-spine-plugin/scripts/check-install.js +0 -569
  74. package/agent-spine-plugin/scripts/check-syntax.js +0 -29
  75. package/agent-spine-plugin/scripts/github-actions.js +0 -11
  76. package/agent-spine-plugin/scripts/release-check.js +0 -128
  77. package/agent-spine-plugin/scripts/run-acceptance.js +0 -19
  78. package/agent-spine-plugin/scripts/run-checks.js +0 -46
  79. package/agent-spine-plugin/scripts/run-tests-hermetic.js +0 -73
  80. package/agent-spine-plugin/spine-example/1-identity.md +0 -12
  81. package/agent-spine-plugin/spine-example/2-voice.md +0 -6
  82. package/agent-spine-plugin/spine-example/3-conduct.md +0 -8
  83. package/agent-spine-plugin/spine-example/4-history.md +0 -4
  84. package/bin/empty-response-retry-policy.cjs +0 -29
  85. package/bin/fredrik-glm-provider.cjs +0 -256
  86. package/bin/package-regression-policy.cjs +0 -77
  87. package/fredrik-glm-profile.toml.example +0 -26
  88. package/release-planned-removals.json +0 -15
  89. package/scripts/check-active-profile-plugin-startup.js +0 -36
  90. package/scripts/check-active-work-steer-regression.js +0 -46
  91. package/scripts/check-approval-observability-regression.js +0 -111
  92. package/scripts/check-approval-queue-shortcuts-regression.js +0 -65
  93. package/scripts/check-bundled-agent-spine-regression.js +0 -48
  94. package/scripts/check-codebase-search-packaging-regression.js +0 -92
  95. package/scripts/check-copy-command-regression.js +0 -74
  96. package/scripts/check-current-turn-read-pin-mutation-regression.js +0 -72
  97. package/scripts/check-current-turn-read-pin-regression.js +0 -94
  98. package/scripts/check-deepseek-native-max-regression.js +0 -49
  99. package/scripts/check-empty-response-effort-downgrade-regression.js +0 -48
  100. package/scripts/check-fredrik-glm-mutation-regression.js +0 -18
  101. package/scripts/check-fredrik-glm-regression.js +0 -169
  102. package/scripts/check-historical-tool-result-preview-regression.js +0 -77
  103. package/scripts/check-history-pressure-offload-regression.js +0 -77
  104. package/scripts/check-mcp-startup-wait-budget.js +0 -48
  105. package/scripts/check-package-regression.js +0 -38
  106. package/scripts/check-plugin-startup-regression.js +0 -53
  107. package/scripts/check-programmatic-context-isolation-regression.js +0 -193
  108. package/scripts/check-programmatic-tool-regression.js +0 -294
  109. package/scripts/check-queue-controls-regression.js +0 -189
  110. package/scripts/check-release-metadata.js +0 -103
  111. package/scripts/check-reload-agent-spine-regression.js +0 -76
  112. package/scripts/check-resume-replay-regression.js +0 -102
  113. package/scripts/check-session-cancel-regression.js +0 -43
  114. package/scripts/check-session-picker-resume-metrics-regression.js +0 -97
  115. package/scripts/check-session-start-hook-context-regression.js +0 -228
  116. package/scripts/check-shell-terminal-isolation-regression.js +0 -81
  117. package/scripts/check-slash-escape-regression.js +0 -89
  118. package/scripts/check-startup-swarm-command-regression.js +0 -24
  119. package/scripts/check-structured-subagent-output-regression.js +0 -331
  120. package/scripts/check-telegram-bridge-watchdog.js +0 -60
  121. package/scripts/check-telegram-direct-work-resume-regression.js +0 -53
  122. package/scripts/check-telegram-loop-exactly-once-regression.js +0 -71
  123. package/scripts/check-todo-loop-regression.js +0 -78
  124. package/scripts/check-todo-progress-regression.js +0 -416
  125. package/scripts/check-todo-recovery-catalog-regression.js +0 -50
  126. package/scripts/check-tool-schema-capacity-regression.js +0 -40
  127. package/scripts/programmatic-tool-runtime.test.mjs +0 -365
  128. package/scripts/structured-subagent-output.test.cjs +0 -170
  129. /package/{scripts → bin}/fix-node-pty-perms.js +0 -0
@@ -0,0 +1,99 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ canonicalEditedToolInputJson,
5
+ validateEditedToolInputObject,
6
+ } = require('./editable-tool-approval-policy.cjs');
7
+
8
+ class EditableToolReprepareError extends Error {
9
+ constructor(code, message) {
10
+ super(message);
11
+ this.name = 'EditableToolReprepareError';
12
+ this.code = code;
13
+ }
14
+ }
15
+
16
+ function fail(code, message) {
17
+ throw new EditableToolReprepareError(code, message);
18
+ }
19
+
20
+ function buildEditedToolCallPlan({
21
+ step,
22
+ call,
23
+ editedArgs,
24
+ editCount,
25
+ preflightToolCall,
26
+ } = {}) {
27
+ if (editCount !== 0) {
28
+ fail('EDITED_REPREPARE_ALREADY_EDITED', 'A tool call may be edited at most once.');
29
+ }
30
+ if (call?.kind !== 'runnable' || call.toolCall === null || typeof call.toolCall !== 'object' || typeof call.toolCall.id !== 'string' || typeof call.toolCall.name !== 'string') {
31
+ fail('EDITED_REPREPARE_CALL_INVALID', 'Only a runnable tool call can be re-prepared.');
32
+ }
33
+ if (!Array.isArray(step?.toolCalls) || typeof preflightToolCall !== 'function') {
34
+ fail('EDITED_REPREPARE_CONTEXT_INVALID', 'Edited re-preparation requires the active ordered tool-call list and preflight function.');
35
+ }
36
+
37
+ const matchingIndexes = [];
38
+ for (let index = 0; index < step.toolCalls.length; index += 1) {
39
+ if (step.toolCalls[index]?.id === call.toolCall.id) matchingIndexes.push(index);
40
+ }
41
+ if (matchingIndexes.length === 0) {
42
+ fail('EDITED_REPREPARE_IDENTITY_MISSING', 'The edited tool call is absent from the active ordered call list.');
43
+ }
44
+ if (matchingIndexes.length !== 1) {
45
+ fail('EDITED_REPREPARE_IDENTITY_AMBIGUOUS', 'The edited tool-call ID is not unique in the active call list.');
46
+ }
47
+ const position = matchingIndexes[0];
48
+ if (step.toolCalls[position] !== call.toolCall || call.toolName !== call.toolCall.name) {
49
+ fail('EDITED_REPREPARE_IDENTITY_CHANGED', 'The active tool-call identity changed before re-preparation.');
50
+ }
51
+
52
+ const safeEditedArgs = validateEditedToolInputObject(editedArgs);
53
+ const patchedToolCall = Object.freeze({
54
+ ...call.toolCall,
55
+ id: call.toolCall.id,
56
+ name: call.toolCall.name,
57
+ arguments: canonicalEditedToolInputJson(safeEditedArgs),
58
+ });
59
+ const patchedToolCalls = step.toolCalls.slice();
60
+ patchedToolCalls[position] = patchedToolCall;
61
+ const editedStep = {
62
+ ...step,
63
+ toolCalls: Object.freeze(patchedToolCalls),
64
+ };
65
+ const repreflight = preflightToolCall(editedStep, patchedToolCall);
66
+ if (repreflight === null || typeof repreflight !== 'object') {
67
+ fail('EDITED_REPREPARE_PREFLIGHT_INVALID', 'Edited tool preflight returned no result.');
68
+ }
69
+ if (repreflight.toolCall?.id !== call.toolCall.id || repreflight.toolCall?.name !== call.toolCall.name || repreflight.toolName !== call.toolName) {
70
+ fail('EDITED_REPREPARE_IDENTITY_CHANGED', 'Edited preflight changed the immutable tool identity.');
71
+ }
72
+ if (repreflight.kind === 'rejected') {
73
+ return Object.freeze({
74
+ kind: 'rejected',
75
+ step: editedStep,
76
+ call: repreflight,
77
+ editCount: 1,
78
+ output: repreflight.output,
79
+ });
80
+ }
81
+ if (repreflight.kind !== 'runnable') {
82
+ fail('EDITED_REPREPARE_PREFLIGHT_INVALID', 'Edited preflight returned an unsupported call state.');
83
+ }
84
+ if (repreflight.tool !== call.tool) {
85
+ fail('EDITED_REPREPARE_REGISTRY_CHANGED', 'The authoritative tool registry entry changed during edited approval.');
86
+ }
87
+ return Object.freeze({
88
+ kind: 'runnable',
89
+ step: editedStep,
90
+ call: repreflight,
91
+ editCount: 1,
92
+ });
93
+ }
94
+
95
+ module.exports = Object.freeze({
96
+ EditableToolReprepareError,
97
+ buildEditedToolCallPlan,
98
+ });
99
+
@@ -0,0 +1,133 @@
1
+ 'use strict';
2
+
3
+ function versionFromStat(stat) {
4
+ if (!stat || typeof stat !== 'object') return null;
5
+ return [
6
+ stat.stDev ?? null,
7
+ stat.stIno ?? null,
8
+ stat.stSize ?? null,
9
+ stat.stMtime ?? null,
10
+ ].join(':');
11
+ }
12
+
13
+ function isNotFoundError(error) {
14
+ return error?.code === 'ENOENT' || error?.code === 'ENOTDIR';
15
+ }
16
+
17
+ function createFileObservationPolicy(options = {}) {
18
+ const caseInsensitive = options.pathClass === 'win32';
19
+ const observations = new Map();
20
+
21
+ function key(filePath) {
22
+ const normalized = String(filePath).replaceAll('\\', '/');
23
+ return caseInsensitive ? normalized.toLowerCase() : normalized;
24
+ }
25
+
26
+ function recordPresent(filePath, stat) {
27
+ const version = versionFromStat(stat);
28
+ if (version === null) throw new TypeError('recordPresent requires a file stat');
29
+ observations.set(key(filePath), { kind: 'present', version });
30
+ }
31
+
32
+ function recordAbsent(filePath) {
33
+ observations.set(key(filePath), { kind: 'absent' });
34
+ }
35
+
36
+ function verifyStableRead(filePath, before, after) {
37
+ const beforeVersion = versionFromStat(before);
38
+ const afterVersion = versionFromStat(after);
39
+ if (beforeVersion === null || afterVersion === null || beforeVersion !== afterVersion) {
40
+ return {
41
+ allowed: false,
42
+ code: 'FS_STALE_VERSION',
43
+ error: `File changed while reading "${filePath}". Read it again before editing or overwriting it.`,
44
+ };
45
+ }
46
+ recordPresent(filePath, after);
47
+ return { allowed: true, version: afterVersion };
48
+ }
49
+
50
+ function authorizeEdit(filePath, currentStat) {
51
+ const prior = observations.get(key(filePath));
52
+ if (currentStat === null) {
53
+ return {
54
+ allowed: false,
55
+ code: prior?.kind === 'absent' ? 'FS_NOT_FOUND' : 'FS_NOT_OBSERVED',
56
+ error: prior?.kind === 'absent'
57
+ ? `Cannot edit "${filePath}": the last Read confirmed that it does not exist.`
58
+ : `Edit requires reading "${filePath}" first. Read the exact target path, then retry.`,
59
+ };
60
+ }
61
+ if (prior === undefined) {
62
+ return {
63
+ allowed: false,
64
+ code: 'FS_NOT_OBSERVED',
65
+ error: `Edit requires reading "${filePath}" first. Read the exact target path, then retry.`,
66
+ };
67
+ }
68
+ if (prior.kind !== 'present' || prior.version !== versionFromStat(currentStat)) {
69
+ return {
70
+ allowed: false,
71
+ code: 'FS_STALE_VERSION',
72
+ error: `"${filePath}" changed since the last Read. Read it again, then retry the Edit.`,
73
+ };
74
+ }
75
+ return { allowed: true, version: prior.version };
76
+ }
77
+
78
+ function authorizeWrite(filePath, currentStat) {
79
+ const prior = observations.get(key(filePath));
80
+ if (currentStat === null) {
81
+ if (prior?.kind === 'present') {
82
+ return {
83
+ allowed: false,
84
+ code: 'FS_STALE_VERSION',
85
+ error: `"${filePath}" disappeared since the last Read. Read it again before recreating it.`,
86
+ };
87
+ }
88
+ return { allowed: true, version: null, create: true };
89
+ }
90
+ if (prior === undefined) {
91
+ return {
92
+ allowed: false,
93
+ code: 'FS_NOT_OBSERVED',
94
+ error: `Write would replace or append to existing file "${filePath}" without a prior Read. Read it first, then retry.`,
95
+ };
96
+ }
97
+ if (prior.kind !== 'present' || prior.version !== versionFromStat(currentStat)) {
98
+ return {
99
+ allowed: false,
100
+ code: 'FS_STALE_VERSION',
101
+ error: `"${filePath}" changed since the last Read. Read it again, then retry the Write.`,
102
+ };
103
+ }
104
+ return { allowed: true, version: prior.version, create: false };
105
+ }
106
+
107
+ function verifyUnchanged(filePath, expectedVersion, currentStat) {
108
+ const currentVersion = versionFromStat(currentStat);
109
+ if (expectedVersion === currentVersion) return { allowed: true };
110
+ return {
111
+ allowed: false,
112
+ code: 'FS_STALE_VERSION',
113
+ error: expectedVersion === null
114
+ ? `"${filePath}" appeared before the new file could be created. Read it before deciding whether to overwrite it.`
115
+ : `"${filePath}" changed before the mutation was written. Read it again, then retry.`,
116
+ };
117
+ }
118
+
119
+ return {
120
+ authorizeEdit,
121
+ authorizeWrite,
122
+ recordAbsent,
123
+ recordPresent,
124
+ verifyStableRead,
125
+ verifyUnchanged,
126
+ };
127
+ }
128
+
129
+ module.exports = {
130
+ createFileObservationPolicy,
131
+ isNotFoundError,
132
+ versionFromStat,
133
+ };
@@ -0,0 +1,146 @@
1
+ 'use strict';
2
+
3
+ const { Readability } = require('@mozilla/readability');
4
+ const { parseHTML } = require('linkedom');
5
+ const TurndownService = require('turndown');
6
+ const { tables } = require('turndown-plugin-gfm');
7
+
8
+ const MAX_LINK_LENGTH = 2_048;
9
+ const JUNK_SELECTORS = Object.freeze([
10
+ 'script',
11
+ 'style',
12
+ 'noscript',
13
+ 'nav',
14
+ 'footer',
15
+ 'header',
16
+ 'aside',
17
+ 'iframe',
18
+ 'svg',
19
+ 'form',
20
+ 'button',
21
+ 'input',
22
+ '[role="navigation"]',
23
+ '[role="banner"]',
24
+ '[role="contentinfo"]',
25
+ '[aria-hidden="true"]',
26
+ '[hidden]',
27
+ ]);
28
+
29
+ function canonicalBaseUrl(value) {
30
+ const parsed = new URL(value);
31
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
32
+ throw new Error('HTML-to-Markdown base URL must use http or https.');
33
+ }
34
+ return parsed.toString();
35
+ }
36
+
37
+ function safeResolvedLink(raw, baseUrl) {
38
+ if (typeof raw !== 'string' || raw.trim().length === 0) return null;
39
+ let resolved;
40
+ try {
41
+ resolved = new URL(raw, baseUrl);
42
+ } catch {
43
+ return null;
44
+ }
45
+ if (resolved.protocol !== 'http:' && resolved.protocol !== 'https:') return null;
46
+ const value = resolved.toString();
47
+ return value.length <= MAX_LINK_LENGTH ? value : null;
48
+ }
49
+
50
+ function removeAll(root, selector) {
51
+ for (const element of root.querySelectorAll(selector)) element.remove();
52
+ }
53
+
54
+ function sanitizeTree(root, baseUrl) {
55
+ for (const selector of JUNK_SELECTORS) removeAll(root, selector);
56
+
57
+ for (const element of root.querySelectorAll('[style]')) {
58
+ const style = element.getAttribute('style') ?? '';
59
+ if (/display\s*:\s*none|visibility\s*:\s*hidden/iu.test(style)) element.remove();
60
+ }
61
+
62
+ for (const selector of [
63
+ 'sup.reference',
64
+ 'sup.noprint',
65
+ '.reflist',
66
+ '.references',
67
+ '.refbegin',
68
+ '.catlinks',
69
+ '.mw-authority-control',
70
+ ]) removeAll(root, selector);
71
+
72
+ for (const anchor of root.querySelectorAll('a[href]')) {
73
+ const safe = safeResolvedLink(anchor.getAttribute('href'), baseUrl);
74
+ if (safe === null) anchor.removeAttribute('href');
75
+ else anchor.setAttribute('href', safe);
76
+ }
77
+
78
+ for (const image of root.querySelectorAll('img')) {
79
+ const alt = (image.getAttribute('alt') ?? '').trim();
80
+ if (alt.length > 0) image.replaceWith(image.ownerDocument.createTextNode(alt));
81
+ else image.remove();
82
+ }
83
+ }
84
+
85
+ function createMarkdownService() {
86
+ const service = new TurndownService({
87
+ headingStyle: 'atx',
88
+ codeBlockStyle: 'fenced',
89
+ bulletListMarker: '-',
90
+ });
91
+ service.use(tables);
92
+ service.remove(['script', 'style', 'noscript', 'iframe', 'svg']);
93
+ return service;
94
+ }
95
+
96
+ function withTitle(title, markdown) {
97
+ const cleanTitle = title.trim();
98
+ if (cleanTitle.length === 0) return markdown;
99
+ const titleHeading = `# ${cleanTitle}`;
100
+ if (markdown === titleHeading || markdown.startsWith(`${titleHeading}\n`)) return markdown;
101
+ return `${titleHeading}\n\n${markdown}`;
102
+ }
103
+
104
+ function renderRoot(root, title, safeBaseUrl) {
105
+ sanitizeTree(root, safeBaseUrl);
106
+ const fallback = (root.textContent ?? '').replace(/\s+/gu, ' ').trim();
107
+ let markdown = createMarkdownService().turndown(root.innerHTML).trim();
108
+ if (markdown.length === 0) markdown = fallback;
109
+ markdown = markdown.replace(/\n{4,}/gu, '\n\n\n').trim();
110
+ return withTitle(title, markdown);
111
+ }
112
+
113
+ function htmlToResearchMarkdown(html, baseUrl) {
114
+ if (typeof html !== 'string' || html.trim().length === 0) return '';
115
+ const safeBaseUrl = canonicalBaseUrl(baseUrl);
116
+ const primary = parseHTML(html);
117
+ try {
118
+ const article = new Readability(primary.document, { charThreshold: 0 }).parse();
119
+ if (article !== null && (article.content ?? '').trim().length > 0) {
120
+ const extracted = parseHTML(article.content);
121
+ const extractedRoot = extracted.document.querySelector('body');
122
+ if (extractedRoot !== null) {
123
+ const markdown = renderRoot(extractedRoot, article.title ?? '', safeBaseUrl);
124
+ if (markdown.length > 0) return markdown;
125
+ }
126
+ }
127
+ } catch {
128
+ // Keep the existing fail-open container fallback.
129
+ }
130
+
131
+ const { document } = parseHTML(html);
132
+ const title = (document.querySelector('title')?.textContent ?? '').trim();
133
+ const root = document.querySelector('article')
134
+ ?? document.querySelector('main')
135
+ ?? document.querySelector('[role="main"]')
136
+ ?? document.querySelector('body');
137
+ return root === null ? '' : renderRoot(root, title, safeBaseUrl);
138
+ }
139
+
140
+ module.exports = Object.freeze({
141
+ JUNK_SELECTORS,
142
+ MAX_LINK_LENGTH,
143
+ canonicalBaseUrl,
144
+ htmlToResearchMarkdown,
145
+ safeResolvedLink,
146
+ });
@@ -539,7 +539,6 @@ async function runLauncher(options = {}) {
539
539
  env.BLUN_SHARED_HOME = privatePaths.sharedHome;
540
540
  env.BLUN_LOG_HOME = privatePaths.sharedHome;
541
541
  env.BLUN_PROFILE = PROFILE.profileName;
542
- env.BLUN_MODEL_MAX_COMPLETION_TOKENS = env.BLUN_MODEL_MAX_COMPLETION_TOKENS || '32768';
543
542
  const mnemoConnect = startMnemoConnectHeartbeat({
544
543
  env,
545
544
  profileName: PROFILE.profileName,
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const { createHash } = require('node:crypto');
4
+
3
5
  const MICRO_COMPACTION_PRESSURE_RATIO = 0.75;
4
6
  const MICRO_COMPACTION_MIN_ADVANCE_MESSAGES = 20;
5
7
  const MICRO_COMPACTION_RECENT_MESSAGES = 4;
@@ -46,6 +48,66 @@ function selectMicroCompactionCutoff(options = {}) {
46
48
  };
47
49
  }
48
50
 
51
+ function redundantHistoricalToolResultIds(messages, cutoff) {
52
+ return new Set(redundantHistoricalToolResultReferences(messages, cutoff).keys());
53
+ }
54
+
55
+ function redundantHistoricalToolResultReferences(messages, cutoff) {
56
+ if (!Array.isArray(messages)) return new Map();
57
+
58
+ const historicalCutoff = Math.min(messages.length, nonNegativeInteger(cutoff));
59
+ const callSignatures = new Map();
60
+ for (const message of messages) {
61
+ if (message?.role !== 'assistant' || !Array.isArray(message.toolCalls)) continue;
62
+ for (const call of message.toolCalls) {
63
+ if (
64
+ typeof call?.id !== 'string'
65
+ || typeof call.name !== 'string'
66
+ || typeof call.arguments !== 'string'
67
+ ) {
68
+ continue;
69
+ }
70
+ callSignatures.set(call.id, JSON.stringify([call.name, call.arguments]));
71
+ }
72
+ }
73
+
74
+ const resultsBySignature = new Map();
75
+ for (let index = 0; index < messages.length; index++) {
76
+ const message = messages[index];
77
+ if (message?.role !== 'tool' || typeof message.toolCallId !== 'string') continue;
78
+ const callSignature = callSignatures.get(message.toolCallId);
79
+ if (callSignature === undefined || !Array.isArray(message.content)) continue;
80
+
81
+ let resultSignature;
82
+ try {
83
+ resultSignature = createHash('sha256')
84
+ .update(callSignature)
85
+ .update('\0')
86
+ .update(JSON.stringify(message.content))
87
+ .digest('hex');
88
+ } catch {
89
+ continue;
90
+ }
91
+
92
+ const entries = resultsBySignature.get(resultSignature) ?? [];
93
+ entries.push({ index, toolCallId: message.toolCallId });
94
+ resultsBySignature.set(resultSignature, entries);
95
+ }
96
+
97
+ const redundantIds = new Map();
98
+ for (const entries of resultsBySignature.values()) {
99
+ if (entries.length < 2) continue;
100
+ const newestToolCallId = entries.at(-1)?.toolCallId;
101
+ if (newestToolCallId === undefined) continue;
102
+ for (const entry of entries.slice(0, -1)) {
103
+ if (entry.index < historicalCutoff) {
104
+ redundantIds.set(entry.toolCallId, newestToolCallId);
105
+ }
106
+ }
107
+ }
108
+ return redundantIds;
109
+ }
110
+
49
111
  function finiteOr(value, fallback) {
50
112
  const number = Number(value);
51
113
  return Number.isFinite(number) ? number : fallback;
@@ -77,5 +139,7 @@ module.exports = {
77
139
  MICRO_COMPACTION_RECENT_MESSAGES,
78
140
  MICRO_COMPACTION_TOOL_ARGUMENTS_ENABLED,
79
141
  MICRO_COMPACTION_TOOL_ARGUMENT_MIN_TOKENS,
142
+ redundantHistoricalToolResultIds,
143
+ redundantHistoricalToolResultReferences,
80
144
  selectMicroCompactionCutoff,
81
145
  };
@@ -5,7 +5,6 @@ const os = require('node:os');
5
5
 
6
6
  const DEFAULT_HEARTBEAT_MS = 60_000;
7
7
  const DEFAULT_TIMEOUT_MS = 5_000;
8
- const DEFAULT_INTERNAL_HUB_URL = 'http://100.85.21.103:7117';
9
8
 
10
9
  function resolveMnemoHubUrl(env = process.env) {
11
10
  const raw = [
@@ -51,7 +50,7 @@ function resolveMnemoProfileConnectConfig(configPath) {
51
50
  ].some((value) => typeof value === 'string' && value.trim().length > 0);
52
51
  const baseUrl = resolveMnemoHubUrl(server.env);
53
52
  if (configuredUrl && !baseUrl) return null;
54
- return { agentName, baseUrl: baseUrl || DEFAULT_INTERNAL_HUB_URL };
53
+ return baseUrl ? { agentName, baseUrl } : null;
55
54
  } catch {
56
55
  return null;
57
56
  }
@@ -196,7 +195,6 @@ function startMnemoConnectHeartbeat(options = {}) {
196
195
 
197
196
  module.exports = {
198
197
  DEFAULT_HEARTBEAT_MS,
199
- DEFAULT_INTERNAL_HUB_URL,
200
198
  DEFAULT_TIMEOUT_MS,
201
199
  postMnemoTool,
202
200
  resolveMnemoAgentName,