dsh-pstack 0.2.0 → 0.2.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/dist/subagent.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { a as POTETO_MODE_SKILL_PATH } from "./paths-BT77khwm.mjs";
2
- import { a as resolveDshHome, i as requireRole, o as selectRoleRoutes, r as readRoleConfiguration, t as modelsFilePath } from "./role-config-NNn5r1JX.mjs";
1
+ import { a as POTETO_MODE_SKILL_PATH } from "./paths-yji9SNak.mjs";
2
+ import { a as selectRoleRoutes, i as resolveDshHome, n as readRoleConfiguration, r as requireRole, t as modelsFilePath } from "./role-config-a4JpVdc-.mjs";
3
3
  import { isAbsolute, join, relative, resolve } from "node:path";
4
4
  import { existsSync, statSync } from "node:fs";
5
5
  // src/internal/effort.ts
@@ -149,6 +149,13 @@ const AGENT_KINDS = [
149
149
  "general"
150
150
  ];
151
151
  const DEFAULT_CONFIG = { provider: DEFAULT_SUBAGENT_PROVIDER };
152
+ /**
153
+ * Depth a child runs at when a call omits `maxDepth` or passes an unusable value.
154
+ *
155
+ * A child is always at least depth 1 (it is one level below its parent), so this is the
156
+ * smallest value that can start a child while forbidding it from delegating further.
157
+ */
158
+ const DEFAULT_CHILD_MAX_DEPTH = 1;
152
159
  /** Raised for a configuration or argument problem, before any child starts. */
153
160
  var DelegationError = class extends Error {
154
161
  constructor(message) {
@@ -214,22 +221,36 @@ function composeChildPrompt(input) {
214
221
  sections.push(`Task:\n\n${input.task}`);
215
222
  return sections.join("\n\n---\n\n");
216
223
  }
224
+ const DELEGATION_ARGUMENT_KEYS = [
225
+ "description",
226
+ "prompt",
227
+ "agent",
228
+ "role",
229
+ "roleIndex",
230
+ "reasoningEffort",
231
+ "cwd",
232
+ "maxDepth"
233
+ ];
234
+ /**
235
+ * Keys a call must pass. `maxDepth` is accepted but not required: a missing or unusable
236
+ * value resolves to `DEFAULT_CHILD_MAX_DEPTH` instead of forcing the caller to guess an
237
+ * integer, which is where the reflexive `0` came from.
238
+ */
239
+ const REQUIRED_DELEGATION_ARGUMENT_KEYS = [
240
+ "description",
241
+ "prompt",
242
+ "agent",
243
+ "role",
244
+ "roleIndex",
245
+ "reasoningEffort",
246
+ "cwd"
247
+ ];
217
248
  /** Validate every required model-facing argument. Null declines an optional setting. */
218
249
  function parseDelegationArgs(raw) {
219
250
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new DelegationError("arguments must be an object");
220
251
  const record = raw;
221
- const known = [
222
- "description",
223
- "prompt",
224
- "agent",
225
- "role",
226
- "roleIndex",
227
- "reasoningEffort",
228
- "cwd",
229
- "maxDepth"
230
- ];
231
- for (const key of known) if (!Object.hasOwn(record, key)) throw new DelegationError(`missing required argument "${key}"; every argument must be passed explicitly`);
232
- for (const key of Object.keys(record)) if (!known.includes(key)) throw new DelegationError(`unknown argument "${key}"; accepted arguments are ${known.join(", ")}`);
252
+ for (const key of REQUIRED_DELEGATION_ARGUMENT_KEYS) if (!Object.hasOwn(record, key)) throw new DelegationError(`missing required argument "${key}"; every argument except maxDepth must be passed explicitly`);
253
+ for (const key of Object.keys(record)) if (!DELEGATION_ARGUMENT_KEYS.includes(key)) throw new DelegationError(`unknown argument "${key}"; accepted arguments are ${DELEGATION_ARGUMENT_KEYS.join(", ")}`);
233
254
  const description = record["description"];
234
255
  if (!isNonEmptyString(description)) throw new DelegationError("description must be a non-empty string: it becomes the child label");
235
256
  const prompt = record["prompt"];
@@ -240,8 +261,9 @@ function parseDelegationArgs(raw) {
240
261
  if (role !== null && !isNonEmptyString(role)) throw new DelegationError("role must be a non-empty string or null");
241
262
  const cwd = record["cwd"];
242
263
  if (cwd !== null && !isNonEmptyString(cwd)) throw new DelegationError("cwd must be a non-empty string or null");
243
- const maxDepth = record["maxDepth"];
244
- if (!isNonNegativeSafeInteger(maxDepth)) throw new DelegationError("maxDepth must be a non-negative safe integer");
264
+ const rawMaxDepth = record["maxDepth"];
265
+ const maxDepth = rawMaxDepth === void 0 ? null : rawMaxDepth;
266
+ if (maxDepth !== null && !isNonNegativeSafeInteger(maxDepth)) throw new DelegationError("maxDepth must be a non-negative safe integer, or null/omitted");
245
267
  const roleIndex = record["roleIndex"];
246
268
  if (roleIndex !== null && !isNonNegativeSafeInteger(roleIndex)) throw new DelegationError("roleIndex must be a non-negative safe integer or null");
247
269
  if (roleIndex !== null && role === null) throw new DelegationError("roleIndex requires a non-null role");
@@ -267,15 +289,30 @@ function routeLabel(route, effortOverride) {
267
289
  }
268
290
  /** Take the smallest of the requested depth, this row's cap, and the Host setting. */
269
291
  function resolveDelegationDepth(configured, requested, hostLimit) {
270
- if (requested !== void 0 && !isNonNegativeSafeInteger(requested)) throw new DelegationError("maxDepth must be a non-negative safe integer");
271
- if (configured !== void 0 && requested !== void 0 && requested > configured) throw new DelegationError(`maxDepth ${requested} exceeds this row's configured cap of ${configured}. Lower the request or raise \`pstack-subagent\` config.maxDepth.`);
292
+ if (requested !== void 0 && requested !== null && !isNonNegativeSafeInteger(requested)) throw new DelegationError("maxDepth must be a non-negative safe integer or null");
293
+ if (configured !== void 0 && requested !== void 0 && requested !== null && requested > configured) throw new DelegationError(`maxDepth ${requested} exceeds this row's configured cap of ${configured}. Lower the request or raise \`pstack-subagent\` config.maxDepth.`);
272
294
  const candidates = [
273
295
  configured,
274
296
  requested,
275
297
  hostLimit
276
- ].filter((value) => value !== void 0);
298
+ ].filter((value) => value !== void 0 && value !== null);
277
299
  return candidates.length === 0 ? void 0 : Math.min(...candidates);
278
300
  }
301
+ /**
302
+ * Turn the per-call `maxDepth` request into an effective depth request.
303
+ *
304
+ * A child is always at least depth 1, so `0` can never start one: it is reported and
305
+ * replaced with `DEFAULT_CHILD_MAX_DEPTH` rather than failing the whole call. Omitting
306
+ * `maxDepth` (null) also uses the default, so a caller never has to guess an integer.
307
+ */
308
+ function requestedChildDepth(requested, diagnostics) {
309
+ if (requested === null) return 1;
310
+ if (requested === 0) {
311
+ diagnostics.push(`maxDepth 0 cannot start a child (the child itself is depth 1), so this call used 1. Omit maxDepth for that default, or pass 1 or more.`);
312
+ return 1;
313
+ }
314
+ return requested;
315
+ }
279
316
  /** Resolve the role file, routes, prompt, and depth into one plan. Pure of service calls. */
280
317
  function planDelegation(args, runtime, config = DEFAULT_CONFIG) {
281
318
  const rolePath = modelsFilePath(runtime.dshHome);
@@ -305,7 +342,7 @@ function planDelegation(args, runtime, config = DEFAULT_CONFIG) {
305
342
  task: args.prompt
306
343
  });
307
344
  const agentPreset = agentPresetFor(args.agent);
308
- const depth = resolveDelegationDepth(config.maxDepth, args.maxDepth, void 0);
345
+ const depth = resolveDelegationDepth(config.maxDepth, requestedChildDepth(args.maxDepth, diagnostics), void 0);
309
346
  const total = routes.length;
310
347
  const children = routes.map((route, index) => {
311
348
  const agentOptions = agentOptionsFor(route, args.reasoningEffort ?? void 0);
@@ -495,9 +532,11 @@ async function delegate(parent, args, runtime, config = DEFAULT_CONFIG, signal =
495
532
  const TOOL_DESCRIPTION = [
496
533
  "Delegate self-contained work to one or more fresh child agents.",
497
534
  "",
498
- "Every argument is required. Pass null for role, roleIndex, reasoningEffort, or cwd when that",
499
- "setting is not used. Choose agent explicitly. maxDepth is a non-negative integer. No argument",
500
- "has an implicit default.",
535
+ "Every argument is required except maxDepth. Pass null for role, roleIndex, reasoningEffort,",
536
+ "or cwd when that setting is not used. Choose agent explicitly. maxDepth is optional: omit it",
537
+ "(or pass null) for the safe default of 1, where the child exists but cannot start its own",
538
+ "children; pass 2 or more, within this row's configured cap, to let it delegate further. A 0 is",
539
+ "treated as 1, because a child is already depth 1 and 0 can never start one.",
501
540
  "",
502
541
  "Returns the id of every child it started plus the route each one resolved. The children run",
503
542
  "in the background: their results arrive later as completion notices in this conversation.",
@@ -546,28 +585,19 @@ function buildParameters() {
546
585
  description: "Required initial working directory, inside this session's directory or a separate Git worktree. Relative paths resolve against this session's directory. Null inherits the session directory."
547
586
  },
548
587
  maxDepth: {
549
- type: "integer",
550
- description: "Required non-negative delegation-depth limit. It can only lower this row's configured cap."
588
+ type: ["integer", "null"],
589
+ description: "Optional delegation-depth cap for the child. Omit or pass null for the safe default of 1 (the child exists but cannot start its own children). Pass 2 or more, within this row's configured cap, to let it delegate further. 0 is treated as 1: a child is already depth 1, so 0 can never start one."
551
590
  },
552
591
  roleIndex: {
553
592
  type: ["integer", "null"],
554
- description: "Required entry index for a list-valued role that is not an automatic panel, 0 or greater. Requires a non-null role. Null selects the first entry."
593
+ description: "Required entry index for a list-valued role that is not an automatic panel, 0 or greater. Requires a non-null role. Null selects the first entry. Call `pstack_roles` to see which roles accept an index."
555
594
  },
556
595
  reasoningEffort: {
557
596
  type: ["string", "null"],
558
597
  description: "Required reasoning-effort override for every child this call starts. Use one token the target model advertises, or null to keep the role line's starting effort. An unknown token fails the whole call before any child starts."
559
598
  }
560
599
  },
561
- required: [
562
- "description",
563
- "prompt",
564
- "agent",
565
- "role",
566
- "roleIndex",
567
- "reasoningEffort",
568
- "cwd",
569
- "maxDepth"
570
- ]
600
+ required: [...REQUIRED_DELEGATION_ARGUMENT_KEYS]
571
601
  };
572
602
  }
573
603
  const OUTPUT_SCHEMA = {
@@ -694,4 +724,4 @@ function describeError(error) {
694
724
  }
695
725
  return String(error);
696
726
  }
697
- export { AGENT_KINDS, AGENT_PRESETS, DEFAULT_SUBAGENT_PROVIDER, DelegationError, PartialDelegationError, TOOL_NAME, agentPresetFor, apply, assertProviderCapabilities, composeChildPrompt, createPstackSubagentTool, delegate, hostRuntime, inject, name, normalizeConfig, parseDelegationArgs, planDelegation, renderDelegationResult, resolveChildCwd, resolveDelegationDepth, routeLabel, startPlannedChildren };
727
+ export { AGENT_KINDS, AGENT_PRESETS, DEFAULT_CHILD_MAX_DEPTH, DEFAULT_SUBAGENT_PROVIDER, DELEGATION_ARGUMENT_KEYS, DelegationError, PartialDelegationError, REQUIRED_DELEGATION_ARGUMENT_KEYS, TOOL_NAME, agentPresetFor, apply, assertProviderCapabilities, composeChildPrompt, createPstackSubagentTool, delegate, hostRuntime, inject, name, normalizeConfig, parseDelegationArgs, planDelegation, renderDelegationResult, requestedChildDepth, resolveChildCwd, resolveDelegationDepth, routeLabel, startPlannedChildren };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-pstack",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "pstack for DeepSeek Harness: rigorous agent workflows ported from cursor/plugins.",
5
5
  "keywords": [
6
6
  "agent-skills",
@@ -38,6 +38,7 @@
38
38
  ".": "./dist/index.mjs",
39
39
  "./models": "./dist/models.mjs",
40
40
  "./remote": "./dist/remote.mjs",
41
+ "./role-catalog": "./dist/role-catalog.mjs",
41
42
  "./roles": "./dist/roles.mjs",
42
43
  "./script": "./dist/script.mjs",
43
44
  "./skill": "./dist/skill.mjs",
@@ -47,7 +48,16 @@
47
48
  "./locale/*.json": "./locale/*.json"
48
49
  },
49
50
  "dependencies": {
51
+ "commander": "14.0.0"
52
+ },
53
+ "devDependencies": {
54
+ "@deepseek-ai/cordis": "~4.0.6-alpha.1",
50
55
  "@deepseek-ai/dsh-agent": "0.2.2-alpha.2",
56
+ "@deepseek-ai/dsh-api-gateway": "0.2.2-alpha.2",
57
+ "@deepseek-ai/dsh-client-locale": "0.2.2-alpha.2",
58
+ "@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.2-alpha.2",
59
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.2-alpha.2",
60
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.2-alpha.2",
51
61
  "@deepseek-ai/dsh-jobs": "0.2.2-alpha.2",
52
62
  "@deepseek-ai/dsh-llm": "0.2.2-alpha.2",
53
63
  "@deepseek-ai/dsh-session": "0.2.2-alpha.2",
@@ -56,16 +66,8 @@
56
66
  "@deepseek-ai/dsh-system-prompt": "0.2.2-alpha.2",
57
67
  "@deepseek-ai/dsh-tools": "0.2.2-alpha.2",
58
68
  "@deepseek-ai/dsh-typert-protocol": "0.2.2-alpha.2",
59
- "@deepseek-ai/dsh-working-directory": "0.2.2-alpha.2",
60
- "commander": "14.0.0"
61
- },
62
- "devDependencies": {
63
- "@deepseek-ai/dsh-api-gateway": "0.2.2-alpha.2",
64
- "@deepseek-ai/dsh-client-locale": "0.2.2-alpha.2",
65
- "@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.2-alpha.2",
66
- "@deepseek-ai/dsh-client-ui-renderer": "0.2.2-alpha.2",
67
- "@deepseek-ai/dsh-client-ui-slots": "0.2.2-alpha.2",
68
69
  "@deepseek-ai/dsh-typert-registry": "0.2.2-alpha.2",
70
+ "@deepseek-ai/dsh-working-directory": "0.2.2-alpha.2",
69
71
  "@types/node": "^24.1.0",
70
72
  "@types/react": "~18.3.1",
71
73
  "@types/react-dom": "~18.3.0",
@@ -130,7 +132,7 @@
130
132
  }
131
133
  ],
132
134
  "scripts": {
133
- "prerelease": "vp run -r check && vp run -r test",
135
+ "prerelease": "vp run build && vp run -r check && vp run typecheck && vp run -r test",
134
136
  "release": "bumpp"
135
137
  }
136
138
  }
@@ -1,19 +0,0 @@
1
- /**
2
- * The one pstack role manifest.
3
- *
4
- * Keys are matched exactly after normalization, and commas belong to some keys
5
- * (`feature, refactoring`, `reflect judgment, divergent, synthesizer`), so nothing here
6
- * may split a key on a comma. A second literal role list anywhere is a bug.
7
- *
8
- * This module has no Node imports: the bundle imports it directly.
9
- */
10
- /** Whether a role holds one route or a comma-separated list of routes. */
11
- type RoleValueShape = "single" | "list";
12
- interface RoleSpec {
13
- /** Exact key as written in the role file. Commas belong to the key. */
14
- readonly key: string;
15
- readonly shape: RoleValueShape;
16
- /** A list role that starts one child per entry automatically. */
17
- readonly autoPanel: boolean;
18
- }
19
- export { RoleValueShape as n, RoleSpec as t };