@goodandready/dsh-cron 0.3.14 → 0.3.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.md +1 -1
- package/README.ru.md +1 -1
- package/README.zh.md +1 -1
- package/lib/index.js +1 -1
- package/lib/runner-worktree.js +35 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -205,7 +205,7 @@ Every task picks its own runtime; non-LLM runtimes need no model and consume no
|
|
|
205
205
|
* **SSH** (`ssh`) — execute a command on a remote host through a `dsh-remote-workspace` profile (`sshProfileId`) or standalone host/key fields.
|
|
206
206
|
* **Docker** (`docker`) — run the command in a container image (`dockerImage`).
|
|
207
207
|
* **Environment variables** — a per-task `env` map (KEY VALUE per line in the UI) applied to external runtimes; secrets do not belong here.
|
|
208
|
-
* **Workspaces and worktrees** — bind a task to a harness workspace (`workspaceId`)
|
|
208
|
+
* **Workspaces and worktrees** — bind a task to a harness workspace (`workspaceId`, resolved through host `workspaceRegistry`) or path, and run code-modifying agent tasks in an isolated git worktree (`worktree`, `keepWorktree`).
|
|
209
209
|
|
|
210
210
|
### 7. Cost Control: Fallback Model & Burn Guard
|
|
211
211
|
* **Fallback Model** — A task can run on the cheap model by default and still finish on the strong one: set `fallbackModel` (and optionally `fallbackProvider`) and a failed run — `error` or `timeout` — is retried **once** on that model before the ordinary retry backoff applies. History records which model produced the result and whether the fallback was used, usage and cost of both attempts are summed, and the `{model}` template variable renders the model that finished the run. Only agent-mediated tasks (`llm`, `skill`, `workflow`) can use a fallback.
|
package/README.ru.md
CHANGED
|
@@ -205,7 +205,7 @@ cron({
|
|
|
205
205
|
* **SSH** (`ssh`) — выполнение команды на удалённом хосте через профиль `dsh-remote-workspace` (`sshProfileId`) или отдельные поля host/key.
|
|
206
206
|
* **Docker** (`docker`) — выполнение команды в контейнере образа (`dockerImage`).
|
|
207
207
|
* **Переменные окружения** — карта `env` на задачу (в UI — строки KEY VALUE) для внешних рантаймов; секретам здесь не место.
|
|
208
|
-
* **Workspace и worktree** — привязка задачи к workspace харнесса (`workspaceId
|
|
208
|
+
* **Workspace и worktree** — привязка задачи к workspace харнесса (`workspaceId`, разрешаемому через службу `workspaceRegistry`) или пути, и запуск в изолированном git worktree (`worktree`, `keepWorktree`).
|
|
209
209
|
|
|
210
210
|
### 7. Экономия: fallback-модель и защита бюджета (Burn Guard)
|
|
211
211
|
* **Fallback-модель** — задача может идти на дешёвой модели по умолчанию и всё же завершиться на сильной: задайте `fallbackModel` (и при необходимости `fallbackProvider`), и сбойный запуск (`error` или `timeout`) один раз повторится на этой модели, прежде чем включится обычный retry с задержкой. В истории видно, какая модель произвела результат и был ли использован fallback; расход и стоимость обеих попыток суммируются; переменная шаблона `{model}` подставляет модель, завершившую запуск. Fallback доступен только агентским типам (`llm`, `skill`, `workflow`).
|
package/README.zh.md
CHANGED
|
@@ -205,7 +205,7 @@ cron({
|
|
|
205
205
|
* **SSH**(`ssh`)—— 通过 `dsh-remote-workspace` 配置(`sshProfileId`)或独立 host/key 字段在远程主机执行命令。
|
|
206
206
|
* **Docker**(`docker`)—— 在镜像容器(`dockerImage`)中执行命令。
|
|
207
207
|
* **环境变量** —— 按任务的 `env` 映射(界面中每行 KEY VALUE)应用于外部运行时;请勿在此存放密钥。
|
|
208
|
-
* **工作区与 worktree** —— 将任务绑定到 Harness 工作区(`workspaceId
|
|
208
|
+
* **工作区与 worktree** —— 将任务绑定到 Harness 工作区(`workspaceId`,通过宿主 `workspaceRegistry` 服务解析)或直接路径;对会修改代码的智能体任务,可在隔离的 git worktree 中运行(`worktree`、`keepWorktree`)。
|
|
209
209
|
|
|
210
210
|
### 7. 成本控制:回退模型与支出保护(Burn Guard)
|
|
211
211
|
* **回退模型** —— 任务可以默认使用便宜模型,失败时改用更强模型完成:设置 `fallbackModel`(可选 `fallbackProvider`),失败(`error` 或 `timeout`)的运行会在该模型上重试一次,之后才进入常规重试退避。历史记录会标明最终产出结果的模型以及是否使用了回退,两次尝试的用量与成本都会累计,模板变量 `{model}` 渲染完成运行的模型。回退仅适用于智能体类型(`llm`、`skill`、`workflow`)。
|
package/lib/index.js
CHANGED
|
@@ -95,7 +95,7 @@ export {
|
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
export const name = '@goodandready/dsh-cron';
|
|
98
|
-
export const inject = ['tools', 'webServer', 'llm', 'agents', 'agentDefaultModel', 'credentials'];
|
|
98
|
+
export const inject = ['tools', 'webServer', 'llm', 'agents', 'agentDefaultModel', 'credentials', 'workspaceRegistry'];
|
|
99
99
|
|
|
100
100
|
import { executeCreateTask } from './task-create.js';
|
|
101
101
|
import {
|
package/lib/runner-worktree.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { logger } from './logger.js';
|
|
2
2
|
import { bestEffort } from './best-effort.js';
|
|
3
3
|
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* Resolve the working directory for a task: explicit cwd, a bound
|
|
6
8
|
* workspace id resolved through the harness, or the process cwd (#31).
|
|
@@ -8,17 +10,45 @@ import { bestEffort } from './best-effort.js';
|
|
|
8
10
|
export function resolveCwd(task, ctx = null) {
|
|
9
11
|
if (task.cwd) return String(task.cwd);
|
|
10
12
|
if (task.workspaceId) {
|
|
11
|
-
|
|
13
|
+
const rawId = String(task.workspaceId).trim();
|
|
14
|
+
if (ctx) {
|
|
12
15
|
const resolved = bestEffort('resolve-workspace-path', () => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
// Issue #363 / GH #12: host workspace service is 'workspaceRegistry' in DeepSeek Harness
|
|
17
|
+
const registry =
|
|
18
|
+
(typeof ctx.get === 'function' ? ctx.get('workspaceRegistry') : null) ||
|
|
19
|
+
ctx.workspaceRegistry ||
|
|
20
|
+
(typeof ctx.get === 'function' ? ctx.get('workspaces') : null) ||
|
|
21
|
+
ctx.workspaces;
|
|
22
|
+
|
|
23
|
+
if (registry) {
|
|
24
|
+
// 1. Direct get(id) lookup on WorkspaceRegistry
|
|
25
|
+
if (typeof registry.get === 'function') {
|
|
26
|
+
const ws = registry.get(rawId);
|
|
27
|
+
if (ws && ws.path) return String(ws.path);
|
|
28
|
+
}
|
|
29
|
+
// 2. List lookup if ID, title, or Path was provided ("Workspace id or path")
|
|
30
|
+
if (typeof registry.list === 'function') {
|
|
31
|
+
const list = registry.list();
|
|
32
|
+
if (Array.isArray(list)) {
|
|
33
|
+
const matched = list.find((w) => w && (w.id === rawId || w.path === rawId || w.title === rawId));
|
|
34
|
+
if (matched && matched.path) return String(matched.path);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
17
37
|
}
|
|
18
38
|
return null;
|
|
19
39
|
});
|
|
20
40
|
if (resolved) return resolved;
|
|
21
41
|
}
|
|
42
|
+
|
|
43
|
+
// 3. Fallback: if task.workspaceId directly points to an existing directory path on disk
|
|
44
|
+
try {
|
|
45
|
+
if (fs.existsSync(rawId) && fs.statSync(rawId).isDirectory()) {
|
|
46
|
+
return rawId;
|
|
47
|
+
}
|
|
48
|
+
} catch (_fsErr) {
|
|
49
|
+
// ignore filesystem stat error
|
|
50
|
+
}
|
|
51
|
+
|
|
22
52
|
// Issue #231: fail-closed if workspaceId was specified but cannot be resolved
|
|
23
53
|
throw new Error(`Workspace "${task.workspaceId}" requested by task could not be resolved`);
|
|
24
54
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-cron",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.15",
|
|
4
4
|
"description": "Background automation runner for DSH: isolated agent runs, script/HTTP/SSH/Docker runtimes, cost guard, notifications, heartbeats.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|