billion-context-dsh 0.2.13 → 0.2.15
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.en.md +1 -1
- package/README.md +1 -1
- package/dist/index.js +29 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[English](./README.en.md) | [中文](./README.md)
|
|
4
4
|
|
|
5
5
|
> **⚠️ Beta notice — not for production use**
|
|
6
|
-
> This project (**v0.2.
|
|
6
|
+
> This project (**v0.2.15**) is a work-in-progress beta. The [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) itself is also in **public beta**. **Do not use either in engineering / production environments** — expect breaking changes and rough edges.
|
|
7
7
|
|
|
8
8
|
<p align="center">
|
|
9
9
|
<strong>Built with gratitude on top of these projects</strong> — please give them a ⭐:
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[中文](./README.md) | [English](./README.en.md)
|
|
4
4
|
|
|
5
5
|
> **⚠️ 测试版声明——请勿用于生产环境**
|
|
6
|
-
> 本项目(**v0.2.
|
|
6
|
+
> 本项目(**v0.2.15**)仍处于开发中的测试版。[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 本身也处于**公开测试版**阶段。**请勿将两者用于工程化 / 生产环境**——预期会有破坏性变更与粗糙之处。
|
|
7
7
|
|
|
8
8
|
<p align="center">
|
|
9
9
|
<strong>衷心感谢以下项目——请给它们一个 ⭐:</strong>
|
package/dist/index.js
CHANGED
|
@@ -3502,7 +3502,7 @@ var AcpStateStore = class {
|
|
|
3502
3502
|
};
|
|
3503
3503
|
|
|
3504
3504
|
// src/tools.ts
|
|
3505
|
-
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
3505
|
+
import { defineTool, ToolArgsError } from "@deepseek-ai/dsh-tools";
|
|
3506
3506
|
|
|
3507
3507
|
// src/config.ts
|
|
3508
3508
|
function kernelConfigFor(input) {
|
|
@@ -3616,7 +3616,7 @@ var DEFAULT_PROMPTS = {
|
|
|
3616
3616
|
footer: "Compress with: compress({ content: [{ startSeq, endSeq, summary }] }) \u2014 content is an array: batch multiple unrelated segments in one call, each entry its own block. Keep ranges disjoint.\nSnapshot taken at nudge time: the seqs go stale once the surface moves (a later compress shadows them), so re-run acp_status for fresh refs before compressing."
|
|
3617
3617
|
},
|
|
3618
3618
|
tools: {
|
|
3619
|
-
compress: "Replace older conversation ranges with dense summaries you write. Each message seq is a surface reference. Single range: compress({ content: [{ startSeq, endSeq, summary }] }). Batch multiple unrelated ranges in one call (each content entry becomes its own block); keep ranges disjoint. Never compress content the current step is actively using. Compress boundaries are SURFACE SEQS (acp_status Surface: row, latest nudge table) \u2014 NOT the block refs (bN, e.g. b1) that acp_status COMPRESSED BLOCKS shows, which are for decompress only. Drilldown mN refs (e.g. m00306) are ALSO accepted as startSeq/endSeq \u2014 they are auto-mapped to the live surface seq; an unknown mN (never assigned on the current surface) fails with guidance. Seq refs must come from the CURRENT surface (acp_status or the latest nudge): a span whose edges were shadowed by an earlier compress is auto-remapped to its still-live content, a fully compressed span is reported as already compressed, and invented/other-session seqs fail with guidance. Good compression moments: stage or subtask completion, strategy switches, intermediate milestones, and wrapping up failed exploration \u2014 when the details are consumed and no longer critical for the task ahead. When you write a summary, turn dead-end exploration into a conclusion (what was tried, why it failed, the next step) \u2014 not a blow-by-blow; and keep the summary the ONLY record: self-contained, so a later reader (or you, after decompress) can continue without the original.",
|
|
3619
|
+
compress: "Replace older conversation ranges with dense summaries you write. Each message seq is a surface reference. Single range: compress({ content: [{ startSeq, endSeq, summary }] }). Batch multiple unrelated ranges in one call (each content entry becomes its own block); keep ranges disjoint. Never compress content the current step is actively using. Compress boundaries are SURFACE SEQS (acp_status Surface: row, latest nudge table) \u2014 NOT the block refs (bN, e.g. b1) that acp_status COMPRESSED BLOCKS shows, which are for decompress only. Drilldown mN refs (e.g. m00306) are ALSO accepted as startSeq/endSeq \u2014 they are auto-mapped to the live surface seq; an unknown mN (never assigned on the current surface) fails with guidance. Seq refs must come from the CURRENT surface (acp_status or the latest nudge): a span whose edges were shadowed by an earlier compress is auto-remapped to its still-live content, a fully compressed span is reported as already compressed, and invented/other-session seqs fail with guidance. Good compression moments: stage or subtask completion whose details you have fully consumed and will not re-check, strategy switches, intermediate milestones, and wrapping up failed exploration \u2014 when the details are consumed and no longer critical for the task ahead. Before compressing, ask: will I need to re-verify any detail from this range in this task? If yes, keep it live. When you write a summary, turn dead-end exploration into a conclusion (what was tried, why it failed, the next step) \u2014 not a blow-by-blow; and keep the summary the ONLY record: self-contained, so a later reader (or you, after decompress) can continue without the original.",
|
|
3620
3620
|
decompress: "Recover the original content of a compressed block by its blockId \u2014 the kernel block ref `bN` shown by acp_status (e.g. b1), or a compaction id from search_context (read-only; does not unshadow the range).",
|
|
3621
3621
|
searchContext: "Search inside compressed blocks (summaries and original content) for information the model no longer sees in context. When a summary lacks a detail you need (exact values, error strings, decisions, verbatim code), SEARCH the compressed blocks FIRST \u2014 never guess or reconstruct from memory: search_context(query) locates the right block, then decompress only that block to recover the original.",
|
|
3622
3622
|
acpStatus: 'Context status: overview of the current context \u2014 CONTEXT BREAKDOWN (tool/text/summaries token shares of the visible total), COMPRESSED BLOCKS ledger, and the nudge decision. No args = overview. Percentages are shares of the visible content, not the context window. Note: the block refs in COMPRESSED BLOCKS (bN, e.g. b1) are for decompress; compress uses the Surface: seq range, not bN. Drilldown: pass scope:"compressed" for a per-block list, or scope:"uncompressed" with view:"messages" (every visible message) / view:"ranges" (merged ranges); tool filters to one tool name, sort reorders (size/time/tool; age for compressed), limit caps rows (default 30). Drilldown row refs are kernel ids (mN) \u2014 feed them straight to compress as startSeq/endSeq (auto-mapped to the live surface seq); bN is for decompress, Surface: seqs also work in compress.'
|
|
@@ -3640,6 +3640,7 @@ WHEN NOT TO COMPRESS:
|
|
|
3640
3640
|
- Content the current step is actively reading or reasoning about.
|
|
3641
3641
|
- Important user messages \u2014 preserve their exact intent, constraints, and acceptance criteria.
|
|
3642
3642
|
- Protected tool outputs \u2014 hard-excluded from compression ranges, survive intact in visible context.
|
|
3643
|
+
- Content you will still need to cite verbatim \u2014 in review/audit/verification tasks, keep source reads un-compressed until the final report is written. If you compressed it and now need the exact detail, decompress costs a full round-trip; prefer delaying the compress.
|
|
3643
3644
|
|
|
3644
3645
|
{howToCompressRules}
|
|
3645
3646
|
|
|
@@ -3855,6 +3856,16 @@ var compressParameters = {
|
|
|
3855
3856
|
// intentionally NOT `required: true` — a required property would reject the
|
|
3856
3857
|
// wrapped shape before `handleCompress` can see it. The tool description
|
|
3857
3858
|
// still tells the model content is mandatory.
|
|
3859
|
+
//
|
|
3860
|
+
// The items fields are the opposite case: startSeq/endSeq/summary MUST be
|
|
3861
|
+
// `required: true`. Without that, a model call that omits `summary` (only
|
|
3862
|
+
// startSeq/endSeq/topic present) passed schema validation and failed late
|
|
3863
|
+
// inside the kernel with "Summary is empty" — and live sessions showed the
|
|
3864
|
+
// model retrying the identical broken call in a loop. With the fields
|
|
3865
|
+
// required, the same call is rejected at the schema gate with
|
|
3866
|
+
// `missing required property "content[0].summary"`, which tells the model
|
|
3867
|
+
// exactly which field to add (same pattern as decompress's required
|
|
3868
|
+
// blockId / search_context's required query).
|
|
3858
3869
|
arguments: { type: "json", description: "Tolerated wrapped-arguments form (model-generated); unwrapped in handleCompress. Prefer passing content directly." },
|
|
3859
3870
|
topic: { type: "string", description: "Fallback topic for entries without their own." },
|
|
3860
3871
|
content: {
|
|
@@ -3864,18 +3875,20 @@ var compressParameters = {
|
|
|
3864
3875
|
type: "object",
|
|
3865
3876
|
properties: {
|
|
3866
3877
|
startSeq: {
|
|
3878
|
+
required: true,
|
|
3867
3879
|
oneOf: [
|
|
3868
3880
|
{ type: "integer", description: "First surface seq of the range." },
|
|
3869
3881
|
{ type: "string", description: "Seq as text; a trailing #callId fragment is ignored." }
|
|
3870
3882
|
]
|
|
3871
3883
|
},
|
|
3872
3884
|
endSeq: {
|
|
3885
|
+
required: true,
|
|
3873
3886
|
oneOf: [
|
|
3874
3887
|
{ type: "integer", description: "Inclusive last surface seq of the range." },
|
|
3875
3888
|
{ type: "string", description: "Seq as text; a trailing #callId fragment is ignored." }
|
|
3876
3889
|
]
|
|
3877
3890
|
},
|
|
3878
|
-
summary: { type: "string", description: "Complete technical summary replacing the range; keep paths, decisions, values verbatim. Minimum 50 characters." },
|
|
3891
|
+
summary: { type: "string", required: true, description: "Complete technical summary replacing the range; keep paths, decisions, values verbatim. Minimum 50 characters." },
|
|
3879
3892
|
topic: { type: "string", description: "Short label (3-5 words) for this range." }
|
|
3880
3893
|
},
|
|
3881
3894
|
additionalProperties: false
|
|
@@ -3946,6 +3959,18 @@ function unwrapEnvelope(args) {
|
|
|
3946
3959
|
if (typeof inner !== "object" || inner === null || Array.isArray(inner)) return args;
|
|
3947
3960
|
return { ...args, ...inner };
|
|
3948
3961
|
}
|
|
3962
|
+
function validateContentItems(content) {
|
|
3963
|
+
const violations = [];
|
|
3964
|
+
content.forEach((item, index) => {
|
|
3965
|
+
const path = `content[${index}]`;
|
|
3966
|
+
if (item.startSeq === void 0) violations.push(`missing required property "${path}.startSeq"`);
|
|
3967
|
+
if (item.endSeq === void 0) violations.push(`missing required property "${path}.endSeq"`);
|
|
3968
|
+
if (typeof item.summary !== "string" || item.summary.trim().length === 0) {
|
|
3969
|
+
violations.push(`missing required property "${path}.summary"`);
|
|
3970
|
+
}
|
|
3971
|
+
});
|
|
3972
|
+
if (violations.length > 0) throw new ToolArgsError(violations);
|
|
3973
|
+
}
|
|
3949
3974
|
async function handleCompress(env, args, exec) {
|
|
3950
3975
|
const agent = requireAgent(exec);
|
|
3951
3976
|
const session = agent.session;
|
|
@@ -3967,6 +3992,7 @@ async function handleCompress(env, args, exec) {
|
|
|
3967
3992
|
};
|
|
3968
3993
|
}
|
|
3969
3994
|
args = unwrapped;
|
|
3995
|
+
validateContentItems(args.content);
|
|
3970
3996
|
const ranges = [];
|
|
3971
3997
|
const alreadyCompressedNotes = [];
|
|
3972
3998
|
for (const range of args.content) {
|