opencode-acp 1.14.16-pr.299.6 → 1.14.16-pr.302.10

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.js CHANGED
@@ -2075,7 +2075,7 @@ THE FORMAT OF COMPRESS
2075
2075
  ]
2076
2076
  }
2077
2077
  \`\`\`
2078
- Each entry needs a topic \u2014 either its own or the top-level fallback.`;
2078
+ Each entry MAY have a topic. Missing topics fall back to the top-level topic, then to an automatic one derived from the summary.`;
2079
2079
 
2080
2080
  // lib/state/persistence.ts
2081
2081
  import * as fs from "fs/promises";
@@ -3756,8 +3756,11 @@ function filterProtectedRecentMessages(selection, searchContext, state, compress
3756
3756
 
3757
3757
  // lib/compress/range-utils.ts
3758
3758
  var BLOCK_PLACEHOLDER_REGEX = /\(b(\d+)\)|\{block_(\d+)\}/gi;
3759
+ function deriveFallbackTopic(summary) {
3760
+ const firstLine = summary.split("\n").map((line) => line.replace(/^#{1,6}\s*/, "").trim()).find((line) => line.length > 0) ?? "compressed range";
3761
+ return firstLine.length > 80 ? `${firstLine.slice(0, 77)}...` : firstLine;
3762
+ }
3759
3763
  function validateArgs(args) {
3760
- const hasTopLevelTopic = typeof args.topic === "string" && args.topic.trim().length > 0;
3761
3764
  if (!Array.isArray(args.content) || args.content.length === 0) {
3762
3765
  throw new Error("content is required and must be a non-empty array");
3763
3766
  }
@@ -3773,18 +3776,12 @@ function validateArgs(args) {
3773
3776
  if (typeof entry?.summary !== "string" || entry.summary.trim().length === 0) {
3774
3777
  throw new Error(`${prefix}.summary is required and must be a non-empty string`);
3775
3778
  }
3776
- const hasEntryTopic = typeof entry?.topic === "string" && entry.topic.trim().length > 0;
3777
- if (!hasEntryTopic && !hasTopLevelTopic) {
3778
- throw new Error(
3779
- `${prefix} needs a topic \u2014 provide ${prefix}.topic or the top-level topic`
3780
- );
3781
- }
3782
3779
  }
3783
3780
  }
3784
3781
  function resolveRanges(args, searchContext, state, logger) {
3785
3782
  return args.content.map((entry, index) => {
3786
3783
  const normalizedEntry = {
3787
- topic: typeof entry.topic === "string" && entry.topic.trim().length > 0 ? entry.topic.trim() : void 0,
3784
+ topic: typeof entry.topic === "string" && entry.topic.trim().length > 0 ? entry.topic.trim() : typeof args.topic === "string" && args.topic.trim().length > 0 ? void 0 : deriveFallbackTopic(entry.summary),
3788
3785
  startId: entry.startId.trim(),
3789
3786
  endId: entry.endId.trim(),
3790
3787
  summary: entry.summary
@@ -5672,11 +5669,6 @@ exact values, errors). Then add "acknowledgeRisk": true to the compress tool cal
5672
5669
  Without acknowledgeRisk: true, the compression will be rejected again.`;
5673
5670
  return new Error(message);
5674
5671
  }
5675
- function buildPreemptiveAcknowledgeError() {
5676
- return new Error(
5677
- '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.'
5678
- );
5679
- }
5680
5672
 
5681
5673
  // lib/compress/pipeline.ts
5682
5674
  function snapshotCompressionState(state) {
@@ -6150,13 +6142,13 @@ function createCompressRangeTool(factoryCtx) {
6150
6142
  }
6151
6143
  const acknowledgeRisk = args.acknowledgeRisk === true;
6152
6144
  const qualityGateRetryPendingBefore = ctx.state.qualityGateRetryPending;
6153
- if (acknowledgeRisk && !ctx.state.qualityGateRetryPending) {
6154
- throw buildPreemptiveAcknowledgeError();
6145
+ const bypassQuality = acknowledgeRisk && ctx.state.qualityGateRetryPending;
6146
+ const ignoredAcknowledgeRisk = acknowledgeRisk && !ctx.state.qualityGateRetryPending;
6147
+ if (ignoredAcknowledgeRisk) {
6148
+ ctx.logger.warn("compress: acknowledgeRisk ignored \u2014 no quality gate rejection pending");
6155
6149
  }
6156
- if (acknowledgeRisk) {
6157
- ctx.state.qualityGateRetryPending = false;
6158
- } else {
6159
- ctx.state.qualityGateRetryPending = false;
6150
+ ctx.state.qualityGateRetryPending = false;
6151
+ if (!bypassQuality) {
6160
6152
  for (const plan of preparedPlans) {
6161
6153
  const result = evaluatePreCommitQuality(
6162
6154
  rawMessages,
@@ -6232,7 +6224,10 @@ function createCompressRangeTool(factoryCtx) {
6232
6224
  const skippedNote = phantomSkipNotice !== null ? `
6233
6225
  \u26A0\uFE0F ${phantomSkipNotice}
6234
6226
  ` : "";
6235
- return `Compressed ${totalCompressedMessages} messages into ${COMPRESSED_BLOCK_HEADER}.${skippedNote}
6227
+ const ackNote = ignoredAcknowledgeRisk ? `
6228
+ \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.
6229
+ ` : "";
6230
+ return `Compressed ${totalCompressedMessages} messages into ${COMPRESSED_BLOCK_HEADER}.${skippedNote}${ackNote}
6236
6231
  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.
6237
6232
  \u{1F4A1} Tip: Use search_context('keyword') to find compressed content when you need it later.`;
6238
6233
  }
@@ -8949,7 +8944,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
8949
8944
  import { join as join3 } from "path";
8950
8945
  import { existsSync as existsSync3 } from "fs";
8951
8946
  import { homedir as homedir3 } from "os";
8952
- var LOG_VERSION = true ? "1.14.16-pr.299.6" : "dev";
8947
+ var LOG_VERSION = true ? "1.14.16-pr.302.10" : "dev";
8953
8948
  var Logger = class {
8954
8949
  logDir;
8955
8950
  enabled;
@@ -9277,7 +9272,7 @@ Rules:
9277
9272
  BATCHING
9278
9273
  When multiple independent ranges are ready and their boundaries do not overlap, include all of them as separate entries in the \`content\` array of a single tool call. Each entry should have its own \`startId\`, \`endId\`, and \`summary\`.
9279
9274
 
9280
- When the ranges cover unrelated topics, give each entry its own \`topic\` for better summary quality \u2014 do not force unrelated content under a single shared topic. Omit the top-level \`topic\` when every entry has its own. Use the top-level \`topic\` only as a fallback when entries don't specify one.
9275
+ When the ranges cover unrelated topics, give each entry its own \`topic\` for better summary quality \u2014 do not force unrelated content under a single shared topic. The top-level \`topic\` is an optional fallback; when no topic is provided at all, one is derived from the summary's first line automatically.
9281
9276
 
9282
9277
  \`\`\`
9283
9278
  compress({ content: [