toolnet-memory 0.3.2 → 0.3.4
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/bin/toolnet-memory +44 -0
- package/bundle/agy-hook.js +39 -88
- package/bundle/agy.js +38 -104
- package/bundle/auto-integrate.js +131 -707
- package/bundle/codex-context.js +44 -54
- package/bundle/codex.js +47 -83
- package/bundle/context-runtime.js +29 -124
- package/bundle/context.js +14 -15
- package/bundle/doctor.js +3 -6
- package/bundle/full-index.js +8 -18
- package/bundle/graph-index.js +4 -4
- package/bundle/impact.js +3 -3
- package/bundle/incremental.js +4 -4
- package/bundle/learner.js +5 -5
- package/bundle/mcp.js +7 -54
- package/bundle/opencode.js +168 -717
- package/bundle/project-manual.js +6 -6
- package/bundle/runtime.js +11 -11
- package/bundle/semantic.js +6 -6
- package/bundle/setup.js +187 -716
- package/bundle/snapshot.js +4 -4
- package/bundle/update.js +1 -4
- package/bundle/work-continuity.js +6 -6
- package/package.json +1 -1
- package/bundle/api.js +0 -52
- package/bundle/claude-hook.js +0 -78
- package/bundle/claude.js +0 -3
- package/bundle/continuity-certify.js +0 -49
- package/bundle/handoff-refresh.js +0 -12
- package/bundle/init.js +0 -763
- package/bundle/memory-agent.js +0 -48
- package/bundle/memory-query.js +0 -7
- package/bundle/production-certify.js +0 -5
- package/bundle/provider.js +0 -3
- package/bundle/recovery-certify.js +0 -55
package/bundle/setup.js
CHANGED
|
@@ -1,271 +1,25 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
`,{encoding:"utf8",mode:384}),vo(s,o)}finally{Go(s,{force:!0})}return o}import{existsSync as Vo,mkdirSync as Jo,readFileSync as Wo,renameSync as Xo,writeFileSync as zo}from"node:fs";import{dirname as Qo}from"node:path";function w(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Zo(e,o){Jo(Qo(e),{recursive:!0,mode:448});let t=`${e}.tmp-${process.pid}-${Date.now()}`;zo(t,`${JSON.stringify(o,null,2)}
|
|
5
|
-
`,{encoding:"utf8",mode:384}),Xo(t,e)}function ke(e){if(!Vo(e))return{};let o=Wo(e,"utf8").trim();if(!o)return{};let t;try{t=JSON.parse(o)}catch(n){throw new Error(`Invalid existing Agy MCP config: ${n instanceof Error?n.message:String(n)}`)}if(!w(t))throw new Error("Invalid existing Agy MCP config: root must be a JSON object.");return t}function Be(e,o){return w(e)?e.command===o&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp":!1}function Fe(e={}){let o=e.configFile??H(),t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.serverName??"toolnet-memory",r=ke(o),s=r.mcpServers;if(s!==void 0&&!w(s))throw new Error("Invalid existing Agy MCP config: mcpServers must be an object.");let i=w(s)?{...s}:{},c=i[n];if(Be(c,t))return{installed:!0,changed:!1,configFile:o,serverName:n,command:t,args:["mcp"]};i[n]={command:t,args:["mcp"]};let a={...r,mcpServers:i};Zo(o,a);let d=ke(o).mcpServers;if(!w(d)||!Be(d[n],t))throw new Error("Agy MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:o,serverName:n,command:t,args:["mcp"]}}var nt=`# ToolNet Memory Continuity
|
|
6
|
-
|
|
7
|
-
ToolNet Memory is the authoritative continuity layer for previous project work.
|
|
8
|
-
|
|
9
|
-
## Resume / continue behavior
|
|
10
|
-
|
|
11
|
-
Whenever the user asks to continue, resume, finish, pick up, return to, or complete previous work:
|
|
12
|
-
|
|
13
|
-
1. FIRST call the ToolNet Memory MCP tool \`memory_agent_ask\`.
|
|
14
|
-
2. Use ToolNet's compact continuity result to determine:
|
|
15
|
-
- current task
|
|
16
|
-
- completed work
|
|
17
|
-
- current or last file
|
|
18
|
-
- TODOs
|
|
19
|
-
- blockers
|
|
20
|
-
- next action
|
|
21
|
-
3. Only AFTER continuity is known may you inspect current source or git to verify repository truth.
|
|
1
|
+
import m from"node:fs";import Te from"node:os";import q from"node:path";import Ae from"node:readline/promises";import{stdin as d,stdout as S}from"node:process";import{existsSync as A}from"node:fs";import{homedir as R}from"node:os";import{join as N}from"node:path";import{spawnSync as me}from"node:child_process";import{existsSync as V,mkdirSync as W,readFileSync as X,writeFileSync as Z}from"node:fs";import{homedir as Q}from"node:os";import{dirname as z,join as ee}from"node:path";function te(e){return`'${e.replace(/'/g,"'\\''")}'`}function Y(e={}){let t=e.hooksFile??ee(Q(),".gemini","config","hooks.json");W(z(t),{recursive:!0});let o={};if(V(t))try{o=JSON.parse(X(t,"utf8"))}catch(s){throw new Error(`Invalid existing Agy hooks.json: ${s instanceof Error?s.message:String(s)}`)}let r=e.binary??"toolnet-memory",n=`${te(r)} session:agy-hook`;return o["toolnet-memory"]={enabled:!0,PreInvocation:[{type:"command",command:`${n} pre`,timeout:15}],PostInvocation:[{type:"command",command:`${n} post`,timeout:15}],Stop:[{type:"command",command:`${n} stop`,timeout:30}]},Z(t,JSON.stringify(o,null,2)+`
|
|
2
|
+
`,{encoding:"utf8",mode:384}),t}import{existsSync as oe,mkdirSync as K,readFileSync as ne,writeFileSync as D}from"node:fs";import{homedir as O}from"node:os";import{join as p}from"node:path";var $="<!-- TOOLNET_MEMORY_BOOTSTRAP_START -->",C="<!-- TOOLNET_MEMORY_BOOTSTRAP_END -->";function re(){let e=p(O(),".config","opencode","AGENTS.md");K(p(O(),".config","opencode"),{recursive:!0});let t=`${$}
|
|
3
|
+
## ToolNet Memory \u2014 Project Continuity
|
|
22
4
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Do NOT reconstruct previous work by reading, listing, searching, or shelling into:
|
|
26
|
-
|
|
27
|
-
- \`.toolnet/sessions/**\`
|
|
28
|
-
- \`state.json\`
|
|
29
|
-
- \`events.jsonl\`
|
|
30
|
-
- raw transcripts
|
|
31
|
-
- \`~/.gemini/antigravity-cli/brain/**\`
|
|
32
|
-
- Antigravity \`transcript.jsonl\`
|
|
33
|
-
- another coding agent's internal session history
|
|
34
|
-
|
|
35
|
-
Do NOT run Bash/cat/tail/grep against those locations to discover previous work.
|
|
36
|
-
|
|
37
|
-
Do NOT search the filesystem for the implementation or schema of \`memory_agent_ask\`.
|
|
38
|
-
Invoke the MCP tool directly.
|
|
5
|
+
When the current workspace belongs to a ToolNet project, identified by a nearest ancestor containing \`.toolnet/project.json\`:
|
|
39
6
|
|
|
40
|
-
|
|
41
|
-
|
|
7
|
+
1. Before planning, editing, or running implementation commands, read that project root's \`.toolnet/context/startup.md\`.
|
|
8
|
+
2. Treat its PROJECT RULES, MISSION, CURRENT OBJECTIVE, rationale, current phase/task, Definition of Done, blockers and next actions as project continuity context.
|
|
9
|
+
3. Do not restart work already marked completed unless repository evidence proves it must be revisited.
|
|
10
|
+
4. Verify current repository state before continuing old work.
|
|
11
|
+
5. If \`.toolnet/context/startup.md\` is missing, run \`toolnet-memory context:sync --project <project-root>\`, then read it.
|
|
12
|
+
6. Never invent missing rationale. If ToolNet says a reason was not explicitly recorded, inspect the implementation or ask rather than guessing.
|
|
42
13
|
|
|
43
|
-
|
|
14
|
+
This applies automatically to every ToolNet-managed project.
|
|
15
|
+
${C}`,o=oe(e)?ne(e,"utf8"):"",r=o.indexOf($),n=o.indexOf(C);return r>=0&&n>=r?o=o.slice(0,r)+t+o.slice(n+C.length):(o=o.trimEnd(),o&&(o+=`
|
|
44
16
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
`),!0}function je(e={}){let o=e.pluginName??"toolnet-memory",t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.pluginRoot??Ce(o),r=J(n,"plugin.json"),s=J(n,"mcp_config.json"),i=J(n,"hooks.json"),c=J(n,"rules","toolnet-memory-continuity.md");$e(n,{recursive:!0,mode:448}),xe(r,`${JSON.stringify({$schema:"https://antigravity.google/schemas/v1/plugin.json",name:o,description:"Persistent project continuity and memory for Antigravity coding sessions."},null,2)}
|
|
49
|
-
`),Fe({configFile:s,binary:t,serverName:"toolnet-memory"}),Ke({hooksFile:i,binary:t}),xe(c,`${nt.trim()}
|
|
50
|
-
`);let a=e.legacyMcpFile??H(),g=e.legacyHooksFile??q(),d=[];return a!==s&&rt(a,"toolnet-memory")&&d.push(a),g!==i&&it(g)&&d.push(g),{installed:!0,pluginRoot:n,files:[r,s,i,c],migratedLegacy:d}}import{existsSync as ct,mkdirSync as Ve,readFileSync as at,writeFileSync as Je}from"node:fs";import{join as lt}from"node:path";var st="memory_agent_ask";function He(){return`
|
|
51
|
-
[TOOLNET MEMORY AGENT]
|
|
17
|
+
`),o+=t),D(e,o.trimEnd()+`
|
|
18
|
+
`,{encoding:"utf8",mode:384}),e}function w(e={}){let t=e.directory??p(O(),".config","opencode","plugins");K(t,{recursive:!0}),re();let o=p(t,"toolnet-memory.js"),r=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=`// Generated by ToolNet Memory.
|
|
19
|
+
// OpenCode session capture + continuity bootstrap.
|
|
52
20
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
Use it automatically BEFORE guessing when:
|
|
57
|
-
|
|
58
|
-
- The user asks to continue, resume, or pick up previous work.
|
|
59
|
-
- The user says things like:
|
|
60
|
-
- "ti\u1EBFp t\u1EE5c task l\xFAc n\xE3y"
|
|
61
|
-
- "l\xE0m ti\u1EBFp ph\u1EA7n \u0111ang d\u1EDF"
|
|
62
|
-
- "agent tr\u01B0\u1EDBc \u0111ang l\xE0m g\xEC?"
|
|
63
|
-
- "d\u1EEBng \u1EDF \u0111\xE2u?"
|
|
64
|
-
- "todo n\xE0o ch\u01B0a xong?"
|
|
65
|
-
- "continue the previous task"
|
|
66
|
-
- "resume the last session"
|
|
67
|
-
- Previous-agent state, unfinished work, blockers,
|
|
68
|
-
decisions, touched files, or next actions are unclear.
|
|
69
|
-
- Fast startup context is not enough to safely continue.
|
|
70
|
-
|
|
71
|
-
Preferred mode:
|
|
72
|
-
|
|
73
|
-
- mode="local"
|
|
74
|
-
for direct factual questions such as:
|
|
75
|
-
current task, last file, blocker, completed TODOs.
|
|
76
|
-
|
|
77
|
-
- mode="ai"
|
|
78
|
-
for composite or ambiguous continuity questions
|
|
79
|
-
that benefit from ToolNet Memory Agent reasoning.
|
|
80
|
-
|
|
81
|
-
Do NOT call it automatically when:
|
|
82
|
-
|
|
83
|
-
- Normal startup context already gives enough information.
|
|
84
|
-
- The question is unrelated to previous project work.
|
|
85
|
-
- The answer is obvious from current repository evidence.
|
|
86
|
-
|
|
87
|
-
Rules:
|
|
88
|
-
|
|
89
|
-
- Never invent previous work.
|
|
90
|
-
- Current repository evidence overrides stale memory.
|
|
91
|
-
- NEVER reconstruct previous work by reading ToolNet internal session files.
|
|
92
|
-
- NEVER read/list/search .toolnet/sessions/**, session state.json,
|
|
93
|
-
events.jsonl, or raw transcripts to discover previous-agent state.
|
|
94
|
-
- Do not search the filesystem for the implementation/schema of
|
|
95
|
-
memory_agent_ask. Invoke the MCP tool directly when deeper
|
|
96
|
-
continuity is required.
|
|
97
|
-
- Do not dump raw transcripts or full memory.
|
|
98
|
-
- After receiving the ToolNet answer, continue the task
|
|
99
|
-
instead of asking the user to repeat known context.
|
|
100
|
-
- If ToolNet says information is not recorded, say so.
|
|
101
|
-
`.trim()}var qe="<!-- TOOLNET_MEMORY_BOOTSTRAP_START -->",se="<!-- TOOLNET_MEMORY_BOOTSTRAP_END -->";function gt(){let e=De();Ve(M(),{recursive:!0});let o=`${qe}
|
|
102
|
-
## ToolNet Memory
|
|
103
|
-
|
|
104
|
-
ToolNet Memory is available for projects that already contain a valid \`.toolnet/project.json\`.
|
|
105
|
-
|
|
106
|
-
Rules:
|
|
107
|
-
|
|
108
|
-
1. Do not create a ToolNet project automatically.
|
|
109
|
-
2. If no valid \`.toolnet/project.json\` exists in the current project or an ancestor, ignore ToolNet Memory.
|
|
110
|
-
3. Normal startup context must stay small and selective.
|
|
111
|
-
4. Do not automatically run deep recovery commands.
|
|
112
|
-
5. Use ToolNet MCP or selective retrieval when older project knowledge is actually needed.
|
|
113
|
-
6. Raw transcripts must not be injected into prompts.
|
|
114
|
-
7. Current repository evidence has priority over stale memory when they conflict.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
${He()}
|
|
118
|
-
|
|
119
|
-
${se}`,t=ct(e)?at(e,"utf8"):"",n=t.indexOf(qe),r=t.indexOf(se);return n>=0&&r>=n?t=t.slice(0,n)+o+t.slice(r+se.length):(t=t.trimEnd(),t&&(t+=`
|
|
120
|
-
|
|
121
|
-
`),t+=o),Je(e,t.trimEnd()+`
|
|
122
|
-
`,{encoding:"utf8",mode:384}),e}function We(e={}){let o=e.directory??he();Ve(o,{recursive:!0}),gt();let t=lt(o,"toolnet-memory.js"),n=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",r=`
|
|
123
|
-
// Generated by ToolNet Memory.
|
|
124
|
-
// OpenCode integration:
|
|
125
|
-
// - project gated
|
|
126
|
-
// - selective context injection
|
|
127
|
-
// - incremental session checkpoints
|
|
128
|
-
// - periodic durability sync
|
|
129
|
-
// - best-effort shutdown flush
|
|
130
|
-
|
|
131
|
-
import fs from "node:fs"
|
|
132
|
-
import path from "node:path"
|
|
133
|
-
import os from "node:os"
|
|
134
|
-
|
|
135
|
-
const TOOLNET_BINARY =
|
|
136
|
-
${JSON.stringify(n)}
|
|
137
|
-
|
|
138
|
-
const CONTEXT_MAX_TOKENS = 700
|
|
139
|
-
|
|
140
|
-
const CONTEXT_CACHE_MS = 5000
|
|
141
|
-
|
|
142
|
-
const PERIODIC_SYNC_MS = 30000
|
|
143
|
-
|
|
144
|
-
const SYNC_TIMEOUT_MS = 15000
|
|
145
|
-
|
|
146
|
-
const STATUS_FILE = path.join(
|
|
147
|
-
os.homedir(),
|
|
148
|
-
".config",
|
|
149
|
-
"toolnet-memory",
|
|
150
|
-
"opencode-sync-status.json"
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
function writeStatus(data) {
|
|
154
|
-
try {
|
|
155
|
-
fs.mkdirSync(
|
|
156
|
-
path.dirname(
|
|
157
|
-
STATUS_FILE
|
|
158
|
-
),
|
|
159
|
-
{
|
|
160
|
-
recursive: true,
|
|
161
|
-
}
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
fs.writeFileSync(
|
|
165
|
-
STATUS_FILE,
|
|
166
|
-
JSON.stringify(
|
|
167
|
-
{
|
|
168
|
-
timestamp:
|
|
169
|
-
new Date()
|
|
170
|
-
.toISOString(),
|
|
171
|
-
...data,
|
|
172
|
-
},
|
|
173
|
-
null,
|
|
174
|
-
2
|
|
175
|
-
) + "\\n"
|
|
176
|
-
)
|
|
177
|
-
} catch {
|
|
178
|
-
// Status reporting must
|
|
179
|
-
// never break OpenCode.
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function validProjectManifest(
|
|
184
|
-
file
|
|
185
|
-
) {
|
|
186
|
-
try {
|
|
187
|
-
const parsed =
|
|
188
|
-
JSON.parse(
|
|
189
|
-
fs.readFileSync(
|
|
190
|
-
file,
|
|
191
|
-
"utf8"
|
|
192
|
-
)
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
return Boolean(
|
|
196
|
-
parsed &&
|
|
197
|
-
typeof parsed ===
|
|
198
|
-
"object" &&
|
|
199
|
-
typeof parsed.id ===
|
|
200
|
-
"string" &&
|
|
201
|
-
parsed.id.length > 0
|
|
202
|
-
)
|
|
203
|
-
} catch {
|
|
204
|
-
return false
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function findProjectRoot(
|
|
209
|
-
inputDirectory
|
|
210
|
-
) {
|
|
211
|
-
let current =
|
|
212
|
-
path.resolve(
|
|
213
|
-
inputDirectory
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
const filesystemRoot =
|
|
217
|
-
path.parse(
|
|
218
|
-
current
|
|
219
|
-
).root
|
|
220
|
-
|
|
221
|
-
while (true) {
|
|
222
|
-
const manifest =
|
|
223
|
-
path.join(
|
|
224
|
-
current,
|
|
225
|
-
".toolnet",
|
|
226
|
-
"project.json"
|
|
227
|
-
)
|
|
228
|
-
|
|
229
|
-
if (
|
|
230
|
-
fs.existsSync(
|
|
231
|
-
manifest
|
|
232
|
-
) &&
|
|
233
|
-
validProjectManifest(
|
|
234
|
-
manifest
|
|
235
|
-
)
|
|
236
|
-
) {
|
|
237
|
-
return current
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (
|
|
241
|
-
current ===
|
|
242
|
-
filesystemRoot
|
|
243
|
-
) {
|
|
244
|
-
break
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const parent =
|
|
248
|
-
path.dirname(
|
|
249
|
-
current
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
if (
|
|
253
|
-
parent === current
|
|
254
|
-
) {
|
|
255
|
-
break
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
current = parent
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return null
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function getSessionId(
|
|
265
|
-
event
|
|
266
|
-
) {
|
|
267
|
-
const p =
|
|
268
|
-
event?.properties ?? {}
|
|
21
|
+
function getSessionId(event) {
|
|
22
|
+
const p = event?.properties ?? {}
|
|
269
23
|
|
|
270
24
|
const candidates = [
|
|
271
25
|
p.sessionID,
|
|
@@ -274,493 +28,210 @@ function getSessionId(
|
|
|
274
28
|
p.session?.id,
|
|
275
29
|
]
|
|
276
30
|
|
|
277
|
-
return (
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
typeof value ===
|
|
281
|
-
"string" &&
|
|
282
|
-
value.length > 0
|
|
283
|
-
) ?? null
|
|
284
|
-
)
|
|
31
|
+
return candidates.find(
|
|
32
|
+
value => typeof value === "string" && value.length > 0
|
|
33
|
+
) ?? null
|
|
285
34
|
}
|
|
286
35
|
|
|
287
|
-
async
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
"ignore",
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
)
|
|
306
|
-
|
|
307
|
-
let timer
|
|
308
|
-
|
|
309
|
-
const timeoutPromise =
|
|
310
|
-
new Promise(
|
|
311
|
-
(_, reject) => {
|
|
312
|
-
timer =
|
|
313
|
-
setTimeout(
|
|
314
|
-
() => {
|
|
315
|
-
try {
|
|
316
|
-
child.kill()
|
|
317
|
-
} catch {}
|
|
318
|
-
|
|
319
|
-
reject(
|
|
320
|
-
new Error(
|
|
321
|
-
"ToolNet command timeout"
|
|
322
|
-
)
|
|
323
|
-
)
|
|
324
|
-
},
|
|
325
|
-
timeout
|
|
326
|
-
)
|
|
327
|
-
}
|
|
328
|
-
)
|
|
329
|
-
|
|
330
|
-
try {
|
|
331
|
-
const exitCode =
|
|
332
|
-
await Promise.race([
|
|
333
|
-
child.exited,
|
|
334
|
-
timeoutPromise,
|
|
335
|
-
])
|
|
336
|
-
|
|
337
|
-
if (
|
|
338
|
-
typeof exitCode ===
|
|
339
|
-
"number" &&
|
|
340
|
-
exitCode !== 0
|
|
341
|
-
) {
|
|
342
|
-
throw new Error(
|
|
343
|
-
\`ToolNet exited with code \${exitCode}\`
|
|
36
|
+
export const ToolNetMemoryPlugin = async ({ directory }) => {
|
|
37
|
+
const binary = ${JSON.stringify(r)}
|
|
38
|
+
|
|
39
|
+
async function refreshContext() {
|
|
40
|
+
try {
|
|
41
|
+
const child = Bun.spawn(
|
|
42
|
+
[
|
|
43
|
+
binary,
|
|
44
|
+
"context:sync",
|
|
45
|
+
"--project",
|
|
46
|
+
directory,
|
|
47
|
+
],
|
|
48
|
+
{
|
|
49
|
+
stdin: "ignore",
|
|
50
|
+
stdout: "ignore",
|
|
51
|
+
stderr: "ignore",
|
|
52
|
+
}
|
|
344
53
|
)
|
|
345
|
-
}
|
|
346
54
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
clearTimeout(
|
|
351
|
-
timer
|
|
352
|
-
)
|
|
55
|
+
await child.exited
|
|
56
|
+
} catch {
|
|
57
|
+
// Context sync must never break OpenCode startup.
|
|
353
58
|
}
|
|
354
59
|
}
|
|
355
|
-
}
|
|
356
60
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
61
|
+
async function readContext() {
|
|
62
|
+
try {
|
|
63
|
+
const child = Bun.spawn(
|
|
64
|
+
[
|
|
65
|
+
binary,
|
|
66
|
+
"context:print",
|
|
67
|
+
"--project",
|
|
68
|
+
directory,
|
|
69
|
+
"--tokens",
|
|
70
|
+
"900",
|
|
71
|
+
],
|
|
72
|
+
{
|
|
73
|
+
stdin: "ignore",
|
|
74
|
+
stdout: "pipe",
|
|
75
|
+
stderr: "ignore",
|
|
76
|
+
}
|
|
371
77
|
)
|
|
372
78
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
"no-toolnet-project",
|
|
378
|
-
directory,
|
|
379
|
-
})
|
|
79
|
+
const text =
|
|
80
|
+
await new Response(
|
|
81
|
+
child.stdout
|
|
82
|
+
).text()
|
|
380
83
|
|
|
381
|
-
|
|
382
|
-
}
|
|
84
|
+
await child.exited
|
|
383
85
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
})
|
|
86
|
+
return text.trim()
|
|
87
|
+
} catch {
|
|
88
|
+
return ""
|
|
89
|
+
}
|
|
90
|
+
}
|
|
390
91
|
|
|
391
|
-
|
|
392
|
-
|
|
92
|
+
function sync(sessionId, flag) {
|
|
93
|
+
if (!sessionId) return
|
|
393
94
|
|
|
394
|
-
|
|
395
|
-
|
|
95
|
+
try {
|
|
96
|
+
const args = [
|
|
97
|
+
binary,
|
|
98
|
+
"session:opencode-sync",
|
|
99
|
+
sessionId,
|
|
100
|
+
"--project",
|
|
101
|
+
directory,
|
|
102
|
+
]
|
|
396
103
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}
|
|
104
|
+
if (flag) {
|
|
105
|
+
args.push(flag)
|
|
106
|
+
}
|
|
401
107
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
108
|
+
const child = Bun.spawn(args, {
|
|
109
|
+
stdin: "ignore",
|
|
110
|
+
stdout: "ignore",
|
|
111
|
+
stderr: "ignore",
|
|
112
|
+
})
|
|
405
113
|
|
|
406
114
|
if (
|
|
407
|
-
|
|
408
|
-
now <
|
|
409
|
-
contextCache.expiresAt
|
|
115
|
+
typeof child.unref === "function"
|
|
410
116
|
) {
|
|
411
|
-
|
|
412
|
-
contextCache.value
|
|
413
|
-
)
|
|
117
|
+
child.unref()
|
|
414
118
|
}
|
|
119
|
+
} catch {
|
|
120
|
+
// Memory capture must never break OpenCode.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
415
123
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
"context:print",
|
|
422
|
-
"--project",
|
|
423
|
-
projectRoot,
|
|
424
|
-
"--tokens",
|
|
425
|
-
String(
|
|
426
|
-
CONTEXT_MAX_TOKENS
|
|
427
|
-
),
|
|
428
|
-
],
|
|
429
|
-
{
|
|
430
|
-
stdin:
|
|
431
|
-
"ignore",
|
|
432
|
-
stdout:
|
|
433
|
-
"pipe",
|
|
434
|
-
stderr:
|
|
435
|
-
"ignore",
|
|
436
|
-
}
|
|
437
|
-
)
|
|
438
|
-
|
|
439
|
-
const textPromise =
|
|
440
|
-
new Response(
|
|
441
|
-
child.stdout
|
|
442
|
-
).text()
|
|
443
|
-
|
|
444
|
-
const exitCode =
|
|
445
|
-
await child.exited
|
|
446
|
-
|
|
447
|
-
if (
|
|
448
|
-
exitCode !== 0
|
|
449
|
-
) {
|
|
450
|
-
return ""
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const text =
|
|
454
|
-
(
|
|
455
|
-
await textPromise
|
|
456
|
-
).trim()
|
|
457
|
-
|
|
458
|
-
contextCache = {
|
|
459
|
-
value: text,
|
|
460
|
-
expiresAt:
|
|
461
|
-
now +
|
|
462
|
-
CONTEXT_CACHE_MS,
|
|
463
|
-
}
|
|
124
|
+
/*
|
|
125
|
+
* Pull the latest project brief from ToolNet remote storage
|
|
126
|
+
* before the new OpenCode session starts doing work.
|
|
127
|
+
*/
|
|
128
|
+
await refreshContext()
|
|
464
129
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
}
|
|
130
|
+
return {
|
|
131
|
+
event: async ({ event }) => {
|
|
132
|
+
const sessionId =
|
|
133
|
+
getSessionId(event)
|
|
470
134
|
|
|
471
|
-
async function syncNow(
|
|
472
|
-
sessionId,
|
|
473
|
-
flag,
|
|
474
|
-
reason
|
|
475
|
-
) {
|
|
476
135
|
if (!sessionId) {
|
|
477
136
|
return
|
|
478
137
|
}
|
|
479
138
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
sessionId,
|
|
484
|
-
"--project",
|
|
485
|
-
projectRoot,
|
|
486
|
-
]
|
|
487
|
-
|
|
488
|
-
if (flag) {
|
|
489
|
-
args.push(
|
|
490
|
-
flag
|
|
491
|
-
)
|
|
139
|
+
if (event.type === "session.idle") {
|
|
140
|
+
sync(sessionId, "--idle")
|
|
141
|
+
return
|
|
492
142
|
}
|
|
493
143
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
)
|
|
498
|
-
|
|
499
|
-
writeStatus({
|
|
500
|
-
active: true,
|
|
501
|
-
projectRoot,
|
|
502
|
-
sessionId,
|
|
503
|
-
reason,
|
|
504
|
-
state:
|
|
505
|
-
"sync-success",
|
|
506
|
-
})
|
|
507
|
-
} catch (error) {
|
|
508
|
-
writeStatus({
|
|
509
|
-
active: true,
|
|
510
|
-
projectRoot,
|
|
511
|
-
sessionId,
|
|
512
|
-
reason,
|
|
513
|
-
state:
|
|
514
|
-
"sync-failed",
|
|
515
|
-
error:
|
|
516
|
-
error instanceof
|
|
517
|
-
Error
|
|
518
|
-
? error.message
|
|
519
|
-
: String(
|
|
520
|
-
error
|
|
521
|
-
),
|
|
522
|
-
})
|
|
523
|
-
|
|
524
|
-
throw error
|
|
144
|
+
if (event.type === "session.compacted") {
|
|
145
|
+
sync(sessionId, "--compacted")
|
|
146
|
+
return
|
|
525
147
|
}
|
|
526
|
-
}
|
|
527
148
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
flag,
|
|
531
|
-
reason
|
|
532
|
-
) {
|
|
533
|
-
if (!sessionId) {
|
|
534
|
-
return syncChain
|
|
149
|
+
if (event.type === "session.error") {
|
|
150
|
+
sync(sessionId, "--error")
|
|
535
151
|
}
|
|
536
|
-
|
|
537
|
-
lastSessionId =
|
|
538
|
-
sessionId
|
|
539
|
-
|
|
540
|
-
syncChain =
|
|
541
|
-
syncChain
|
|
542
|
-
.catch(
|
|
543
|
-
() =>
|
|
544
|
-
undefined
|
|
545
|
-
)
|
|
546
|
-
.then(
|
|
547
|
-
() =>
|
|
548
|
-
syncNow(
|
|
549
|
-
sessionId,
|
|
550
|
-
flag,
|
|
551
|
-
reason
|
|
552
|
-
)
|
|
553
|
-
)
|
|
554
|
-
|
|
555
|
-
return syncChain
|
|
556
|
-
}
|
|
152
|
+
},
|
|
557
153
|
|
|
558
154
|
/*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
* This is intentionally independent
|
|
562
|
-
* from session.idle/dispose because
|
|
563
|
-
* abrupt SSH/process termination may
|
|
564
|
-
* skip shutdown hooks.
|
|
565
|
-
*
|
|
566
|
-
* unref() prevents the timer itself
|
|
567
|
-
* from keeping OpenCode alive.
|
|
155
|
+
* Official OpenCode compaction hook.
|
|
156
|
+
* Preserve ToolNet's semantic state after context compaction.
|
|
568
157
|
*/
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
()
|
|
572
|
-
if (
|
|
573
|
-
lastSessionId
|
|
574
|
-
) {
|
|
575
|
-
void queueSync(
|
|
576
|
-
lastSessionId,
|
|
577
|
-
null,
|
|
578
|
-
"periodic"
|
|
579
|
-
)
|
|
580
|
-
}
|
|
581
|
-
},
|
|
582
|
-
PERIODIC_SYNC_MS
|
|
583
|
-
)
|
|
584
|
-
|
|
585
|
-
if (
|
|
586
|
-
typeof periodic.unref ===
|
|
587
|
-
"function"
|
|
588
|
-
) {
|
|
589
|
-
periodic.unref()
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
return {
|
|
593
|
-
event: async ({
|
|
594
|
-
event,
|
|
595
|
-
}) => {
|
|
596
|
-
const sessionId =
|
|
597
|
-
getSessionId(
|
|
598
|
-
event
|
|
599
|
-
)
|
|
600
|
-
|
|
601
|
-
if (sessionId) {
|
|
602
|
-
lastSessionId =
|
|
603
|
-
sessionId
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
if (
|
|
607
|
-
event.type ===
|
|
608
|
-
"session.idle"
|
|
609
|
-
) {
|
|
610
|
-
await queueSync(
|
|
611
|
-
sessionId,
|
|
612
|
-
"--idle",
|
|
613
|
-
"session.idle"
|
|
614
|
-
)
|
|
615
|
-
|
|
616
|
-
return
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
if (
|
|
620
|
-
event.type ===
|
|
621
|
-
"session.compacted"
|
|
622
|
-
) {
|
|
623
|
-
await queueSync(
|
|
624
|
-
sessionId,
|
|
625
|
-
"--compacted",
|
|
626
|
-
"session.compacted"
|
|
627
|
-
)
|
|
628
|
-
|
|
629
|
-
contextCache = {
|
|
630
|
-
value: "",
|
|
631
|
-
expiresAt: 0,
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
return
|
|
635
|
-
}
|
|
158
|
+
"experimental.session.compacting": async (_input, output) => {
|
|
159
|
+
const context =
|
|
160
|
+
await readContext()
|
|
636
161
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
await queueSync(
|
|
642
|
-
sessionId,
|
|
643
|
-
"--error",
|
|
644
|
-
"session.error"
|
|
645
|
-
)
|
|
646
|
-
|
|
647
|
-
return
|
|
648
|
-
}
|
|
649
|
-
},
|
|
650
|
-
|
|
651
|
-
/*
|
|
652
|
-
* VERIFIED on OpenCode 1.18.14:
|
|
653
|
-
* this hook fires on real model turns.
|
|
654
|
-
*
|
|
655
|
-
* It remains experimental, therefore
|
|
656
|
-
* AGENTS.md + MCP stay as fallbacks.
|
|
657
|
-
*/
|
|
658
|
-
"experimental.chat.system.transform":
|
|
659
|
-
async (
|
|
660
|
-
_input,
|
|
661
|
-
output
|
|
662
|
-
) => {
|
|
663
|
-
const context =
|
|
664
|
-
await readContext()
|
|
665
|
-
|
|
666
|
-
if (!context) {
|
|
667
|
-
return
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
if (
|
|
671
|
-
Array.isArray(
|
|
672
|
-
output?.system
|
|
673
|
-
)
|
|
674
|
-
) {
|
|
675
|
-
output.system.push(
|
|
676
|
-
context
|
|
677
|
-
)
|
|
678
|
-
|
|
679
|
-
return
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
if (
|
|
683
|
-
typeof output?.system ===
|
|
684
|
-
"string"
|
|
685
|
-
) {
|
|
686
|
-
output.system =
|
|
687
|
-
output.system
|
|
688
|
-
? \`\${output.system}\\n\\n\${context}\`
|
|
689
|
-
: context
|
|
690
|
-
}
|
|
691
|
-
},
|
|
692
|
-
|
|
693
|
-
/*
|
|
694
|
-
* Optional compaction survival hook.
|
|
695
|
-
* We keep it as a supplementary path,
|
|
696
|
-
* never as the only continuity path.
|
|
697
|
-
*/
|
|
698
|
-
"experimental.session.compacting":
|
|
699
|
-
async (
|
|
700
|
-
_input,
|
|
701
|
-
output
|
|
702
|
-
) => {
|
|
703
|
-
const context =
|
|
704
|
-
await readContext()
|
|
705
|
-
|
|
706
|
-
if (
|
|
707
|
-
context &&
|
|
708
|
-
Array.isArray(
|
|
709
|
-
output?.context
|
|
710
|
-
)
|
|
711
|
-
) {
|
|
712
|
-
output.context.push(
|
|
713
|
-
context
|
|
714
|
-
)
|
|
715
|
-
}
|
|
716
|
-
},
|
|
717
|
-
|
|
718
|
-
/*
|
|
719
|
-
* VERIFIED for clean OpenCode exits.
|
|
720
|
-
* Best effort only: kill -9 / crash /
|
|
721
|
-
* machine loss cannot guarantee this.
|
|
722
|
-
*/
|
|
723
|
-
dispose: async () => {
|
|
724
|
-
clearInterval(
|
|
725
|
-
periodic
|
|
162
|
+
if (
|
|
163
|
+
context &&
|
|
164
|
+
Array.isArray(
|
|
165
|
+
output.context
|
|
726
166
|
)
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
)
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
lastSessionId,
|
|
734
|
-
"--idle",
|
|
735
|
-
"dispose"
|
|
736
|
-
)
|
|
737
|
-
} catch {
|
|
738
|
-
// Status already recorded.
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
try {
|
|
743
|
-
await syncChain
|
|
744
|
-
} catch {
|
|
745
|
-
// Do not block OpenCode shutdown.
|
|
746
|
-
}
|
|
747
|
-
},
|
|
748
|
-
}
|
|
167
|
+
) {
|
|
168
|
+
output.context.push(
|
|
169
|
+
context
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
},
|
|
749
173
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
`),
|
|
753
|
-
`);
|
|
754
|
-
`,{encoding:"utf8",mode:384}),
|
|
755
|
-
`),
|
|
756
|
-
`)||(
|
|
757
|
-
`),
|
|
758
|
-
`,{encoding:"utf8",mode:384}),
|
|
759
|
-
|
|
760
|
-
`,{encoding:"utf8",mode:384}),vt(t,e)}finally{Gt(t,{force:!0})}}function uo(e={}){let o=e.stateFile??we(),t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.serverName??"toolnet-memory",r=_o(o),s=r.mcpServers;if(s!==void 0&&!K(s))throw new Error("Invalid existing Claude Code config: mcpServers must be an object.");let i=K(s)?{...s}:{},c=i[n];if(mo(c,t))return{installed:!0,changed:!1,configFile:o,serverName:n,command:[t,"mcp"],repaired:!1};let a=c!==void 0;i[n]={type:"stdio",command:t,args:["mcp"]},qt(o,{...r,mcpServers:i});let d=_o(o).mcpServers;if(!K(d)||!mo(d[n],t))throw new Error("Claude Code MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:o,serverName:n,command:[t,"mcp"],repaired:a}}function fo(e={}){let o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=Eo({binary:o,settingsFile:e.settingsFile}),n=uo({binary:o,stateFile:e.stateFile});return{hooks:t,mcp:n,files:[t.settingsFile,n.configFile]}}function Oo(){return Ue()}function de(e={}){let o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=[],n=Oo(),r=new Map(n.map(s=>[s.agent,s.detected]));if(!(e.force===!0||r.get("agy")===!0))t.push({agent:"agy",detected:!1,installed:!1,targets:[]});else try{let i=je({binary:o});t.push({agent:"agy",detected:!0,installed:!0,targets:i.files})}catch(i){t.push({agent:"agy",detected:!0,installed:!1,targets:[],error:i instanceof Error?i.message:String(i)})}if(!(e.force===!0||r.get("opencode")===!0))t.push({agent:"opencode",detected:!1,installed:!1,targets:[]});else try{let i=We({binary:o}),c=eo({binary:o});t.push({agent:"opencode",detected:!0,installed:!0,targets:[i,c.configFile,`mcp:${c.serverName}`]})}catch(i){t.push({agent:"opencode",detected:!0,installed:!1,targets:[],error:i instanceof Error?i.message:String(i)})}if(!(e.force===!0||r.get("claude")===!0))t.push({agent:"claude",detected:!1,installed:!1,targets:[]});else try{let i=fo({binary:o});t.push({agent:"claude",detected:!0,installed:!0,targets:[i.hooks.settingsFile,i.mcp.configFile,`mcp:${i.mcp.serverName}`]})}catch(i){t.push({agent:"claude",detected:!0,installed:!1,targets:[],error:i instanceof Error?i.message:String(i)})}if(!(e.force===!0||r.get("codex")===!0))t.push({agent:"codex",detected:!1,installed:!1,targets:[]});else try{let i=io({binary:o}),c=co({binary:o}),a=go({binary:o});if(!a.installed)throw new Error(a.error??"Codex MCP registration failed");let g=[i.configFile,c,`mcp:${a.serverName}`];i.preservedPrevious&&g.push(i.previousFile),t.push({agent:"codex",detected:!0,installed:!0,targets:g})}catch(i){t.push({agent:"codex",detected:!0,installed:!1,targets:[],error:i instanceof Error?i.message:String(i)})}return t}function Vt(e){console.log(""),console.log("ToolNet Memory Integration Detection"),console.log("===================================="),console.log("");for(let o of e){let t=o.agent==="agy"?"Agy / Antigravity":o.agent==="opencode"?"OpenCode":o.agent==="claude"?"Claude Code":"Codex";if(!o.detected){console.log(`\u25CB ${t}: not detected`);continue}console.log(`\u2713 ${t}: detected`);for(let n of o.evidence)console.log(` ${n}`)}console.log("")}function Jt(e){console.log(""),console.log("ToolNet Memory AI Integrations"),console.log("=============================="),console.log("");for(let o of e){let t=o.agent==="agy"?"Agy / Antigravity":o.agent==="opencode"?"OpenCode":"Codex";if(!o.detected){console.log(`- ${t}: not detected`);continue}if(o.installed){console.log(`\u2713 ${t}: automatic memory enabled`);continue}console.log(`\u2717 ${t}: integration failed`),o.error&&console.log(` ${o.error}`)}console.log("")}async function Wt(){let e=process.argv.slice(2),o=e.includes("--all"),t=e.includes("--json");if(e.includes("--detect-only")){let s=Oo();if(t){console.log(JSON.stringify(s,null,2));return}Vt(s);return}let r=de({force:o});if(t){console.log(JSON.stringify(r,null,2));return}Jt(r)}var Xt=process.argv[1]&&(process.argv[1].endsWith("auto-integrate.js")||process.argv[1].endsWith("auto-integrate.ts"));Xt&&Wt().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});var Ee=B.join(_e.homedir(),".config","toolnet-memory"),p=B.join(Ee,".env"),en=new Set(["MEMORY_STORAGE_PROVIDER","R2_ACCOUNT_ID","R2_BUCKET","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","S3_ENDPOINT","S3_REGION","S3_BUCKET","S3_ACCESS_KEY_ID","S3_SECRET_ACCESS_KEY","S3_FORCE_PATH_STYLE","HF_NAMESPACE","HF_BUCKET","HF_S3_ACCESS_KEY_ID","HF_S3_SECRET_ACCESS_KEY","HF_URL","HF_TOKEN","HF_EMBEDDING_MODEL","TOOLNET_LLM_PROVIDER","TOOLNET_LLM_API_KEY","TOOLNET_LLM_BASE_URL","TOOLNET_LLM_MODEL","TOOLNET_LLM_FALLBACK_1_PROVIDER","TOOLNET_LLM_FALLBACK_1_API_KEY","TOOLNET_LLM_FALLBACK_1_BASE_URL","TOOLNET_LLM_FALLBACK_1_MODEL","TOOLNET_LLM_FALLBACK_1_ACCOUNT_ID","TOOLNET_LLM_FALLBACK_2_PROVIDER","TOOLNET_LLM_FALLBACK_2_API_KEY","TOOLNET_LLM_FALLBACK_2_BASE_URL","TOOLNET_LLM_FALLBACK_2_MODEL","TOOLNET_LLM_FALLBACK_2_ACCOUNT_ID","TOOLNET_LLM_FALLBACK_COOLDOWN_MS","TOOLNET_LLM_MAX_RETRIES","TOOLNET_LLM_ACCOUNT_ID","TOOLNET_EMBEDDING_PROVIDER","TOOLNET_EMBEDDING_API_KEY","TOOLNET_EMBEDDING_BASE_URL","TOOLNET_EMBEDDING_MODEL","TOOLNET_EMBEDDING_ACCOUNT_ID","MEMORY_LOCAL_STORAGE_PATH","MEMORY_LOCAL_CACHE_MB","MEMORY_AUTO_CAPTURE","MEMORY_AUTO_RETRIEVE","MEMORY_AUTO_SUMMARIZE","MEMORY_AUTO_SYNC","MEMORY_MAX_CANDIDATES","MEMORY_RERANK_TOP","MEMORY_FINAL_CONTEXT","MEMORY_TOKEN_BUDGET","TOOLNET_SESSION_LEARNING","TOOLNET_WORK_CONTINUITY","TOOLNET_SEMANTIC_CONTINUITY","TOOLNET_SMART_HANDOFF"]);function on(e){let o=new Map;for(let t of e.split(/\r?\n/)){let n=t.trim();if(!n||n.startsWith("#"))continue;let r=n.indexOf("=");if(r===-1)continue;let s=n.slice(0,r).trim(),i=n.slice(r+1).trim();s&&o.set(s,i)}return o}function N(e){let o=e.get("MEMORY_STORAGE_PROVIDER")?.trim();return o==="r2"||o==="s3"||o==="local"||o==="huggingface"?o:e.get("R2_ACCOUNT_ID")&&e.get("R2_BUCKET")?"r2":e.get("S3_BUCKET")?"s3":e.get("HF_BUCKET")&&e.get("HF_S3_ACCESS_KEY_ID")?"huggingface":e.get("MEMORY_LOCAL_STORAGE_PATH")?"local":"r2"}function F(e){switch(e){case"r2":return"Cloudflare R2";case"s3":return"S3 / S3-compatible";case"huggingface":return"Hugging Face S3";case"local":return"Local";default:return e}}function Ao(e){switch(e){case"r2":return["R2_ACCOUNT_ID","R2_BUCKET","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY"];case"s3":return["S3_BUCKET","S3_ACCESS_KEY_ID","S3_SECRET_ACCESS_KEY"];case"huggingface":return["HF_BUCKET","HF_S3_ACCESS_KEY_ID","HF_S3_SECRET_ACCESS_KEY"];case"local":return[];default:return[]}}function yo(e){let o=N(e);return o==="local"?!0:Ao(o).every(t=>!!e.get(t)?.trim())}function me(e){return e?e.length<=8?"configured":`${e.slice(0,4)}\u2022\u2022\u2022\u2022${e.slice(-3)}`:"not configured"}function tn(e){let t=["# ==========================================================","# TOOLNET MEMORY","# Generated by: toolnet-memory setup","# Do not commit this file.","# ==========================================================","",`MEMORY_STORAGE_PROVIDER=${N(e)}`,"","# ----------------------------------------------------------","# Cloudflare R2","# ----------------------------------------------------------",`R2_ACCOUNT_ID=${e.get("R2_ACCOUNT_ID")??""}`,`R2_BUCKET=${e.get("R2_BUCKET")??"toolnet-memory"}`,`R2_ACCESS_KEY_ID=${e.get("R2_ACCESS_KEY_ID")??""}`,`R2_SECRET_ACCESS_KEY=${e.get("R2_SECRET_ACCESS_KEY")??""}`,"","# ----------------------------------------------------------","# Generic S3 / S3-compatible","# ----------------------------------------------------------",`S3_ENDPOINT=${e.get("S3_ENDPOINT")??""}`,`S3_REGION=${e.get("S3_REGION")??"us-east-1"}`,`S3_BUCKET=${e.get("S3_BUCKET")??"toolnet-memory"}`,`S3_ACCESS_KEY_ID=${e.get("S3_ACCESS_KEY_ID")??""}`,`S3_SECRET_ACCESS_KEY=${e.get("S3_SECRET_ACCESS_KEY")??""}`,`S3_FORCE_PATH_STYLE=${e.get("S3_FORCE_PATH_STYLE")??"false"}`,"","# ----------------------------------------------------------","# Hugging Face S3","# ----------------------------------------------------------",`HF_NAMESPACE=${e.get("HF_NAMESPACE")??""}`,`HF_BUCKET=${e.get("HF_BUCKET")??"toolnet-memory"}`,`HF_S3_ACCESS_KEY_ID=${e.get("HF_S3_ACCESS_KEY_ID")??""}`,`HF_S3_SECRET_ACCESS_KEY=${e.get("HF_S3_SECRET_ACCESS_KEY")??""}`,`HF_URL=${e.get("HF_URL")??""}`,"","# ----------------------------------------------------------","# AI / LLM - canonical ToolNet configuration","# ----------------------------------------------------------",`TOOLNET_LLM_PROVIDER=${e.get("TOOLNET_LLM_PROVIDER")??""}`,`TOOLNET_LLM_API_KEY=${e.get("TOOLNET_LLM_API_KEY")??""}`,`TOOLNET_LLM_BASE_URL=${e.get("TOOLNET_LLM_BASE_URL")??""}`,`TOOLNET_LLM_MODEL=${e.get("TOOLNET_LLM_MODEL")??""}`,`TOOLNET_LLM_ACCOUNT_ID=${e.get("TOOLNET_LLM_ACCOUNT_ID")??""}`,"","# ----------------------------------------------------------","# LLM fallback chain","# ----------------------------------------------------------",`TOOLNET_LLM_FALLBACK_1_PROVIDER=${e.get("TOOLNET_LLM_FALLBACK_1_PROVIDER")??""}`,`TOOLNET_LLM_FALLBACK_1_API_KEY=${e.get("TOOLNET_LLM_FALLBACK_1_API_KEY")??""}`,`TOOLNET_LLM_FALLBACK_1_BASE_URL=${e.get("TOOLNET_LLM_FALLBACK_1_BASE_URL")??""}`,`TOOLNET_LLM_FALLBACK_1_MODEL=${e.get("TOOLNET_LLM_FALLBACK_1_MODEL")??""}`,`TOOLNET_LLM_FALLBACK_1_ACCOUNT_ID=${e.get("TOOLNET_LLM_FALLBACK_1_ACCOUNT_ID")??""}`,`TOOLNET_LLM_FALLBACK_2_PROVIDER=${e.get("TOOLNET_LLM_FALLBACK_2_PROVIDER")??""}`,`TOOLNET_LLM_FALLBACK_2_API_KEY=${e.get("TOOLNET_LLM_FALLBACK_2_API_KEY")??""}`,`TOOLNET_LLM_FALLBACK_2_BASE_URL=${e.get("TOOLNET_LLM_FALLBACK_2_BASE_URL")??""}`,`TOOLNET_LLM_FALLBACK_2_MODEL=${e.get("TOOLNET_LLM_FALLBACK_2_MODEL")??""}`,`TOOLNET_LLM_FALLBACK_2_ACCOUNT_ID=${e.get("TOOLNET_LLM_FALLBACK_2_ACCOUNT_ID")??""}`,`TOOLNET_LLM_FALLBACK_COOLDOWN_MS=${e.get("TOOLNET_LLM_FALLBACK_COOLDOWN_MS")??"60000"}`,`TOOLNET_LLM_MAX_RETRIES=${e.get("TOOLNET_LLM_MAX_RETRIES")??"1"}`,"","# ----------------------------------------------------------","# Embedding - canonical ToolNet configuration","# ----------------------------------------------------------",`TOOLNET_EMBEDDING_PROVIDER=${e.get("TOOLNET_EMBEDDING_PROVIDER")??""}`,`TOOLNET_EMBEDDING_API_KEY=${e.get("TOOLNET_EMBEDDING_API_KEY")??""}`,`TOOLNET_EMBEDDING_BASE_URL=${e.get("TOOLNET_EMBEDDING_BASE_URL")??""}`,`TOOLNET_EMBEDDING_MODEL=${e.get("TOOLNET_EMBEDDING_MODEL")??""}`,`TOOLNET_EMBEDDING_ACCOUNT_ID=${e.get("TOOLNET_EMBEDDING_ACCOUNT_ID")??""}`,"","# ----------------------------------------------------------","# Embedding - legacy/current compatibility","# ----------------------------------------------------------",`HF_TOKEN=${e.get("HF_TOKEN")??""}`,`HF_EMBEDDING_MODEL=${e.get("HF_EMBEDDING_MODEL")??"sentence-transformers/all-MiniLM-L6-v2"}`,"","# ----------------------------------------------------------","# Local storage/cache","# ----------------------------------------------------------",`MEMORY_LOCAL_STORAGE_PATH=${e.get("MEMORY_LOCAL_STORAGE_PATH")??""}`,`MEMORY_LOCAL_CACHE_MB=${e.get("MEMORY_LOCAL_CACHE_MB")??"200"}`,"","# ----------------------------------------------------------","# Automation","# ----------------------------------------------------------",`MEMORY_AUTO_CAPTURE=${e.get("MEMORY_AUTO_CAPTURE")??"true"}`,`MEMORY_AUTO_RETRIEVE=${e.get("MEMORY_AUTO_RETRIEVE")??"true"}`,`MEMORY_AUTO_SUMMARIZE=${e.get("MEMORY_AUTO_SUMMARIZE")??"true"}`,`MEMORY_AUTO_SYNC=${e.get("MEMORY_AUTO_SYNC")??"true"}`,"","# ----------------------------------------------------------","# Retrieval","# ----------------------------------------------------------",`MEMORY_MAX_CANDIDATES=${e.get("MEMORY_MAX_CANDIDATES")??"50"}`,`MEMORY_RERANK_TOP=${e.get("MEMORY_RERANK_TOP")??"10"}`,`MEMORY_FINAL_CONTEXT=${e.get("MEMORY_FINAL_CONTEXT")??"5"}`,`MEMORY_TOKEN_BUDGET=${e.get("MEMORY_TOKEN_BUDGET")??"2000"}`,"","# ----------------------------------------------------------","# Automatic Session Memory","# ----------------------------------------------------------",`TOOLNET_SESSION_LEARNING=${e.get("TOOLNET_SESSION_LEARNING")??"1"}`,`TOOLNET_WORK_CONTINUITY=${e.get("TOOLNET_WORK_CONTINUITY")??"1"}`,`TOOLNET_SEMANTIC_CONTINUITY=${e.get("TOOLNET_SEMANTIC_CONTINUITY")??"1"}`,`TOOLNET_SMART_HANDOFF=${e.get("TOOLNET_SMART_HANDOFF")??"1"}`],n=[...e.entries()].filter(([r])=>!en.has(r));if(n.length>0){t.push("","# ----------------------------------------------------------","# Preserved settings","# ----------------------------------------------------------");for(let[r,s]of n)t.push(`${r}=${s}`)}return`${t.join(`
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
`,{encoding:"utf8",mode:384}),A.unlinkSync(t),{ok:!0,message:`Writable: ${o}`}}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}}async function an(e,o){switch(e){case"r2":return nn(o);case"s3":return rn(o);case"huggingface":return sn(o);case"local":return cn(o)}}async function ln(e,o){console.log(""),console.log(`Testing ${F(e)}...`);let t=await an(e,o);return t.ok?console.log(`\u2713 ${t.message}`):(console.log("\u2717 Connection test failed"),console.log(` ${t.message}`)),console.log(""),t}function gn(){console.log(""),console.log("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.log("\u2551 TOOLNET MEMORY SETUP \u2551"),console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),console.log("")}function dn(e){let o=N(e);console.log("Current configuration"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(`Storage : ${F(o)} ${yo(e)?"\u2713":"\u26A0 incomplete"}`);let t=e.get("TOOLNET_LLM_PROVIDER"),n=e.get("TOOLNET_LLM_MODEL"),r=e.get("TOOLNET_EMBEDDING_PROVIDER");console.log(`LLM : ${t?`${y(t)}${n?` / ${n}`:""}`:"not configured"}`),console.log(`Embedding: ${r||"legacy/default"}`),console.log("")}async function En(e){console.log("Setup"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" 1. Storage"),console.log(" 2. AI Model"),console.log(" 3. Finish & Save"),console.log(" 0. Exit without saving"),console.log("");let o=(await e.question("Choose [1-3]: ")).trim();return o==="1"?"storage":o==="2"?"ai":o==="0"?"exit":"finish"}async function _n(e,o){console.log(""),console.log("Storage"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(` 1. Cloudflare R2${o==="r2"?" \u2713 current":""}`),console.log(` 2. S3 / S3-compatible${o==="s3"?" \u2713 current":""}`),console.log(` 3. Hugging Face S3${o==="huggingface"?" \u2713 current":""}`),console.log(` 4. Local${o==="local"?" \u2713 current":""}`),console.log(""),console.log(" 0. Back"),console.log("");let t=(await e.question("Choose storage: ")).trim();return t==="0"?"back":t==="2"?"s3":t==="3"?"huggingface":t==="4"?"local":"r2"}async function mn(e,o){console.log(""),console.log("Cloudflare R2"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let t=await e.question(o.get("R2_ACCOUNT_ID")?`ACCOUNT ID [${o.get("R2_ACCOUNT_ID")}]: `:"ACCOUNT ID: "),n=await e.question(o.get("R2_ACCESS_KEY_ID")?`ACCESS KEY ID [${me(o.get("R2_ACCESS_KEY_ID"))}]: `:"ACCESS KEY ID: "),r=await e.question(`BUCKET [${o.get("R2_BUCKET")||"toolnet-memory"}]: `);L(o,"R2_ACCOUNT_ID",t),L(o,"R2_ACCESS_KEY_ID",n),L(o,"R2_BUCKET",r,"toolnet-memory");let s=o.get("R2_ACCOUNT_ID")?.trim();s&&console.log(`URL: ${Mo(s)}`);let i=await b(e,o.get("R2_SECRET_ACCESS_KEY")?"SECRET ACCESS KEY [configured, Enter = keep]: ":"SECRET ACCESS KEY: ");i.trim()&&o.set("R2_SECRET_ACCESS_KEY",i.trim())}async function un(e,o){console.log(""),console.log("S3 / S3-compatible"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let t=await e.question(o.get("S3_ENDPOINT")?`URL / ENDPOINT [${o.get("S3_ENDPOINT")}]: `:"URL / ENDPOINT [blank = AWS S3]: "),n=await e.question(`REGION [${o.get("S3_REGION")||"us-east-1"}]: `),r=await e.question(o.get("S3_ACCESS_KEY_ID")?`ACCESS KEY ID [${me(o.get("S3_ACCESS_KEY_ID"))}]: `:"ACCESS KEY ID: "),s=await e.question(`BUCKET [${o.get("S3_BUCKET")||"toolnet-memory"}]: `),i=o.get("S3_FORCE_PATH_STYLE")==="true",c=await e.question(`FORCE PATH STYLE [${i?"Y":"N"}] (y/n): `);if(t.trim()&&o.set("S3_ENDPOINT",C(t)),L(o,"S3_REGION",n,"us-east-1"),L(o,"S3_ACCESS_KEY_ID",r),L(o,"S3_BUCKET",s,"toolnet-memory"),c.trim()){let g=c.trim().toLowerCase();o.set("S3_FORCE_PATH_STYLE",g==="y"||g==="yes"?"true":"false")}else o.has("S3_FORCE_PATH_STYLE")||o.set("S3_FORCE_PATH_STYLE","false");let a=await b(e,o.get("S3_SECRET_ACCESS_KEY")?"SECRET ACCESS KEY [configured, Enter = keep]: ":"SECRET ACCESS KEY: ");a.trim()&&o.set("S3_SECRET_ACCESS_KEY",a.trim())}async function fn(e,o){console.log(""),console.log("Hugging Face S3"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let t=await e.question(o.get("HF_NAMESPACE")?`NAMESPACE [${o.get("HF_NAMESPACE")}]: `:"NAMESPACE [optional]: "),n=await e.question(o.get("HF_S3_ACCESS_KEY_ID")?`ACCESS KEY ID [${me(o.get("HF_S3_ACCESS_KEY_ID"))}]: `:"ACCESS KEY ID: "),r=await e.question(`BUCKET [${o.get("HF_BUCKET")||"toolnet-memory"}]: `),s=await e.question(o.get("HF_URL")?`URL [${o.get("HF_URL")}]: `:"URL / S3 ENDPOINT: ");L(o,"HF_NAMESPACE",t),L(o,"HF_S3_ACCESS_KEY_ID",n),L(o,"HF_BUCKET",r,"toolnet-memory"),s.trim()&&o.set("HF_URL",C(s));let i=await b(e,o.get("HF_S3_SECRET_ACCESS_KEY")?"SECRET ACCESS KEY [configured, Enter = keep]: ":"SECRET ACCESS KEY: ");i.trim()&&o.set("HF_S3_SECRET_ACCESS_KEY",i.trim())}async function On(e,o){console.log(""),console.log("Local Storage"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let t=o.get("MEMORY_LOCAL_STORAGE_PATH")??B.join(_e.homedir(),".local","share","toolnet-memory"),n=await e.question(`LOCAL PATH [${t}]: `);L(o,"MEMORY_LOCAL_STORAGE_PATH",n,t)}async function pn(e,o){let t=new Map(o);for(;;){let n=await _n(e,N(o));if(n==="back")return;let r=new Map(o);o.set("MEMORY_STORAGE_PROVIDER",n),n==="r2"?await mn(e,o):n==="s3"?await un(e,o):n==="huggingface"?await fn(e,o):await On(e,o);let s=Ao(n).filter(a=>!o.get(a)?.trim());if(s.length){console.log(""),console.log("\u26A0 Missing required fields:");for(let g of s)console.log(` - ${g}`);console.log(""),console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let a=(await e.question("Choose [1]: ")).trim()||"1";if(a==="2"){O(o),console.log(""),console.log("\u26A0 Saved with incomplete configuration"),console.log("");return}if(a==="3"){o.clear();for(let[g,d]of r)o.set(g,d);continue}if(a==="4"){o.clear();for(let[g,d]of t)o.set(g,d);console.log(""),console.log("Storage changes cancelled."),console.log("");return}continue}if((await ln(n,o)).ok){O(o),console.log(`\u2713 ${F(n)} configuration saved`),console.log(` ${p}`),console.log("");return}console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let c=(await e.question("Choose [1]: ")).trim()||"1";if(c==="2"){O(o),console.log(""),console.log("\u26A0 Saved even though connection test failed"),console.log("");return}if(c==="3"){o.clear();for(let[a,g]of r)o.set(a,g);continue}if(c==="4"){o.clear();for(let[a,g]of t)o.set(a,g);console.log(""),console.log("Storage changes cancelled."),console.log("");return}}}var I=[{id:"openai-compatible",label:"OpenAI-compatible",apiKeyRequired:!0,baseUrlRequired:!0},{id:"alibaba",label:"Alibaba / DashScope",baseUrl:"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",suggestedModel:"qwen3.6-flash",apiKeyRequired:!0},{id:"openrouter",label:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",apiKeyRequired:!0},{id:"groq",label:"Groq",baseUrl:"https://api.groq.com/openai/v1",apiKeyRequired:!0},{id:"deepseek",label:"DeepSeek",baseUrl:"https://api.deepseek.com",suggestedModel:"deepseek-v4-flash",apiKeyRequired:!0},{id:"nvidia",label:"NVIDIA NIM",baseUrl:"https://integrate.api.nvidia.com/v1",suggestedModel:"deepseek-ai/deepseek-v4-pro",apiKeyRequired:!0},{id:"gemini",label:"Gemini",baseUrl:"https://generativelanguage.googleapis.com/v1beta",suggestedModel:"gemini-3.6-flash",apiKeyRequired:!0},{id:"huggingface",label:"Hugging Face",baseUrl:"https://router.huggingface.co/v1",apiKeyRequired:!0},{id:"ollama",label:"Ollama / Local",baseUrl:"http://127.0.0.1:11434/v1",apiKeyRequired:!1},{id:"custom",label:"Custom endpoint",apiKeyRequired:!1,baseUrlRequired:!0},{id:"cloudflare",label:"Cloudflare Workers AI",suggestedModel:"@cf/meta/llama-3.1-8b-instruct",apiKeyRequired:!0,accountIdRequired:!0}];function Ln(e){return I.find(o=>o.id===e)}function y(e){return Ln(e)?.label??e??"not configured"}function Io(e){let o=e.get("TOOLNET_LLM_PROVIDER")?.trim();return I.some(t=>t.id===o)?o:void 0}async function fe(e,o){console.log(""),console.log("AI Model"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),I.forEach((r,s)=>{console.log(` ${s+1}. ${r.label}${o===r.id?" \u2713 current":""}`)}),console.log(""),console.log(" 0. Back"),console.log("");let t=(await e.question("Choose provider: ")).trim();if(t==="0")return"back";let n=Number(t)-1;return Number.isInteger(n)&&n>=0&&n<I.length?I[n].id:(console.log(""),console.log("\u26A0 Invalid provider selection"),fe(e,o))}function Tn(e,o){return!(!e.get("TOOLNET_LLM_MODEL")?.trim()||o.apiKeyRequired&&!e.get("TOOLNET_LLM_API_KEY")?.trim()||o.accountIdRequired&&!e.get("TOOLNET_LLM_ACCOUNT_ID")?.trim()||o.baseUrlRequired&&!e.get("TOOLNET_LLM_BASE_URL")?.trim())}function An(e){e.delete("TOOLNET_LLM_API_KEY"),e.delete("TOOLNET_LLM_BASE_URL"),e.delete("TOOLNET_LLM_MODEL"),e.delete("TOOLNET_LLM_ACCOUNT_ID")}async function yn(e,o,t){console.log(""),console.log(t.label),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let n=o.get("TOOLNET_LLM_PROVIDER");if(n&&n!==t.id&&An(o),o.set("TOOLNET_LLM_PROVIDER",t.id),t.accountIdRequired){let a=o.get("TOOLNET_LLM_ACCOUNT_ID"),g=await e.question(a?`ACCOUNT ID [${a}]: `:"ACCOUNT ID: ");L(o,"TOOLNET_LLM_ACCOUNT_ID",g)}else o.delete("TOOLNET_LLM_ACCOUNT_ID");if(t.apiKeyRequired||t.id==="custom"){let a=o.get("TOOLNET_LLM_API_KEY"),g=await b(e,a?"API KEY [configured, Enter = keep]: ":t.apiKeyRequired?"API KEY: ":"API KEY [optional]: ");g.trim()&&o.set("TOOLNET_LLM_API_KEY",g.trim())}else o.delete("TOOLNET_LLM_API_KEY");if(t.id!=="cloudflare"){let g=o.get("TOOLNET_LLM_BASE_URL")||t.baseUrl||"",f=(await e.question(g?`BASE URL [${g}]: `:t.baseUrlRequired?"BASE URL: ":"BASE URL [optional]: ")).trim()||g;f?o.set("TOOLNET_LLM_BASE_URL",C(f)):o.delete("TOOLNET_LLM_BASE_URL")}else o.delete("TOOLNET_LLM_BASE_URL");let s=o.get("TOOLNET_LLM_MODEL")||t.suggestedModel||"",c=(await e.question(s?`MODEL [${s}]: `:"MODEL: ")).trim()||s;c&&o.set("TOOLNET_LLM_MODEL",c)}function Mn(e){let o=Io(e);if(!o)throw new Error("AI provider is not configured");return{id:o,apiKey:e.get("TOOLNET_LLM_API_KEY")?.trim()||void 0,baseUrl:e.get("TOOLNET_LLM_BASE_URL")?.trim()||void 0,model:e.get("TOOLNET_LLM_MODEL")?.trim()||void 0,accountId:e.get("TOOLNET_LLM_ACCOUNT_ID")?.trim()||void 0}}async function In(e){let o=Mn(e);console.log(""),console.log(`Testing ${y(o.id)}...`);try{let n=await Me(o).healthCheck();return n.ok?(console.log(`\u2713 Provider reachable${n.latencyMs?` (${n.latencyMs} ms)`:""}`),console.log(`\u2713 Model: ${n.model??o.model??"configured"}`),console.log(""),{ok:!0,message:n.message}):(console.log("\u2717 AI provider test failed"),console.log(` ${n.message}`),console.log(""),{ok:!1,message:n.message})}catch(t){let n=t instanceof Error?t.message:String(t);return console.log("\u2717 AI provider test failed"),console.log(` ${n}`),console.log(""),{ok:!1,message:n}}}var z=[{id:"local",label:"Local / Hash",apiKeyRequired:!1},{id:"huggingface",label:"Hugging Face",suggestedModel:"sentence-transformers/all-MiniLM-L6-v2",apiKeyRequired:!0},{id:"openai-compatible",label:"OpenAI-compatible",apiKeyRequired:!0,baseUrlRequired:!0},{id:"alibaba",label:"Alibaba / DashScope",baseUrl:"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",suggestedModel:"text-embedding-v4",apiKeyRequired:!0},{id:"openrouter",label:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",apiKeyRequired:!0},{id:"nvidia",label:"NVIDIA NIM",baseUrl:"https://integrate.api.nvidia.com/v1",apiKeyRequired:!0},{id:"ollama",label:"Ollama / Local",baseUrl:"http://127.0.0.1:11434/v1",apiKeyRequired:!1},{id:"gemini",label:"Gemini",baseUrl:"https://generativelanguage.googleapis.com/v1beta",suggestedModel:"gemini-embedding-001",apiKeyRequired:!0},{id:"cloudflare",label:"Cloudflare Workers AI",suggestedModel:"@cf/baai/bge-base-en-v1.5",apiKeyRequired:!0,accountIdRequired:!0},{id:"custom",label:"Custom OpenAI-compatible endpoint",apiKeyRequired:!1,baseUrlRequired:!0}];function Oe(e){return z.find(o=>o.id===e)?.label??e??"not configured"}async function No(e,o){console.log(""),console.log("Embedding Model"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),z.forEach((r,s)=>{console.log(` ${s+1}. ${r.label}${o===r.id?" \u2713 current":""}`)}),console.log(""),console.log(" 0. Back"),console.log("");let t=(await e.question("Choose embedding provider: ")).trim();if(t==="0")return"back";let n=Number(t)-1;return Number.isInteger(n)&&n>=0&&n<z.length?z[n]:(console.log(""),console.log("\u26A0 Invalid selection"),No(e,o))}function po(e){e.delete("TOOLNET_EMBEDDING_API_KEY"),e.delete("TOOLNET_EMBEDDING_BASE_URL"),e.delete("TOOLNET_EMBEDDING_MODEL"),e.delete("TOOLNET_EMBEDDING_ACCOUNT_ID")}async function Nn(e,o,t){let n=o.get("TOOLNET_EMBEDDING_PROVIDER");if(n&&n!==t.id&&po(o),o.set("TOOLNET_EMBEDDING_PROVIDER",t.id),console.log(""),console.log(t.label),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),t.id==="local"){po(o),console.log("\u2713 Local embedding selected"),console.log(" No API key required.");return}if(t.accountIdRequired){let a=o.get("TOOLNET_EMBEDDING_ACCOUNT_ID"),g=await e.question(a?`ACCOUNT ID [${a}]: `:"ACCOUNT ID: ");L(o,"TOOLNET_EMBEDDING_ACCOUNT_ID",g)}else o.delete("TOOLNET_EMBEDDING_ACCOUNT_ID");if(t.apiKeyRequired||t.id==="custom"){let a=o.get("TOOLNET_EMBEDDING_API_KEY"),g=await b(e,a?"API KEY [configured, Enter = keep]: ":t.apiKeyRequired?"API KEY: ":"API KEY [optional]: ");g.trim()&&o.set("TOOLNET_EMBEDDING_API_KEY",g.trim())}else o.delete("TOOLNET_EMBEDDING_API_KEY");if(t.id==="cloudflare"){let a=o.get("TOOLNET_EMBEDDING_ACCOUNT_ID")?.trim();if(a){let g=`https://api.cloudflare.com/client/v4/accounts/${a}/ai/v1`;o.set("TOOLNET_EMBEDDING_BASE_URL",g),console.log(`BASE URL: ${g}`)}}else{let g=o.get("TOOLNET_EMBEDDING_BASE_URL")||t.baseUrl||"",f=(await e.question(g?`BASE URL [${g}]: `:t.baseUrlRequired?"BASE URL: ":"BASE URL [optional]: ")).trim()||g;f&&o.set("TOOLNET_EMBEDDING_BASE_URL",C(f))}let s=o.get("TOOLNET_EMBEDDING_MODEL")||t.suggestedModel||"",c=(await e.question(s?`MODEL [${s}]: `:"MODEL: ")).trim()||s;c&&o.set("TOOLNET_EMBEDDING_MODEL",c)}function Cn(e,o){return o.id==="local"?!0:o.apiKeyRequired&&!e.get("TOOLNET_EMBEDDING_API_KEY")?.trim()||o.accountIdRequired&&!e.get("TOOLNET_EMBEDDING_ACCOUNT_ID")?.trim()||o.baseUrlRequired&&!e.get("TOOLNET_EMBEDDING_BASE_URL")?.trim()?!1:!!e.get("TOOLNET_EMBEDDING_MODEL")?.trim()}async function Co(e){let o=e.get("TOOLNET_EMBEDDING_PROVIDER")?.trim();if(console.log(""),console.log(`Testing embedding: ${Oe(o)}...`),o==="local")return console.log("\u2713 Local embedding ready"),console.log(""),!0;let t=e.get("TOOLNET_EMBEDDING_API_KEY")?.trim(),n=e.get("TOOLNET_EMBEDDING_MODEL")?.trim(),r=e.get("TOOLNET_EMBEDDING_BASE_URL")?.trim();try{if(!n)throw new Error("Embedding model is missing");if(o==="huggingface"){if(!t)throw new Error("API key is missing");let s=await fetch(`https://router.huggingface.co/hf-inference/models/${n}/pipeline/feature-extraction`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({inputs:["toolnet memory test"]})});if(!s.ok)throw new Error(`HTTP ${s.status}: ${await s.text()}`)}else if(o==="gemini"){if(!t)throw new Error("API key is missing");let s=n.replace(/^models\//,"");r=r||"https://generativelanguage.googleapis.com/v1beta";let i=await fetch(`${r.replace(/\/+$/,"")}/models/${encodeURIComponent(s)}:embedContent?key=${encodeURIComponent(t)}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({model:`models/${s}`,content:{parts:[{text:"toolnet memory test"}]}})});if(!i.ok)throw new Error(`HTTP ${i.status}: ${await i.text()}`)}else{if(!r)throw new Error("BASE URL is missing");let s=await fetch(`${r.replace(/\/+$/,"")}/embeddings`,{method:"POST",headers:{"content-type":"application/json",...t?{authorization:`Bearer ${t}`}:{}},body:JSON.stringify({model:n,input:["toolnet memory test"]})});if(!s.ok)throw new Error(`HTTP ${s.status}: ${await s.text()}`);let i=await s.json();if(!Array.isArray(i.data)||!Array.isArray(i.data[0]?.embedding))throw new Error("Invalid embedding response")}return console.log("\u2713 Embedding provider reachable"),console.log(`\u2713 Model: ${n}`),console.log(""),!0}catch(s){return console.log("\u2717 Embedding test failed"),console.log(` ${s instanceof Error?s.message:String(s)}`),console.log(""),!1}}async function Sn(e,o){let t=new Map(o);for(;;){let n=await No(e,o.get("TOOLNET_EMBEDDING_PROVIDER"));if(n==="back")return;if(await Nn(e,o,n),!Cn(o,n)){console.log(""),console.log("\u26A0 Embedding configuration is incomplete."),console.log(""),console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let i=(await e.question("Choose [1]: ")).trim()||"1";if(i==="2"){O(o);return}if(i==="3")continue;if(i==="4"){o.clear();for(let[c,a]of t)o.set(c,a);return}continue}if(await Co(o)){O(o),console.log(`\u2713 ${n.label} embedding configuration saved`),console.log(` ${p}`),console.log("");return}console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let s=(await e.question("Choose [1]: ")).trim()||"1";if(s==="2"){O(o);return}if(s!=="3"&&s==="4"){o.clear();for(let[i,c]of t)o.set(i,c);return}}}async function Rn(e,o){let t=o.get("TOOLNET_LLM_PROVIDER")?.trim();if(!t){console.log(""),console.log("\u26A0 Configure LLM first."),console.log("");return}if(t==="deepseek"||t==="groq"){console.log(""),console.log(`\u26A0 ${y(t)} is configured as LLM-only.`),console.log("Choose Embedding separately."),console.log("");return}o.set("TOOLNET_EMBEDDING_PROVIDER",t);let n=o.get("TOOLNET_LLM_API_KEY"),r=o.get("TOOLNET_LLM_BASE_URL"),s=o.get("TOOLNET_LLM_ACCOUNT_ID");n&&o.set("TOOLNET_EMBEDDING_API_KEY",n),r&&o.set("TOOLNET_EMBEDDING_BASE_URL",r),s&&o.set("TOOLNET_EMBEDDING_ACCOUNT_ID",s);let i="";t==="alibaba"?i="text-embedding-v4":t==="gemini"?i="gemini-embedding-001":t==="cloudflare"?i="@cf/baai/bge-base-en-v1.5":t==="huggingface"&&(i="sentence-transformers/all-MiniLM-L6-v2");let a=(await e.question(i?`EMBEDDING MODEL [${i}]: `:"EMBEDDING MODEL: ")).trim()||i;if(!a){console.log(""),console.log("\u26A0 Embedding model is required."),console.log("");return}if(o.set("TOOLNET_EMBEDDING_MODEL",a),!await Co(o)){let d=(await e.question("Save anyway? (y/N): ")).trim().toLowerCase();if(d!=="y"&&d!=="yes")return}O(o),console.log(""),console.log("\u2713 LLM credentials reused for Embedding"),console.log(`\u2713 Embedding model: ${a}`),console.log("")}function Q(e){return`TOOLNET_LLM_FALLBACK_${e}`}function Z(e,o){let t=Q(o);for(let n of["PROVIDER","API_KEY","BASE_URL","MODEL","ACCOUNT_ID"])e.delete(`${t}_${n}`)}function Lo(e,o){let t=Q(o),n=e.get(`${t}_PROVIDER`);if(!n)return"not configured";let r=e.get(`${t}_MODEL`);return`${y(n)}${r?` / ${r}`:""}`}async function To(e,o,t){console.log(""),console.log(`Fallback ${t}`),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let n=await fe(e,void 0);if(n==="back")return;let r=o.get("TOOLNET_LLM_PROVIDER");if(n===r){console.log(""),console.log("\u26A0 Fallback cannot be the same provider as Primary."),console.log("");return}let s=t===1?2:1,i=o.get(`${Q(s)}_PROVIDER`);if(n===i){console.log(""),console.log("\u26A0 This provider is already used by the other fallback."),console.log("");return}let c=I.find(_=>_.id===n);if(!c)return;let a=Q(t);if(Z(o,t),o.set(`${a}_PROVIDER`,n),c.accountIdRequired){let _=await e.question("ACCOUNT ID: ");_.trim()&&o.set(`${a}_ACCOUNT_ID`,_.trim())}if(c.apiKeyRequired||n==="custom"){let _=await b(e,c.apiKeyRequired?"API KEY: ":"API KEY [optional]: ");_.trim()&&o.set(`${a}_API_KEY`,_.trim())}if(n==="cloudflare"){let _=o.get(`${a}_ACCOUNT_ID`);_&&o.set(`${a}_BASE_URL`,`https://api.cloudflare.com/client/v4/accounts/${_}/ai`)}else{let _=c.baseUrl??"",pe=(await e.question(_?`BASE URL [${_}]: `:c.baseUrlRequired?"BASE URL: ":"BASE URL [optional]: ")).trim()||_;pe&&o.set(`${a}_BASE_URL`,C(pe))}let g=c.suggestedModel??"",f=(await e.question(g?`MODEL [${g}]: `:"MODEL: ")).trim()||g;if(!f){console.log(""),console.log("\u26A0 MODEL is required."),console.log(""),Z(o,t);return}o.set(`${a}_MODEL`,f),O(o),console.log(""),console.log(`\u2713 Fallback ${t} saved`),console.log(` ${y(n)} / ${f}`),console.log("")}async function hn(e,o){let t=o.get("TOOLNET_LLM_FALLBACK_COOLDOWN_MS")||"60000",n=o.get("TOOLNET_LLM_MAX_RETRIES")||"1";console.log(""),console.log("Fallback Policy"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let r=await e.question(`COOLDOWN MS [${t}]: `);if(r.trim()){let i=Number(r.trim());Number.isFinite(i)&&i>=0?o.set("TOOLNET_LLM_FALLBACK_COOLDOWN_MS",String(Math.floor(i))):console.log("\u26A0 Invalid cooldown; keeping previous value.")}let s=await e.question(`MAX RETRIES [${n}]: `);if(s.trim()){let i=Number(s.trim());Number.isFinite(i)&&i>=0&&i<=5?o.set("TOOLNET_LLM_MAX_RETRIES",String(Math.floor(i))):console.log("\u26A0 MAX RETRIES must be between 0 and 5.")}O(o),console.log(""),console.log("\u2713 Fallback policy saved"),console.log("")}async function Dn(e,o){for(;;){console.log(""),console.log("LLM Fallback"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(` Primary : ${o.get("TOOLNET_LLM_PROVIDER")?`${y(o.get("TOOLNET_LLM_PROVIDER"))} / ${o.get("TOOLNET_LLM_MODEL")||"model not configured"}`:"not configured"}`),console.log(` Fallback 1 : ${Lo(o,1)}`),console.log(` Fallback 2 : ${Lo(o,2)}`),console.log(` Cooldown : ${o.get("TOOLNET_LLM_FALLBACK_COOLDOWN_MS")||"60000"} ms`),console.log(` Retries : ${o.get("TOOLNET_LLM_MAX_RETRIES")||"1"}`),console.log(""),console.log(" 1. Configure Fallback 1"),console.log(" 2. Configure Fallback 2"),console.log(" 3. Remove Fallback 1"),console.log(" 4. Remove Fallback 2"),console.log(" 5. Retry / cooldown settings"),console.log(" 0. Back"),console.log("");let t=(await e.question("Choose: ")).trim();if(t==="0")return;if(t==="1"){await To(e,o,1);continue}if(t==="2"){await To(e,o,2);continue}if(t==="3"){Z(o,1),O(o),console.log(""),console.log("\u2713 Fallback 1 removed"),console.log("");continue}if(t==="4"){Z(o,2),O(o),console.log(""),console.log("\u2713 Fallback 2 removed"),console.log("");continue}if(t==="5"){await hn(e,o);continue}console.log(""),console.log("\u26A0 Invalid selection")}}async function bn(e,o){for(;;){console.log(""),console.log("AI Model"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let t=o.get("TOOLNET_LLM_PROVIDER"),n=o.get("TOOLNET_EMBEDDING_PROVIDER");console.log(` LLM : ${t?`${y(t)} / ${o.get("TOOLNET_LLM_MODEL")||"model not configured"}`:"not configured"}`),console.log(` Embedding : ${n?`${Oe(n)} / ${o.get("TOOLNET_EMBEDDING_MODEL")||(n==="local"?"local hash":"model not configured")}`:"legacy/default"}`),console.log(""),console.log(" 1. Configure LLM"),console.log(" 2. Configure Embedding"),console.log(" 3. Use LLM provider credentials for Embedding"),console.log(" 4. Configure LLM Fallbacks"),console.log(" 0. Back"),console.log("");let r=(await e.question("Choose: ")).trim();if(r==="0")return;if(r==="1"){await Pn(e,o);continue}if(r==="2"){await Sn(e,o);continue}if(r==="3"){await Rn(e,o);continue}if(r==="4"){await Dn(e,o);continue}console.log(""),console.log("\u26A0 Invalid selection")}}async function Pn(e,o){let t=new Map(o);for(;;){let n=await fe(e,Io(o));if(n==="back")return;let r=I.find(c=>c.id===n);if(!r)continue;if(await yn(e,o,r),!Tn(o,r)){console.log(""),console.log("\u26A0 AI configuration is incomplete."),console.log(""),console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let c=(await e.question("Choose [1]: ")).trim()||"1";if(c==="2"){O(o),console.log(""),console.log("\u26A0 AI configuration saved without validation"),console.log(` ${p}`),console.log("");return}if(c==="3")continue;if(c==="4"){o.clear();for(let[a,g]of t)o.set(a,g);console.log(""),console.log("AI changes cancelled."),console.log("");return}continue}if((await In(o)).ok){O(o),console.log(`\u2713 ${r.label} configuration saved`),console.log(` ${p}`),console.log("");return}console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let i=(await e.question("Choose [1]: ")).trim()||"1";if(i==="2"){O(o),console.log(""),console.log("\u26A0 AI configuration saved even though provider test failed"),console.log(` ${p}`),console.log("");return}if(i!=="3"&&i==="4"){o.clear();for(let[c,a]of t)o.set(c,a);console.log(""),console.log("AI changes cancelled."),console.log("");return}}}function wn(){try{let o=de().filter(t=>t.installed);if(o.length===0)return;console.log(""),console.log("Automatic AI memory");for(let t of o){let n=t.agent==="agy"?"Agy / Antigravity":t.agent==="opencode"?"OpenCode":t.agent==="codex"?"Codex":t.agent;console.log(` \u2713 ${n}`)}}catch{}}function E(e,...o){for(let t of o){let n=e.get(t)?.trim();if(n)return n}}function m(e,o,t){t&&!e.get(o)?.trim()&&e.set(o,t)}function Un(e){let o=!1,t=JSON.stringify([...e.entries()]);if(!e.get("TOOLNET_LLM_PROVIDER")?.trim()){let s;E(e,"GROQ_API_KEY")?s="groq":E(e,"DEEPSEEK_API_KEY")?s="deepseek":E(e,"NVIDIA_API_KEY","NVIDIA_NIM_API_KEY")?s="nvidia":E(e,"OPENROUTER_API_KEY")?s="openrouter":E(e,"ALIBABA_API_KEY","DASHSCOPE_API_KEY")?s="alibaba":E(e,"GEMINI_API_KEY","GOOGLE_API_KEY")?s="gemini":E(e,"CLOUDFLARE_API_TOKEN")&&E(e,"CLOUDFLARE_ACCOUNT_ID")?s="cloudflare":E(e,"HF_TOKEN")?s="huggingface":E(e,"OLLAMA_MODEL","OLLAMA_BASE_URL")?s="ollama":E(e,"OPENAI_API_KEY","MODEL_API_KEY")&&(s="openai-compatible"),s&&e.set("TOOLNET_LLM_PROVIDER",s)}switch(e.get("TOOLNET_LLM_PROVIDER")?.trim()){case"groq":m(e,"TOOLNET_LLM_API_KEY",E(e,"GROQ_API_KEY")),m(e,"TOOLNET_LLM_BASE_URL",E(e,"GROQ_BASE_URL")||"https://api.groq.com/openai/v1"),m(e,"TOOLNET_LLM_MODEL",E(e,"GROQ_MODEL"));break;case"deepseek":m(e,"TOOLNET_LLM_API_KEY",E(e,"DEEPSEEK_API_KEY")),m(e,"TOOLNET_LLM_BASE_URL",E(e,"DEEPSEEK_BASE_URL")||"https://api.deepseek.com"),m(e,"TOOLNET_LLM_MODEL",E(e,"DEEPSEEK_MODEL")||"deepseek-v4-flash");break;case"nvidia":m(e,"TOOLNET_LLM_API_KEY",E(e,"NVIDIA_API_KEY","NVIDIA_NIM_API_KEY")),m(e,"TOOLNET_LLM_BASE_URL",E(e,"NVIDIA_BASE_URL","NVIDIA_NIM_BASE_URL")||"https://integrate.api.nvidia.com/v1"),m(e,"TOOLNET_LLM_MODEL",E(e,"NVIDIA_MODEL","NVIDIA_NIM_MODEL"));break;case"openrouter":m(e,"TOOLNET_LLM_API_KEY",E(e,"OPENROUTER_API_KEY")),m(e,"TOOLNET_LLM_BASE_URL",E(e,"OPENROUTER_BASE_URL")||"https://openrouter.ai/api/v1"),m(e,"TOOLNET_LLM_MODEL",E(e,"OPENROUTER_MODEL"));break;case"alibaba":m(e,"TOOLNET_LLM_API_KEY",E(e,"ALIBABA_API_KEY","DASHSCOPE_API_KEY")),m(e,"TOOLNET_LLM_BASE_URL",E(e,"ALIBABA_BASE_URL","DASHSCOPE_BASE_URL")),m(e,"TOOLNET_LLM_MODEL",E(e,"ALIBABA_MODEL","DASHSCOPE_MODEL"));break;case"gemini":m(e,"TOOLNET_LLM_API_KEY",E(e,"GEMINI_API_KEY","GOOGLE_API_KEY")),m(e,"TOOLNET_LLM_BASE_URL",E(e,"GEMINI_BASE_URL")||"https://generativelanguage.googleapis.com/v1beta"),m(e,"TOOLNET_LLM_MODEL",E(e,"GEMINI_MODEL"));break;case"huggingface":m(e,"TOOLNET_LLM_API_KEY",E(e,"HF_TOKEN")),m(e,"TOOLNET_LLM_BASE_URL",E(e,"HF_INFERENCE_BASE_URL")||"https://router.huggingface.co/v1"),m(e,"TOOLNET_LLM_MODEL",E(e,"HF_LLM_MODEL","HF_MODEL"));break;case"ollama":m(e,"TOOLNET_LLM_API_KEY",E(e,"OLLAMA_API_KEY")),m(e,"TOOLNET_LLM_BASE_URL",E(e,"OLLAMA_BASE_URL")||"http://127.0.0.1:11434/v1"),m(e,"TOOLNET_LLM_MODEL",E(e,"OLLAMA_MODEL"));break;case"cloudflare":m(e,"TOOLNET_LLM_API_KEY",E(e,"CLOUDFLARE_API_TOKEN")),m(e,"TOOLNET_LLM_ACCOUNT_ID",E(e,"CLOUDFLARE_ACCOUNT_ID")),m(e,"TOOLNET_LLM_MODEL",E(e,"CLOUDFLARE_MODEL"));break;case"openai-compatible":m(e,"TOOLNET_LLM_API_KEY",E(e,"OPENAI_API_KEY","MODEL_API_KEY")),m(e,"TOOLNET_LLM_BASE_URL",E(e,"OPENAI_BASE_URL","MODEL_BASE_URL")),m(e,"TOOLNET_LLM_MODEL",E(e,"OPENAI_MODEL","MODEL_NAME"));break}!e.get("TOOLNET_EMBEDDING_PROVIDER")?.trim()&&E(e,"HF_TOKEN")&&(e.set("TOOLNET_EMBEDDING_PROVIDER","huggingface"),m(e,"TOOLNET_EMBEDDING_API_KEY",E(e,"HF_TOKEN")),m(e,"TOOLNET_EMBEDDING_MODEL",E(e,"HF_EMBEDDING_MODEL")||"sentence-transformers/all-MiniLM-L6-v2"));let r=JSON.stringify([...e.entries()]);return o=t!==r,o}function X(e,o="not configured"){return e?.trim()||o}function Kn(e){let o=F(N(e)),t=e.get("TOOLNET_LLM_PROVIDER"),n=e.get("TOOLNET_LLM_MODEL"),r=e.get("TOOLNET_EMBEDDING_PROVIDER"),s=e.get("TOOLNET_EMBEDDING_MODEL"),i=e.get("TOOLNET_LLM_FALLBACK_1_PROVIDER"),c=e.get("TOOLNET_LLM_FALLBACK_2_PROVIDER");console.log(""),console.log("TOOLNET MEMORY READY"),console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),console.log(`Storage : ${o}`),console.log(`LLM : ${t?`${y(t)} / ${X(n)}`:"not configured"}`),console.log(`Fallback 1 : ${i?`${y(i)} / ${X(e.get("TOOLNET_LLM_FALLBACK_1_MODEL"))}`:"none"}`),console.log(`Fallback 2 : ${c?`${y(c)} / ${X(e.get("TOOLNET_LLM_FALLBACK_2_MODEL"))}`:"none"}`),console.log(`Embedding : ${r?`${r==="local"?"Local / Hash":Oe(r)} / ${X(s,r==="local"?"local hash":"not configured")}`:"legacy/default"}`),console.log(""),console.log(`Config : ${p}`),console.log(`Permissions: ${A.statSync(p).mode.toString(8).slice(-3)}`),console.log(""),console.log("Secrets : hidden"),console.log("Config mode: canonical TOOLNET_*"),console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550")}function So(e){Un(e),e.has("TOOLNET_LLM_FALLBACK_COOLDOWN_MS")||e.set("TOOLNET_LLM_FALLBACK_COOLDOWN_MS","60000"),e.has("TOOLNET_LLM_MAX_RETRIES")||e.set("TOOLNET_LLM_MAX_RETRIES","1"),e.has("MEMORY_STORAGE_PROVIDER")||e.set("MEMORY_STORAGE_PROVIDER",N(e)),e.has("MEMORY_LOCAL_CACHE_MB")||e.set("MEMORY_LOCAL_CACHE_MB","200"),e.has("MEMORY_AUTO_CAPTURE")||e.set("MEMORY_AUTO_CAPTURE","true"),e.has("MEMORY_AUTO_RETRIEVE")||e.set("MEMORY_AUTO_RETRIEVE","true"),e.has("MEMORY_AUTO_SUMMARIZE")||e.set("MEMORY_AUTO_SUMMARIZE","true"),e.has("MEMORY_AUTO_SYNC")||e.set("MEMORY_AUTO_SYNC","true"),e.has("MEMORY_MAX_CANDIDATES")||e.set("MEMORY_MAX_CANDIDATES","50"),e.has("MEMORY_RERANK_TOP")||e.set("MEMORY_RERANK_TOP","10"),e.has("MEMORY_FINAL_CONTEXT")||e.set("MEMORY_FINAL_CONTEXT","5"),e.has("MEMORY_TOKEN_BUDGET")||e.set("MEMORY_TOKEN_BUDGET","2000"),e.has("TOOLNET_SESSION_LEARNING")||e.set("TOOLNET_SESSION_LEARNING","1"),e.has("TOOLNET_WORK_CONTINUITY")||e.set("TOOLNET_WORK_CONTINUITY","1"),e.has("TOOLNET_SEMANTIC_CONTINUITY")||e.set("TOOLNET_SEMANTIC_CONTINUITY","1"),e.has("TOOLNET_SMART_HANDOFF")||e.set("TOOLNET_SMART_HANDOFF","1")}async function kn(e,o){So(e),o||O(e),console.log("TOOLNET MEMORY SETUP"),console.log(""),console.log("Interactive terminal not detected."),console.log(`Config: ${p}`),console.log(`Storage: ${F(N(e))}`),console.log(""),console.log("Run from an interactive terminal to configure providers:"),console.log(" toolnet-memory setup")}async function Bn(){let e=A.existsSync(p),o=e?on(A.readFileSync(p,"utf8")):new Map,t=new Map(o);if(So(t),!T.isTTY||!k.isTTY){await kn(t,e);return}let n=zt.createInterface({input:T,output:k}),r=!1;try{for(;;){gn(),dn(t);let s=await En(n);if(s==="storage"){let i=JSON.stringify([...t.entries()]);await pn(n,t),r=r||i!==JSON.stringify([...t.entries()]);continue}if(s==="ai"){let i=JSON.stringify([...t.entries()]);await bn(n,t),r=r||i!==JSON.stringify([...t.entries()]);continue}if(s==="exit"){if(!r){console.log(""),console.log("No changes made.");return}console.log("");let i=(await n.question("Discard unsaved changes? (y/N): ")).trim().toLowerCase();if(i==="y"||i==="yes"){console.log(""),console.log("Changes discarded.");return}continue}O(t),yo(t)||(console.log(""),console.log("\u26A0 Storage configuration is incomplete.")),wn(),Kn(t),console.log(""),console.log("Validate:"),console.log(" toolnet-memory provider:status"),console.log(" toolnet-memory provider:test"),console.log(" toolnet-memory doctor"),console.log("");return}}finally{n.close()}}Bn().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exit(1)});
|
|
174
|
+
}
|
|
175
|
+
`;return D(o,n,{encoding:"utf8",mode:384}),o}import{existsSync as ie,mkdirSync as k,readFileSync as se,writeFileSync as b}from"node:fs";import{homedir as H}from"node:os";import{dirname as P,join as T}from"node:path";function ce(e){let t=[],o=/"((?:\\.|[^"\\])*)"|'([^']*)'/g,r;for(;r=o.exec(e);){let n=r[1]??r[2]??"";try{t.push(r[1]!==void 0?JSON.parse(`"${n}"`):n)}catch{t.push(n)}}return t}function L(e={}){let t=e.configFile??T(process.env.CODEX_HOME??T(H(),".codex"),"config.toml"),o=e.previousFile??T(H(),".config","toolnet-memory","codex-notify-previous.json");k(P(t),{recursive:!0}),k(P(o),{recursive:!0});let r=ie(t)?se(t,"utf8"):"",n=e.binary??"toolnet-memory",s=`notify = [${JSON.stringify(n)}, "session:codex-notify"]`,i=r.split(`
|
|
176
|
+
`),a=i.findIndex(l=>/^\s*\[/.test(l));a<0&&(a=i.length);let f=-1,c=-1;for(let l=0;l<a;l+=1)if(/^\s*notify\s*=/.test(i[l])){if(f=l,c=l,i[l].includes("[")&&!i[l].includes("]"))for(;c+1<a&&(c+=1,!i[c].includes("]")););break}let g=[];if(f>=0){let l=i.slice(f,c+1).join(`
|
|
177
|
+
`);g=ce(l),i.splice(f,c-f+1,s)}else a=i.findIndex(l=>/^\s*\[/.test(l)),a<0&&(a=i.length),i.splice(a,0,s);let E=g.length>=2&&g[g.length-1]==="session:codex-notify";return g.length>0&&!E&&b(o,JSON.stringify(g,null,2)+`
|
|
178
|
+
`,{encoding:"utf8",mode:384}),r=i.join(`
|
|
179
|
+
`),r.endsWith(`
|
|
180
|
+
`)||(r+=`
|
|
181
|
+
`),b(t,r,{encoding:"utf8",mode:384}),{configFile:t,previousFile:o,preservedPrevious:g.length>0&&!E}}import{existsSync as ae,mkdirSync as le,readFileSync as ge,writeFileSync as de}from"node:fs";import{homedir as ue}from"node:os";import{dirname as fe,join as U}from"node:path";function Ee(e){return`'${e.replace(/'/g,"'\\''")}'`}function v(e={}){let t=e.hooksFile??U(process.env.CODEX_HOME??U(ue(),".codex"),"hooks.json");le(fe(t),{recursive:!0});let o={};if(ae(t))try{o=JSON.parse(ge(t,"utf8"))}catch(a){throw new Error(`Invalid existing Codex hooks.json: ${a instanceof Error?a.message:String(a)}`)}let r=o.hooks&&typeof o.hooks=="object"&&!Array.isArray(o.hooks)?o.hooks:{};o.hooks=r;let s=(Array.isArray(r.SessionStart)?r.SessionStart:[]).filter(a=>{try{return!JSON.stringify(a).includes("session:codex-context")}catch{return!0}}),i=e.binary??"toolnet-memory";return s.push({matcher:"startup|resume|clear|compact",hooks:[{type:"command",command:`${Ee(i)} session:codex-context`,timeout:15,additionalContextLimit:1e3,statusMessage:"Loading ToolNet project continuity"}]}),r.SessionStart=s,de(t,JSON.stringify(o,null,2)+`
|
|
182
|
+
`,{encoding:"utf8",mode:384}),t}function h(e){return me("sh",["-lc",`command -v ${JSON.stringify(e)} >/dev/null 2>&1`],{stdio:"ignore"}).status===0}function _e(){return h("agy")||A(N(R(),".gemini"))}function Se(){return h("opencode")||A(N(R(),".config","opencode"))}function pe(){return h("codex")||A(process.env.CODEX_HOME??N(R(),".codex"))}function I(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=[];if(!(e.force===!0||_e()))o.push({agent:"agy",detected:!1,installed:!1,targets:[]});else try{let n=Y({binary:t});o.push({agent:"agy",detected:!0,installed:!0,targets:[n]})}catch(n){o.push({agent:"agy",detected:!0,installed:!1,targets:[],error:n instanceof Error?n.message:String(n)})}if(!(e.force===!0||Se()))o.push({agent:"opencode",detected:!1,installed:!1,targets:[]});else try{let n=w({binary:t});o.push({agent:"opencode",detected:!0,installed:!0,targets:[n]})}catch(n){o.push({agent:"opencode",detected:!0,installed:!1,targets:[],error:n instanceof Error?n.message:String(n)})}if(!(e.force===!0||pe()))o.push({agent:"codex",detected:!1,installed:!1,targets:[]});else try{let n=L({binary:t}),s=v({binary:t}),i=[n.configFile,s];n.preservedPrevious&&i.push(n.previousFile),o.push({agent:"codex",detected:!0,installed:!0,targets:i})}catch(n){o.push({agent:"codex",detected:!0,installed:!1,targets:[],error:n instanceof Error?n.message:String(n)})}return o}function ye(e){console.log(""),console.log("ToolNet Memory AI Integrations"),console.log("=============================="),console.log("");for(let t of e){let o=t.agent==="agy"?"Agy / Antigravity":t.agent==="opencode"?"OpenCode":"Codex";if(!t.detected){console.log(`- ${o}: not detected`);continue}if(t.installed){console.log(`\u2713 ${o}: automatic memory enabled`);continue}console.log(`\u2717 ${o}: integration failed`),t.error&&console.log(` ${t.error}`)}console.log("")}async function Ce(){let e=process.argv.slice(2),t=e.includes("--all"),o=e.includes("--json"),r=I({force:t});if(o){console.log(JSON.stringify(r,null,2));return}ye(r)}var Oe=process.argv[1]&&(process.argv[1].endsWith("auto-integrate.js")||process.argv[1].endsWith("auto-integrate.ts"));Oe&&Ce().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});var x=q.join(Te.homedir(),".config","toolnet-memory"),_=q.join(x,".env");function Re(e){let t=new Map;for(let o of e.split(/\r?\n/)){let r=o.trim();if(!r||r.startsWith("#"))continue;let n=r.indexOf("=");n!==-1&&t.set(r.slice(0,n).trim(),r.slice(n+1).trim())}return t}function J(e){let t=e.get("MEMORY_STORAGE_PROVIDER")?.trim();return t==="r2"||t==="s3"||t==="local"||t==="huggingface"?t:e.get("R2_ACCOUNT_ID")&&e.get("R2_BUCKET")?"r2":e.get("S3_BUCKET")?"s3":e.get("HF_NAMESPACE")&&e.get("HF_BUCKET")?"huggingface":"r2"}function B(e){return e==="r2"?["R2_ACCOUNT_ID","R2_BUCKET","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY"]:e==="s3"?["S3_BUCKET","S3_ACCESS_KEY_ID","S3_SECRET_ACCESS_KEY"]:e==="huggingface"?["HF_NAMESPACE","HF_BUCKET","HF_S3_ACCESS_KEY_ID","HF_S3_SECRET_ACCESS_KEY"]:[]}function y(e){return e==="r2"?"Cloudflare R2":e==="s3"?"S3-compatible storage":e==="huggingface"?"Hugging Face S3 (legacy)":"Local storage"}function j(e){m.mkdirSync(x,{recursive:!0,mode:448});let o=`# ==========================================================
|
|
183
|
+
# TOOLNET MEMORY
|
|
184
|
+
# ==========================================================
|
|
185
|
+
|
|
186
|
+
MEMORY_STORAGE_PROVIDER=${J(e)}
|
|
187
|
+
|
|
188
|
+
# Cloudflare R2
|
|
189
|
+
R2_ACCOUNT_ID=${e.get("R2_ACCOUNT_ID")??""}
|
|
190
|
+
R2_BUCKET=${e.get("R2_BUCKET")??"toolnet-memory"}
|
|
191
|
+
R2_ACCESS_KEY_ID=${e.get("R2_ACCESS_KEY_ID")??""}
|
|
192
|
+
R2_SECRET_ACCESS_KEY=${e.get("R2_SECRET_ACCESS_KEY")??""}
|
|
193
|
+
|
|
194
|
+
# Generic S3 / S3-compatible storage
|
|
195
|
+
# Leave S3_ENDPOINT empty for AWS S3.
|
|
196
|
+
S3_ENDPOINT=${e.get("S3_ENDPOINT")??""}
|
|
197
|
+
S3_REGION=${e.get("S3_REGION")??"us-east-1"}
|
|
198
|
+
S3_BUCKET=${e.get("S3_BUCKET")??"toolnet-memory"}
|
|
199
|
+
S3_ACCESS_KEY_ID=${e.get("S3_ACCESS_KEY_ID")??""}
|
|
200
|
+
S3_SECRET_ACCESS_KEY=${e.get("S3_SECRET_ACCESS_KEY")??""}
|
|
201
|
+
S3_FORCE_PATH_STYLE=${e.get("S3_FORCE_PATH_STYLE")??"false"}
|
|
202
|
+
|
|
203
|
+
# Hugging Face S3 (legacy compatibility)
|
|
204
|
+
HF_NAMESPACE=${e.get("HF_NAMESPACE")??""}
|
|
205
|
+
HF_BUCKET=${e.get("HF_BUCKET")??"toolnet-memory"}
|
|
206
|
+
HF_S3_ACCESS_KEY_ID=${e.get("HF_S3_ACCESS_KEY_ID")??""}
|
|
207
|
+
HF_S3_SECRET_ACCESS_KEY=${e.get("HF_S3_SECRET_ACCESS_KEY")??""}
|
|
208
|
+
|
|
209
|
+
# Embedding
|
|
210
|
+
HF_TOKEN=${e.get("HF_TOKEN")??""}
|
|
211
|
+
HF_EMBEDDING_MODEL=${e.get("HF_EMBEDDING_MODEL")??"sentence-transformers/all-MiniLM-L6-v2"}
|
|
212
|
+
|
|
213
|
+
# Local cache
|
|
214
|
+
MEMORY_LOCAL_STORAGE_PATH=${e.get("MEMORY_LOCAL_STORAGE_PATH")??""}
|
|
215
|
+
MEMORY_LOCAL_CACHE_MB=${e.get("MEMORY_LOCAL_CACHE_MB")??"200"}
|
|
216
|
+
|
|
217
|
+
# Automation
|
|
218
|
+
MEMORY_AUTO_CAPTURE=${e.get("MEMORY_AUTO_CAPTURE")??"true"}
|
|
219
|
+
MEMORY_AUTO_RETRIEVE=${e.get("MEMORY_AUTO_RETRIEVE")??"true"}
|
|
220
|
+
MEMORY_AUTO_SUMMARIZE=${e.get("MEMORY_AUTO_SUMMARIZE")??"true"}
|
|
221
|
+
MEMORY_AUTO_SYNC=${e.get("MEMORY_AUTO_SYNC")??"true"}
|
|
222
|
+
|
|
223
|
+
# Retrieval
|
|
224
|
+
MEMORY_MAX_CANDIDATES=${e.get("MEMORY_MAX_CANDIDATES")??"50"}
|
|
225
|
+
MEMORY_RERANK_TOP=${e.get("MEMORY_RERANK_TOP")??"10"}
|
|
226
|
+
MEMORY_FINAL_CONTEXT=${e.get("MEMORY_FINAL_CONTEXT")??"5"}
|
|
227
|
+
MEMORY_TOKEN_BUDGET=${e.get("MEMORY_TOKEN_BUDGET")??"2000"}
|
|
228
|
+
|
|
229
|
+
# Automatic Session Memory
|
|
230
|
+
TOOLNET_SESSION_LEARNING=${e.get("TOOLNET_SESSION_LEARNING")??"1"}
|
|
231
|
+
TOOLNET_WORK_CONTINUITY=${e.get("TOOLNET_WORK_CONTINUITY")??"1"}
|
|
232
|
+
TOOLNET_SEMANTIC_CONTINUITY=${e.get("TOOLNET_SEMANTIC_CONTINUITY")??"1"}
|
|
233
|
+
TOOLNET_SMART_HANDOFF=${e.get("TOOLNET_SMART_HANDOFF")??"1"}
|
|
234
|
+
`;m.writeFileSync(_,o,{encoding:"utf8",mode:384}),m.chmodSync(x,448),m.chmodSync(_,384)}function G(e,t=!0){let o=e.trim().toLowerCase();return o?o==="y"||o==="yes":t}async function Ne(e){return d.isTTY?(S.write(e),new Promise(t=>{let o="",r=()=>{d.off("data",n),d.setRawMode?.(!1),d.pause(),S.write(`
|
|
235
|
+
`),t(o)},n=s=>{for(let i of s.toString("utf8")){if(i==="\r"||i===`
|
|
236
|
+
`){r();return}if(i===""&&(d.setRawMode?.(!1),S.write(`
|
|
237
|
+
`),process.exit(130)),i==="\x7F"){o=o.slice(0,-1);continue}o+=i}};d.resume(),d.setRawMode?.(!0),d.on("data",n)})):""}function M(){try{let t=I().filter(o=>o.installed);if(t.length>0){console.log(""),console.log("Automatic AI memory:");for(let o of t){let r=o.agent==="agy"?"Agy / Antigravity":o.agent==="opencode"?"OpenCode":"Codex";console.log(` \u2713 ${r}`)}}}catch{}}function u(e,t,o,r){o.trim()?e.set(t,o.trim()):!e.get(t)&&r!==void 0&&e.set(t,r)}async function he(e,t){console.log("Storage provider:"),console.log(" 1. Cloudflare R2 (recommended)"),console.log(" 2. S3 / S3-compatible"),console.log(" 3. Local"),console.log(" 4. Hugging Face S3 (legacy)"),console.log("");let o=t==="s3"?"2":t==="local"?"3":t==="huggingface"?"4":"1",n=(await e.question(`Choose [${o}]: `)).trim()||o;return n==="2"?"s3":n==="3"?"local":n==="4"?"huggingface":"r2"}async function Ie(){let e=m.existsSync(_),t=e?Re(m.readFileSync(_,"utf8")):new Map,o=J(t),r=B(o),n=r.every(c=>!!t.get(c)?.trim());if(console.log(""),console.log("TOOLNET MEMORY SETUP"),console.log("===================="),console.log(""),console.log(`Config: ${_}`),console.log(""),!d.isTTY||!S.isTTY){e||(t.set("MEMORY_STORAGE_PROVIDER",o),j(t)),n?console.log(`\u2713 ${y(o)} already configured`):(console.log("Configuration pending."),console.log("Run:"),console.log(" toolnet-memory setup")),M();return}let s=Ae.createInterface({input:d,output:S});if(n){console.log(`\u2713 ${y(o)} already configured`),console.log("");let c=await s.question("Use existing storage configuration? (Y/n) [Y]: ");if(G(c)){s.close(),console.log(""),console.log(`\u2713 Existing ${y(o)} configuration kept`),console.log(""),M(),console.log("Next:"),console.log(" toolnet-memory doctor");return}console.log("")}o=await he(s,o),t.set("MEMORY_STORAGE_PROVIDER",o),console.log("");let i="",a="";if(o==="r2"){let c=await s.question(t.get("R2_ACCOUNT_ID")?`Cloudflare Account ID [${t.get("R2_ACCOUNT_ID")}]: `:"Cloudflare Account ID: "),g=await s.question(`R2 Bucket [${t.get("R2_BUCKET")||"toolnet-memory"}]: `),E=await s.question(t.get("R2_ACCESS_KEY_ID")?"R2 Access Key ID [configured]: ":"R2 Access Key ID: ");u(t,"R2_ACCOUNT_ID",c),u(t,"R2_BUCKET",g,"toolnet-memory"),u(t,"R2_ACCESS_KEY_ID",E),i="R2_SECRET_ACCESS_KEY",a=t.get(i)?"R2 Secret Access Key [configured]: ":"R2 Secret Access Key: "}else if(o==="s3"){let c=await s.question(t.get("S3_ENDPOINT")?`S3 Endpoint [${t.get("S3_ENDPOINT")}]: `:"S3 Endpoint [blank = AWS S3]: "),g=await s.question(`S3 Region [${t.get("S3_REGION")||"us-east-1"}]: `),E=await s.question(`S3 Bucket [${t.get("S3_BUCKET")||"toolnet-memory"}]: `),l=await s.question(t.get("S3_ACCESS_KEY_ID")?"S3 Access Key ID [configured]: ":"S3 Access Key ID: "),F=await s.question(`Force path-style? (y/N) [${t.get("S3_FORCE_PATH_STYLE")==="true"?"Y":"N"}]: `);c.trim()&&t.set("S3_ENDPOINT",c.trim()),u(t,"S3_REGION",g,"us-east-1"),u(t,"S3_BUCKET",E,"toolnet-memory"),u(t,"S3_ACCESS_KEY_ID",l),F.trim()?t.set("S3_FORCE_PATH_STYLE",G(F,!1)?"true":"false"):t.get("S3_FORCE_PATH_STYLE")||t.set("S3_FORCE_PATH_STYLE","false"),i="S3_SECRET_ACCESS_KEY",a=t.get(i)?"S3 Secret Access Key [configured]: ":"S3 Secret Access Key: "}else if(o==="huggingface"){let c=await s.question(t.get("HF_NAMESPACE")?`Hugging Face namespace [${t.get("HF_NAMESPACE")}]: `:"Hugging Face namespace: "),g=await s.question(`Bucket [${t.get("HF_BUCKET")||"toolnet-memory"}]: `),E=await s.question(t.get("HF_S3_ACCESS_KEY_ID")?"S3 Access Key ID [configured]: ":"S3 Access Key ID: ");u(t,"HF_NAMESPACE",c),u(t,"HF_BUCKET",g,"toolnet-memory"),u(t,"HF_S3_ACCESS_KEY_ID",E),i="HF_S3_SECRET_ACCESS_KEY",a=t.get(i)?"S3 Secret Access Key [configured]: ":"S3 Secret Access Key: "}if(s.close(),i){let c=await Ne(a);c.trim()&&t.set(i,c.trim())}j(t),r=B(o);let f=r.filter(c=>!t.get(c)?.trim());if(console.log(""),console.log("\u2713 Configuration saved"),console.log(` ${_}`),console.log(""),f.length){console.log("Missing configuration:");for(let c of f)console.log(` - ${c}`);console.log(""),console.log("Run setup again:"),console.log(" toolnet-memory setup");return}console.log(`\u2713 ${y(o)} configuration complete`),console.log(""),M(),console.log("Next:"),console.log(" toolnet-memory doctor")}Ie().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exit(1)});
|