@agimon-ai/doompi-workflow 0.0.1-alpha.127 → 0.0.1-alpha.128

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.
@@ -28,6 +28,34 @@ let hono_streaming = require("hono/streaming");
28
28
  let _agimon_ai_doompi_core_web = require("@agimon-ai/doompi-core/web");
29
29
  let node_os = require("node:os");
30
30
  node_os = require_workflowTerminal.__toESM(node_os, 1);
31
+ //#region src/schemas/runConfig.ts
32
+ /** A YAML list, or one comma-separated string, as `--domains a,b` accepts. */
33
+ const nameList = zod.z.union([zod.z.string(), zod.z.array(zod.z.string())]).transform((value) => (Array.isArray(value) ? value : value.split(",")).map((name) => name.trim()).filter((name) => name.length > 0));
34
+ const singleName = zod.z.string().trim().min(1);
35
+ /**
36
+ * The DoomPi keys of a workflow step's `runConfig`.
37
+ *
38
+ * The engine treats `runConfig` as an opaque map, so this is where a typo such
39
+ * as `majormode` is caught instead of silently running on workspace defaults.
40
+ */
41
+ const doompiRunConfigSchema = zod.z.object({
42
+ majorMode: singleName.optional().describe("Major mode the step session runs in."),
43
+ minorModes: nameList.optional().describe("Minor modes activated in the step session."),
44
+ profile: singleName.optional().describe("Profile the step session runs as."),
45
+ domains: nameList.optional().describe("Domains selected for the step session. An empty list selects none."),
46
+ model: singleName.optional().describe("Model selector, provider/id."),
47
+ thinking: singleName.optional().describe("Thinking level for the model."),
48
+ subagentModel: singleName.optional().describe("Preferred Team subagent model, independent of the step model."),
49
+ subagentThinking: singleName.optional().describe("Preferred Team subagent thinking level.")
50
+ }).strict();
51
+ /**
52
+ * The same keys for a templated step, whose `runConfig` is also the data its
53
+ * command template reads: keys DoomPi does not use are left to the template.
54
+ */
55
+ const doompiTemplateRunConfigSchema = doompiRunConfigSchema.strip();
56
+ /** The runConfig keys DoomPi reads itself, the host keys `workflow-mcp doctor` checks steps against. */
57
+ const DOOMPI_RUN_CONFIG_KEYS = doompiRunConfigSchema.keyof().options;
58
+ //#endregion
31
59
  //#region src/services/workflowRuns/index.ts
32
60
  /**
33
61
  * MIRRORS @agimon-ai/workflow-mcp's on-disk registry
@@ -659,34 +687,6 @@ function createServerLauncher(dependencies) {
659
687
  };
660
688
  }
661
689
  //#endregion
662
- //#region src/schemas/runConfig.ts
663
- /** A YAML list, or one comma-separated string, as `--domains a,b` accepts. */
664
- const nameList = zod.z.union([zod.z.string(), zod.z.array(zod.z.string())]).transform((value) => (Array.isArray(value) ? value : value.split(",")).map((name) => name.trim()).filter((name) => name.length > 0));
665
- const singleName = zod.z.string().trim().min(1);
666
- /**
667
- * The DoomPi keys of a workflow step's `runConfig`.
668
- *
669
- * The engine treats `runConfig` as an opaque map, so this is where a typo such
670
- * as `majormode` is caught instead of silently running on workspace defaults.
671
- */
672
- const doompiRunConfigSchema = zod.z.object({
673
- majorMode: singleName.optional().describe("Major mode the step session runs in."),
674
- minorModes: nameList.optional().describe("Minor modes activated in the step session."),
675
- profile: singleName.optional().describe("Profile the step session runs as."),
676
- domains: nameList.optional().describe("Domains selected for the step session. An empty list selects none."),
677
- model: singleName.optional().describe("Model selector, provider/id."),
678
- thinking: singleName.optional().describe("Thinking level for the model."),
679
- subagentModel: singleName.optional().describe("Preferred Team subagent model, independent of the step model."),
680
- subagentThinking: singleName.optional().describe("Preferred Team subagent thinking level.")
681
- }).strict();
682
- /**
683
- * The same keys for a templated step, whose `runConfig` is also the data its
684
- * command template reads: keys DoomPi does not use are left to the template.
685
- */
686
- const doompiTemplateRunConfigSchema = doompiRunConfigSchema.strip();
687
- /** The runConfig keys DoomPi reads itself, the host keys `workflow-mcp doctor` checks steps against. */
688
- const DOOMPI_RUN_CONFIG_KEYS = doompiRunConfigSchema.keyof().options;
689
- //#endregion
690
690
  //#region src/types/webWorkflows.ts
691
691
  /** A customRun step ran as this child session. */
692
692
  const STEP_SESSION_REF_KIND = "session";
@@ -718,7 +718,9 @@ const DOOMPI_KEYS = new Set(DOOMPI_RUN_CONFIG_KEYS);
718
718
  * A templated step's may also carry keys its command template reads. A key
719
719
  * that is neither, such as `majormode`, fails the step rather than running it
720
720
  * on workspace defaults. An engine that does not say what its template reads
721
- * leaves such keys unchecked.
721
+ * leaves such keys unchecked. A step must name its major mode, itself or
722
+ * through the workflow's top-level `runConfig`: the workspace default may be an
723
+ * interactive mode whose tools, like asking the user, hang an unattended step.
722
724
  */
723
725
  function readDoompiRunConfig(runConfig, template) {
724
726
  const parsed = (template === void 0 ? doompiRunConfigSchema : doompiTemplateRunConfigSchema).safeParse(runConfig ?? {});
@@ -731,6 +733,7 @@ function readDoompiRunConfig(runConfig, template) {
731
733
  const unknown = Object.keys(runConfig).filter((key) => !DOOMPI_KEYS.has(key) && !reads.has(key));
732
734
  if (unknown.length > 0) throw new Error(`Invalid runConfig: ${unknown.join(", ")} is neither a DoomPi setting nor read by the "${template.name}" command.`);
733
735
  }
736
+ if (parsed.data.majorMode === void 0) throw new Error("Invalid runConfig: majorMode is required; set it on the step or in the workflow's top-level runConfig.");
734
737
  return parsed.data;
735
738
  }
736
739
  /** The selection a step session is pinned to; unset keys keep the workspace defaults. */
@@ -2320,6 +2323,22 @@ function errorOf(value) {
2320
2323
  function errorMessage(error) {
2321
2324
  return error instanceof Error ? error.message : String(error);
2322
2325
  }
2326
+ /**
2327
+ * The selection a workflow session runs in: the workflow's top-level
2328
+ * `runConfig` plus the workflow mode. Its owner agent works unattended, so a
2329
+ * workflow that names no major mode is refused rather than left on the
2330
+ * workspace default, which may be an interactive mode that asks the user.
2331
+ */
2332
+ function workflowSessionSelection(workflow) {
2333
+ const config = doompiTemplateRunConfigSchema.parse(workflow.runConfig ?? {});
2334
+ if (config.majorMode === void 0) throw new Error("This workflow sets no top-level runConfig.majorMode, so its workflow session would run in the workspace default mode. Set one.");
2335
+ const selection = sessionSelection(config);
2336
+ const minorModes = (selection.minorModes ?? []).filter((mode) => mode !== WORKFLOW_MODE_ID);
2337
+ return {
2338
+ ...selection,
2339
+ minorModes: [...minorModes, WORKFLOW_MODE_ID]
2340
+ };
2341
+ }
2323
2342
  /** The text of a launch's tool result, as the launch tool and the API report it. */
2324
2343
  function launchResultOf(result) {
2325
2344
  return textResult(result.content.map((item) => item.type === "text" ? item.text : "").filter((line) => line !== "").join("\n") || "Workflow launch requested.", result.isError === true);
@@ -2575,13 +2594,14 @@ function createWorkflowServerRuntime(host, serverHost) {
2575
2594
  creatingWorkflowSessions += 1;
2576
2595
  let child;
2577
2596
  try {
2597
+ const selection = workflowSessionSelection(feature.parser.parseWorkflowFile(workflowPath));
2578
2598
  const name = workflowSessionName(workflowPath, (await catalogReader.read(where.cwd)).find((candidate) => candidate.path === workflowPath)?.name);
2579
2599
  child = (await sessionService.create({
2580
2600
  cwd: where.cwd,
2581
2601
  name,
2582
2602
  parentSessionId: self,
2583
2603
  sessionProvenance: require_workflowTerminal.WORKFLOW_SESSION_PROVENANCE,
2584
- selection: { minorModes: [WORKFLOW_MODE_ID] }
2604
+ selection
2585
2605
  })).sessionId;
2586
2606
  const result = await launchIn(child, {
2587
2607
  ...parameters,