@tractorscorch/clank 1.1.0 → 1.2.0
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/CHANGELOG.md +11 -0
- package/README.md +3 -3
- package/dist/index.js +269 -53
- package/dist/index.js.map +1 -1
- package/package.json +58 -58
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [1.2.0] — 2026-03-22
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- **Two-tier context compaction** — critical for local model performance:
|
|
13
|
+
- Tier 1 (fast): system prompt budgeting, tool result dedup, message truncation, aggressive dropping
|
|
14
|
+
- Tier 2 (LLM-summarized): model generates conversation recap replacing oldest messages. Preserves meaning over long sessions.
|
|
15
|
+
- Token budgeting: reserves 25% for response, budgets system prompt separately from conversation
|
|
16
|
+
- **`clank update`** — update to latest npm version, preserves config/sessions/memory, restarts gateway
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
9
20
|
## [1.1.0] — 2026-03-22
|
|
10
21
|
|
|
11
22
|
### Security Hardening
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<p align="center">
|
|
12
12
|
<a href="https://github.com/ItsTrag1c/Clank/releases/latest"><img src="https://img.shields.io/badge/version-1.1.0-blue.svg" alt="Version" /></a>
|
|
13
13
|
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License" /></a>
|
|
14
|
-
<a href="https://www.npmjs.com/package/clank"><img src="https://img.shields.io/npm/v/clank.svg" alt="npm" /></a>
|
|
14
|
+
<a href="https://www.npmjs.com/package/@tractorscorch/clank"><img src="https://img.shields.io/npm/v/@tractorscorch/clank.svg" alt="npm" /></a>
|
|
15
15
|
<a href="https://github.com/ItsTrag1c/Clank/stargazers"><img src="https://img.shields.io/github/stars/ItsTrag1c/Clank.svg" alt="Stars" /></a>
|
|
16
16
|
</p>
|
|
17
17
|
|
|
@@ -53,7 +53,7 @@ Clank is a personal AI gateway — **one daemon, many frontends**. It connects y
|
|
|
53
53
|
## Quick Start
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
npm install -g clank
|
|
56
|
+
npm install -g @tractorscorch/clank
|
|
57
57
|
clank setup
|
|
58
58
|
clank
|
|
59
59
|
```
|
|
@@ -157,7 +157,7 @@ See [SECURITY.md](SECURITY.md) for the full security model.
|
|
|
157
157
|
|--|--|
|
|
158
158
|
| **Website** | [clanksuite.dev](https://clanksuite.dev) |
|
|
159
159
|
| **GitHub** | [ItsTrag1c/Clank](https://github.com/ItsTrag1c/Clank) |
|
|
160
|
-
| **npm** | [npmjs.com/package/clank](https://www.npmjs.com/package/clank) |
|
|
160
|
+
| **npm** | [npmjs.com/package/@tractorscorch/clank](https://www.npmjs.com/package/@tractorscorch/clank) |
|
|
161
161
|
| **Twitter/X** | [@ClankSuite](https://x.com/ClankSuite) |
|
|
162
162
|
| **Reddit** | [u/ClankSuite](https://reddit.com/u/ClankSuite) |
|
|
163
163
|
| **Legacy** | [Clank-Legacy](https://github.com/ItsTrag1c/Clank-Legacy) (archived CLI v2.7.0 + Desktop v2.6.1) |
|
package/dist/index.js
CHANGED
|
@@ -28,10 +28,25 @@ var init_context_engine = __esm({
|
|
|
28
28
|
messages = [];
|
|
29
29
|
contextWindowSize;
|
|
30
30
|
isLocal;
|
|
31
|
+
systemPromptTokens = 0;
|
|
32
|
+
/** Provider for tier 2 LLM-summarized compaction */
|
|
33
|
+
provider = null;
|
|
34
|
+
modelId = "";
|
|
35
|
+
/** Cache of tool results by file path to detect duplicates */
|
|
36
|
+
toolResultHashes = /* @__PURE__ */ new Map();
|
|
31
37
|
constructor(opts) {
|
|
32
38
|
this.contextWindowSize = opts.contextWindow;
|
|
33
39
|
this.isLocal = opts.isLocal;
|
|
34
40
|
}
|
|
41
|
+
/** Set the provider for tier 2 compaction */
|
|
42
|
+
setProvider(provider, modelId) {
|
|
43
|
+
this.provider = provider;
|
|
44
|
+
this.modelId = modelId;
|
|
45
|
+
}
|
|
46
|
+
/** Set the system prompt size for token budgeting */
|
|
47
|
+
setSystemPromptSize(tokens) {
|
|
48
|
+
this.systemPromptTokens = tokens;
|
|
49
|
+
}
|
|
35
50
|
/** Get all messages */
|
|
36
51
|
getMessages() {
|
|
37
52
|
return this.messages;
|
|
@@ -63,38 +78,99 @@ var init_context_engine = __esm({
|
|
|
63
78
|
}
|
|
64
79
|
return Math.ceil(chars / 4);
|
|
65
80
|
}
|
|
66
|
-
/**
|
|
67
|
-
|
|
68
|
-
|
|
81
|
+
/** Calculate token budgets */
|
|
82
|
+
getBudget() {
|
|
83
|
+
const responseReserve = Math.floor(this.contextWindowSize * 0.25);
|
|
84
|
+
const available = this.contextWindowSize - responseReserve;
|
|
85
|
+
const systemPrompt = Math.min(this.systemPromptTokens, Math.floor(available * 0.3));
|
|
86
|
+
const conversation = available - systemPrompt;
|
|
87
|
+
return { systemPrompt, conversation, responseReserve };
|
|
88
|
+
}
|
|
89
|
+
/** Get context utilization as a percentage of the conversation budget */
|
|
69
90
|
utilizationPercent() {
|
|
70
|
-
|
|
91
|
+
const budget = this.getBudget();
|
|
92
|
+
return this.estimateTokens() / budget.conversation * 100;
|
|
71
93
|
}
|
|
72
94
|
/**
|
|
73
95
|
* Check if compaction is needed.
|
|
74
96
|
* Local models trigger earlier (60%) to leave room for the response.
|
|
75
|
-
* Cloud models can wait longer (80%)
|
|
97
|
+
* Cloud models can wait longer (80%).
|
|
76
98
|
*/
|
|
77
99
|
needsCompaction() {
|
|
78
100
|
const threshold = this.isLocal ? 60 : 80;
|
|
79
101
|
return this.utilizationPercent() >= threshold;
|
|
80
102
|
}
|
|
81
103
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* This is the key local-model optimization. We aggressively
|
|
85
|
-
* reduce context while preserving the most important information:
|
|
86
|
-
* - Recent messages (protected zone)
|
|
87
|
-
* - System-level context
|
|
88
|
-
* - Key decision points
|
|
104
|
+
* Run compaction — tier 1 first, tier 2 if still over budget.
|
|
105
|
+
* Returns the result with which tier was used.
|
|
89
106
|
*/
|
|
107
|
+
async compactSmart() {
|
|
108
|
+
const before = this.messages.length;
|
|
109
|
+
const tokensBefore = this.estimateTokens();
|
|
110
|
+
this.compactTier1();
|
|
111
|
+
if (this.utilizationPercent() < 70) {
|
|
112
|
+
return {
|
|
113
|
+
ok: true,
|
|
114
|
+
tier: 1,
|
|
115
|
+
messagesBefore: before,
|
|
116
|
+
messagesAfter: this.messages.length,
|
|
117
|
+
estimatedTokensBefore: tokensBefore,
|
|
118
|
+
estimatedTokensAfter: this.estimateTokens()
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (this.provider) {
|
|
122
|
+
await this.compactTier2();
|
|
123
|
+
} else {
|
|
124
|
+
this.compactTier1Aggressive();
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
ok: true,
|
|
128
|
+
tier: this.provider ? 2 : 1,
|
|
129
|
+
messagesBefore: before,
|
|
130
|
+
messagesAfter: this.messages.length,
|
|
131
|
+
estimatedTokensBefore: tokensBefore,
|
|
132
|
+
estimatedTokensAfter: this.estimateTokens()
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/** Synchronous compact (backward compat — uses tier 1 only) */
|
|
90
136
|
compact() {
|
|
91
137
|
const before = this.messages.length;
|
|
92
138
|
const tokensBefore = this.estimateTokens();
|
|
139
|
+
this.compactTier1();
|
|
140
|
+
if (this.utilizationPercent() >= 70) {
|
|
141
|
+
this.compactTier1Aggressive();
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
ok: true,
|
|
145
|
+
tier: 1,
|
|
146
|
+
messagesBefore: before,
|
|
147
|
+
messagesAfter: this.messages.length,
|
|
148
|
+
estimatedTokensBefore: tokensBefore,
|
|
149
|
+
estimatedTokensAfter: this.estimateTokens()
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Tier 1: Fast mechanical compaction (no LLM calls).
|
|
154
|
+
*/
|
|
155
|
+
compactTier1() {
|
|
93
156
|
const protectedCount = 6;
|
|
157
|
+
if (this.messages.length <= protectedCount) return;
|
|
94
158
|
const protectedZone = this.messages.slice(-protectedCount);
|
|
95
159
|
const compactable = this.messages.slice(0, -protectedCount);
|
|
96
160
|
const compacted = [];
|
|
97
|
-
|
|
161
|
+
const seenToolResults = /* @__PURE__ */ new Map();
|
|
162
|
+
for (let i = compactable.length - 1; i >= 0; i--) {
|
|
163
|
+
const msg = compactable[i];
|
|
164
|
+
if (msg.role === "tool" && msg.tool_call_id) {
|
|
165
|
+
const content = typeof msg.content === "string" ? msg.content : "";
|
|
166
|
+
const key = msg.tool_call_id;
|
|
167
|
+
if (!seenToolResults.has(key)) {
|
|
168
|
+
seenToolResults.set(key, i);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
for (let i = 0; i < compactable.length; i++) {
|
|
173
|
+
const msg = compactable[i];
|
|
98
174
|
if (msg._compacted) {
|
|
99
175
|
compacted.push(msg);
|
|
100
176
|
continue;
|
|
@@ -122,29 +198,98 @@ var init_context_engine = __esm({
|
|
|
122
198
|
} else {
|
|
123
199
|
compacted.push(msg);
|
|
124
200
|
}
|
|
201
|
+
} else if (msg.role === "user") {
|
|
202
|
+
if (content.length > 2e3) {
|
|
203
|
+
compacted.push({
|
|
204
|
+
...msg,
|
|
205
|
+
content: content.slice(0, 800) + "\n... (truncated)",
|
|
206
|
+
_compacted: true
|
|
207
|
+
});
|
|
208
|
+
} else {
|
|
209
|
+
compacted.push(msg);
|
|
210
|
+
}
|
|
125
211
|
} else {
|
|
126
212
|
compacted.push(msg);
|
|
127
213
|
}
|
|
128
214
|
}
|
|
129
215
|
this.messages = [...compacted, ...protectedZone];
|
|
130
|
-
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Tier 1 aggressive: drop oldest messages when regular compaction isn't enough.
|
|
219
|
+
*/
|
|
220
|
+
compactTier1Aggressive() {
|
|
221
|
+
const protectedCount = 6;
|
|
222
|
+
const budget = this.getBudget();
|
|
223
|
+
while (this.estimateTokens() > budget.conversation * 0.7 && this.messages.length > protectedCount + 2) {
|
|
131
224
|
const dropIdx = this.messages.findIndex((m) => m.role !== "system");
|
|
132
225
|
if (dropIdx === -1 || dropIdx >= this.messages.length - protectedCount) break;
|
|
133
226
|
this.messages.splice(dropIdx, 1);
|
|
134
227
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Tier 2: LLM-summarized compaction.
|
|
231
|
+
*
|
|
232
|
+
* Takes the oldest messages (outside protected zone), sends them to
|
|
233
|
+
* the model with a summarization prompt, and replaces them with a
|
|
234
|
+
* single "conversation recap" message. This preserves meaning that
|
|
235
|
+
* mechanical truncation loses.
|
|
236
|
+
*/
|
|
237
|
+
async compactTier2() {
|
|
238
|
+
if (!this.provider) return;
|
|
239
|
+
const protectedCount = 6;
|
|
240
|
+
if (this.messages.length <= protectedCount + 2) return;
|
|
241
|
+
const cutoff = Math.max(2, this.messages.length - protectedCount - 2);
|
|
242
|
+
const toSummarize = this.messages.slice(0, cutoff);
|
|
243
|
+
const toKeep = this.messages.slice(cutoff);
|
|
244
|
+
const conversationText = toSummarize.map((m) => {
|
|
245
|
+
const content = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
246
|
+
const truncated = content.length > 500 ? content.slice(0, 500) + "..." : content;
|
|
247
|
+
return `${m.role}: ${truncated}`;
|
|
248
|
+
}).join("\n\n");
|
|
249
|
+
const summaryPrompt = [
|
|
250
|
+
"Summarize this conversation concisely. Capture:",
|
|
251
|
+
"- Key decisions made",
|
|
252
|
+
"- Files modified and why",
|
|
253
|
+
"- Current task status",
|
|
254
|
+
"- Important context the assistant needs going forward",
|
|
255
|
+
"",
|
|
256
|
+
"Be brief (under 300 words). Use bullet points.",
|
|
257
|
+
"",
|
|
258
|
+
"Conversation:",
|
|
259
|
+
conversationText
|
|
260
|
+
].join("\n");
|
|
261
|
+
try {
|
|
262
|
+
let summary = "";
|
|
263
|
+
for await (const event of this.provider.stream(
|
|
264
|
+
[{ role: "user", content: summaryPrompt }],
|
|
265
|
+
"You are a conversation summarizer. Output only the summary, nothing else.",
|
|
266
|
+
[]
|
|
267
|
+
// no tools
|
|
268
|
+
)) {
|
|
269
|
+
if (event.type === "text") {
|
|
270
|
+
summary += event.content;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (summary.trim()) {
|
|
274
|
+
const recapMessage = {
|
|
275
|
+
role: "user",
|
|
276
|
+
content: `[Conversation recap \u2014 earlier messages were compacted]
|
|
277
|
+
|
|
278
|
+
${summary.trim()}`,
|
|
279
|
+
_compacted: true
|
|
280
|
+
};
|
|
281
|
+
this.messages = [recapMessage, ...toKeep];
|
|
282
|
+
}
|
|
283
|
+
} catch {
|
|
284
|
+
this.compactTier1Aggressive();
|
|
285
|
+
}
|
|
142
286
|
}
|
|
143
287
|
/** Clear all messages */
|
|
144
288
|
clear() {
|
|
145
289
|
this.messages = [];
|
|
290
|
+
this.toolResultHashes.clear();
|
|
146
291
|
}
|
|
147
|
-
/** Update the context window size
|
|
292
|
+
/** Update the context window size */
|
|
148
293
|
setContextWindow(size) {
|
|
149
294
|
this.contextWindowSize = size;
|
|
150
295
|
}
|
|
@@ -567,10 +712,12 @@ var init_agent = __esm({
|
|
|
567
712
|
contextWindow: opts.provider.provider.contextWindow(),
|
|
568
713
|
isLocal: opts.provider.isLocal
|
|
569
714
|
});
|
|
715
|
+
this.contextEngine.setProvider(opts.provider.provider, opts.identity.model.primary);
|
|
570
716
|
}
|
|
571
717
|
/** Set the system prompt */
|
|
572
718
|
setSystemPrompt(prompt) {
|
|
573
719
|
this.systemPrompt = prompt;
|
|
720
|
+
this.contextEngine.setSystemPromptSize(Math.ceil(prompt.length / 4));
|
|
574
721
|
}
|
|
575
722
|
/** Load or create a session */
|
|
576
723
|
async loadSession(normalizedKey, channel) {
|
|
@@ -621,7 +768,15 @@ var init_agent = __esm({
|
|
|
621
768
|
iterationCount++;
|
|
622
769
|
if (this.contextEngine.needsCompaction()) {
|
|
623
770
|
this.emit("context-compacting");
|
|
624
|
-
this.contextEngine.
|
|
771
|
+
const compactResult = await this.contextEngine.compactSmart();
|
|
772
|
+
if (compactResult.tier === 2) {
|
|
773
|
+
this.emit("usage", {
|
|
774
|
+
promptTokens: 0,
|
|
775
|
+
outputTokens: 0,
|
|
776
|
+
iterationCount,
|
|
777
|
+
contextPercent: Math.round(this.contextEngine.utilizationPercent())
|
|
778
|
+
});
|
|
779
|
+
}
|
|
625
780
|
}
|
|
626
781
|
const toolDefs = this.toolRegistry.getDefinitions({
|
|
627
782
|
tier: this.identity.toolTier,
|
|
@@ -5172,7 +5327,7 @@ var init_server = __esm({
|
|
|
5172
5327
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
5173
5328
|
res.end(JSON.stringify({
|
|
5174
5329
|
status: "ok",
|
|
5175
|
-
version: "1.
|
|
5330
|
+
version: "1.2.0",
|
|
5176
5331
|
uptime: process.uptime(),
|
|
5177
5332
|
clients: this.clients.size,
|
|
5178
5333
|
agents: this.engines.size
|
|
@@ -5280,7 +5435,7 @@ var init_server = __esm({
|
|
|
5280
5435
|
const hello = {
|
|
5281
5436
|
type: "hello",
|
|
5282
5437
|
protocol: PROTOCOL_VERSION,
|
|
5283
|
-
version: "1.
|
|
5438
|
+
version: "1.2.0",
|
|
5284
5439
|
agents: this.config.agents.list.map((a) => ({
|
|
5285
5440
|
id: a.id,
|
|
5286
5441
|
name: a.name || a.id,
|
|
@@ -6614,7 +6769,7 @@ async function runTui(opts) {
|
|
|
6614
6769
|
ws.on("open", () => {
|
|
6615
6770
|
ws.send(JSON.stringify({
|
|
6616
6771
|
type: "connect",
|
|
6617
|
-
params: { auth: { token }, mode: "tui", version: "1.
|
|
6772
|
+
params: { auth: { token }, mode: "tui", version: "1.2.0" }
|
|
6618
6773
|
}));
|
|
6619
6774
|
});
|
|
6620
6775
|
ws.on("message", (data) => {
|
|
@@ -6661,9 +6816,9 @@ async function runTui(opts) {
|
|
|
6661
6816
|
if (input.startsWith("!")) {
|
|
6662
6817
|
const cmd = input.slice(1).trim();
|
|
6663
6818
|
if (cmd) {
|
|
6664
|
-
const { execSync:
|
|
6819
|
+
const { execSync: execSync3 } = await import("child_process");
|
|
6665
6820
|
try {
|
|
6666
|
-
const out =
|
|
6821
|
+
const out = execSync3(cmd, { encoding: "utf-8", timeout: 3e4, env: { ...process.env, CLANK_SHELL: "tui-local" } });
|
|
6667
6822
|
console.log(out);
|
|
6668
6823
|
} catch (err) {
|
|
6669
6824
|
console.log(red5(err.stderr || err.message));
|
|
@@ -6899,6 +7054,63 @@ var init_tui = __esm({
|
|
|
6899
7054
|
}
|
|
6900
7055
|
});
|
|
6901
7056
|
|
|
7057
|
+
// src/cli/update.ts
|
|
7058
|
+
var update_exports = {};
|
|
7059
|
+
__export(update_exports, {
|
|
7060
|
+
runUpdate: () => runUpdate
|
|
7061
|
+
});
|
|
7062
|
+
import { execSync as execSync2 } from "child_process";
|
|
7063
|
+
async function runUpdate() {
|
|
7064
|
+
console.log("");
|
|
7065
|
+
console.log(dim9(" Updating Clank..."));
|
|
7066
|
+
console.log(dim9(" Stopping gateway..."));
|
|
7067
|
+
try {
|
|
7068
|
+
const { gatewayStop: gatewayStop2 } = await Promise.resolve().then(() => (init_gateway_cmd(), gateway_cmd_exports));
|
|
7069
|
+
await gatewayStop2();
|
|
7070
|
+
} catch {
|
|
7071
|
+
}
|
|
7072
|
+
console.log(dim9(" Pulling latest version..."));
|
|
7073
|
+
try {
|
|
7074
|
+
const output = execSync2("npm install -g @tractorscorch/clank@latest", {
|
|
7075
|
+
encoding: "utf-8",
|
|
7076
|
+
timeout: 12e4
|
|
7077
|
+
});
|
|
7078
|
+
console.log(dim9(` ${output.trim()}`));
|
|
7079
|
+
} catch (err) {
|
|
7080
|
+
console.error(red6(` Update failed: ${err instanceof Error ? err.message : err}`));
|
|
7081
|
+
console.error(dim9(" Try manually: npm install -g @tractorscorch/clank@latest"));
|
|
7082
|
+
return;
|
|
7083
|
+
}
|
|
7084
|
+
try {
|
|
7085
|
+
const newVersion = execSync2("clank --version", { encoding: "utf-8" }).trim();
|
|
7086
|
+
console.log(green9(` Updated to v${newVersion}`));
|
|
7087
|
+
} catch {
|
|
7088
|
+
console.log(green9(" Package updated"));
|
|
7089
|
+
}
|
|
7090
|
+
console.log(dim9(" Restarting gateway..."));
|
|
7091
|
+
try {
|
|
7092
|
+
const { gatewayStartBackground: gatewayStartBackground2 } = await Promise.resolve().then(() => (init_gateway_cmd(), gateway_cmd_exports));
|
|
7093
|
+
await gatewayStartBackground2();
|
|
7094
|
+
console.log(green9(" Gateway restarted"));
|
|
7095
|
+
} catch (err) {
|
|
7096
|
+
console.log(dim9(" Gateway not restarted. Start manually: clank gateway start"));
|
|
7097
|
+
}
|
|
7098
|
+
console.log("");
|
|
7099
|
+
console.log(green9(" Clank updated successfully."));
|
|
7100
|
+
console.log(dim9(" Config, sessions, and memory preserved."));
|
|
7101
|
+
console.log("");
|
|
7102
|
+
}
|
|
7103
|
+
var dim9, green9, red6;
|
|
7104
|
+
var init_update = __esm({
|
|
7105
|
+
"src/cli/update.ts"() {
|
|
7106
|
+
"use strict";
|
|
7107
|
+
init_esm_shims();
|
|
7108
|
+
dim9 = (s) => `\x1B[2m${s}\x1B[0m`;
|
|
7109
|
+
green9 = (s) => `\x1B[32m${s}\x1B[0m`;
|
|
7110
|
+
red6 = (s) => `\x1B[31m${s}\x1B[0m`;
|
|
7111
|
+
}
|
|
7112
|
+
});
|
|
7113
|
+
|
|
6902
7114
|
// src/cli/uninstall.ts
|
|
6903
7115
|
var uninstall_exports = {};
|
|
6904
7116
|
__export(uninstall_exports, {
|
|
@@ -6913,14 +7125,14 @@ async function runUninstall(opts) {
|
|
|
6913
7125
|
console.log(bold4(" Uninstall Clank"));
|
|
6914
7126
|
console.log("");
|
|
6915
7127
|
console.log(" This will permanently remove:");
|
|
6916
|
-
console.log(
|
|
6917
|
-
console.log(
|
|
6918
|
-
console.log(
|
|
6919
|
-
console.log(
|
|
6920
|
-
console.log(
|
|
6921
|
-
console.log(
|
|
6922
|
-
console.log(
|
|
6923
|
-
console.log(
|
|
7128
|
+
console.log(red7(` ${configDir}`));
|
|
7129
|
+
console.log(dim10(" \u251C\u2500\u2500 config.json5 (configuration)"));
|
|
7130
|
+
console.log(dim10(" \u251C\u2500\u2500 conversations/ (chat history)"));
|
|
7131
|
+
console.log(dim10(" \u251C\u2500\u2500 memory/ (agent memory)"));
|
|
7132
|
+
console.log(dim10(" \u251C\u2500\u2500 workspace/ (SOUL.md, USER.md, etc.)"));
|
|
7133
|
+
console.log(dim10(" \u251C\u2500\u2500 logs/ (gateway logs)"));
|
|
7134
|
+
console.log(dim10(" \u251C\u2500\u2500 cron/ (scheduled jobs)"));
|
|
7135
|
+
console.log(dim10(" \u2514\u2500\u2500 plugins/ (installed plugins)"));
|
|
6924
7136
|
console.log("");
|
|
6925
7137
|
if (!opts.yes) {
|
|
6926
7138
|
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
@@ -6929,51 +7141,51 @@ async function runUninstall(opts) {
|
|
|
6929
7141
|
});
|
|
6930
7142
|
rl.close();
|
|
6931
7143
|
if (answer.trim().toLowerCase() !== "y") {
|
|
6932
|
-
console.log(
|
|
7144
|
+
console.log(dim10(" Uninstall cancelled."));
|
|
6933
7145
|
return;
|
|
6934
7146
|
}
|
|
6935
7147
|
}
|
|
6936
|
-
console.log(
|
|
7148
|
+
console.log(dim10(" Stopping gateway..."));
|
|
6937
7149
|
try {
|
|
6938
7150
|
await gatewayStop();
|
|
6939
7151
|
} catch {
|
|
6940
7152
|
}
|
|
6941
|
-
console.log(
|
|
7153
|
+
console.log(dim10(" Removing system service..."));
|
|
6942
7154
|
try {
|
|
6943
7155
|
const { uninstallDaemon: uninstallDaemon2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
|
|
6944
7156
|
await uninstallDaemon2();
|
|
6945
7157
|
} catch {
|
|
6946
7158
|
}
|
|
6947
|
-
console.log(
|
|
7159
|
+
console.log(dim10(" Deleting data..."));
|
|
6948
7160
|
if (existsSync9(configDir)) {
|
|
6949
7161
|
await rm(configDir, { recursive: true, force: true });
|
|
6950
|
-
console.log(
|
|
7162
|
+
console.log(green10(` Removed ${configDir}`));
|
|
6951
7163
|
} else {
|
|
6952
|
-
console.log(
|
|
7164
|
+
console.log(dim10(" No data directory found."));
|
|
6953
7165
|
}
|
|
6954
|
-
console.log(
|
|
7166
|
+
console.log(dim10(" Uninstalling npm package..."));
|
|
6955
7167
|
try {
|
|
6956
|
-
const { execSync:
|
|
6957
|
-
|
|
6958
|
-
console.log(
|
|
7168
|
+
const { execSync: execSync3 } = await import("child_process");
|
|
7169
|
+
execSync3("npm uninstall -g @tractorscorch/clank", { stdio: "ignore" });
|
|
7170
|
+
console.log(green10(" npm package uninstalled"));
|
|
6959
7171
|
} catch {
|
|
6960
|
-
console.log(
|
|
7172
|
+
console.log(dim10(" Could not uninstall npm package (may not be globally installed)"));
|
|
6961
7173
|
}
|
|
6962
7174
|
console.log("");
|
|
6963
|
-
console.log(
|
|
7175
|
+
console.log(green10(" Clank has been completely removed."));
|
|
6964
7176
|
console.log("");
|
|
6965
7177
|
}
|
|
6966
|
-
var
|
|
7178
|
+
var dim10, bold4, green10, red7, yellow4;
|
|
6967
7179
|
var init_uninstall = __esm({
|
|
6968
7180
|
"src/cli/uninstall.ts"() {
|
|
6969
7181
|
"use strict";
|
|
6970
7182
|
init_esm_shims();
|
|
6971
7183
|
init_config2();
|
|
6972
7184
|
init_gateway_cmd();
|
|
6973
|
-
|
|
7185
|
+
dim10 = (s) => `\x1B[2m${s}\x1B[0m`;
|
|
6974
7186
|
bold4 = (s) => `\x1B[1m${s}\x1B[0m`;
|
|
6975
|
-
|
|
6976
|
-
|
|
7187
|
+
green10 = (s) => `\x1B[32m${s}\x1B[0m`;
|
|
7188
|
+
red7 = (s) => `\x1B[31m${s}\x1B[0m`;
|
|
6977
7189
|
yellow4 = (s) => `\x1B[33m${s}\x1B[0m`;
|
|
6978
7190
|
}
|
|
6979
7191
|
});
|
|
@@ -6986,7 +7198,7 @@ import { fileURLToPath as fileURLToPath5 } from "url";
|
|
|
6986
7198
|
import { dirname as dirname5, join as join18 } from "path";
|
|
6987
7199
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
6988
7200
|
var __dirname3 = dirname5(__filename3);
|
|
6989
|
-
var version = "1.
|
|
7201
|
+
var version = "1.2.0";
|
|
6990
7202
|
try {
|
|
6991
7203
|
const pkg = JSON.parse(readFileSync(join18(__dirname3, "..", "package.json"), "utf-8"));
|
|
6992
7204
|
version = pkg.version;
|
|
@@ -7145,6 +7357,10 @@ program.command("channels").description("Show channel adapter status").action(as
|
|
|
7145
7357
|
}
|
|
7146
7358
|
if (Object.keys(channels).length === 0) console.log(" (none configured)");
|
|
7147
7359
|
});
|
|
7360
|
+
program.command("update").description("Update Clank to the latest version and restart gateway").action(async () => {
|
|
7361
|
+
const { runUpdate: runUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
|
|
7362
|
+
await runUpdate2();
|
|
7363
|
+
});
|
|
7148
7364
|
program.command("uninstall").description("Remove Clank completely (config, data, service, package)").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
|
|
7149
7365
|
const { runUninstall: runUninstall2 } = await Promise.resolve().then(() => (init_uninstall(), uninstall_exports));
|
|
7150
7366
|
await runUninstall2(opts);
|