dsh-context-core 0.1.1

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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -0
  3. package/README.zh-CN.md +80 -0
  4. package/dist/compat/@deepseek-ai__dsh-session@0.1.7-rc.2.patch +25 -0
  5. package/dist/compat/DSH-LICENSE +21 -0
  6. package/dist/compat/README.md +28 -0
  7. package/dist/compat/README.zh-CN.md +28 -0
  8. package/dist/compat/dsh-session-source.patch +16 -0
  9. package/dist/config.d.ts +4 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +27 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/host.d.ts +30 -0
  14. package/dist/host.d.ts.map +1 -0
  15. package/dist/host.js +185 -0
  16. package/dist/host.js.map +1 -0
  17. package/dist/index.d.ts +8 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +5 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/pipeline.d.ts +104 -0
  22. package/dist/pipeline.d.ts.map +1 -0
  23. package/dist/pipeline.js +2 -0
  24. package/dist/pipeline.js.map +1 -0
  25. package/dist/plugin.d.ts +38 -0
  26. package/dist/plugin.d.ts.map +1 -0
  27. package/dist/plugin.js +180 -0
  28. package/dist/plugin.js.map +1 -0
  29. package/dist/tools/create-profile-patch.mjs +187 -0
  30. package/dist/transaction.d.ts +29 -0
  31. package/dist/transaction.d.ts.map +1 -0
  32. package/dist/transaction.js +122 -0
  33. package/dist/transaction.js.map +1 -0
  34. package/dist/types.d.ts +82 -0
  35. package/dist/types.d.ts.map +1 -0
  36. package/dist/types.js +2 -0
  37. package/dist/types.js.map +1 -0
  38. package/package.json +61 -0
  39. package/src/config.ts +18 -0
  40. package/src/host.ts +189 -0
  41. package/src/index.ts +7 -0
  42. package/src/pipeline.ts +114 -0
  43. package/src/plugin.ts +160 -0
  44. package/src/transaction.ts +121 -0
  45. package/src/types.ts +81 -0
@@ -0,0 +1,104 @@
1
+ import type { ContentBlock, Message, RequestMessage, TokenUsage, ToolSchema } from '@deepseek-ai/dsh-llm';
2
+ import type { CompactionResult } from '@deepseek-ai/dsh-compaction';
3
+ import type { SessionSeq } from '@deepseek-ai/dsh-session';
4
+ import type { ContextConfig } from './types.js';
5
+ /** A durable message with the host's observations; plugins choose their own prices and interpretation. */
6
+ export interface ContextEntry {
7
+ seq: SessionSeq;
8
+ message: Message;
9
+ time: number;
10
+ tokens: number;
11
+ usage?: TokenUsage;
12
+ finish?: string;
13
+ toolName?: string;
14
+ toolArguments?: string;
15
+ }
16
+ /** Immutable observations for one admitted operation. */
17
+ export interface ContextSnapshot {
18
+ entries: readonly ContextEntry[];
19
+ /** Full durable message history, including content replaced by earlier checkpoints. */
20
+ archive: readonly ContextEntry[];
21
+ contextWindow: number;
22
+ maxOutputTokens: number;
23
+ inputLimit?: number;
24
+ provider: string;
25
+ model: string;
26
+ tools: readonly ToolSchema[];
27
+ measuredTokens: number;
28
+ now: number;
29
+ /** Stable through failed retries; advances at a new turn or successful assistant response. */
30
+ requestSeries: string;
31
+ /** Stable for an entire user turn; absent for hosts without a turn lifecycle. */
32
+ turnKey?: string;
33
+ cwd: string;
34
+ sessionId: string;
35
+ /** Observed host recovery pointers; absent capabilities must not be claimed. */
36
+ recovery?: ContextRecovery;
37
+ }
38
+ export type ContextTrigger = 'pressure' | 'manual' | 'context-overflow' | 'request-too-large';
39
+ /** Low-level auxiliary model call. Formatting, clipping, retry and output validation belong to the plugin. */
40
+ export interface SummaryRequest {
41
+ messages: readonly RequestMessage[];
42
+ instruction: string;
43
+ maxTokens: number;
44
+ includeTools?: boolean;
45
+ provider?: string;
46
+ model?: string;
47
+ }
48
+ /** One settled call, preserved even when a plugin later rejects its text. */
49
+ export interface SummaryResponse {
50
+ text: string;
51
+ content: ContentBlock[];
52
+ provider: string;
53
+ model: string;
54
+ maxTokens: number;
55
+ usage?: TokenUsage;
56
+ finish?: string;
57
+ }
58
+ /** Checkpoint and recovered context that will replace the selected history atomically. */
59
+ export interface Checkpoint {
60
+ summary: string;
61
+ beforeSummary?: readonly ContentBlock[];
62
+ restored?: readonly ContentBlock[];
63
+ }
64
+ /** Explicit replacement selected by a plugin's microcompaction algorithm. */
65
+ export interface ContextReplacement {
66
+ seq: SessionSeq;
67
+ content: readonly ContentBlock[];
68
+ }
69
+ /** Observations supplied by an installed host integration. */
70
+ export interface ContextRecovery {
71
+ approvedPlanPath?: string;
72
+ transcriptPath?: string;
73
+ wirePath?: string;
74
+ windowLines?: string;
75
+ todos?: string;
76
+ reminders?: readonly ContentBlock[];
77
+ replStateCleared?: boolean;
78
+ }
79
+ /** Host primitives contain no source-agent trigger, retention, pruning or retry policy. */
80
+ export interface ContextHost {
81
+ readonly signal: AbortSignal;
82
+ snapshot(): Promise<ContextSnapshot>;
83
+ summarize(request: SummaryRequest): Promise<SummaryResponse>;
84
+ replace(replacements: readonly ContextReplacement[]): void;
85
+ compact(entries: readonly ContextEntry[], summarize: () => Promise<Checkpoint>): Promise<CompactionResult>;
86
+ /** Read through DSH's filesystem provider; null means absent or unavailable, never a fabricated file snapshot. */
87
+ readFile(path: string, maxChars: number): Promise<string | null>;
88
+ /** Append plugin state as an ignorable durable event, keeping replay independent of live plugin instances. */
89
+ record(kind: string, data: Record<string, unknown>): void;
90
+ records(kind: string): readonly Record<string, unknown>[];
91
+ }
92
+ /** Each package owns the complete sequence of decisions and transformations. */
93
+ export interface ContextPipeline {
94
+ run(host: ContextHost, trigger: ContextTrigger): Promise<CompactionResult | null>;
95
+ /** Explicit range requests still use the package's summary and recovery sequence. */
96
+ summarizeRange(host: ContextHost, entries: readonly ContextEntry[]): Promise<Checkpoint>;
97
+ /** Optional native branch-navigation integration, invoked explicitly by the host. */
98
+ summarizeBranch?(host: ContextHost, entries: readonly ContextEntry[]): Promise<string>;
99
+ }
100
+ export interface PipelineDefinition {
101
+ id: string;
102
+ create(config?: ContextConfig): ContextPipeline;
103
+ }
104
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ /** Cordis registration and lifecycle delegation, without agent-specific decisions. */
2
+ import { Context } from '@deepseek-ai/cordis';
3
+ import type { CompactionAgentContext, ManualCompactAgentContext } from '@deepseek-ai/dsh-compaction';
4
+ import type { SessionSeq } from '@deepseek-ai/dsh-session';
5
+ import type { ContextConfig } from './types.js';
6
+ import type { PipelineDefinition } from './pipeline.js';
7
+ /** Cordis plugin providing one context engine. */
8
+ export interface ContextPlugin {
9
+ name: string;
10
+ inject: string[];
11
+ apply(ctx: Context, config?: ContextConfig): void;
12
+ }
13
+ declare module '@deepseek-ai/cordis' {
14
+ interface Events {
15
+ /**
16
+ * Summarize an explicit abandoned branch under the caller's maintenance lock.
17
+ * @param agent - idle session owner whose durable log contains the selected events.
18
+ * @param seqs - branch message events in conversation order.
19
+ * @param signal - cancellation forwarded to the summary provider.
20
+ * @param next - delegate if this context plugin has no branch workflow.
21
+ * @mode waterfall
22
+ */
23
+ 'context-zoo/summarize-branch'(agent: CompactionAgentContext, seqs: readonly SessionSeq[], signal: AbortSignal, next: () => Promise<string | undefined>): Promise<string | undefined>;
24
+ }
25
+ }
26
+ /**
27
+ * Run a plugin's explicit branch workflow and flush its durable summary metadata.
28
+ * The navigation integration inserts the returned text in its new branch as a logged message.
29
+ * @param ctx - Cordis context with the selected plugin.
30
+ * @param agent - idle agent containing the abandoned branch events.
31
+ * @param seqs - message sequence numbers in branch order.
32
+ * @param signal - caller cancellation.
33
+ * @returns the branch summary, or undefined when the plugin has no branch workflow.
34
+ */
35
+ export declare function summarizeBranch(ctx: Context, agent: ManualCompactAgentContext, seqs: readonly SessionSeq[], signal: AbortSignal): Promise<string | undefined>;
36
+ /** Register a source-owned pipeline using the common DSH service and event protocols. */
37
+ export declare function createContextPlugin(definition: PipelineDefinition): ContextPlugin;
38
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAG9C,OAAO,KAAK,EAAE,sBAAsB,EAAuC,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAI1I,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAI3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAmC,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEzF,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CACnD;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,MAAM;QACd;;;;;;;WAOG;QACH,8BAA8B,CAAC,KAAK,EAAE,sBAAsB,EAAE,IAAI,EAAE,SAAS,UAAU,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;KACvL;CACF;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,yBAAyB,EAAE,IAAI,EAAE,SAAS,UAAU,EAAE,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAe7J;AAED,yFAAyF;AACzF,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,kBAAkB,GAAG,aAAa,CAgGjF"}
package/dist/plugin.js ADDED
@@ -0,0 +1,180 @@
1
+ /** Cordis registration and lifecycle delegation, without agent-specific decisions. */
2
+ import { Context } from '@deepseek-ai/cordis';
3
+ import { CompactionEngine, ManualCompactionError } from '@deepseek-ai/dsh-compaction';
4
+ import { CONTEXT_WINDOW_EXCEEDED_CODE } from '@deepseek-ai/dsh-llm';
5
+ import { Session, SessionId } from '@deepseek-ai/dsh-session';
6
+ import { validateConfig } from './config.js';
7
+ import { createHost } from './host.js';
8
+ import { assertInactive } from './transaction.js';
9
+ /**
10
+ * Run a plugin's explicit branch workflow and flush its durable summary metadata.
11
+ * The navigation integration inserts the returned text in its new branch as a logged message.
12
+ * @param ctx - Cordis context with the selected plugin.
13
+ * @param agent - idle agent containing the abandoned branch events.
14
+ * @param seqs - message sequence numbers in branch order.
15
+ * @param signal - caller cancellation.
16
+ * @returns the branch summary, or undefined when the plugin has no branch workflow.
17
+ */
18
+ export function summarizeBranch(ctx, agent, seqs, signal) {
19
+ signal.throwIfAborted();
20
+ return agent.runMaintenance(async (agentSignal) => {
21
+ const operationSignal = AbortSignal.any([agentSignal, signal]);
22
+ let summary;
23
+ let failed = false;
24
+ let failure;
25
+ try {
26
+ summary = await ctx.waterfall('context-zoo/summarize-branch', agent, seqs, operationSignal, async () => undefined);
27
+ }
28
+ catch (error) {
29
+ failed = true;
30
+ failure = error;
31
+ }
32
+ try {
33
+ await ctx.sessions.flush(agent.session);
34
+ }
35
+ catch (error) {
36
+ if (!failed) {
37
+ failed = true;
38
+ failure = error;
39
+ }
40
+ }
41
+ operationSignal.throwIfAborted();
42
+ if (failed)
43
+ throw failure;
44
+ return summary;
45
+ });
46
+ }
47
+ /** Register a source-owned pipeline using the common DSH service and event protocols. */
48
+ export function createContextPlugin(definition) {
49
+ return {
50
+ name: `context-${definition.id}`,
51
+ inject: ['llm', 'tokenMeter', 'sessions'],
52
+ apply(ctx, config = {}) {
53
+ validateConfig(config);
54
+ const probe = Session.create(SessionId('context-zoo-capability-probe'));
55
+ const marker = probe.append('context-zoo/state', { plugin: definition.id, kind: 'probe', data: {} }, { ignorable: true });
56
+ if (marker.ignorable !== true)
57
+ throw new Error('DSH Session.append needs the supplied ignorable-event patch; see dsh-context-core/dist/compat/README.md');
58
+ const settings = Object.freeze({ ...config });
59
+ const pipelines = new WeakMap();
60
+ const pipelineFor = (session) => {
61
+ let pipeline = pipelines.get(session);
62
+ if (!pipeline) {
63
+ pipeline = definition.create(settings);
64
+ pipelines.set(session, pipeline);
65
+ }
66
+ return pipeline;
67
+ };
68
+ const run = async (agent, trigger, signal, manual = false, sourceCommandId) => {
69
+ signal.throwIfAborted();
70
+ assertInactive(agent.session);
71
+ return pipelineFor(agent.session).run(createHost(ctx, agent, definition.id, settings, signal, manual, sourceCommandId), trigger);
72
+ };
73
+ class PipelineEngine extends CompactionEngine {
74
+ compactIfNeeded(agent, trigger, signal) {
75
+ return run(agent, trigger, signal);
76
+ }
77
+ async compactRegion(start, end, agent, signal = new AbortController().signal) {
78
+ const host = createHost(ctx, agent, definition.id, settings, signal);
79
+ const snapshot = await host.snapshot();
80
+ const first = snapshot.entries.findIndex(entry => entry.seq === start);
81
+ const last = snapshot.entries.findIndex(entry => entry.seq === end);
82
+ if (first < 0 || last < first)
83
+ throw new Error('Invalid context range');
84
+ const entries = snapshot.entries.slice(first, last + 1);
85
+ return host.compact(entries, () => pipelineFor(agent.session).summarizeRange(host, entries));
86
+ }
87
+ compactNow(agent, signal, sourceCommandId) {
88
+ signal.throwIfAborted();
89
+ try {
90
+ return agent.runMaintenance(async (agentSignal) => {
91
+ const operationSignal = AbortSignal.any([agentSignal, signal]);
92
+ const before = agent.session.seq;
93
+ let result = null;
94
+ let failed = false;
95
+ let failure;
96
+ try {
97
+ result = await run(agent, 'manual', operationSignal, true, sourceCommandId);
98
+ }
99
+ catch (error) {
100
+ failed = true;
101
+ failure = error;
102
+ }
103
+ if (agent.session.seq !== before) {
104
+ try {
105
+ await ctx.sessions.flush(agent.session);
106
+ }
107
+ catch (error) {
108
+ if (!failed) {
109
+ failed = true;
110
+ failure = new ManualCompactionError('persistence', 'Manual compaction could not be flushed', { cause: error });
111
+ }
112
+ }
113
+ }
114
+ signal.throwIfAborted();
115
+ if (agentSignal.aborted)
116
+ throw new ManualCompactionError('cancelled', 'Manual compaction was cancelled', { cause: operationSignal.reason });
117
+ if (failed)
118
+ throw failure;
119
+ return result;
120
+ });
121
+ }
122
+ catch (error) {
123
+ throw new ManualCompactionError('busy', 'Manual compaction requires an idle agent', { cause: error });
124
+ }
125
+ }
126
+ }
127
+ ctx.plugin(PipelineEngine);
128
+ ctx.on('context-zoo/summarize-branch', async (agent, seqs, signal, next) => {
129
+ const pipeline = pipelineFor(agent.session);
130
+ if (!pipeline.summarizeBranch)
131
+ return next();
132
+ assertInactive(agent.session);
133
+ const host = createHost(ctx, agent, definition.id, settings, signal, true);
134
+ const snapshot = await host.snapshot();
135
+ const bySeq = new Map(snapshot.archive.map(entry => [entry.seq, entry]));
136
+ const entries = seqs.map(seq => {
137
+ const entry = bySeq.get(seq);
138
+ if (!entry)
139
+ throw new Error(`Missing branch message ${seq}`);
140
+ return entry;
141
+ });
142
+ const summary = await pipeline.summarizeBranch(host, entries);
143
+ signal.throwIfAborted();
144
+ host.record('branch-summary', { seqs: [...seqs], summary });
145
+ return summary;
146
+ });
147
+ if (settings.auto === false)
148
+ return;
149
+ ctx.on('agent/pre-step', async ({ agent, signal }, next) => {
150
+ if (!signal.aborted) {
151
+ try {
152
+ await run(agent, 'pressure', signal);
153
+ }
154
+ catch (error) {
155
+ if (!signal.aborted)
156
+ ctx.logger.warn(`${definition.id} context preparation failed: ${error instanceof Error ? error.message : String(error)}`);
157
+ }
158
+ }
159
+ return next();
160
+ });
161
+ ctx.on('agent/request-error', async ({ agent, failure, signal }, next) => {
162
+ const trigger = failure.status === 413 ? 'request-too-large' : failure.code === CONTEXT_WINDOW_EXCEEDED_CODE ? 'context-overflow' : undefined;
163
+ if (!trigger || signal.aborted)
164
+ return next();
165
+ const generation = agent.session.surface.replaceGeneration;
166
+ try {
167
+ await run(agent, trigger, signal);
168
+ }
169
+ catch (error) {
170
+ if (!signal.aborted)
171
+ ctx.logger.warn(`${definition.id} context recovery failed: ${error instanceof Error ? error.message : String(error)}`);
172
+ }
173
+ if (!signal.aborted && agent.session.surface.replaceGeneration > generation)
174
+ return { kind: 'retry' };
175
+ return next();
176
+ });
177
+ },
178
+ };
179
+ }
180
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env node
2
+ /** Generate a loader overlay from a resolved DSH profile without editing that profile. */
3
+ import { readFileSync, realpathSync } from 'node:fs';
4
+ import { pathToFileURL } from 'node:url';
5
+ import { parse, stringify } from 'yaml';
6
+
7
+ const agentIds = ['claude-code', 'codex', 'opencode', 'pi', 'qwen-code', 'zcode', 'kimi-code', 'cline'];
8
+ const managedNames = new Set(agentIds.map(id => `dsh-context-${id}`));
9
+ const nativeEngine = '@deepseek-ai/dsh-compaction-basic';
10
+ const nativePruner = '@deepseek-ai/dsh-compaction-tool-result-pruner';
11
+ const presetName = '@deepseek-ai/dsh-agent-preset';
12
+ const rootGroupId = 'context-zoo';
13
+
14
+ const jsTag = {
15
+ tag: 'tag:yaml.org,2002:js',
16
+ identify: value => isRecord(value) && typeof value.__jsExpr === 'string' && Object.keys(value).length === 1,
17
+ resolve: value => ({ __jsExpr: value }),
18
+ stringify: item => JSON.stringify(item.value.__jsExpr),
19
+ };
20
+
21
+ function isRecord(value) {
22
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
23
+ }
24
+
25
+ function assertRows(rows) {
26
+ if (!Array.isArray(rows) || !rows.every(isRecord)) throw new Error('Expected a resolved DSH profile entry list');
27
+ }
28
+
29
+ /** Parse a DSH config dump while preserving its unevaluated !!js expressions. */
30
+ export function parseProfileDump(source) {
31
+ const entries = parse(source, { customTags: [jsTag] });
32
+ assertRows(entries);
33
+ return entries;
34
+ }
35
+
36
+ /** Print a loader overlay using DSH's !!js YAML tag for preserved expressions. */
37
+ export function stringifyProfilePatch(patches) {
38
+ return stringify(patches, { customTags: [jsTag], lineWidth: 0 });
39
+ }
40
+
41
+ function isEngine(entry) {
42
+ return entry.name === nativeEngine || managedNames.has(entry.name);
43
+ }
44
+
45
+ function activeEngine(entry) {
46
+ if (!isEngine(entry) || entry.disabled === true) return false;
47
+ if (entry.disabled !== undefined && entry.disabled !== null && entry.disabled !== false) {
48
+ throw new Error(`Cannot select a conditionally disabled context engine: ${entry.id ?? entry.name}`);
49
+ }
50
+ return true;
51
+ }
52
+
53
+ function requireId(entry) {
54
+ if (typeof entry.id !== 'string' || entry.id.length === 0) throw new Error(`The profile entry needs an id: ${entry.name}`);
55
+ return entry.id;
56
+ }
57
+
58
+ function replaceEngine(entry, packageName) {
59
+ return { ...entry, name: packageName, config: entry.name === nativeEngine ? {} : (entry.config ?? {}) };
60
+ }
61
+
62
+ /** Resolve the compaction realms declared by groups; ordinary groups share their parent's services. */
63
+ function inspectComposition(entries) {
64
+ const rootRealm = {};
65
+ const namedRealms = new Map();
66
+ const engineRealms = new Map();
67
+ const engines = new Set();
68
+ const pruners = new Map();
69
+ const rootIds = new Set();
70
+ const checkIds = (rows, ids) => {
71
+ assertRows(rows);
72
+ for (const entry of rows) {
73
+ if (entry.id !== undefined) {
74
+ if (ids.has(entry.id)) throw new Error(`Duplicate loader entry id: ${entry.id}`);
75
+ ids.add(entry.id);
76
+ }
77
+ if (entry.group === true && Array.isArray(entry.config)) checkIds(entry.config, ids);
78
+ if (entry.name === presetName && isRecord(entry.config)) checkIds(entry.config.plugins, new Set());
79
+ }
80
+ };
81
+ checkIds(entries, rootIds);
82
+ const visit = (rows, parentRealm, conditional = false, inPreset = false) => {
83
+ for (const entry of rows) {
84
+ if (entry.disabled === true) continue;
85
+ let realm = parentRealm;
86
+ const label = entry.isolate?.compaction;
87
+ if (label === true) realm = {};
88
+ else if (typeof label === 'string' && label.length > 0) {
89
+ if (!namedRealms.has(label)) namedRealms.set(label, {});
90
+ realm = namedRealms.get(label);
91
+ } else if (label !== undefined) throw new Error(`Invalid compaction isolation on ${entry.id ?? entry.name}`);
92
+ const uncertain = conditional || (entry.disabled !== undefined && entry.disabled !== null && entry.disabled !== false);
93
+ if (activeEngine(entry)) {
94
+ if (uncertain) throw new Error(`Cannot replace a context engine under a conditionally disabled entry: ${entry.id ?? entry.name}`);
95
+ if (inPreset && realm === rootRealm) throw new Error(`Preset context engines require compaction isolation: ${entry.id ?? entry.name}`);
96
+ if (engineRealms.has(realm)) throw new Error('A compaction realm contains more than one active compaction engine');
97
+ engineRealms.set(realm, entry);
98
+ engines.add(entry);
99
+ }
100
+ if (entry.name === nativePruner) pruners.set(entry, realm);
101
+ if (entry.group === true && Array.isArray(entry.config)) visit(entry.config, realm, uncertain, inPreset);
102
+ // The registry mounts each preset from its host owner; a declaration's local services are not inherited.
103
+ if (entry.name === presetName && isRecord(entry.config)) visit(entry.config.plugins, rootRealm, uncertain, true);
104
+ }
105
+ };
106
+ visit(entries, rootRealm);
107
+ return { engines, pruners: new Set([...pruners].filter(([, realm]) => engineRealms.has(realm)).map(([entry]) => entry)), rootIds };
108
+ }
109
+
110
+ /**
111
+ * Replace active native or zoo engines in a resolved profile and preserve every other setting.
112
+ * Group and preset config overrides contain their full original config because DSH replaces it.
113
+ * @param entries - The entry list printed by dsh --dump-config.
114
+ * @param agentId - One of the supported context strategy ids.
115
+ * @returns A loader patch list to apply after the profile's existing layers.
116
+ */
117
+ export function createProfilePatch(entries, agentId) {
118
+ assertRows(entries);
119
+ if (!agentIds.includes(agentId)) throw new Error(`Unknown context strategy ${JSON.stringify(agentId)}; choose ${agentIds.join(', ')}`);
120
+ const packageName = `dsh-context-${agentId}`;
121
+ const copied = structuredClone(entries);
122
+ const { engines, pruners, rootIds } = inspectComposition(copied);
123
+ let changes = 0;
124
+
125
+ const rewriteRows = (rows) => {
126
+ assertRows(rows);
127
+ return rows.map(entry => {
128
+ if (entry.disabled === true) return entry;
129
+ if (engines.has(entry)) {
130
+ changes++;
131
+ return replaceEngine(entry, packageName);
132
+ }
133
+ if (pruners.has(entry)) { changes++; return { ...entry, disabled: true }; }
134
+ if (entry.group === true && Array.isArray(entry.config)) return { ...entry, config: rewriteRows(entry.config) };
135
+ if (entry.name === presetName && isRecord(entry.config)) {
136
+ return { ...entry, config: { ...entry.config, plugins: rewriteRows(entry.config.plugins) } };
137
+ }
138
+ return entry;
139
+ });
140
+ };
141
+
142
+ const patches = [];
143
+ const direct = copied.filter(entry => engines.has(entry));
144
+ if (direct.length > 1) throw new Error('Replacing multiple separately isolated host engines requires a group configuration');
145
+ for (const entry of copied) {
146
+ if (entry.disabled === true) continue;
147
+ if (engines.has(entry)) {
148
+ patches.push({ id: requireId(entry), name: entry.name, disabled: true });
149
+ continue;
150
+ }
151
+ if (pruners.has(entry)) {
152
+ patches.push({ id: requireId(entry), name: entry.name, disabled: true });
153
+ continue;
154
+ }
155
+ const before = changes;
156
+ let config;
157
+ if (entry.group === true && Array.isArray(entry.config)) config = rewriteRows(entry.config);
158
+ else if (entry.name === presetName && isRecord(entry.config)) {
159
+ config = { ...entry.config, plugins: rewriteRows(entry.config.plugins) };
160
+ }
161
+ if (changes !== before) patches.push({ id: requireId(entry), name: entry.name, config });
162
+ }
163
+ if (direct.length > 0) {
164
+ for (const id of [rootGroupId, 'context-zoo-engine']) {
165
+ if (rootIds.has(id)) throw new Error(`Cannot insert context engine: profile id ${id} is already in use`);
166
+ }
167
+ patches.push({ insert: [{
168
+ id: rootGroupId,
169
+ name: 'cordis:group',
170
+ group: true,
171
+ config: [{ ...replaceEngine(direct[0], packageName), id: 'context-zoo-engine' }],
172
+ }] });
173
+ }
174
+ if (engines.size === 0) throw new Error('No active native or zoo compaction engine was found in the resolved profile');
175
+ return patches;
176
+ }
177
+
178
+ if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) {
179
+ try {
180
+ const [agentId, filename, ...extra] = process.argv.slice(2);
181
+ if (!agentId || !filename || extra.length > 0) throw new Error('Usage: dsh-context-patch <agent-id> <resolved-profile.yml>');
182
+ process.stdout.write(stringifyProfilePatch(createProfilePatch(parseProfileDump(readFileSync(filename, 'utf8')), agentId)));
183
+ } catch (error) {
184
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
185
+ process.exitCode = 1;
186
+ }
187
+ }
@@ -0,0 +1,29 @@
1
+ import type { CompactionResult } from '@deepseek-ai/dsh-compaction';
2
+ import type { CommandId } from '@deepseek-ai/dsh-commands/brand';
3
+ import type { Session } from '@deepseek-ai/dsh-session';
4
+ import type { TokenMeter } from '@deepseek-ai/dsh-token-meter';
5
+ import type { Checkpoint, ContextEntry, SummaryResponse } from './pipeline.js';
6
+ /** Inspect current durable ownership, excluding interrupted constructor seeds. */
7
+ export declare function entryState(session: Session): {
8
+ active: boolean;
9
+ turn: number | null;
10
+ };
11
+ /** Reject competing mutation before any surface change. */
12
+ export declare function assertInactive(session: Session): void;
13
+ export interface TransactionOptions {
14
+ session: Session;
15
+ meter: TokenMeter;
16
+ entries: readonly ContextEntry[];
17
+ signal: AbortSignal;
18
+ manual: boolean;
19
+ sourceCommandId?: CommandId;
20
+ summarize(): Promise<Checkpoint>;
21
+ calls(): readonly (SummaryResponse | undefined)[];
22
+ target: {
23
+ provider: string;
24
+ model: string;
25
+ };
26
+ }
27
+ /** Commit the chosen range only after its summary and recovery have both succeeded. */
28
+ export declare function compactTransaction(options: TransactionOptions): Promise<CompactionResult>;
29
+ //# sourceMappingURL=transaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAGjE,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE/E,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAWrF;AAED,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAErD;AAgBD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IACjC,KAAK,IAAI,SAAS,CAAC,eAAe,GAAG,SAAS,CAAC,EAAE,CAAC;IAClD,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,uFAAuF;AACvF,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8D/F"}