opencode-acp 1.14.23 → 1.14.24
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 +5 -2
- package/README.zh-CN.md +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +144 -20
- package/dist/index.js.map +1 -1
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/config.d.ts +3 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/logger.d.ts +22 -5
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/messages/inject/inject.d.ts.map +1 -1
- package/dist/lib/update.d.ts +2 -1
- package/dist/lib/update.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -282,8 +282,11 @@ Each level overrides the previous, so project settings take priority over global
|
|
|
282
282
|
// on the installed dist-tag/spec (@stable follows stable, @latest follows latest).
|
|
283
283
|
// Version-locked plugin specs are not updated.
|
|
284
284
|
"autoUpdate": true,
|
|
285
|
-
//
|
|
286
|
-
//
|
|
285
|
+
// File log verbosity: "debug" | "info" | "warn" | "error" | "silent".
|
|
286
|
+
// Default "info" writes decision-level events (nudges, transforms, updates)
|
|
287
|
+
// to ~/.config/opencode/logs/acp/daily/<date>.log
|
|
288
|
+
"logLevel": "info",
|
|
289
|
+
// Enable full DEBUG logging + per-request snapshots (overrides logLevel)
|
|
287
290
|
"debug": false,
|
|
288
291
|
// Notification display: "off", "minimal", or "detailed"
|
|
289
292
|
"pruneNotification": "off",
|
package/README.zh-CN.md
CHANGED
|
@@ -236,8 +236,11 @@ ACP 使用自己的配置文件,按以下顺序搜索:
|
|
|
236
236
|
// 自动更新 npm 安装的 ACP:跟踪安装所用 dist-tag/规范(@stable 跟随 stable,@latest 跟随 latest)。
|
|
237
237
|
// 版本锁定的规范不会被更新。
|
|
238
238
|
"autoUpdate": true,
|
|
239
|
-
//
|
|
240
|
-
//
|
|
239
|
+
// 文件日志级别: "debug" | "info" | "warn" | "error" | "silent"
|
|
240
|
+
// 默认 "info":决策级事件(压缩提示、转换摘要、更新检查)落盘到
|
|
241
|
+
// ~/.config/opencode/logs/acp/daily/<日期>.log
|
|
242
|
+
"logLevel": "info",
|
|
243
|
+
// 启用完整 DEBUG 日志 + 按请求快照(优先于 logLevel)
|
|
241
244
|
"debug": false,
|
|
242
245
|
// Notification display: "off", "minimal", or "detailed"
|
|
243
246
|
"pruneNotification": "detailed",
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AA2BjD,QAAA,MAAM,MAAM,EAAE,MAqJK,CAAA;AAEnB,eAAe,MAAM,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -868,6 +868,7 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
868
868
|
"enabled",
|
|
869
869
|
"autoUpdate",
|
|
870
870
|
"debug",
|
|
871
|
+
"logLevel",
|
|
871
872
|
"showUpdateToasts",
|
|
872
873
|
"allowSubAgents",
|
|
873
874
|
"pruneNotification",
|
|
@@ -1466,6 +1467,7 @@ var defaultConfig = {
|
|
|
1466
1467
|
enabled: true,
|
|
1467
1468
|
autoUpdate: true,
|
|
1468
1469
|
debug: false,
|
|
1470
|
+
logLevel: "info",
|
|
1469
1471
|
allowSubAgents: true,
|
|
1470
1472
|
pruneNotification: "off",
|
|
1471
1473
|
// [FIX #20] Default to toast — chat-mode notifications inject an empty
|
|
@@ -1727,6 +1729,7 @@ function mergeLayer(config, data) {
|
|
|
1727
1729
|
enabled: data.enabled ?? config.enabled,
|
|
1728
1730
|
autoUpdate: data.autoUpdate ?? config.autoUpdate,
|
|
1729
1731
|
debug: data.debug ?? config.debug,
|
|
1732
|
+
logLevel: data.logLevel ?? config.logLevel,
|
|
1730
1733
|
allowSubAgents: data.allowSubAgents ?? data.experimental?.allowSubAgents ?? config.allowSubAgents,
|
|
1731
1734
|
pruneNotification: data.pruneNotification ?? config.pruneNotification,
|
|
1732
1735
|
pruneNotificationType: data.pruneNotificationType ?? config.pruneNotificationType,
|
|
@@ -7757,6 +7760,13 @@ Multiple entries create separate blocks: \`content: [{ startId: "b${firstBlock.b
|
|
|
7757
7760
|
${rules}`;
|
|
7758
7761
|
appendToLastTextPart(suffixMessage, tierText);
|
|
7759
7762
|
shouldInject = true;
|
|
7763
|
+
logger.info(`Tier ${tc.triggerTier} trigger nudge injected`, {
|
|
7764
|
+
session: state.sessionId,
|
|
7765
|
+
action,
|
|
7766
|
+
targetTier: tc.targetTier,
|
|
7767
|
+
blocks: candidates.length,
|
|
7768
|
+
candidateTokens
|
|
7769
|
+
});
|
|
7760
7770
|
if (tc.triggerTier === 2) {
|
|
7761
7771
|
state.nudges.lastTier2NudgeTokens = currentTokens;
|
|
7762
7772
|
} else {
|
|
@@ -7766,6 +7776,32 @@ ${rules}`;
|
|
|
7766
7776
|
}
|
|
7767
7777
|
}
|
|
7768
7778
|
state.nudges.shouldInjectThisTurn = shouldInject;
|
|
7779
|
+
const usagePct = currentTokens !== void 0 && modelContextLimit ? `${(currentTokens / modelContextLimit * 100).toFixed(1)}%` : void 0;
|
|
7780
|
+
if (shouldInjectNudge) {
|
|
7781
|
+
logger.info("Compression nudge injected", {
|
|
7782
|
+
session: state.sessionId,
|
|
7783
|
+
trigger: emergencyOverride ? "emergency" : "growth",
|
|
7784
|
+
currentTokens,
|
|
7785
|
+
usagePct,
|
|
7786
|
+
growthSinceBaseline,
|
|
7787
|
+
growthFloor,
|
|
7788
|
+
recommendedRanges: recommendedRanges.length
|
|
7789
|
+
});
|
|
7790
|
+
} else if (shouldInjectNotice) {
|
|
7791
|
+
logger.info("Emergency /compact notice injected (no compressible targets)", {
|
|
7792
|
+
session: state.sessionId,
|
|
7793
|
+
currentTokens,
|
|
7794
|
+
usagePct
|
|
7795
|
+
});
|
|
7796
|
+
} else if (nudgeAllowed && nothingToCompress) {
|
|
7797
|
+
logger.info("Nudge suppressed: nothing to compress", {
|
|
7798
|
+
session: state.sessionId,
|
|
7799
|
+
reason: allProtected ? "all_protected" : allInProtectedZone ? "in_protected_zone" : "below_effective_floor",
|
|
7800
|
+
currentTokens,
|
|
7801
|
+
usagePct,
|
|
7802
|
+
compressibleRanges: contextRanges.compressible.length
|
|
7803
|
+
});
|
|
7804
|
+
}
|
|
7769
7805
|
if (shouldInject && config.debug && contextRanges.compressible.length > 0) {
|
|
7770
7806
|
const compressible = contextRanges.compressible;
|
|
7771
7807
|
const fmt = (n) => n >= 1e3 ? `${(n / 1e3).toFixed(1)}K` : String(n);
|
|
@@ -9074,15 +9110,36 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
|
9074
9110
|
import { join as join3 } from "path";
|
|
9075
9111
|
import { existsSync as existsSync3 } from "fs";
|
|
9076
9112
|
import { homedir as homedir3 } from "os";
|
|
9077
|
-
var LOG_VERSION = true ? "1.14.
|
|
9113
|
+
var LOG_VERSION = true ? "1.14.24" : "dev";
|
|
9114
|
+
var LEVEL_RANK = {
|
|
9115
|
+
debug: 10,
|
|
9116
|
+
info: 20,
|
|
9117
|
+
warn: 30,
|
|
9118
|
+
error: 40,
|
|
9119
|
+
silent: 99
|
|
9120
|
+
};
|
|
9078
9121
|
var Logger = class {
|
|
9079
9122
|
logDir;
|
|
9080
|
-
enabled
|
|
9081
|
-
|
|
9082
|
-
|
|
9123
|
+
/** Resolved verbosity; replaces the old boolean `enabled` flag. */
|
|
9124
|
+
level;
|
|
9125
|
+
/**
|
|
9126
|
+
* @param enabled legacy boolean toggle — `true` maps to `debug`,
|
|
9127
|
+
* `false` maps to `warn` (errors + warnings only).
|
|
9128
|
+
* @param level explicit verbosity; when given it wins over `enabled`.
|
|
9129
|
+
*/
|
|
9130
|
+
constructor(enabled, level) {
|
|
9131
|
+
const resolved = level !== void 0 && LEVEL_RANK[level] !== void 0 ? level : void 0;
|
|
9132
|
+
this.level = resolved ?? (enabled ? "debug" : "warn");
|
|
9083
9133
|
const configHome = process.env.XDG_CONFIG_HOME || join3(homedir3(), ".config");
|
|
9084
9134
|
this.logDir = join3(configHome, "opencode", "logs", "acp");
|
|
9085
9135
|
}
|
|
9136
|
+
/** Back-compat view of the old flag: true only at full debug verbosity. */
|
|
9137
|
+
get enabled() {
|
|
9138
|
+
return this.level === "debug";
|
|
9139
|
+
}
|
|
9140
|
+
shouldWrite(level) {
|
|
9141
|
+
return LEVEL_RANK[level] >= LEVEL_RANK[this.level];
|
|
9142
|
+
}
|
|
9086
9143
|
async ensureLogDir() {
|
|
9087
9144
|
if (!existsSync3(this.logDir)) {
|
|
9088
9145
|
await mkdir2(this.logDir, { recursive: true });
|
|
@@ -9129,7 +9186,7 @@ var Logger = class {
|
|
|
9129
9186
|
}
|
|
9130
9187
|
}
|
|
9131
9188
|
async write(level, component, message, data) {
|
|
9132
|
-
if (!this.
|
|
9189
|
+
if (!this.shouldWrite(level.toLowerCase())) return;
|
|
9133
9190
|
try {
|
|
9134
9191
|
await this.ensureLogDir();
|
|
9135
9192
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9146,12 +9203,12 @@ var Logger = class {
|
|
|
9146
9203
|
}
|
|
9147
9204
|
}
|
|
9148
9205
|
info(message, data) {
|
|
9149
|
-
if (!this.
|
|
9206
|
+
if (!this.shouldWrite("info")) return;
|
|
9150
9207
|
const component = this.getCallerFile(2);
|
|
9151
9208
|
return this.write("INFO", component, message, data);
|
|
9152
9209
|
}
|
|
9153
9210
|
debug(message, data) {
|
|
9154
|
-
if (!this.
|
|
9211
|
+
if (!this.shouldWrite("debug")) return;
|
|
9155
9212
|
const component = this.getCallerFile(2);
|
|
9156
9213
|
return this.write("DEBUG", component, message, data);
|
|
9157
9214
|
}
|
|
@@ -9249,7 +9306,7 @@ var Logger = class {
|
|
|
9249
9306
|
});
|
|
9250
9307
|
}
|
|
9251
9308
|
async saveContext(sessionId, messages) {
|
|
9252
|
-
if (
|
|
9309
|
+
if (this.level !== "debug") return;
|
|
9253
9310
|
try {
|
|
9254
9311
|
const contextDir = join3(this.logDir, "context", sessionId);
|
|
9255
9312
|
if (!existsSync3(contextDir)) {
|
|
@@ -11010,6 +11067,7 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
11010
11067
|
requestModel?.providerID,
|
|
11011
11068
|
requestModel?.modelID
|
|
11012
11069
|
);
|
|
11070
|
+
const prevModelID = state.modelID;
|
|
11013
11071
|
if (requestModelLimit !== void 0) {
|
|
11014
11072
|
state.modelContextLimit = requestModelLimit;
|
|
11015
11073
|
state.modelProviderID = requestModel?.providerID;
|
|
@@ -11029,6 +11087,14 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
11029
11087
|
state.modelProviderID = requestModel.providerID;
|
|
11030
11088
|
state.modelID = requestModel.modelID;
|
|
11031
11089
|
}
|
|
11090
|
+
if (requestModel?.modelID && requestModel.modelID !== prevModelID) {
|
|
11091
|
+
logger.info("Model switched mid-session", {
|
|
11092
|
+
session: state.sessionId,
|
|
11093
|
+
from: prevModelID,
|
|
11094
|
+
to: requestModel.modelID,
|
|
11095
|
+
contextLimit: state.modelContextLimit
|
|
11096
|
+
});
|
|
11097
|
+
}
|
|
11032
11098
|
await updatePerTurnState(state, logger, messages);
|
|
11033
11099
|
}
|
|
11034
11100
|
syncCompressPermissionState(state, config, hostPermissions, output.messages);
|
|
@@ -11090,6 +11156,17 @@ ${text}`);
|
|
|
11090
11156
|
hideFailedCompressCalls(output.messages);
|
|
11091
11157
|
stripStaleMetadata(output.messages);
|
|
11092
11158
|
dropEmptyMessages(output.messages);
|
|
11159
|
+
const postTokens = getCurrentTokenUsage(state, output.messages);
|
|
11160
|
+
logger.info("Chat transform complete", {
|
|
11161
|
+
session: state.sessionId,
|
|
11162
|
+
model: state.modelID,
|
|
11163
|
+
messages: output.messages.length,
|
|
11164
|
+
prePruneTokens,
|
|
11165
|
+
postTokens,
|
|
11166
|
+
contextLimit: state.modelContextLimit,
|
|
11167
|
+
usagePct: postTokens !== void 0 && state.modelContextLimit ? `${(postTokens / state.modelContextLimit * 100).toFixed(1)}%` : void 0,
|
|
11168
|
+
nudged: state.nudges.shouldInjectThisTurn
|
|
11169
|
+
});
|
|
11093
11170
|
if (state.sessionId) {
|
|
11094
11171
|
await logger.saveContext(state.sessionId, output.messages);
|
|
11095
11172
|
}
|
|
@@ -11267,12 +11344,31 @@ import { readFile as readFile2, rm } from "fs/promises";
|
|
|
11267
11344
|
import { basename, dirname as dirname4, join as join6 } from "path";
|
|
11268
11345
|
import { fileURLToPath } from "url";
|
|
11269
11346
|
var PACKAGE_NAME = "opencode-acp";
|
|
11270
|
-
function startAutoUpdate(ctx, enabled) {
|
|
11271
|
-
if (!enabled)
|
|
11347
|
+
function startAutoUpdate(ctx, enabled, logger) {
|
|
11348
|
+
if (!enabled) {
|
|
11349
|
+
logger?.info("Auto-update disabled by config");
|
|
11350
|
+
return;
|
|
11351
|
+
}
|
|
11352
|
+
logger?.info("Auto-update check starting");
|
|
11272
11353
|
const controller = new AbortController();
|
|
11273
11354
|
const timeout = setTimeout(() => controller.abort(), 1e4);
|
|
11274
|
-
void checkAutoUpdate(controller.signal).then((result) => {
|
|
11275
|
-
if (!result.updated)
|
|
11355
|
+
void checkAutoUpdate(controller.signal, logger).then((result) => {
|
|
11356
|
+
if (!result.updated) {
|
|
11357
|
+
if ("error" in result) {
|
|
11358
|
+
logger?.warn("Auto-update failed", {
|
|
11359
|
+
error: result.error,
|
|
11360
|
+
name: result.name,
|
|
11361
|
+
current: result.current,
|
|
11362
|
+
latest: result.latest
|
|
11363
|
+
});
|
|
11364
|
+
}
|
|
11365
|
+
return;
|
|
11366
|
+
}
|
|
11367
|
+
logger?.info("Auto-update applied update", {
|
|
11368
|
+
name: result.name,
|
|
11369
|
+
from: result.current,
|
|
11370
|
+
to: result.latest
|
|
11371
|
+
});
|
|
11276
11372
|
setTimeout(() => {
|
|
11277
11373
|
ctx.client.tui.showToast({
|
|
11278
11374
|
body: {
|
|
@@ -11286,17 +11382,37 @@ function startAutoUpdate(ctx, enabled) {
|
|
|
11286
11382
|
}).catch(() => {
|
|
11287
11383
|
}).finally(() => clearTimeout(timeout));
|
|
11288
11384
|
}
|
|
11289
|
-
async function checkAutoUpdate(signal) {
|
|
11385
|
+
async function checkAutoUpdate(signal, logger) {
|
|
11290
11386
|
const packageDir = await findPackageDir(PACKAGE_NAME);
|
|
11291
|
-
if (!packageDir)
|
|
11387
|
+
if (!packageDir) {
|
|
11388
|
+
logger?.info("Auto-update skipped: package dir not found");
|
|
11389
|
+
return { updated: false };
|
|
11390
|
+
}
|
|
11292
11391
|
const pkg = await readPackageJson(join6(packageDir, "package.json"));
|
|
11293
|
-
if (!pkg?.name || !pkg.version)
|
|
11392
|
+
if (!pkg?.name || !pkg.version) {
|
|
11393
|
+
logger?.info("Auto-update skipped: package.json unreadable", { packageDir });
|
|
11394
|
+
return { updated: false };
|
|
11395
|
+
}
|
|
11294
11396
|
const target = await updateTarget(packageDir, pkg.name);
|
|
11295
|
-
if (!target)
|
|
11397
|
+
if (!target) {
|
|
11398
|
+
logger?.info("Auto-update skipped: no update target", { name: pkg.name, version: pkg.version });
|
|
11399
|
+
return { updated: false };
|
|
11400
|
+
}
|
|
11296
11401
|
const tag = specUpdateTag(target.spec);
|
|
11297
|
-
if (!tag)
|
|
11402
|
+
if (!tag) {
|
|
11403
|
+
logger?.info("Auto-update skipped: spec not auto-updatable", { spec: target.spec });
|
|
11404
|
+
return { updated: false };
|
|
11405
|
+
}
|
|
11298
11406
|
const latest = await fetchLatestVersion(pkg.name, tag, signal);
|
|
11299
|
-
if (!latest
|
|
11407
|
+
if (!latest) {
|
|
11408
|
+
logger?.info("Auto-update skipped: no version published for tag", { name: pkg.name, tag });
|
|
11409
|
+
return { updated: false };
|
|
11410
|
+
}
|
|
11411
|
+
if (!isVersionNewer(latest, pkg.version)) {
|
|
11412
|
+
logger?.info("Auto-update: already up to date", { name: pkg.name, tag, current: pkg.version, latest });
|
|
11413
|
+
return { updated: false };
|
|
11414
|
+
}
|
|
11415
|
+
logger?.info("Auto-update: newer version available", { name: pkg.name, tag, current: pkg.version, latest });
|
|
11300
11416
|
try {
|
|
11301
11417
|
await rm(target.removeDir, { recursive: true, force: true });
|
|
11302
11418
|
} catch {
|
|
@@ -11429,7 +11545,15 @@ var server = (async (ctx) => {
|
|
|
11429
11545
|
if (!config.enabled) {
|
|
11430
11546
|
return {};
|
|
11431
11547
|
}
|
|
11432
|
-
const logger = new Logger(config.debug);
|
|
11548
|
+
const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
|
|
11549
|
+
logger.info("ACP plugin initialized", {
|
|
11550
|
+
version: true ? "1.14.24" : "dev",
|
|
11551
|
+
workspace: ctx.directory,
|
|
11552
|
+
logLevel: logger.level,
|
|
11553
|
+
debug: config.debug,
|
|
11554
|
+
autoUpdate: config.autoUpdate,
|
|
11555
|
+
secureMode: isSecureMode()
|
|
11556
|
+
});
|
|
11433
11557
|
const registry4 = new SessionStateRegistry(logger);
|
|
11434
11558
|
const prompts = new PromptStore(logger, ctx.directory, config.experimental.customPrompts);
|
|
11435
11559
|
const hostPermissions = {
|
|
@@ -11459,7 +11583,7 @@ var server = (async (ctx) => {
|
|
|
11459
11583
|
}
|
|
11460
11584
|
);
|
|
11461
11585
|
logger.info("DCP initialized");
|
|
11462
|
-
startAutoUpdate(ctx, config.autoUpdate);
|
|
11586
|
+
startAutoUpdate(ctx, config.autoUpdate, logger);
|
|
11463
11587
|
const compressToolContext = {
|
|
11464
11588
|
client: ctx.client,
|
|
11465
11589
|
registry: registry4,
|