@carljia/omd-dsh 0.1.0 → 0.1.2
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/cli.js +106 -11
- package/lib/ulw.d.ts +13 -0
- package/lib/ulw.js +55 -0
- package/lib/vendor/omd-ulw.mjs +55 -0
- package/omd-matrix.json +14 -2
- package/package.json +1 -1
- package/presets/omd-executor/agent.cordis.yml +4 -1
package/lib/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { promises as fs, existsSync, realpathSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { promises as fs, existsSync, realpathSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { dirname, join, relative, resolve, basename } from "node:path";
|
|
5
5
|
import { homedir } from "node:os";
|
|
@@ -25,7 +25,7 @@ import { createInterface } from "node:readline/promises";
|
|
|
25
25
|
* absolute file:// URLs into the harness node_modules tree.
|
|
26
26
|
*/
|
|
27
27
|
const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
28
|
-
const VENDOR_SOURCES = ["omd-mode.mjs", "omd-task.mjs"];
|
|
28
|
+
const VENDOR_SOURCES = ["omd-mode.mjs", "omd-task.mjs", "omd-ulw.mjs"];
|
|
29
29
|
const MATRIX_PATH = join(PACKAGE_ROOT, "omd-matrix.json");
|
|
30
30
|
const MODE_FENCE = { start: "# [omd-dsh:mode:start]", end: "# [omd-dsh:mode:end]" };
|
|
31
31
|
const TASK_FENCE = { start: "# [omd-dsh:task:start]", end: "# [omd-dsh:task:end]" };
|
|
@@ -37,7 +37,7 @@ function usage() {
|
|
|
37
37
|
" setup interactive: discover DSH models, then guide per-mode/tier model selection",
|
|
38
38
|
" models print the discovered DSH model catalog",
|
|
39
39
|
" options:",
|
|
40
|
-
" --harness <path> node_modules dir of the DSH harness install (
|
|
40
|
+
" --harness <path> node_modules dir of the DSH harness install (saved locally after first use; otherwise auto-detected)",
|
|
41
41
|
" --dry-run (sync) print planned writes without touching the filesystem",
|
|
42
42
|
" --verbose (sync) print per-file detail",
|
|
43
43
|
].join("\n");
|
|
@@ -55,6 +55,60 @@ function findNodeModules(start) {
|
|
|
55
55
|
current = parent;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
function harnessCachePath() { return join(dshHome(), "omd-dsh-harness.json"); }
|
|
59
|
+
/** Read the cached harness node_modules, ignoring a stale/missing entry. */
|
|
60
|
+
function readCachedHarness() {
|
|
61
|
+
try {
|
|
62
|
+
const p = harnessCachePath();
|
|
63
|
+
if (!existsSync(p))
|
|
64
|
+
return undefined;
|
|
65
|
+
const parsed = JSON.parse(readFileSync(p, "utf8"));
|
|
66
|
+
const nm = parsed && typeof parsed === "object" ? parsed.harnessNodeModules : undefined;
|
|
67
|
+
if (typeof nm !== "string" || nm === "")
|
|
68
|
+
return undefined;
|
|
69
|
+
if (!existsSync(join(nm, "@deepseek-ai", "dsh-scope", "package.json")))
|
|
70
|
+
return undefined;
|
|
71
|
+
return nm;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** Persist the resolved harness node_modules for later runs (best-effort). */
|
|
78
|
+
function writeCachedHarness(harnessNodeModules) {
|
|
79
|
+
try {
|
|
80
|
+
writeFileSync(harnessCachePath(), JSON.stringify({ harnessNodeModules }, null, 2) + "\n", "utf8");
|
|
81
|
+
}
|
|
82
|
+
catch { /* best-effort */ }
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Resolve the DSH harness node_modules:
|
|
86
|
+
* 1. --harness flag (and cache it for later);
|
|
87
|
+
* 2. auto-detect via the dsh executable on PATH;
|
|
88
|
+
* 3. fall back to the locally cached value.
|
|
89
|
+
*/
|
|
90
|
+
function resolveHarness(flags) {
|
|
91
|
+
let nm;
|
|
92
|
+
if (flags.harness !== undefined) {
|
|
93
|
+
nm = findNodeModules(flags.harness);
|
|
94
|
+
if (nm !== undefined) {
|
|
95
|
+
try {
|
|
96
|
+
nm = realpathSync(nm);
|
|
97
|
+
writeCachedHarness(nm);
|
|
98
|
+
}
|
|
99
|
+
catch { /* keep nm as-is */ }
|
|
100
|
+
}
|
|
101
|
+
return nm;
|
|
102
|
+
}
|
|
103
|
+
nm = locateHarnessViaDsh() ?? locateHarnessViaNpxCache() ?? readCachedHarness();
|
|
104
|
+
if (nm !== undefined) {
|
|
105
|
+
try {
|
|
106
|
+
nm = realpathSync(nm);
|
|
107
|
+
}
|
|
108
|
+
catch { /* keep */ }
|
|
109
|
+
}
|
|
110
|
+
return nm;
|
|
111
|
+
}
|
|
58
112
|
function locateHarnessViaDsh() {
|
|
59
113
|
const candidates = [];
|
|
60
114
|
try {
|
|
@@ -79,6 +133,51 @@ function locateHarnessViaDsh() {
|
|
|
79
133
|
}
|
|
80
134
|
return undefined;
|
|
81
135
|
}
|
|
136
|
+
/** Candidate npx cache roots where a non-global DSH install may live. */
|
|
137
|
+
function npxCacheRoots() {
|
|
138
|
+
const roots = [];
|
|
139
|
+
if (process.platform === "win32") {
|
|
140
|
+
const localAppData = process.env.LOCALAPPDATA;
|
|
141
|
+
if (localAppData)
|
|
142
|
+
roots.push(join(localAppData, "npm-cache", "_npx"));
|
|
143
|
+
const appData = process.env.APPDATA;
|
|
144
|
+
if (appData)
|
|
145
|
+
roots.push(join(appData, "npm-cache", "_npx"));
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
roots.push(join(homedir(), ".npm", "_npx"));
|
|
149
|
+
}
|
|
150
|
+
return roots;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Best-effort scan of the npx cache for a DSH install whose node_modules
|
|
154
|
+
* carries @deepseek-ai/dsh-scope. Picks the most recently touched one.
|
|
155
|
+
*/
|
|
156
|
+
function locateHarnessViaNpxCache() {
|
|
157
|
+
const matches = [];
|
|
158
|
+
for (const root of npxCacheRoots()) {
|
|
159
|
+
let entries;
|
|
160
|
+
try {
|
|
161
|
+
entries = readdirSync(root);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
for (const entry of entries) {
|
|
167
|
+
const nm = join(root, entry, "node_modules");
|
|
168
|
+
if (!existsSync(join(nm, "@deepseek-ai", "dsh-scope", "package.json")))
|
|
169
|
+
continue;
|
|
170
|
+
let mtime = 0;
|
|
171
|
+
try {
|
|
172
|
+
mtime = statSync(join(root, entry)).mtimeMs;
|
|
173
|
+
}
|
|
174
|
+
catch { /* keep 0 */ }
|
|
175
|
+
matches.push({ nm, mtime });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
matches.sort((a, b) => b.mtime - a.mtime);
|
|
179
|
+
return matches.length > 0 ? matches[0].nm : undefined;
|
|
180
|
+
}
|
|
82
181
|
function resolveHarnessModule(harnessNodeModules, specifier) {
|
|
83
182
|
const segments = specifier.split("/");
|
|
84
183
|
const scope = segments[0].startsWith("@") ? segments[0] + "/" + segments[1] : segments[0];
|
|
@@ -451,7 +550,7 @@ async function runSetup(flags, harnessNodeModules) {
|
|
|
451
550
|
rl.close();
|
|
452
551
|
if (syncNow === "" || /^y/i.test(syncNow)) {
|
|
453
552
|
if (harnessNodeModules === undefined) {
|
|
454
|
-
console.error("omd-dsh setup: 无法定位 DSH harness node_modules
|
|
553
|
+
console.error("omd-dsh setup: 无法定位 DSH harness node_modules,跳过同步。首次请运行 `omd-dsh sync --harness <路径>`(之后会自动缓存,无需重复指定)。");
|
|
455
554
|
}
|
|
456
555
|
else {
|
|
457
556
|
await runSync(flags, harnessNodeModules);
|
|
@@ -501,19 +600,15 @@ async function main() {
|
|
|
501
600
|
return;
|
|
502
601
|
}
|
|
503
602
|
if (command === "setup") {
|
|
504
|
-
|
|
505
|
-
if (harnessNodeModules !== undefined)
|
|
506
|
-
harnessNodeModules = realpathSync(harnessNodeModules);
|
|
507
|
-
await runSetup(flags, harnessNodeModules);
|
|
603
|
+
await runSetup(flags, resolveHarness(flags));
|
|
508
604
|
return;
|
|
509
605
|
}
|
|
510
|
-
|
|
606
|
+
const harnessNodeModules = resolveHarness(flags);
|
|
511
607
|
if (harnessNodeModules === undefined || !existsSync(join(harnessNodeModules, "@deepseek-ai", "dsh-scope", "package.json"))) {
|
|
512
|
-
console.error("omd-dsh sync: cannot locate the DSH harness node_modules.\n - ensure the dsh executable is on PATH, or\n - pass --harness <path to the harness node_modules directory
|
|
608
|
+
console.error("omd-dsh sync: cannot locate the DSH harness node_modules.\n - ensure the dsh executable is on PATH, or\n - pass --harness <path to the harness node_modules directory> (saved for later runs).\n\n" + usage());
|
|
513
609
|
process.exitCode = 2;
|
|
514
610
|
return;
|
|
515
611
|
}
|
|
516
|
-
harnessNodeModules = realpathSync(harnessNodeModules);
|
|
517
612
|
await runSync(flags, harnessNodeModules);
|
|
518
613
|
}
|
|
519
614
|
main().catch((error) => {
|
package/lib/ulw.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @carljia/omd-dsh/ulw
|
|
3
|
+
*
|
|
4
|
+
* omd-ulw: human-facing `/ulw` command — the "ultrawork" trigger. It arms a
|
|
5
|
+
* goal for the task; goal auto-continuation then drives the agent to
|
|
6
|
+
* completion without further input.
|
|
7
|
+
*/
|
|
8
|
+
/** Cordis plugin name. */
|
|
9
|
+
declare const name = "omd-ulw";
|
|
10
|
+
/** The goal domain is already required by tool-goal in the same preset. */
|
|
11
|
+
declare const inject: string[];
|
|
12
|
+
declare function apply(ctx: any): void;
|
|
13
|
+
export { apply, inject, name };
|
package/lib/ulw.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @carljia/omd-dsh/ulw
|
|
3
|
+
*
|
|
4
|
+
* omd-ulw: human-facing `/ulw` command — the "ultrawork" trigger. It arms a
|
|
5
|
+
* goal for the task; goal auto-continuation then drives the agent to
|
|
6
|
+
* completion without further input.
|
|
7
|
+
*/
|
|
8
|
+
/** Cordis plugin name. */
|
|
9
|
+
const name = "omd-ulw";
|
|
10
|
+
/** The goal domain is already required by tool-goal in the same preset. */
|
|
11
|
+
const inject = ["goals"];
|
|
12
|
+
/** Execute one /ulw invocation through the goal domain. */
|
|
13
|
+
function executeUlw(ctx, invocation) {
|
|
14
|
+
const task = invocation.rawInput.trim();
|
|
15
|
+
if (task.length === 0) {
|
|
16
|
+
return {
|
|
17
|
+
kind: "error",
|
|
18
|
+
text: "Usage: /ulw <task> — arm a goal and work on it autonomously until done.",
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const current = ctx.goals.get(invocation.agent);
|
|
23
|
+
if (current !== undefined && current.phase !== "complete") {
|
|
24
|
+
return {
|
|
25
|
+
kind: "error",
|
|
26
|
+
text: `A goal is already ${current.phase}. Run /goal clear first, then /ulw <task>.`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
ctx.goals.create(invocation.agent, { objective: task });
|
|
30
|
+
return {
|
|
31
|
+
kind: "success",
|
|
32
|
+
text: `Ultrawork armed — working to completion.\nObjective: ${task}`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
return {
|
|
37
|
+
kind: "error",
|
|
38
|
+
text: `ulw failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function apply(ctx) {
|
|
43
|
+
ctx.inject(["commands"], (commandCtx) => {
|
|
44
|
+
commandCtx.commands.register({
|
|
45
|
+
name: "ulw",
|
|
46
|
+
description: "ultrawork: arm a goal for a task and work on it autonomously until done",
|
|
47
|
+
input: {
|
|
48
|
+
hint: "<task>",
|
|
49
|
+
images: false,
|
|
50
|
+
},
|
|
51
|
+
handler: (invocation) => executeUlw(ctx, invocation),
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @carljia/omd-dsh/ulw
|
|
3
|
+
*
|
|
4
|
+
* omd-ulw: human-facing `/ulw` command — the "ultrawork" trigger. It arms a
|
|
5
|
+
* goal for the task; goal auto-continuation then drives the agent to
|
|
6
|
+
* completion without further input.
|
|
7
|
+
*/
|
|
8
|
+
/** Cordis plugin name. */
|
|
9
|
+
const name = "omd-ulw";
|
|
10
|
+
/** The goal domain is already required by tool-goal in the same preset. */
|
|
11
|
+
const inject = ["goals"];
|
|
12
|
+
/** Execute one /ulw invocation through the goal domain. */
|
|
13
|
+
function executeUlw(ctx, invocation) {
|
|
14
|
+
const task = invocation.rawInput.trim();
|
|
15
|
+
if (task.length === 0) {
|
|
16
|
+
return {
|
|
17
|
+
kind: "error",
|
|
18
|
+
text: "Usage: /ulw <task> — arm a goal and work on it autonomously until done.",
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const current = ctx.goals.get(invocation.agent);
|
|
23
|
+
if (current !== undefined && current.phase !== "complete") {
|
|
24
|
+
return {
|
|
25
|
+
kind: "error",
|
|
26
|
+
text: `A goal is already ${current.phase}. Run /goal clear first, then /ulw <task>.`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
ctx.goals.create(invocation.agent, { objective: task });
|
|
30
|
+
return {
|
|
31
|
+
kind: "success",
|
|
32
|
+
text: `Ultrawork armed — working to completion.\nObjective: ${task}`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
return {
|
|
37
|
+
kind: "error",
|
|
38
|
+
text: `ulw failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function apply(ctx) {
|
|
43
|
+
ctx.inject(["commands"], (commandCtx) => {
|
|
44
|
+
commandCtx.commands.register({
|
|
45
|
+
name: "ulw",
|
|
46
|
+
description: "ultrawork: arm a goal for a task and work on it autonomously until done",
|
|
47
|
+
input: {
|
|
48
|
+
hint: "<task>",
|
|
49
|
+
images: false,
|
|
50
|
+
},
|
|
51
|
+
handler: (invocation) => executeUlw(ctx, invocation),
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
export { apply, inject, name };
|
package/omd-matrix.json
CHANGED
|
@@ -13,7 +13,13 @@
|
|
|
13
13
|
"model": "deepseek-v4-flash",
|
|
14
14
|
"hint": "cheap and fast — repetitive investigation, searching, summarising, mechanical work",
|
|
15
15
|
"persona": "You are a FAST worker subagent (快速执行子代理): complete the assigned task efficiently with the tools you have; prefer short, focused answers.",
|
|
16
|
-
"toolFilter": {
|
|
16
|
+
"toolFilter": {
|
|
17
|
+
"deny": [
|
|
18
|
+
"write",
|
|
19
|
+
"edit"
|
|
20
|
+
],
|
|
21
|
+
"denyShell": true
|
|
22
|
+
}
|
|
17
23
|
},
|
|
18
24
|
"deep": {
|
|
19
25
|
"provider": "deepseek-official",
|
|
@@ -32,7 +38,13 @@
|
|
|
32
38
|
"model": "deepseek-v4-flash",
|
|
33
39
|
"hint": "cheap and fast — repetitive investigation, searching, summarising, mechanical work",
|
|
34
40
|
"persona": "You are a FAST worker subagent (快速执行子代理): complete the assigned task efficiently with the tools you have; prefer short, focused answers.",
|
|
35
|
-
"toolFilter": {
|
|
41
|
+
"toolFilter": {
|
|
42
|
+
"deny": [
|
|
43
|
+
"write",
|
|
44
|
+
"edit"
|
|
45
|
+
],
|
|
46
|
+
"denyShell": true
|
|
47
|
+
}
|
|
36
48
|
},
|
|
37
49
|
"deep": {
|
|
38
50
|
"provider": "deepseek-official",
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
name: '@deepseek-ai/dsh-persona'
|
|
5
5
|
config:
|
|
6
6
|
text: >-
|
|
7
|
-
You are in OMD EXECUTOR mode (OMD · 执行者): a full-capability autonomous executor on DeepSeek Harness. Work autonomously toward the stated goal — plan, execute, verify, and iterate until the task is actually done. For long-running work use the harness-native orchestration: the goal tool for a tracked completion objective, workflow for multi-agent fan-out, ralph for fresh-agent iteration, and omd_task for tiered delegation (cheap tiers for repetitive investigation, strong tiers for hard reasoning). Do not stop to ask when the path forward is clear. 本模式路由模型:{{model}}(provider: {{provider}})。
|
|
7
|
+
You are in OMD EXECUTOR mode (OMD · 执行者): a full-capability autonomous executor on DeepSeek Harness. Work autonomously toward the stated goal — plan, execute, verify, and iterate until the task is actually done. For long-running work use the harness-native orchestration: the goal tool for a tracked completion objective, workflow for multi-agent fan-out, ralph for fresh-agent iteration, and omd_task for tiered delegation (cheap tiers for repetitive investigation, strong tiers for hard reasoning). Do not stop to ask when the path forward is clear. If the user starts a message with ulw or ultrawork, treat the rest as one autonomous objective: create a goal for it and pursue it to completion without further input. 本模式路由模型:{{model}}(provider: {{provider}})。
|
|
8
8
|
|
|
9
9
|
# [omd-dsh:mode:start]
|
|
10
10
|
# [omd-dsh:mode:end]
|
|
@@ -41,6 +41,9 @@
|
|
|
41
41
|
- id: tool-goal
|
|
42
42
|
name: '@deepseek-ai/dsh-tool-goal'
|
|
43
43
|
|
|
44
|
+
- id: omd-ulw
|
|
45
|
+
name: '../.omd-vendor/omd-ulw.mjs'
|
|
46
|
+
|
|
44
47
|
- id: compaction
|
|
45
48
|
name: cordis:group
|
|
46
49
|
group: true
|