opencode-acp 1.14.19-pr.314.26 → 1.14.19-pr.315.29
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/dist/index.d.ts.map +1 -1
- package/dist/index.js +138 -95
- package/dist/index.js.map +1 -1
- package/dist/lib/compress/decompress.d.ts.map +1 -1
- package/dist/lib/compress/quality-gate/index.d.ts +1 -1
- package/dist/lib/compress/quality-gate/index.d.ts.map +1 -1
- package/dist/lib/compress/quality-gate/rejection.d.ts +0 -1
- package/dist/lib/compress/quality-gate/rejection.d.ts.map +1 -1
- package/dist/lib/compress/range.d.ts.map +1 -1
- package/dist/lib/compress/status.d.ts.map +1 -1
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/messages/inject/inject.d.ts.map +1 -1
- package/dist/lib/state/index.d.ts +1 -0
- package/dist/lib/state/index.d.ts.map +1 -1
- package/dist/lib/state/model-limits.d.ts +27 -0
- package/dist/lib/state/model-limits.d.ts.map +1 -0
- package/dist/lib/state/persistence.d.ts +2 -0
- package/dist/lib/state/persistence.d.ts.map +1 -1
- package/dist/lib/state/state.d.ts +1 -1
- package/dist/lib/state/state.d.ts.map +1 -1
- package/dist/lib/state/types.d.ts +5 -1
- package/dist/lib/state/types.d.ts.map +1 -1
- package/dist/lib/ui/notification.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AA2BjD,QAAA,MAAM,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AA2BjD,QAAA,MAAM,MAAM,EAAE,MA6IK,CAAA;AAEnB,eAAe,MAAM,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -2418,7 +2418,9 @@ async function saveSessionState(sessionState, logger, sessionName) {
|
|
|
2418
2418
|
nextRef: sessionState.messageIds.nextRef
|
|
2419
2419
|
},
|
|
2420
2420
|
lastCompaction: sessionState.lastCompaction,
|
|
2421
|
-
modelContextLimit: sessionState.modelContextLimit
|
|
2421
|
+
modelContextLimit: sessionState.modelContextLimit,
|
|
2422
|
+
modelProviderID: sessionState.modelProviderID,
|
|
2423
|
+
modelID: sessionState.modelID
|
|
2422
2424
|
};
|
|
2423
2425
|
await writePersistedSessionState(sessionState.sessionId, state, logger);
|
|
2424
2426
|
}
|
|
@@ -2949,6 +2951,51 @@ function applyPendingCompressionDurations(state) {
|
|
|
2949
2951
|
return updates;
|
|
2950
2952
|
}
|
|
2951
2953
|
|
|
2954
|
+
// lib/state/model-limits.ts
|
|
2955
|
+
function createModelLimitCatalog() {
|
|
2956
|
+
const modelLimits = /* @__PURE__ */ new Map();
|
|
2957
|
+
return {
|
|
2958
|
+
record(providerId, modelId, limit) {
|
|
2959
|
+
if (!providerId || !modelId || typeof limit !== "number" || limit <= 0) return;
|
|
2960
|
+
modelLimits.set(`${providerId}/${modelId}`, limit);
|
|
2961
|
+
},
|
|
2962
|
+
resolve(providerId, modelId) {
|
|
2963
|
+
if (!providerId || !modelId) return void 0;
|
|
2964
|
+
return modelLimits.get(`${providerId}/${modelId}`);
|
|
2965
|
+
},
|
|
2966
|
+
/**
|
|
2967
|
+
* Best-effort one-time seed from the host's provider catalog
|
|
2968
|
+
* (`client.config.providers()` → GET /config/providers). Never throws;
|
|
2969
|
+
* returns the number of model-limit entries recorded.
|
|
2970
|
+
*/
|
|
2971
|
+
async hydrateFromClient(client) {
|
|
2972
|
+
try {
|
|
2973
|
+
const config = client;
|
|
2974
|
+
const result = await config.config?.providers?.();
|
|
2975
|
+
const payload = result;
|
|
2976
|
+
const providers = payload?.data?.providers;
|
|
2977
|
+
if (!Array.isArray(providers)) return 0;
|
|
2978
|
+
let recorded = 0;
|
|
2979
|
+
for (const provider of providers) {
|
|
2980
|
+
const { id, models } = provider ?? {};
|
|
2981
|
+
if (typeof id !== "string" || !models) continue;
|
|
2982
|
+
for (const [modelId, model] of Object.entries(models)) {
|
|
2983
|
+
const limit = model?.limit;
|
|
2984
|
+
const context = limit?.context;
|
|
2985
|
+
if (typeof context === "number" && context > 0) {
|
|
2986
|
+
modelLimits.set(`${id}/${modelId}`, context);
|
|
2987
|
+
recorded++;
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
return recorded;
|
|
2992
|
+
} catch {
|
|
2993
|
+
return 0;
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
};
|
|
2997
|
+
}
|
|
2998
|
+
|
|
2952
2999
|
// lib/compress/search.ts
|
|
2953
3000
|
import { tool } from "@opencode-ai/plugin";
|
|
2954
3001
|
async function fetchSessionMessages(client, sessionId) {
|
|
@@ -4140,56 +4187,25 @@ var SessionStateRegistry = class {
|
|
|
4140
4187
|
startsByCallId: /* @__PURE__ */ new Map(),
|
|
4141
4188
|
pendingByCallId: /* @__PURE__ */ new Map()
|
|
4142
4189
|
};
|
|
4143
|
-
// [FIX #312]
|
|
4144
|
-
//
|
|
4145
|
-
//
|
|
4146
|
-
//
|
|
4147
|
-
//
|
|
4148
|
-
|
|
4149
|
-
// threshold (emergencyThresholdPercent, min/maxContextLimit "%", adaptive
|
|
4150
|
-
// nudge growth, GC tiers) is still computed against the PREVIOUS model's
|
|
4151
|
-
// limit. This catalog lets the messages hook reconcile against the model
|
|
4152
|
-
// named on the request's user message instead of waiting one turn.
|
|
4153
|
-
// Entries are recorded live by the system hook every request and seeded once
|
|
4154
|
-
// at plugin init from the host's /config/providers catalog.
|
|
4155
|
-
modelLimits = /* @__PURE__ */ new Map();
|
|
4190
|
+
// [FIX #312] Model-limit catalog (full rationale in ./model-limits.ts):
|
|
4191
|
+
// lets the messages hook reconcile state.modelContextLimit against the
|
|
4192
|
+
// model named on the request's user message instead of waiting one turn
|
|
4193
|
+
// for the system hook. Shared implementation — the test registry stub
|
|
4194
|
+
// composes the same factory.
|
|
4195
|
+
catalog = createModelLimitCatalog();
|
|
4156
4196
|
recordModelLimit(providerId, modelId, limit) {
|
|
4157
|
-
|
|
4158
|
-
this.modelLimits.set(`${providerId}/${modelId}`, limit);
|
|
4197
|
+
this.catalog.record(providerId, modelId, limit);
|
|
4159
4198
|
}
|
|
4160
4199
|
resolveModelLimit(providerId, modelId) {
|
|
4161
|
-
|
|
4162
|
-
return this.modelLimits.get(`${providerId}/${modelId}`);
|
|
4200
|
+
return this.catalog.resolve(providerId, modelId);
|
|
4163
4201
|
}
|
|
4164
4202
|
/**
|
|
4165
4203
|
* Best-effort one-time seed from the host's provider catalog
|
|
4166
4204
|
* (`client.config.providers()` → GET /config/providers). Never throws;
|
|
4167
4205
|
* returns the number of model-limit entries recorded.
|
|
4168
4206
|
*/
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
const config = client;
|
|
4172
|
-
const result = await config.config?.providers?.();
|
|
4173
|
-
const payload = result;
|
|
4174
|
-
const providers = payload?.data?.providers;
|
|
4175
|
-
if (!Array.isArray(providers)) return 0;
|
|
4176
|
-
let recorded = 0;
|
|
4177
|
-
for (const provider of providers) {
|
|
4178
|
-
const { id, models } = provider ?? {};
|
|
4179
|
-
if (typeof id !== "string" || !models) continue;
|
|
4180
|
-
for (const [modelId, model] of Object.entries(models)) {
|
|
4181
|
-
const limit = model?.limit;
|
|
4182
|
-
const context = limit?.context;
|
|
4183
|
-
if (typeof context === "number" && context > 0) {
|
|
4184
|
-
this.modelLimits.set(`${id}/${modelId}`, context);
|
|
4185
|
-
recorded++;
|
|
4186
|
-
}
|
|
4187
|
-
}
|
|
4188
|
-
}
|
|
4189
|
-
return recorded;
|
|
4190
|
-
} catch {
|
|
4191
|
-
return 0;
|
|
4192
|
-
}
|
|
4207
|
+
hydrateModelLimitsFromClient(client) {
|
|
4208
|
+
return this.catalog.hydrateFromClient(client);
|
|
4193
4209
|
}
|
|
4194
4210
|
get(sessionId) {
|
|
4195
4211
|
return this.states.get(sessionId);
|
|
@@ -4279,6 +4295,8 @@ function createSessionState() {
|
|
|
4279
4295
|
lastCompaction: 0,
|
|
4280
4296
|
currentTurn: 0,
|
|
4281
4297
|
modelContextLimit: void 0,
|
|
4298
|
+
modelProviderID: void 0,
|
|
4299
|
+
modelID: void 0,
|
|
4282
4300
|
systemPromptTokens: void 0,
|
|
4283
4301
|
qualityGateRetryPending: false
|
|
4284
4302
|
};
|
|
@@ -4318,6 +4336,8 @@ function resetSessionState(state) {
|
|
|
4318
4336
|
state.lastCompaction = 0;
|
|
4319
4337
|
state.currentTurn = 0;
|
|
4320
4338
|
state.modelContextLimit = void 0;
|
|
4339
|
+
state.modelProviderID = void 0;
|
|
4340
|
+
state.modelID = void 0;
|
|
4321
4341
|
state.systemPromptTokens = void 0;
|
|
4322
4342
|
state.qualityGateRetryPending = false;
|
|
4323
4343
|
}
|
|
@@ -4392,6 +4412,8 @@ async function ensureSessionInitialized(client, state, sessionId, logger, messag
|
|
|
4392
4412
|
}
|
|
4393
4413
|
if (typeof persisted.modelContextLimit === "number" && persisted.modelContextLimit > 0) {
|
|
4394
4414
|
state.modelContextLimit = persisted.modelContextLimit;
|
|
4415
|
+
state.modelProviderID = persisted.modelProviderID;
|
|
4416
|
+
state.modelID = persisted.modelID;
|
|
4395
4417
|
}
|
|
4396
4418
|
const applied = applyPendingCompressionDurations(state);
|
|
4397
4419
|
if (applied > 0) {
|
|
@@ -4739,8 +4761,8 @@ ${progressBar}`;
|
|
|
4739
4761
|
let toastMessage = message;
|
|
4740
4762
|
toastMessage = config.pruneNotification === "minimal" ? toastMessage : truncateToastBody(toastMessage);
|
|
4741
4763
|
if (config.debug) {
|
|
4742
|
-
|
|
4743
|
-
|
|
4764
|
+
logger.debug(`[ACP Debug] Compress notification:
|
|
4765
|
+
${message}`);
|
|
4744
4766
|
}
|
|
4745
4767
|
await client.tui.showToast({
|
|
4746
4768
|
body: {
|
|
@@ -5723,11 +5745,6 @@ exact values, errors). Then add "acknowledgeRisk": true to the compress tool cal
|
|
|
5723
5745
|
Without acknowledgeRisk: true, the compression will be rejected again.`;
|
|
5724
5746
|
return new Error(message);
|
|
5725
5747
|
}
|
|
5726
|
-
function buildPreemptiveAcknowledgeError() {
|
|
5727
|
-
return new Error(
|
|
5728
|
-
'Parameter "acknowledgeRisk": true was provided, but no quality gate rejection is pending. This parameter is only valid immediately after a compression was rejected by the quality gate. Remove it and try again.'
|
|
5729
|
-
);
|
|
5730
|
-
}
|
|
5731
5748
|
|
|
5732
5749
|
// lib/compress/pipeline.ts
|
|
5733
5750
|
function snapshotCompressionState(state) {
|
|
@@ -6201,13 +6218,13 @@ function createCompressRangeTool(factoryCtx) {
|
|
|
6201
6218
|
}
|
|
6202
6219
|
const acknowledgeRisk = args.acknowledgeRisk === true;
|
|
6203
6220
|
const qualityGateRetryPendingBefore = ctx.state.qualityGateRetryPending;
|
|
6204
|
-
|
|
6205
|
-
|
|
6221
|
+
const bypassQuality = acknowledgeRisk && ctx.state.qualityGateRetryPending;
|
|
6222
|
+
const ignoredAcknowledgeRisk = acknowledgeRisk && !ctx.state.qualityGateRetryPending;
|
|
6223
|
+
if (ignoredAcknowledgeRisk) {
|
|
6224
|
+
ctx.logger.warn("compress: acknowledgeRisk ignored \u2014 no quality gate rejection pending");
|
|
6206
6225
|
}
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
} else {
|
|
6210
|
-
ctx.state.qualityGateRetryPending = false;
|
|
6226
|
+
ctx.state.qualityGateRetryPending = false;
|
|
6227
|
+
if (!bypassQuality) {
|
|
6211
6228
|
for (const plan of preparedPlans) {
|
|
6212
6229
|
const result = evaluatePreCommitQuality(
|
|
6213
6230
|
rawMessages,
|
|
@@ -6283,7 +6300,10 @@ function createCompressRangeTool(factoryCtx) {
|
|
|
6283
6300
|
const skippedNote = phantomSkipNotice !== null ? `
|
|
6284
6301
|
\u26A0\uFE0F ${phantomSkipNotice}
|
|
6285
6302
|
` : "";
|
|
6286
|
-
|
|
6303
|
+
const ackNote = ignoredAcknowledgeRisk ? `
|
|
6304
|
+
\u26A0\uFE0F acknowledgeRisk was ignored: no quality gate rejection was pending, so quality checks ran normally. Only pass it when retrying immediately after a quality gate rejection.
|
|
6305
|
+
` : "";
|
|
6306
|
+
return `Compressed ${totalCompressedMessages} messages into ${COMPRESSED_BLOCK_HEADER}.${skippedNote}${ackNote}
|
|
6287
6307
|
IMPORTANT: This was an automatic context compression. You MUST continue your previous task exactly where you left off. Do NOT ask the user what to do next.
|
|
6288
6308
|
\u{1F4A1} Tip: Use search_context('keyword') to find compressed content when you need it later.`;
|
|
6289
6309
|
}
|
|
@@ -7617,16 +7637,6 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
7617
7637
|
{ logger }
|
|
7618
7638
|
);
|
|
7619
7639
|
const hasRecommendations = recommendedRanges.length > 0;
|
|
7620
|
-
if (config.debug && contextRanges.compressible.length > 0) {
|
|
7621
|
-
const compressible = contextRanges.compressible;
|
|
7622
|
-
const fmt = (n) => n >= 1e3 ? `${(n / 1e3).toFixed(1)}K` : String(n);
|
|
7623
|
-
const lines = [
|
|
7624
|
-
`[ACP Debug] Recommendation filter:`,
|
|
7625
|
-
` Input: ${compressible.length} range(s), ${fmt(compressible.reduce((s, r) => s + r.tokens, 0))} tokens`,
|
|
7626
|
-
` Output: ${recommendedRanges.length} range(s) (last segment marked dangerous)`
|
|
7627
|
-
];
|
|
7628
|
-
logger.debug(lines.join("\n"));
|
|
7629
|
-
}
|
|
7630
7640
|
const allProtected = contextRanges.compressible.length === 0 && contextRanges.protected.length > 0;
|
|
7631
7641
|
const allInProtectedZone = protectedRefs.size > 0 && unprotectedCompressible.length === 0;
|
|
7632
7642
|
const nothingToCompress = allProtected || allInProtectedZone;
|
|
@@ -7722,6 +7732,16 @@ ${rules}`;
|
|
|
7722
7732
|
}
|
|
7723
7733
|
}
|
|
7724
7734
|
state.nudges.shouldInjectThisTurn = shouldInject;
|
|
7735
|
+
if (shouldInject && config.debug && contextRanges.compressible.length > 0) {
|
|
7736
|
+
const compressible = contextRanges.compressible;
|
|
7737
|
+
const fmt = (n) => n >= 1e3 ? `${(n / 1e3).toFixed(1)}K` : String(n);
|
|
7738
|
+
const lines = [
|
|
7739
|
+
`[ACP Debug] Recommendation filter:`,
|
|
7740
|
+
` Input: ${compressible.length} range(s), ${fmt(compressible.reduce((s, r) => s + r.tokens, 0))} tokens`,
|
|
7741
|
+
` Output: ${recommendedRanges.length} range(s) (last segment marked dangerous)`
|
|
7742
|
+
];
|
|
7743
|
+
logger.debug(lines.join("\n"));
|
|
7744
|
+
}
|
|
7725
7745
|
let tipsText = null;
|
|
7726
7746
|
if (shouldInject) {
|
|
7727
7747
|
if (suffixMessage && composition.total > 0) {
|
|
@@ -8176,10 +8196,6 @@ function resolveSingleBlockTarget(messagesState, blockIdArg) {
|
|
|
8176
8196
|
error: `Error: Block ${target.displayId} is nested inside active block ${activeAncestorBlockId}. Decompress block ${activeAncestorBlockId} first.`
|
|
8177
8197
|
};
|
|
8178
8198
|
}
|
|
8179
|
-
return {
|
|
8180
|
-
ok: false,
|
|
8181
|
-
error: `Error: Block ${target.displayId} is not active. It may have already been decompressed.`
|
|
8182
|
-
};
|
|
8183
8199
|
}
|
|
8184
8200
|
return { ok: true, targets: [target] };
|
|
8185
8201
|
}
|
|
@@ -8332,7 +8348,7 @@ function createDecompressTool(factoryCtx) {
|
|
|
8332
8348
|
const blockMessages = rawMessages.filter((m) => msgIdSet.has(extractMessageId(m)));
|
|
8333
8349
|
const lines2 = blockMessages.map(extractMessageText2);
|
|
8334
8350
|
const { writeFile: writeFile3 } = await import("fs/promises");
|
|
8335
|
-
const fileContent = lines2.length > 0 ? lines2.join("\n\n---\n\n") :
|
|
8351
|
+
const fileContent = lines2.length > 0 ? lines2.join("\n\n---\n\n") : targets[0]?.blocks[0]?.summary ?? "(no content available)";
|
|
8336
8352
|
await writeFile3(targetPath, fileContent, "utf-8");
|
|
8337
8353
|
const displayIds2 = targets.map((t) => `b${t.displayId}`).join(", ");
|
|
8338
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.`;
|
|
@@ -8789,16 +8805,23 @@ function renderCompressedDrilldown(blocks, sort, limit, blocksById) {
|
|
|
8789
8805
|
lines.push(`Sorted by ${sort === "time" ? "time" : sort === "age" ? "age" : "size"}`);
|
|
8790
8806
|
lines.push("");
|
|
8791
8807
|
const shown = sorted.slice(0, limit);
|
|
8808
|
+
const activeCount = sorted.filter((b) => b.active).length;
|
|
8809
|
+
const inactiveCount = sorted.length - activeCount;
|
|
8810
|
+
if (inactiveCount > 0) {
|
|
8811
|
+
lines.push(`${activeCount} active, ${inactiveCount} inactive/consumed`);
|
|
8812
|
+
lines.push("");
|
|
8813
|
+
}
|
|
8792
8814
|
for (const b of shown) {
|
|
8793
8815
|
const survived = b.survivedCount ?? 0;
|
|
8794
8816
|
const gen = b.generation ?? "young";
|
|
8795
8817
|
const effCount = b.effectiveMessageIds?.length ?? 0;
|
|
8796
8818
|
const consumed = b.includedBlockIds && b.includedBlockIds.length > 0 ? ` nested=[${b.includedBlockIds.map((n) => `b${n}`).join(",")}]` : "";
|
|
8819
|
+
const status = b.active ? "" : " [inactive]";
|
|
8797
8820
|
const topic = b.topic || "(no topic)";
|
|
8798
8821
|
const tier = tierLabel(b);
|
|
8799
8822
|
const effTokens = getEffectiveCompressedTokens(b, blocksById);
|
|
8800
8823
|
lines.push(
|
|
8801
|
-
` b${b.blockId} (${tier}) ${formatTokens(effTokens)}\u2192${formatTokens(b.summaryTokens)} ${formatAge(b.createdAt)} ${formatIdRange(b)} age=${survived} ${gen} eff=${effCount}${consumed}`
|
|
8824
|
+
` b${b.blockId} (${tier}) ${formatTokens(effTokens)}\u2192${formatTokens(b.summaryTokens)} ${formatAge(b.createdAt)} ${formatIdRange(b)} age=${survived} ${gen} eff=${effCount}${consumed}${status}`
|
|
8802
8825
|
);
|
|
8803
8826
|
lines.push(` "${topic}"`);
|
|
8804
8827
|
}
|
|
@@ -8819,8 +8842,10 @@ function buildStatusReport(renderCtx, rawMessages, options) {
|
|
|
8819
8842
|
const sort = options?.sort ?? "size";
|
|
8820
8843
|
const limit = options?.limit ?? 30;
|
|
8821
8844
|
const msgState = renderCtx.state.prune.messages;
|
|
8822
|
-
const
|
|
8823
|
-
|
|
8845
|
+
const allBlocks = Array.from(msgState.blocksById.values()).sort(
|
|
8846
|
+
(a, b) => a.blockId - b.blockId
|
|
8847
|
+
);
|
|
8848
|
+
const activeBlocks = allBlocks.filter((b) => b.active);
|
|
8824
8849
|
const lines = [];
|
|
8825
8850
|
if (scope === "compressed") {
|
|
8826
8851
|
lines.push(...renderCompressedDrilldown(allBlocks, sort, limit, msgState.blocksById));
|
|
@@ -8842,7 +8867,7 @@ function buildStatusReport(renderCtx, rawMessages, options) {
|
|
|
8842
8867
|
visibleMsgs,
|
|
8843
8868
|
summaryTokens,
|
|
8844
8869
|
systemTokens,
|
|
8845
|
-
|
|
8870
|
+
activeBlocks,
|
|
8846
8871
|
false,
|
|
8847
8872
|
rawMessages,
|
|
8848
8873
|
renderCtx
|
|
@@ -9000,7 +9025,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
|
9000
9025
|
import { join as join3 } from "path";
|
|
9001
9026
|
import { existsSync as existsSync3 } from "fs";
|
|
9002
9027
|
import { homedir as homedir3 } from "os";
|
|
9003
|
-
var LOG_VERSION = true ? "1.14.19-pr.
|
|
9028
|
+
var LOG_VERSION = true ? "1.14.19-pr.315.29" : "dev";
|
|
9004
9029
|
var Logger = class {
|
|
9005
9030
|
logDir;
|
|
9006
9031
|
enabled;
|
|
@@ -10575,6 +10600,8 @@ function createSystemPromptHandler(registry4, logger, config, prompts) {
|
|
|
10575
10600
|
const state = input.sessionID ? registry4.get(input.sessionID) : void 0;
|
|
10576
10601
|
if (state && input.model?.limit?.context) {
|
|
10577
10602
|
state.modelContextLimit = input.model.limit.context;
|
|
10603
|
+
state.modelProviderID = input.model?.providerID;
|
|
10604
|
+
state.modelID = input.model?.id;
|
|
10578
10605
|
}
|
|
10579
10606
|
if (!state || state.isSubAgent && !config.allowSubAgents) {
|
|
10580
10607
|
return;
|
|
@@ -10634,6 +10661,22 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
10634
10661
|
);
|
|
10635
10662
|
if (requestModelLimit !== void 0) {
|
|
10636
10663
|
state.modelContextLimit = requestModelLimit;
|
|
10664
|
+
state.modelProviderID = requestModel?.providerID;
|
|
10665
|
+
state.modelID = requestModel?.modelID;
|
|
10666
|
+
} else if (
|
|
10667
|
+
// [FIX #312 fallback] Catalog miss: we cannot CORRECT the
|
|
10668
|
+
// limit, but we can tell when it belongs to a DIFFERENT model.
|
|
10669
|
+
// Invalidate instead of letting every percentage threshold
|
|
10670
|
+
// below run against the wrong window (#312's false positive).
|
|
10671
|
+
// States persisted before this identity pair existed carry no
|
|
10672
|
+
// identity and are treated as stale for the same reason.
|
|
10673
|
+
// Consumers already tolerate undefined — fresh sessions run
|
|
10674
|
+
// with it until the first system.transform sets the pair.
|
|
10675
|
+
requestModel?.providerID && requestModel?.modelID && state.modelContextLimit !== void 0 && (state.modelProviderID !== requestModel.providerID || state.modelID !== requestModel.modelID)
|
|
10676
|
+
) {
|
|
10677
|
+
state.modelContextLimit = void 0;
|
|
10678
|
+
state.modelProviderID = requestModel.providerID;
|
|
10679
|
+
state.modelID = requestModel.modelID;
|
|
10637
10680
|
}
|
|
10638
10681
|
await updatePerTurnState(state, logger, messages);
|
|
10639
10682
|
}
|
|
@@ -10680,23 +10723,6 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
10680
10723
|
config.debug ? (text) => {
|
|
10681
10724
|
logger.debug(`[ACP Debug] Nudge injected:
|
|
10682
10725
|
${text}`);
|
|
10683
|
-
if (state.sessionId && lastUserMessage) {
|
|
10684
|
-
const userInfo = lastUserMessage.info;
|
|
10685
|
-
sendIgnoredMessage(
|
|
10686
|
-
client,
|
|
10687
|
-
state.sessionId,
|
|
10688
|
-
`[ACP Debug Nudge]
|
|
10689
|
-
${text}`,
|
|
10690
|
-
{
|
|
10691
|
-
providerId: userInfo.model?.providerID,
|
|
10692
|
-
modelId: userInfo.model?.modelID,
|
|
10693
|
-
agent: userInfo.agent,
|
|
10694
|
-
variant: userInfo.variant
|
|
10695
|
-
},
|
|
10696
|
-
logger
|
|
10697
|
-
).catch(() => {
|
|
10698
|
-
});
|
|
10699
|
-
}
|
|
10700
10726
|
client.tui.showToast({
|
|
10701
10727
|
body: {
|
|
10702
10728
|
title: "ACP: Nudge Injected",
|
|
@@ -11020,8 +11046,25 @@ var server = (async (ctx) => {
|
|
|
11020
11046
|
if (isSecureMode()) {
|
|
11021
11047
|
configureClientAuth(ctx.client);
|
|
11022
11048
|
}
|
|
11023
|
-
registry4.hydrateModelLimitsFromClient(ctx.client).
|
|
11024
|
-
|
|
11049
|
+
registry4.hydrateModelLimitsFromClient(ctx.client).then(
|
|
11050
|
+
(recorded) => {
|
|
11051
|
+
if (recorded > 0) {
|
|
11052
|
+
logger.info("Model limit catalog seeded from provider config", {
|
|
11053
|
+
models: recorded
|
|
11054
|
+
});
|
|
11055
|
+
} else {
|
|
11056
|
+
logger.warn(
|
|
11057
|
+
"Model limit catalog seeding recorded no entries \u2014 falling back to per-request refresh (system.transform)"
|
|
11058
|
+
);
|
|
11059
|
+
}
|
|
11060
|
+
},
|
|
11061
|
+
(error) => {
|
|
11062
|
+
logger.warn(
|
|
11063
|
+
"Model limit catalog seeding failed \u2014 falling back to per-request refresh (system.transform)",
|
|
11064
|
+
{ error: error instanceof Error ? error.message : String(error) }
|
|
11065
|
+
);
|
|
11066
|
+
}
|
|
11067
|
+
);
|
|
11025
11068
|
logger.info("DCP initialized");
|
|
11026
11069
|
startAutoUpdate(ctx, config.autoUpdate);
|
|
11027
11070
|
const compressToolContext = {
|