opencode-acp 1.14.20 → 1.14.21-pr.320.35
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/README.md +4 -800
- package/README.zh-CN.md +4 -755
- package/dist/index.js +350 -22
- package/dist/index.js.map +1 -1
- package/dist/lib/commands/export.d.ts +57 -0
- package/dist/lib/commands/export.d.ts.map +1 -0
- package/dist/lib/hooks.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2900,14 +2900,14 @@ function applyCompressionState(state, input, selection, anchorMessageId, blockId
|
|
|
2900
2900
|
block.directMessageIds = [...newlyCompressedMessageIds];
|
|
2901
2901
|
block.directToolIds = [...newlyCompressedToolIds];
|
|
2902
2902
|
block.compressedTokens = compressedTokens;
|
|
2903
|
-
let
|
|
2903
|
+
let effectiveTokens2 = compressedTokens;
|
|
2904
2904
|
for (const consumedBlockId of consumed) {
|
|
2905
2905
|
const cb = messagesState.blocksById.get(consumedBlockId);
|
|
2906
2906
|
if (cb && (cb.tier ?? 1) === targetTierForConsumption) {
|
|
2907
|
-
|
|
2907
|
+
effectiveTokens2 += cb.effectiveCompressedTokens ?? cb.compressedTokens;
|
|
2908
2908
|
}
|
|
2909
2909
|
}
|
|
2910
|
-
block.effectiveCompressedTokens =
|
|
2910
|
+
block.effectiveCompressedTokens = effectiveTokens2;
|
|
2911
2911
|
state.stats.pruneTokenCounter += compressedTokens;
|
|
2912
2912
|
state.stats.totalPruneTokens += state.stats.pruneTokenCounter;
|
|
2913
2913
|
state.stats.pruneTokenCounter = 0;
|
|
@@ -8347,9 +8347,9 @@ function createDecompressTool(factoryCtx) {
|
|
|
8347
8347
|
}
|
|
8348
8348
|
const blockMessages = rawMessages.filter((m) => msgIdSet.has(extractMessageId(m)));
|
|
8349
8349
|
const lines2 = blockMessages.map(extractMessageText2);
|
|
8350
|
-
const { writeFile:
|
|
8350
|
+
const { writeFile: writeFile4 } = await import("fs/promises");
|
|
8351
8351
|
const fileContent = lines2.length > 0 ? lines2.join("\n\n---\n\n") : targets[0]?.blocks[0]?.summary ?? "(no content available)";
|
|
8352
|
-
await
|
|
8352
|
+
await writeFile4(targetPath, fileContent, "utf-8");
|
|
8353
8353
|
const displayIds2 = targets.map((t) => `b${t.displayId}`).join(", ");
|
|
8354
8354
|
return `Block(s) ${displayIds2} content (${blockMessages.length} messages, ${fileContent.length} chars) written to ${targetPath}. Block(s) stay compressed \u2014 context unchanged. Use read tool to access specific parts.`;
|
|
8355
8355
|
}
|
|
@@ -9025,7 +9025,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
|
9025
9025
|
import { join as join3 } from "path";
|
|
9026
9026
|
import { existsSync as existsSync3 } from "fs";
|
|
9027
9027
|
import { homedir as homedir3 } from "os";
|
|
9028
|
-
var LOG_VERSION = true ? "1.14.
|
|
9028
|
+
var LOG_VERSION = true ? "1.14.21-pr.320.35" : "dev";
|
|
9029
9029
|
var Logger = class {
|
|
9030
9030
|
logDir;
|
|
9031
9031
|
enabled;
|
|
@@ -10089,6 +10089,308 @@ ${report}`;
|
|
|
10089
10089
|
);
|
|
10090
10090
|
}
|
|
10091
10091
|
|
|
10092
|
+
// lib/commands/export.ts
|
|
10093
|
+
import * as fs2 from "fs/promises";
|
|
10094
|
+
import { existsSync as existsSync5 } from "fs";
|
|
10095
|
+
import { dirname as dirname3, isAbsolute, join as join5, resolve } from "path";
|
|
10096
|
+
var ALL_TIERS = [1, 2, 3];
|
|
10097
|
+
var TIER_NAMES = {
|
|
10098
|
+
1: "Tier 1 \u2014 Capture",
|
|
10099
|
+
2: "Tier 2 \u2014 Distilled",
|
|
10100
|
+
3: "Tier 3 \u2014 Condensed"
|
|
10101
|
+
};
|
|
10102
|
+
function parseExportArgs(rawArgs) {
|
|
10103
|
+
const options = {
|
|
10104
|
+
outputPath: "",
|
|
10105
|
+
// "" sentinel => default path resolved later
|
|
10106
|
+
tiers: /* @__PURE__ */ new Set(),
|
|
10107
|
+
includeMetadata: true,
|
|
10108
|
+
append: false
|
|
10109
|
+
};
|
|
10110
|
+
const tokens = tokenize2(rawArgs);
|
|
10111
|
+
let i = 0;
|
|
10112
|
+
while (i < tokens.length) {
|
|
10113
|
+
const tok = tokens[i];
|
|
10114
|
+
const [flag, inlineValue] = splitFlag(tok);
|
|
10115
|
+
switch (flag) {
|
|
10116
|
+
case "--output":
|
|
10117
|
+
case "-o": {
|
|
10118
|
+
const value = inlineValue ?? tokens[i + 1];
|
|
10119
|
+
if (value === void 0) {
|
|
10120
|
+
throw new Error("--output requires a path (use `-` for stdout)");
|
|
10121
|
+
}
|
|
10122
|
+
options.outputPath = value;
|
|
10123
|
+
i += inlineValue !== void 0 ? 1 : 2;
|
|
10124
|
+
break;
|
|
10125
|
+
}
|
|
10126
|
+
case "--tier":
|
|
10127
|
+
case "-t": {
|
|
10128
|
+
const value = inlineValue ?? tokens[i + 1];
|
|
10129
|
+
if (value === void 0) {
|
|
10130
|
+
throw new Error("--tier requires a value (e.g. t2,t3 or all)");
|
|
10131
|
+
}
|
|
10132
|
+
options.tiers = parseTiers(value);
|
|
10133
|
+
i += inlineValue !== void 0 ? 1 : 2;
|
|
10134
|
+
break;
|
|
10135
|
+
}
|
|
10136
|
+
case "--no-metadata":
|
|
10137
|
+
if (inlineValue !== void 0) {
|
|
10138
|
+
throw new Error("--no-metadata does not take a value");
|
|
10139
|
+
}
|
|
10140
|
+
options.includeMetadata = false;
|
|
10141
|
+
i += 1;
|
|
10142
|
+
break;
|
|
10143
|
+
case "--metadata":
|
|
10144
|
+
if (inlineValue !== void 0) {
|
|
10145
|
+
throw new Error("--metadata does not take a value");
|
|
10146
|
+
}
|
|
10147
|
+
options.includeMetadata = true;
|
|
10148
|
+
i += 1;
|
|
10149
|
+
break;
|
|
10150
|
+
case "--append":
|
|
10151
|
+
if (inlineValue !== void 0) {
|
|
10152
|
+
throw new Error("--append does not take a value");
|
|
10153
|
+
}
|
|
10154
|
+
options.append = true;
|
|
10155
|
+
i += 1;
|
|
10156
|
+
break;
|
|
10157
|
+
case "--stdout":
|
|
10158
|
+
if (inlineValue !== void 0) {
|
|
10159
|
+
throw new Error("--stdout does not take a value");
|
|
10160
|
+
}
|
|
10161
|
+
options.outputPath = "-";
|
|
10162
|
+
i += 1;
|
|
10163
|
+
break;
|
|
10164
|
+
default:
|
|
10165
|
+
throw new Error(
|
|
10166
|
+
`Unknown flag: ${tok}. Supported: --output, --tier, --no-metadata, --append, --stdout.`
|
|
10167
|
+
);
|
|
10168
|
+
}
|
|
10169
|
+
}
|
|
10170
|
+
return options;
|
|
10171
|
+
}
|
|
10172
|
+
function tokenize2(input) {
|
|
10173
|
+
const tokens = [];
|
|
10174
|
+
const re = /"([^"]*)"|'([^']*)'|(\S+)/g;
|
|
10175
|
+
let m;
|
|
10176
|
+
while ((m = re.exec(input)) !== null) {
|
|
10177
|
+
tokens.push(m[1] ?? m[2] ?? m[3]);
|
|
10178
|
+
}
|
|
10179
|
+
return tokens;
|
|
10180
|
+
}
|
|
10181
|
+
function splitFlag(tok) {
|
|
10182
|
+
const eq = tok.indexOf("=");
|
|
10183
|
+
if (eq === -1) return [tok, void 0];
|
|
10184
|
+
return [tok.slice(0, eq), tok.slice(eq + 1)];
|
|
10185
|
+
}
|
|
10186
|
+
function parseTiers(raw) {
|
|
10187
|
+
const lower = raw.trim().toLowerCase();
|
|
10188
|
+
if (lower === "all") return new Set(ALL_TIERS);
|
|
10189
|
+
const parts = lower.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
10190
|
+
const result = /* @__PURE__ */ new Set();
|
|
10191
|
+
for (const part of parts) {
|
|
10192
|
+
const digits = part.replace(/^t/i, "");
|
|
10193
|
+
const n = Number(digits);
|
|
10194
|
+
if (!Number.isInteger(n) || n < 1 || n > 3) {
|
|
10195
|
+
throw new Error(
|
|
10196
|
+
`Invalid tier "${part}". Expected t1, t2, t3, a combination (t2,t3), or "all".`
|
|
10197
|
+
);
|
|
10198
|
+
}
|
|
10199
|
+
result.add(n);
|
|
10200
|
+
}
|
|
10201
|
+
if (result.size === 0) {
|
|
10202
|
+
throw new Error(`Invalid tier "${raw}". Expected t1, t2, t3, or "all".`);
|
|
10203
|
+
}
|
|
10204
|
+
return result;
|
|
10205
|
+
}
|
|
10206
|
+
function resolveDefaultOutputPath(sessionId, cwd) {
|
|
10207
|
+
const short = (sessionId || "session").slice(0, 8);
|
|
10208
|
+
return join5(cwd, ".opencode", `acp-export-${short}.md`);
|
|
10209
|
+
}
|
|
10210
|
+
function formatTokens2(n) {
|
|
10211
|
+
if (!Number.isFinite(n) || n <= 0) return "0";
|
|
10212
|
+
return n >= 1e3 ? `${(n / 1e3).toFixed(1)}K` : String(n);
|
|
10213
|
+
}
|
|
10214
|
+
function effectiveTokens(block) {
|
|
10215
|
+
return block.effectiveCompressedTokens ?? block.compressedTokens ?? 0;
|
|
10216
|
+
}
|
|
10217
|
+
function collectActiveBlocks(state) {
|
|
10218
|
+
const msgState = state.prune.messages;
|
|
10219
|
+
const blocks = [];
|
|
10220
|
+
for (const id of msgState.activeBlockIds) {
|
|
10221
|
+
const block = msgState.blocksById.get(id);
|
|
10222
|
+
if (block && block.active) {
|
|
10223
|
+
blocks.push(block);
|
|
10224
|
+
}
|
|
10225
|
+
}
|
|
10226
|
+
return blocks;
|
|
10227
|
+
}
|
|
10228
|
+
function filterByTier(blocks, tiers) {
|
|
10229
|
+
if (tiers.size === 0) return blocks;
|
|
10230
|
+
return blocks.filter((b) => tiers.has(b.tier ?? 1));
|
|
10231
|
+
}
|
|
10232
|
+
function tokenSpans(blocks) {
|
|
10233
|
+
return {
|
|
10234
|
+
effective: blocks.reduce((s, b) => s + effectiveTokens(b), 0),
|
|
10235
|
+
summary: blocks.reduce((s, b) => s + (b.summaryTokens || 0), 0)
|
|
10236
|
+
};
|
|
10237
|
+
}
|
|
10238
|
+
function tierCounts(blocks) {
|
|
10239
|
+
const counts = {};
|
|
10240
|
+
for (const b of blocks) {
|
|
10241
|
+
const t = b.tier ?? 1;
|
|
10242
|
+
counts[t] = (counts[t] || 0) + 1;
|
|
10243
|
+
}
|
|
10244
|
+
return ALL_TIERS.filter((t) => counts[t]).map((t) => `T${t}: ${counts[t]}`).join(", ");
|
|
10245
|
+
}
|
|
10246
|
+
function renderExportMarkdown(params) {
|
|
10247
|
+
const { sessionId, generatedAt, blocks, tiers, includeMetadata } = params;
|
|
10248
|
+
const out = [];
|
|
10249
|
+
const tierFilterLabel = tiers.size === 0 ? "all" : ALL_TIERS.filter((t) => tiers.has(t)).map((t) => `T${t}`).join(", ");
|
|
10250
|
+
out.push("# ACP Session Export");
|
|
10251
|
+
out.push("");
|
|
10252
|
+
out.push(`- **Session**: \`${(sessionId || "unknown").slice(0, 16)}\``);
|
|
10253
|
+
out.push(`- **Generated**: ${generatedAt.toISOString()}`);
|
|
10254
|
+
out.push(`- **Blocks exported**: ${blocks.length}`);
|
|
10255
|
+
const breakdown = tierCounts(blocks);
|
|
10256
|
+
if (breakdown) {
|
|
10257
|
+
out.push(` - ${breakdown}`);
|
|
10258
|
+
}
|
|
10259
|
+
out.push(`- **Tiers**: ${tierFilterLabel}`);
|
|
10260
|
+
const span = tokenSpans(blocks);
|
|
10261
|
+
if (blocks.length > 0) {
|
|
10262
|
+
out.push(
|
|
10263
|
+
`- **Coverage**: ${formatTokens2(span.effective)} original \u2192 ${formatTokens2(span.summary)} summary`
|
|
10264
|
+
);
|
|
10265
|
+
}
|
|
10266
|
+
out.push("");
|
|
10267
|
+
out.push("---");
|
|
10268
|
+
out.push("");
|
|
10269
|
+
if (blocks.length === 0) {
|
|
10270
|
+
out.push("_No active compression blocks match the selected tiers._");
|
|
10271
|
+
out.push("");
|
|
10272
|
+
out.push(
|
|
10273
|
+
"Tip: run `/acp export --tier all` to include every active tier, or trigger a compression first."
|
|
10274
|
+
);
|
|
10275
|
+
return out.join("\n");
|
|
10276
|
+
}
|
|
10277
|
+
for (const tier of [3, 2, 1]) {
|
|
10278
|
+
const tierBlocks = blocks.filter((b) => (b.tier ?? 1) === tier).sort((a, b) => a.blockId - b.blockId);
|
|
10279
|
+
if (tierBlocks.length === 0) continue;
|
|
10280
|
+
out.push(`## ${TIER_NAMES[tier]}`);
|
|
10281
|
+
out.push("");
|
|
10282
|
+
for (const block of tierBlocks) {
|
|
10283
|
+
const topic = block.topic || block.batchTopic || "(no topic)";
|
|
10284
|
+
out.push(`### b${block.blockId} \u2014 ${topic}`);
|
|
10285
|
+
out.push("");
|
|
10286
|
+
if (includeMetadata) {
|
|
10287
|
+
const mode = block.mode ?? "range";
|
|
10288
|
+
const msgCount = block.effectiveMessageIds?.length ?? 0;
|
|
10289
|
+
const created = new Date(block.createdAt).toISOString();
|
|
10290
|
+
const age = block.survivedCount ?? 0;
|
|
10291
|
+
out.push(`- **Tier**: T${tier} \xB7 **Mode**: ${mode}`);
|
|
10292
|
+
out.push(`- **Messages**: ${msgCount} (effective)`);
|
|
10293
|
+
out.push(
|
|
10294
|
+
`- **Tokens**: ${formatTokens2(effectiveTokens(block))} \u2192 ${formatTokens2(block.summaryTokens || 0)} summary`
|
|
10295
|
+
);
|
|
10296
|
+
out.push(`- **Created**: ${created}`);
|
|
10297
|
+
out.push(`- **Age**: survived ${age} transform${age === 1 ? "" : "s"}`);
|
|
10298
|
+
out.push("");
|
|
10299
|
+
}
|
|
10300
|
+
const summary = (block.summary || "").trim() || "_(empty summary)_";
|
|
10301
|
+
out.push(summary);
|
|
10302
|
+
out.push("");
|
|
10303
|
+
out.push("---");
|
|
10304
|
+
out.push("");
|
|
10305
|
+
}
|
|
10306
|
+
}
|
|
10307
|
+
return out.join("\n");
|
|
10308
|
+
}
|
|
10309
|
+
async function handleExportCommand(ctx, args) {
|
|
10310
|
+
const { client, state, logger, sessionId } = ctx;
|
|
10311
|
+
let options;
|
|
10312
|
+
try {
|
|
10313
|
+
options = parseExportArgs(args);
|
|
10314
|
+
} catch (err) {
|
|
10315
|
+
const msg = err?.message ?? String(err);
|
|
10316
|
+
logger.warn("export: argument parse failed", { error: msg, args });
|
|
10317
|
+
await sendExportNotice(client, sessionId, ctx, `[ACP Export] ${msg}`);
|
|
10318
|
+
return;
|
|
10319
|
+
}
|
|
10320
|
+
const tiers = options.tiers;
|
|
10321
|
+
const allActive = collectActiveBlocks(state);
|
|
10322
|
+
const blocks = filterByTier(allActive, tiers);
|
|
10323
|
+
const generatedAt = /* @__PURE__ */ new Date();
|
|
10324
|
+
const markdown = renderExportMarkdown({
|
|
10325
|
+
sessionId,
|
|
10326
|
+
generatedAt,
|
|
10327
|
+
blocks,
|
|
10328
|
+
tiers,
|
|
10329
|
+
includeMetadata: options.includeMetadata
|
|
10330
|
+
});
|
|
10331
|
+
if (options.outputPath === "-") {
|
|
10332
|
+
await sendExportNotice(client, sessionId, ctx, markdown);
|
|
10333
|
+
return;
|
|
10334
|
+
}
|
|
10335
|
+
const cwd = ctx.workingDirectory || process.cwd();
|
|
10336
|
+
const targetPath = options.outputPath !== "" ? isAbsolute(options.outputPath) ? options.outputPath : resolve(cwd, options.outputPath) : resolveDefaultOutputPath(sessionId, cwd);
|
|
10337
|
+
try {
|
|
10338
|
+
const dir = dirname3(targetPath);
|
|
10339
|
+
if (!existsSync5(dir)) {
|
|
10340
|
+
await fs2.mkdir(dir, { recursive: true });
|
|
10341
|
+
}
|
|
10342
|
+
const flag = options.append ? "a" : "w";
|
|
10343
|
+
if (options.append && existsSync5(targetPath)) {
|
|
10344
|
+
await fs2.appendFile(targetPath, `
|
|
10345
|
+
|
|
10346
|
+
---
|
|
10347
|
+
|
|
10348
|
+
${markdown}`, "utf-8");
|
|
10349
|
+
} else {
|
|
10350
|
+
await fs2.writeFile(targetPath, markdown, { flag, encoding: "utf-8" });
|
|
10351
|
+
}
|
|
10352
|
+
} catch (err) {
|
|
10353
|
+
const msg = err?.message ?? String(err);
|
|
10354
|
+
logger.warn("export: file write failed", { path: targetPath, error: msg });
|
|
10355
|
+
await sendExportNotice(
|
|
10356
|
+
client,
|
|
10357
|
+
sessionId,
|
|
10358
|
+
ctx,
|
|
10359
|
+
`[ACP Export] Failed to write \`${targetPath}\`: ${msg}`
|
|
10360
|
+
);
|
|
10361
|
+
return;
|
|
10362
|
+
}
|
|
10363
|
+
logger.info("export: wrote markdown", {
|
|
10364
|
+
path: targetPath,
|
|
10365
|
+
blocks: blocks.length,
|
|
10366
|
+
tiers: tiers.size ? [...tiers].sort().join(",") : "all"
|
|
10367
|
+
});
|
|
10368
|
+
const summary = formatExportSummary(targetPath, blocks, allActive, generatedAt);
|
|
10369
|
+
await sendExportNotice(client, sessionId, ctx, summary);
|
|
10370
|
+
}
|
|
10371
|
+
function formatExportSummary(path, exported, allActive, generatedAt) {
|
|
10372
|
+
const lines = [];
|
|
10373
|
+
lines.push("[ACP Export]");
|
|
10374
|
+
lines.push(`Wrote ${exported.length} block${exported.length === 1 ? "" : "s"} to:`);
|
|
10375
|
+
lines.push(` ${path}`);
|
|
10376
|
+
if (exported.length === 0) {
|
|
10377
|
+
lines.push("");
|
|
10378
|
+
lines.push(
|
|
10379
|
+
`No matching blocks (of ${allActive.length} active). Try \`/acp export --tier all\`.`
|
|
10380
|
+
);
|
|
10381
|
+
} else {
|
|
10382
|
+
lines.push("");
|
|
10383
|
+
lines.push(`Generated ${generatedAt.toISOString()}.`);
|
|
10384
|
+
lines.push(
|
|
10385
|
+
"Review, edit, and commit as a devlog / AGENTS.md supplement \u2014 export is user-driven, never auto-injected."
|
|
10386
|
+
);
|
|
10387
|
+
}
|
|
10388
|
+
return lines.join("\n");
|
|
10389
|
+
}
|
|
10390
|
+
async function sendExportNotice(client, sessionId, ctx, text) {
|
|
10391
|
+
await sendIgnoredMessage(client, sessionId, text, {}, ctx.logger);
|
|
10392
|
+
}
|
|
10393
|
+
|
|
10092
10394
|
// lib/messages/filter/registry.ts
|
|
10093
10395
|
var registry3 = /* @__PURE__ */ new Map();
|
|
10094
10396
|
function registerMessageFilter(filter) {
|
|
@@ -10744,6 +11046,20 @@ ${text}`);
|
|
|
10744
11046
|
}
|
|
10745
11047
|
};
|
|
10746
11048
|
}
|
|
11049
|
+
function buildHelpText() {
|
|
11050
|
+
return [
|
|
11051
|
+
"[ACP] Available commands:",
|
|
11052
|
+
"",
|
|
11053
|
+
" /acp Show compression status (same as /acp stats)",
|
|
11054
|
+
" /acp context Token usage breakdown (system, user, assistant, tools)",
|
|
11055
|
+
" /acp stats Compression status: blocks, context usage, ranges",
|
|
11056
|
+
" /acp export Export active compression blocks to markdown",
|
|
11057
|
+
" Options: --output <path>, --tier t1,t2,t3, --stdout, --append",
|
|
11058
|
+
" /acp help Show this help",
|
|
11059
|
+
"",
|
|
11060
|
+
"Also accepts /dcp for backward compatibility."
|
|
11061
|
+
].join("\n");
|
|
11062
|
+
}
|
|
10747
11063
|
function createCommandExecuteHandler(client, registry4, logger, config, workingDirectory, hostPermissions) {
|
|
10748
11064
|
return async (input, output) => {
|
|
10749
11065
|
if (!config.commands.enabled) {
|
|
@@ -10761,23 +11077,35 @@ function createCommandExecuteHandler(client, registry4, logger, config, workingD
|
|
|
10761
11077
|
config
|
|
10762
11078
|
);
|
|
10763
11079
|
syncCompressPermissionState(state, config, hostPermissions, messages);
|
|
10764
|
-
const effectivePermission = compressPermission(state, config);
|
|
10765
|
-
if (effectivePermission === "deny") {
|
|
10766
|
-
return;
|
|
10767
|
-
}
|
|
10768
11080
|
const commandCtx = {
|
|
10769
11081
|
client,
|
|
10770
11082
|
state,
|
|
10771
11083
|
config,
|
|
10772
11084
|
logger,
|
|
10773
11085
|
sessionId: input.sessionID,
|
|
10774
|
-
messages
|
|
11086
|
+
messages,
|
|
11087
|
+
workingDirectory
|
|
10775
11088
|
};
|
|
10776
11089
|
const sub = input.arguments?.trim().toLowerCase();
|
|
10777
|
-
if (sub === "stats" || sub === "status") {
|
|
11090
|
+
if (sub === "stats" || sub === "status" || sub === "") {
|
|
10778
11091
|
await handleStatsCommand(commandCtx);
|
|
10779
11092
|
throw new Error("__DCP_CONTEXT_HANDLED__");
|
|
10780
11093
|
}
|
|
11094
|
+
if (sub === "export" || sub.startsWith("export ")) {
|
|
11095
|
+
const exportArgs = input.arguments?.trim().slice("export".length).trim() || "";
|
|
11096
|
+
await handleExportCommand(commandCtx, exportArgs);
|
|
11097
|
+
throw new Error("__DCP_CONTEXT_HANDLED__");
|
|
11098
|
+
}
|
|
11099
|
+
if (sub === "help") {
|
|
11100
|
+
await sendIgnoredMessage(
|
|
11101
|
+
client,
|
|
11102
|
+
input.sessionID,
|
|
11103
|
+
buildHelpText(),
|
|
11104
|
+
{},
|
|
11105
|
+
logger
|
|
11106
|
+
);
|
|
11107
|
+
throw new Error("__DCP_CONTEXT_HANDLED__");
|
|
11108
|
+
}
|
|
10781
11109
|
await handleContextCommand(commandCtx);
|
|
10782
11110
|
throw new Error("__DCP_CONTEXT_HANDLED__");
|
|
10783
11111
|
}
|
|
@@ -10887,7 +11215,7 @@ function configureClientAuth(client) {
|
|
|
10887
11215
|
|
|
10888
11216
|
// lib/update.ts
|
|
10889
11217
|
import { readFile as readFile2, rm } from "fs/promises";
|
|
10890
|
-
import { basename, dirname as
|
|
11218
|
+
import { basename, dirname as dirname4, join as join6 } from "path";
|
|
10891
11219
|
import { fileURLToPath } from "url";
|
|
10892
11220
|
var PACKAGE_NAME = "opencode-acp";
|
|
10893
11221
|
function startAutoUpdate(ctx, enabled) {
|
|
@@ -10912,7 +11240,7 @@ function startAutoUpdate(ctx, enabled) {
|
|
|
10912
11240
|
async function checkAutoUpdate(signal) {
|
|
10913
11241
|
const packageDir = await findPackageDir(PACKAGE_NAME);
|
|
10914
11242
|
if (!packageDir) return { updated: false };
|
|
10915
|
-
const pkg = await readPackageJson(
|
|
11243
|
+
const pkg = await readPackageJson(join6(packageDir, "package.json"));
|
|
10916
11244
|
if (!pkg?.name || !pkg.version) return { updated: false };
|
|
10917
11245
|
const latest = await fetchLatestVersion(pkg.name, signal);
|
|
10918
11246
|
if (!latest || !isVersionNewer(latest, pkg.version)) return { updated: false };
|
|
@@ -10932,21 +11260,21 @@ async function checkAutoUpdate(signal) {
|
|
|
10932
11260
|
return { updated: true, name: pkg.name, current: pkg.version, latest };
|
|
10933
11261
|
}
|
|
10934
11262
|
async function findPackageDir(name) {
|
|
10935
|
-
let dir =
|
|
11263
|
+
let dir = dirname4(fileURLToPath(import.meta.url));
|
|
10936
11264
|
for (; ; ) {
|
|
10937
|
-
const pkg = await readPackageJson(
|
|
11265
|
+
const pkg = await readPackageJson(join6(dir, "package.json"));
|
|
10938
11266
|
if (pkg?.name === name) return dir;
|
|
10939
|
-
const parent =
|
|
11267
|
+
const parent = dirname4(dir);
|
|
10940
11268
|
if (parent === dir) return void 0;
|
|
10941
11269
|
dir = parent;
|
|
10942
11270
|
}
|
|
10943
11271
|
}
|
|
10944
11272
|
async function updateRemoveDir(packageDir, name) {
|
|
10945
|
-
const packageParent =
|
|
10946
|
-
const nodeModulesDir = basename(packageParent).startsWith("@") ?
|
|
11273
|
+
const packageParent = dirname4(packageDir);
|
|
11274
|
+
const nodeModulesDir = basename(packageParent).startsWith("@") ? dirname4(packageParent) : packageParent;
|
|
10947
11275
|
if (basename(nodeModulesDir) !== "node_modules") return void 0;
|
|
10948
|
-
const wrapperDir =
|
|
10949
|
-
const wrapperPkg = await readPackageJson(
|
|
11276
|
+
const wrapperDir = dirname4(nodeModulesDir);
|
|
11277
|
+
const wrapperPkg = await readPackageJson(join6(wrapperDir, "package.json"));
|
|
10950
11278
|
const spec = wrapperSpec(wrapperDir, name) ?? wrapperPkg?.dependencies?.[name];
|
|
10951
11279
|
if (!spec || !isAutoUpdatableSpec(spec)) return void 0;
|
|
10952
11280
|
return wrapperDir;
|
|
@@ -10954,7 +11282,7 @@ async function updateRemoveDir(packageDir, name) {
|
|
|
10954
11282
|
function wrapperSpec(wrapperDir, name) {
|
|
10955
11283
|
if (name.startsWith("@")) {
|
|
10956
11284
|
const [scope, pkg] = name.split("/");
|
|
10957
|
-
if (!scope || !pkg || basename(
|
|
11285
|
+
if (!scope || !pkg || basename(dirname4(wrapperDir)) !== scope) return void 0;
|
|
10958
11286
|
const prefix2 = `${pkg}@`;
|
|
10959
11287
|
const base2 = basename(wrapperDir);
|
|
10960
11288
|
return base2.startsWith(prefix2) ? base2.slice(prefix2.length) : void 0;
|