@cosmicstack/mercury-agent 1.2.1 → 1.2.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicstack/mercury-agent",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "Soul-driven AI agent with Second Brain memory, permission-hardened tools, token budgets, and multi-channel access. Runs 24/7 from CLI or Telegram.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,6 +20,7 @@
20
20
  "typecheck": "tsc --noEmit",
21
21
  "test": "vitest run",
22
22
  "test:watch": "vitest",
23
+ "postinstall": "patch-package || echo 'patch-package unavailable \u2014 skipping ink patch (dev installs only)'",
23
24
  "prepublishOnly": "npm run build"
24
25
  },
25
26
  "keywords": [
@@ -57,6 +58,7 @@
57
58
  },
58
59
  "files": [
59
60
  "dist",
61
+ "patches",
60
62
  "src/web/static"
61
63
  ],
62
64
  "dependencies": {
@@ -80,6 +82,7 @@
80
82
  "node-cron": "^3.0.3",
81
83
  "ollama-ai-provider": "^1.2.0",
82
84
  "pino": "^10.3.1",
85
+ "patch-package": "^8.0.1",
83
86
  "qrcode-terminal": "^0.12.0",
84
87
  "react": "^18.3.1",
85
88
  "sql.js": "^1.14.1",
@@ -0,0 +1,161 @@
1
+ diff --git a/node_modules/ink/build/components/Static.d.ts b/node_modules/ink/build/components/Static.d.ts
2
+ index 9a25884..a4d515b 100644
3
+ --- a/node_modules/ink/build/components/Static.d.ts
4
+ +++ b/node_modules/ink/build/components/Static.d.ts
5
+ @@ -15,6 +15,14 @@ export type Props<T> = {
6
+ * Note that `key` must be assigned to the root component.
7
+ */
8
+ readonly children: (item: T, index: number) => ReactNode;
9
+ + /**
10
+ + * Optional identity function used to track which items have already been
11
+ + * rendered. When provided, each item is rendered exactly once per
12
+ + * `<Static>` instance lifetime even if the `items` array is kept bounded
13
+ + * by shifting the window (which the built-in positional index cannot
14
+ + * handle). Keys returning `undefined` are ignored.
15
+ + */
16
+ + readonly itemKey?: (item: T) => string | undefined;
17
+ };
18
+ /**
19
+ * `<Static>` component permanently renders its output above everything else.
20
+ diff --git a/node_modules/ink/build/components/Static.js b/node_modules/ink/build/components/Static.js
21
+ index 9c54f14..6274f9a 100644
22
+ --- a/node_modules/ink/build/components/Static.js
23
+ +++ b/node_modules/ink/build/components/Static.js
24
+ @@ -1,4 +1,4 @@
25
+ -import React, { useMemo, useState, useLayoutEffect } from 'react';
26
+ +import React, { useMemo, useState, useLayoutEffect, useRef } from 'react';
27
+ /**
28
+ * `<Static>` component permanently renders its output above everything else.
29
+ * It's useful for displaying activity like completed tasks or logs - things that
30
+ @@ -10,18 +10,61 @@ import React, { useMemo, useState, useLayoutEffect } from 'react';
31
+ * For example, [Tap](https://github.com/tapjs/node-tap) uses `<Static>` to display
32
+ * a list of completed tests. [Gatsby](https://github.com/gatsbyjs/gatsby) uses it
33
+ * to display a list of generated pages, while still displaying a live progress bar.
34
+ + *
35
+ + * Patched (Cosmic Stack): supports an optional `itemKey` identity function.
36
+ + * The built-in positional index assumes `items` only ever appends — a caller
37
+ + * that keeps the array bounded by dropping the oldest items (a sliding
38
+ + * window) breaks it: `items.slice(index)` returns nothing, new items are
39
+ + * never rendered, and every commit unmounts the whole subtree. With
40
+ + * `itemKey`, each item is tracked by identity and rendered exactly once per
41
+ + * instance lifetime, so bounded sliding windows are safe.
42
+ */
43
+ export default function Static(props) {
44
+ - const { items, children: render, style: customStyle } = props;
45
+ + const { items, children: render, style: customStyle, itemKey } = props;
46
+ const [index, setIndex] = useState(0);
47
+ + // Identity of items already written to the terminal in this instance.
48
+ + // Only used when `itemKey` is provided.
49
+ + const committedKeys = useRef(null);
50
+ + // Bumped after committing keys so the memo recomputes and the rendered
51
+ + // children are unmounted — the positional path does this via setIndex.
52
+ + // Without it, committed children stay mounted and the renderer keeps
53
+ + // re-printing them into the terminal on EVERY subsequent render (each
54
+ + // pass re-emits `staticOutput` while the nodes are still attached).
55
+ + const [commitTick, setCommitTick] = useState(0);
56
+ const itemsToRender = useMemo(() => {
57
+ + if (typeof itemKey === 'function') {
58
+ + if (!committedKeys.current) {
59
+ + committedKeys.current = new Set();
60
+ + }
61
+ + const committed = committedKeys.current;
62
+ + const out = [];
63
+ + for (const item of items) {
64
+ + const key = itemKey(item);
65
+ + if (key !== undefined && !committed.has(key)) {
66
+ + out.push(item);
67
+ + }
68
+ + }
69
+ + return out;
70
+ + }
71
+ return items.slice(index);
72
+ - }, [items, index]);
73
+ + }, [items, index, itemKey, commitTick]);
74
+ useLayoutEffect(() => {
75
+ + if (typeof itemKey === 'function') {
76
+ + if (committedKeys.current && itemsToRender.length > 0) {
77
+ + for (const item of itemsToRender) {
78
+ + committedKeys.current.add(itemKey(item));
79
+ + }
80
+ + // Unmount what was just written: without this, the nodes stay
81
+ + // attached and every later render re-prints them (duplicate
82
+ + // transcript lines accumulating over time).
83
+ + setCommitTick((v) => v + 1);
84
+ + }
85
+ + return;
86
+ + }
87
+ setIndex(items.length);
88
+ - }, [items.length]);
89
+ + }, [itemsToRender, itemKey, items.length]);
90
+ const children = itemsToRender.map((item, itemIndex) => {
91
+ - return render(item, index + itemIndex);
92
+ + return render(item, itemIndex);
93
+ });
94
+ const style = useMemo(() => ({
95
+ position: 'absolute',
96
+ diff --git a/node_modules/ink/build/reconciler.js b/node_modules/ink/build/reconciler.js
97
+ index 55acec7..035907a 100644
98
+ --- a/node_modules/ink/build/reconciler.js
99
+ +++ b/node_modules/ink/build/reconciler.js
100
+ @@ -58,6 +58,42 @@ const cleanupYogaNode = (node) => {
101
+ node?.unsetMeasureFunc();
102
+ node?.freeRecursive();
103
+ };
104
+ +// `freeRecursive` releases Yoga's WASM memory but leaves every JavaScript
105
+ +// reference pointing at freed memory. The renderer and layout code read those
106
+ +// references through optional chaining, so nulling them here turns what was a
107
+ +// fatal WASM trap ("RuntimeError: memory access out of bounds" in
108
+ +// getComputedWidth) into a clean no-op. Upstream only clears the direct
109
+ +// reference (ink >=7); ancestors of <Static> that were freed wholesale left
110
+ +// `rootNode.staticNode` dangling. See facebook/yoga#1818 and the equivalent
111
+ +// downstream fix in qwen-code#7816.
112
+ +const clearYogaRefs = (node) => {
113
+ + node.yogaNode = undefined;
114
+ + // Host elements carry a childNodes array; ink's `#text` nodes do not.
115
+ + if (Array.isArray(node.childNodes)) {
116
+ + for (const child of node.childNodes) {
117
+ + clearYogaRefs(child);
118
+ + }
119
+ + }
120
+ +};
121
+ +const containsNode = (ancestor, target) => {
122
+ + let current = target;
123
+ + while (current) {
124
+ + if (current === ancestor) return true;
125
+ + current = current.parentNode;
126
+ + }
127
+ + return false;
128
+ +};
129
+ +const cleanupRemovedNode = (node, removeNode) => {
130
+ + cleanupYogaNode(removeNode.yogaNode);
131
+ + clearYogaRefs(removeNode);
132
+ + // `staticNode` is cached on the root container, but removeChild receives
133
+ + // the direct parent — climb to the root before checking.
134
+ + let rootNode = node;
135
+ + while (rootNode?.parentNode) rootNode = rootNode.parentNode;
136
+ + if (rootNode?.staticNode && containsNode(removeNode, rootNode.staticNode)) {
137
+ + rootNode.staticNode = undefined;
138
+ + }
139
+ +};
140
+ export default createReconciler({
141
+ getRootHostContext: () => ({
142
+ isInsideText: false,
143
+ @@ -173,7 +209,7 @@ export default createReconciler({
144
+ insertInContainerBefore: insertBeforeNode,
145
+ removeChildFromContainer(node, removeNode) {
146
+ removeChildNode(node, removeNode);
147
+ - cleanupYogaNode(removeNode.yogaNode);
148
+ + cleanupRemovedNode(node, removeNode);
149
+ },
150
+ prepareUpdate(node, _type, oldProps, newProps, rootNode) {
151
+ if (node.internal_static) {
152
+ @@ -213,7 +249,7 @@ export default createReconciler({
153
+ },
154
+ removeChild(node, removeNode) {
155
+ removeChildNode(node, removeNode);
156
+ - cleanupYogaNode(removeNode.yogaNode);
157
+ + cleanupRemovedNode(node, removeNode);
158
+ },
159
+ });
160
+ //# sourceMappingURL=reconciler.js.map
161
+