@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 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`) and, for code-modifying agent tasks, run it in an isolated git worktree (`worktree`, `keepWorktree`).
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`) и, для изменяющих код агентских задач, запуск в изолированном git worktree (`worktree`, `keepWorktree`).
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`);对会修改代码的智能体任务,可在隔离的 git worktree 中运行(`worktree`、`keepWorktree`)。
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 {
@@ -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
- if (ctx && typeof ctx.get === 'function') {
13
+ const rawId = String(task.workspaceId).trim();
14
+ if (ctx) {
12
15
  const resolved = bestEffort('resolve-workspace-path', () => {
13
- const workspaces = ctx.get('workspaces');
14
- if (workspaces && typeof workspaces.get === 'function') {
15
- const ws = workspaces.get(task.workspaceId);
16
- return ws && ws.path ? String(ws.path) : null;
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.14",
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",