dsh-loop-engine 1.0.0-rc4 → 1.0.0-rc6
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/lib/index.js +27 -8
- package/lib/invariant.js +33 -10
- package/lib/types/patch-manager.d.ts +4 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -3695,19 +3695,38 @@ function ensureTrailingNewline(text) {
|
|
|
3695
3695
|
return text.endsWith("\n") ? text : `${text}
|
|
3696
3696
|
`;
|
|
3697
3697
|
}
|
|
3698
|
+
function hasRootEntry(text) {
|
|
3699
|
+
return /^(?:- |\[)/m.test(text);
|
|
3700
|
+
}
|
|
3701
|
+
function dropSeedPlaceholder(text) {
|
|
3702
|
+
return text.replace(/^\[\]\n/m, "");
|
|
3703
|
+
}
|
|
3704
|
+
function seedEmptyArray(text) {
|
|
3705
|
+
const head = text.replace(/\n+$/, "");
|
|
3706
|
+
return head === "" ? "[]\n" : `${head}
|
|
3707
|
+
[]
|
|
3708
|
+
`;
|
|
3709
|
+
}
|
|
3698
3710
|
function applyManagedBlock(text, engine) {
|
|
3699
3711
|
const block = renderManagedBlock(engine);
|
|
3700
3712
|
const span = managedSpan(text);
|
|
3713
|
+
let result;
|
|
3701
3714
|
if (!span.present) {
|
|
3702
|
-
if (block === "")
|
|
3703
|
-
|
|
3704
|
-
|
|
3715
|
+
if (block === "") {
|
|
3716
|
+
result = text;
|
|
3717
|
+
} else {
|
|
3718
|
+
const base = ensureTrailingNewline(text);
|
|
3719
|
+
result = `${base}
|
|
3705
3720
|
${block}`;
|
|
3706
|
-
|
|
3707
|
-
if (block === "") {
|
|
3708
|
-
|
|
3709
|
-
}
|
|
3710
|
-
|
|
3721
|
+
}
|
|
3722
|
+
} else if (block === "") {
|
|
3723
|
+
result = span.tail.startsWith("\n") ? `${span.head}${span.tail.slice(1)}` : `${span.head}${span.tail}`;
|
|
3724
|
+
} else {
|
|
3725
|
+
result = `${span.head}${span.blankBefore ? "\n" : ""}${block}${span.tail}`;
|
|
3726
|
+
}
|
|
3727
|
+
if (block !== "") return dropSeedPlaceholder(result);
|
|
3728
|
+
if (text.trim() === "") return result;
|
|
3729
|
+
return hasRootEntry(result) ? result : seedEmptyArray(result);
|
|
3711
3730
|
}
|
|
3712
3731
|
|
|
3713
3732
|
// src/commands.ts
|
package/lib/invariant.js
CHANGED
|
@@ -45,19 +45,38 @@ function ensureTrailingNewline(text) {
|
|
|
45
45
|
return text.endsWith("\n") ? text : `${text}
|
|
46
46
|
`;
|
|
47
47
|
}
|
|
48
|
+
function hasRootEntry(text) {
|
|
49
|
+
return /^(?:- |\[)/m.test(text);
|
|
50
|
+
}
|
|
51
|
+
function dropSeedPlaceholder(text) {
|
|
52
|
+
return text.replace(/^\[\]\n/m, "");
|
|
53
|
+
}
|
|
54
|
+
function seedEmptyArray(text) {
|
|
55
|
+
const head = text.replace(/\n+$/, "");
|
|
56
|
+
return head === "" ? "[]\n" : `${head}
|
|
57
|
+
[]
|
|
58
|
+
`;
|
|
59
|
+
}
|
|
48
60
|
function applyManagedBlock(text, engine) {
|
|
49
61
|
const block = renderManagedBlock(engine);
|
|
50
62
|
const span = managedSpan(text);
|
|
63
|
+
let result;
|
|
51
64
|
if (!span.present) {
|
|
52
|
-
if (block === "")
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
if (block === "") {
|
|
66
|
+
result = text;
|
|
67
|
+
} else {
|
|
68
|
+
const base = ensureTrailingNewline(text);
|
|
69
|
+
result = `${base}
|
|
55
70
|
${block}`;
|
|
71
|
+
}
|
|
72
|
+
} else if (block === "") {
|
|
73
|
+
result = span.tail.startsWith("\n") ? `${span.head}${span.tail.slice(1)}` : `${span.head}${span.tail}`;
|
|
74
|
+
} else {
|
|
75
|
+
result = `${span.head}${span.blankBefore ? "\n" : ""}${block}${span.tail}`;
|
|
56
76
|
}
|
|
57
|
-
if (block
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return `${span.head}${span.blankBefore ? "\n" : ""}${block}${span.tail}`;
|
|
77
|
+
if (block !== "") return dropSeedPlaceholder(result);
|
|
78
|
+
if (text.trim() === "") return result;
|
|
79
|
+
return hasRootEntry(result) ? result : seedEmptyArray(result);
|
|
61
80
|
}
|
|
62
81
|
|
|
63
82
|
// src/invariant.ts
|
|
@@ -66,13 +85,17 @@ var name = "loop-engine-invariant";
|
|
|
66
85
|
var inject = ["invariants"];
|
|
67
86
|
var install = (ctx, fail) => {
|
|
68
87
|
void ctx;
|
|
69
|
-
const seed = "
|
|
88
|
+
const seed = "";
|
|
89
|
+
const commentOnly = "# dsh profile patch layer\n";
|
|
70
90
|
for (const engine of LOOP_ENGINE_IDS) {
|
|
71
91
|
const applied = applyManagedBlock(seed, engine);
|
|
72
92
|
const reborn = applyManagedBlock(applied, currentEngineOf(applied));
|
|
73
|
-
if (reborn !== applied) fail(`
|
|
74
|
-
if (engine === "in-process" && applied !== seed) fail("in-process engine must leave
|
|
93
|
+
if (reborn !== applied) fail(`bare round trip for ${engine} is not a fixed point`);
|
|
94
|
+
if (engine === "in-process" && applied !== seed) fail("in-process engine must leave a bare layer unchanged");
|
|
75
95
|
if (engine !== "in-process" && currentEngineOf(renderManagedBlock(engine)) !== engine) fail(`${engine} block must read back as the ${engine} engine`);
|
|
96
|
+
if (engine === "in-process" && applyManagedBlock(commentOnly, engine) === commentOnly) {
|
|
97
|
+
fail("in-process engine must re-seed a comment-only file to a loadable top-level array");
|
|
98
|
+
}
|
|
76
99
|
}
|
|
77
100
|
};
|
|
78
101
|
var apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
@@ -38,7 +38,10 @@ export declare function currentEngineOf(text: string): LoopEngineId;
|
|
|
38
38
|
/**
|
|
39
39
|
* Produce the next patch-file text for a target engine, preserving every byte
|
|
40
40
|
* outside the managed span. Appends the span when absent; replaces or removes
|
|
41
|
-
* it when present.
|
|
41
|
+
* it when present. The managed block is a root-level collection, so a leftover
|
|
42
|
+
* seed `[]` is dropped when adding it, and a removal that leaves no entries is
|
|
43
|
+
* re-seeded back to `[]` — either way the file stays a single valid top-level
|
|
44
|
+
* array the harness can boot.
|
|
42
45
|
* @param text - current patch-file text.
|
|
43
46
|
* @param engine - target engine.
|
|
44
47
|
* @returns the rewritten patch-file text.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-loop-engine",
|
|
3
3
|
"description": "Web-switchable agent loop engine selection for the DeepSeek Harness - out-of-tree plugin (Claude Code / Codex drivers) maintained by @kuun993, zero main-repo changes",
|
|
4
|
-
"version": "1.0.0-
|
|
4
|
+
"version": "1.0.0-rc6",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|