@zaalipro/dsh-workflows 0.1.0-rc.12

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.
Files changed (229) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +224 -0
  3. package/README.i18n.yaml +4 -0
  4. package/README.md +111 -0
  5. package/README.zh.md +111 -0
  6. package/cordis.patch.yml +10 -0
  7. package/docs/architecture.i18n.yaml +4 -0
  8. package/docs/architecture.md +177 -0
  9. package/docs/architecture.zh.md +177 -0
  10. package/docs/testing.i18n.yaml +4 -0
  11. package/docs/testing.md +125 -0
  12. package/docs/testing.zh.md +125 -0
  13. package/docs/user-guide.i18n.yaml +4 -0
  14. package/docs/user-guide.md +351 -0
  15. package/docs/user-guide.zh.md +351 -0
  16. package/lib/client-types/WorkflowMemberInspector.d.ts +28 -0
  17. package/lib/client-types/WorkflowMemberInspector.d.ts.map +1 -0
  18. package/lib/client-types/WorkflowMemberInspector.js +181 -0
  19. package/lib/client-types/WorkflowMemberInspector.js.map +1 -0
  20. package/lib/client-types/WorkflowRunPanel.d.ts +43 -0
  21. package/lib/client-types/WorkflowRunPanel.d.ts.map +1 -0
  22. package/lib/client-types/WorkflowRunPanel.js +130 -0
  23. package/lib/client-types/WorkflowRunPanel.js.map +1 -0
  24. package/lib/client-types/WorkflowsDashboard.d.ts +49 -0
  25. package/lib/client-types/WorkflowsDashboard.d.ts.map +1 -0
  26. package/lib/client-types/WorkflowsDashboard.js +942 -0
  27. package/lib/client-types/WorkflowsDashboard.js.map +1 -0
  28. package/lib/client-types/adapter.d.ts +60 -0
  29. package/lib/client-types/adapter.d.ts.map +1 -0
  30. package/lib/client-types/adapter.js +117 -0
  31. package/lib/client-types/adapter.js.map +1 -0
  32. package/lib/client-types/chat-renderer.d.ts +10 -0
  33. package/lib/client-types/chat-renderer.d.ts.map +1 -0
  34. package/lib/client-types/chat-renderer.js +11 -0
  35. package/lib/client-types/chat-renderer.js.map +1 -0
  36. package/lib/client-types/contract.d.ts +210 -0
  37. package/lib/client-types/contract.d.ts.map +1 -0
  38. package/lib/client-types/contract.js +37 -0
  39. package/lib/client-types/contract.js.map +1 -0
  40. package/lib/client-types/controller.d.ts +83 -0
  41. package/lib/client-types/controller.d.ts.map +1 -0
  42. package/lib/client-types/controller.js +705 -0
  43. package/lib/client-types/controller.js.map +1 -0
  44. package/lib/client-types/index.d.ts +19 -0
  45. package/lib/client-types/index.d.ts.map +1 -0
  46. package/lib/client-types/index.js +731 -0
  47. package/lib/client-types/index.js.map +1 -0
  48. package/lib/client-types/locales.d.ts +257 -0
  49. package/lib/client-types/locales.d.ts.map +1 -0
  50. package/lib/client-types/locales.js +270 -0
  51. package/lib/client-types/locales.js.map +1 -0
  52. package/lib/client-types/slot-components.d.ts +38 -0
  53. package/lib/client-types/slot-components.d.ts.map +1 -0
  54. package/lib/client-types/slot-components.js +22 -0
  55. package/lib/client-types/slot-components.js.map +1 -0
  56. package/lib/client-types/store.d.ts +69 -0
  57. package/lib/client-types/store.d.ts.map +1 -0
  58. package/lib/client-types/store.js +135 -0
  59. package/lib/client-types/store.js.map +1 -0
  60. package/lib/client-types/workflow-definition.d.ts +52 -0
  61. package/lib/client-types/workflow-definition.d.ts.map +1 -0
  62. package/lib/client-types/workflow-definition.js +135 -0
  63. package/lib/client-types/workflow-definition.js.map +1 -0
  64. package/lib/client.js +11065 -0
  65. package/lib/client.js.map +1 -0
  66. package/lib/compat-engine/index.js +1926 -0
  67. package/lib/compat-engine/index.js.map +1 -0
  68. package/lib/compat-engine/worker.cjs +1500 -0
  69. package/lib/compat-engine/worker.cjs.map +1 -0
  70. package/lib/typert.host.d.ts +3 -0
  71. package/lib/typert.host.js +1709 -0
  72. package/lib/typert.remote-client.d.ts +57 -0
  73. package/lib/typert.remote-client.js +1662 -0
  74. package/lib/types/commands/aliases.d.ts +4 -0
  75. package/lib/types/commands/aliases.d.ts.map +1 -0
  76. package/lib/types/commands/aliases.js +25 -0
  77. package/lib/types/commands/aliases.js.map +1 -0
  78. package/lib/types/commands/index.d.ts +66 -0
  79. package/lib/types/commands/index.d.ts.map +1 -0
  80. package/lib/types/commands/index.js +550 -0
  81. package/lib/types/commands/index.js.map +1 -0
  82. package/lib/types/commands/parser.d.ts +17 -0
  83. package/lib/types/commands/parser.d.ts.map +1 -0
  84. package/lib/types/commands/parser.js +45 -0
  85. package/lib/types/commands/parser.js.map +1 -0
  86. package/lib/types/config.d.ts +71 -0
  87. package/lib/types/config.d.ts.map +1 -0
  88. package/lib/types/config.js +109 -0
  89. package/lib/types/config.js.map +1 -0
  90. package/lib/types/index.d.ts +41 -0
  91. package/lib/types/index.d.ts.map +1 -0
  92. package/lib/types/index.js +483 -0
  93. package/lib/types/index.js.map +1 -0
  94. package/lib/types/invariant.d.ts +21 -0
  95. package/lib/types/invariant.d.ts.map +1 -0
  96. package/lib/types/invariant.js +85 -0
  97. package/lib/types/invariant.js.map +1 -0
  98. package/lib/types/registry/definition.d.ts +24 -0
  99. package/lib/types/registry/definition.d.ts.map +1 -0
  100. package/lib/types/registry/definition.js +189 -0
  101. package/lib/types/registry/definition.js.map +1 -0
  102. package/lib/types/registry/index.d.ts +100 -0
  103. package/lib/types/registry/index.d.ts.map +1 -0
  104. package/lib/types/registry/index.js +899 -0
  105. package/lib/types/registry/index.js.map +1 -0
  106. package/lib/types/registry/names.d.ts +19 -0
  107. package/lib/types/registry/names.d.ts.map +1 -0
  108. package/lib/types/registry/names.js +69 -0
  109. package/lib/types/registry/names.js.map +1 -0
  110. package/lib/types/registry/remote.d.ts +15 -0
  111. package/lib/types/registry/remote.d.ts.map +1 -0
  112. package/lib/types/registry/remote.js +128 -0
  113. package/lib/types/registry/remote.js.map +1 -0
  114. package/lib/types/registry/roots.d.ts +44 -0
  115. package/lib/types/registry/roots.d.ts.map +1 -0
  116. package/lib/types/registry/roots.js +118 -0
  117. package/lib/types/registry/roots.js.map +1 -0
  118. package/lib/types/registry/types.d.ts +62 -0
  119. package/lib/types/registry/types.d.ts.map +1 -0
  120. package/lib/types/registry/types.js +2 -0
  121. package/lib/types/registry/types.js.map +1 -0
  122. package/lib/types/registry/watchers.d.ts +70 -0
  123. package/lib/types/registry/watchers.d.ts.map +1 -0
  124. package/lib/types/registry/watchers.js +152 -0
  125. package/lib/types/registry/watchers.js.map +1 -0
  126. package/lib/types/remote-events.d.ts +42 -0
  127. package/lib/types/remote-events.d.ts.map +1 -0
  128. package/lib/types/remote-events.js +21 -0
  129. package/lib/types/remote-events.js.map +1 -0
  130. package/lib/types/run-recorder.d.ts +44 -0
  131. package/lib/types/run-recorder.d.ts.map +1 -0
  132. package/lib/types/run-recorder.js +356 -0
  133. package/lib/types/run-recorder.js.map +1 -0
  134. package/lib/types/supervisor/canned-validate.d.ts +25 -0
  135. package/lib/types/supervisor/canned-validate.d.ts.map +1 -0
  136. package/lib/types/supervisor/canned-validate.js +122 -0
  137. package/lib/types/supervisor/canned-validate.js.map +1 -0
  138. package/lib/types/supervisor/completion-notice.d.ts +49 -0
  139. package/lib/types/supervisor/completion-notice.d.ts.map +1 -0
  140. package/lib/types/supervisor/completion-notice.js +281 -0
  141. package/lib/types/supervisor/completion-notice.js.map +1 -0
  142. package/lib/types/supervisor/cursors.d.ts +68 -0
  143. package/lib/types/supervisor/cursors.d.ts.map +1 -0
  144. package/lib/types/supervisor/cursors.js +158 -0
  145. package/lib/types/supervisor/cursors.js.map +1 -0
  146. package/lib/types/supervisor/engine-compat.d.ts +48 -0
  147. package/lib/types/supervisor/engine-compat.d.ts.map +1 -0
  148. package/lib/types/supervisor/engine-compat.js +116 -0
  149. package/lib/types/supervisor/engine-compat.js.map +1 -0
  150. package/lib/types/supervisor/index.d.ts +183 -0
  151. package/lib/types/supervisor/index.d.ts.map +1 -0
  152. package/lib/types/supervisor/index.js +2040 -0
  153. package/lib/types/supervisor/index.js.map +1 -0
  154. package/lib/types/supervisor/parallel-compat.d.ts +36 -0
  155. package/lib/types/supervisor/parallel-compat.d.ts.map +1 -0
  156. package/lib/types/supervisor/parallel-compat.js +180 -0
  157. package/lib/types/supervisor/parallel-compat.js.map +1 -0
  158. package/lib/types/supervisor/remote.d.ts +25 -0
  159. package/lib/types/supervisor/remote.d.ts.map +1 -0
  160. package/lib/types/supervisor/remote.js +478 -0
  161. package/lib/types/supervisor/remote.js.map +1 -0
  162. package/lib/types/supervisor/storage/bounded-file.d.ts +41 -0
  163. package/lib/types/supervisor/storage/bounded-file.d.ts.map +1 -0
  164. package/lib/types/supervisor/storage/bounded-file.js +186 -0
  165. package/lib/types/supervisor/storage/bounded-file.js.map +1 -0
  166. package/lib/types/supervisor/storage/details-codec.d.ts +14 -0
  167. package/lib/types/supervisor/storage/details-codec.d.ts.map +1 -0
  168. package/lib/types/supervisor/storage/details-codec.js +359 -0
  169. package/lib/types/supervisor/storage/details-codec.js.map +1 -0
  170. package/lib/types/supervisor/storage/index.d.ts +26 -0
  171. package/lib/types/supervisor/storage/index.d.ts.map +1 -0
  172. package/lib/types/supervisor/storage/index.js +100 -0
  173. package/lib/types/supervisor/storage/index.js.map +1 -0
  174. package/lib/types/supervisor/storage/lease.d.ts +34 -0
  175. package/lib/types/supervisor/storage/lease.d.ts.map +1 -0
  176. package/lib/types/supervisor/storage/lease.js +289 -0
  177. package/lib/types/supervisor/storage/lease.js.map +1 -0
  178. package/lib/types/supervisor/storage/manifest-codec.d.ts +10 -0
  179. package/lib/types/supervisor/storage/manifest-codec.d.ts.map +1 -0
  180. package/lib/types/supervisor/storage/manifest-codec.js +335 -0
  181. package/lib/types/supervisor/storage/manifest-codec.js.map +1 -0
  182. package/lib/types/supervisor/storage/manifest-store.d.ts +99 -0
  183. package/lib/types/supervisor/storage/manifest-store.d.ts.map +1 -0
  184. package/lib/types/supervisor/storage/manifest-store.js +1606 -0
  185. package/lib/types/supervisor/storage/manifest-store.js.map +1 -0
  186. package/lib/types/supervisor/storage/manifest-types.d.ts +269 -0
  187. package/lib/types/supervisor/storage/manifest-types.d.ts.map +1 -0
  188. package/lib/types/supervisor/storage/manifest-types.js +2 -0
  189. package/lib/types/supervisor/storage/manifest-types.js.map +1 -0
  190. package/lib/types/supervisor/storage/private-root.d.ts +143 -0
  191. package/lib/types/supervisor/storage/private-root.d.ts.map +1 -0
  192. package/lib/types/supervisor/storage/private-root.js +860 -0
  193. package/lib/types/supervisor/storage/private-root.js.map +1 -0
  194. package/lib/types/supervisor/storage/recovery.d.ts +14 -0
  195. package/lib/types/supervisor/storage/recovery.d.ts.map +1 -0
  196. package/lib/types/supervisor/storage/recovery.js +126 -0
  197. package/lib/types/supervisor/storage/recovery.js.map +1 -0
  198. package/lib/types/supervisor/storage/run-files.d.ts +67 -0
  199. package/lib/types/supervisor/storage/run-files.d.ts.map +1 -0
  200. package/lib/types/supervisor/storage/run-files.js +346 -0
  201. package/lib/types/supervisor/storage/run-files.js.map +1 -0
  202. package/lib/types/supervisor/types.d.ts +295 -0
  203. package/lib/types/supervisor/types.d.ts.map +1 -0
  204. package/lib/types/supervisor/types.js +3 -0
  205. package/lib/types/supervisor/types.js.map +1 -0
  206. package/lib/types/supervisor/value-view.d.ts +19 -0
  207. package/lib/types/supervisor/value-view.d.ts.map +1 -0
  208. package/lib/types/supervisor/value-view.js +183 -0
  209. package/lib/types/supervisor/value-view.js.map +1 -0
  210. package/lib/types/tool/index.d.ts +86 -0
  211. package/lib/types/tool/index.d.ts.map +1 -0
  212. package/lib/types/tool/index.js +810 -0
  213. package/lib/types/tool/index.js.map +1 -0
  214. package/lib/types/tool/schema.d.ts +158 -0
  215. package/lib/types/tool/schema.d.ts.map +1 -0
  216. package/lib/types/tool/schema.js +137 -0
  217. package/lib/types/tool/schema.js.map +1 -0
  218. package/lib/types/types.d.ts +9 -0
  219. package/lib/types/types.d.ts.map +1 -0
  220. package/lib/types/types.js +3 -0
  221. package/lib/types/types.js.map +1 -0
  222. package/lib/types/user-questions.d.ts +9 -0
  223. package/lib/types/user-questions.d.ts.map +1 -0
  224. package/lib/types/user-questions.js +91 -0
  225. package/lib/types/user-questions.js.map +1 -0
  226. package/package.json +291 -0
  227. package/skills/create-workflow/SKILL.md +166 -0
  228. package/vendor/workflow-engine/LICENSE +21 -0
  229. package/vendor/workflow-engine/README.md +1 -0
@@ -0,0 +1,4 @@
1
+ import type { WorkflowDefinitionSummary } from '../registry/types.js';
2
+ /** Allocate aliases in UTF-16 name order without stealing a sibling's bare name. */
3
+ export declare function allocateWorkflowCommandNames(definitions: readonly Pick<WorkflowDefinitionSummary, 'name'>[], occupiedNames: ReadonlySet<string>): ReadonlyMap<string, string>;
4
+ //# sourceMappingURL=aliases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aliases.d.ts","sourceRoot":"","sources":["../../../src/commands/aliases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAA;AAErE,oFAAoF;AACpF,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,SAAS,IAAI,CAAC,yBAAyB,EAAE,MAAM,CAAC,EAAE,EAC/D,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,GACjC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAqB7B"}
@@ -0,0 +1,25 @@
1
+ /** Allocate aliases in UTF-16 name order without stealing a sibling's bare name. */
2
+ export function allocateWorkflowCommandNames(definitions, occupiedNames) {
3
+ const allocated = new Map();
4
+ const reservedBareNames = new Set(definitions.map(definition => definition.name));
5
+ const used = new Set();
6
+ const sortedNames = [...reservedBareNames].sort();
7
+ for (const definitionName of sortedNames) {
8
+ if (occupiedNames.has(definitionName))
9
+ continue;
10
+ allocated.set(definitionName, definitionName);
11
+ used.add(definitionName);
12
+ }
13
+ for (const definitionName of sortedNames) {
14
+ if (allocated.has(definitionName))
15
+ continue;
16
+ let commandName = `workflow-${definitionName}`;
17
+ while (reservedBareNames.has(commandName) || used.has(commandName) || occupiedNames.has(commandName)) {
18
+ commandName = `workflow-${commandName}`;
19
+ }
20
+ allocated.set(definitionName, commandName);
21
+ used.add(commandName);
22
+ }
23
+ return allocated;
24
+ }
25
+ //# sourceMappingURL=aliases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aliases.js","sourceRoot":"","sources":["../../../src/commands/aliases.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,MAAM,UAAU,4BAA4B,CAC1C,WAA+D,EAC/D,aAAkC;IAElC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAA;IAC3C,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAA;IACjF,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,MAAM,WAAW,GAAG,CAAC,GAAG,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAA;IAEjD,KAAK,MAAM,cAAc,IAAI,WAAW,EAAE,CAAC;QACzC,IAAI,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC;YAAE,SAAQ;QAC/C,SAAS,CAAC,GAAG,CAAC,cAAc,EAAE,cAAc,CAAC,CAAA;QAC7C,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;IAC1B,CAAC;IACD,KAAK,MAAM,cAAc,IAAI,WAAW,EAAE,CAAC;QACzC,IAAI,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC;YAAE,SAAQ;QAC3C,IAAI,WAAW,GAAG,YAAY,cAAc,EAAE,CAAA;QAC9C,OAAO,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YACrG,WAAW,GAAG,YAAY,WAAW,EAAE,CAAA;QACzC,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAA;QAC1C,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACvB,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { allocateWorkflowCommandNames } from './aliases.js';
2
+ import type { WorkflowRegistry } from '../registry/index.js';
3
+ import type { WorkflowSupervisor } from '../supervisor/index.js';
4
+ export * from './parser.js';
5
+ export * from './aliases.js';
6
+ export declare const name = "commands";
7
+ export interface CommandsConfig {
8
+ readonly enabled?: boolean;
9
+ /** Root composition registers the protected skill as a separate child. */
10
+ readonly registerSkill?: boolean;
11
+ }
12
+ export declare const CommandsConfig: {
13
+ readonly enabled: true;
14
+ };
15
+ export interface CommandResult {
16
+ readonly content: string;
17
+ readonly isError?: boolean;
18
+ }
19
+ export declare const COMMAND_SUCCESS: {
20
+ pause: (display: string) => string;
21
+ resume: (display: string) => string;
22
+ stop: (display: string) => string;
23
+ };
24
+ export declare const CREATE_WORKFLOW_COMMAND_DESCRIPTION = "Author, smoke-check, and save a new workflow (create-workflow skill)";
25
+ export declare const WORKFLOWS_COMMAND_DESCRIPTION = "Open saved workflows and live runs";
26
+ /**
27
+ * The steered user message must be exactly what the user typed. Enforcement
28
+ * (no interview, validate_only, auto-save) lives in the skill content and the
29
+ * tool defaults — not in visible user text.
30
+ */
31
+ export declare function createWorkflowSteerText(detail: string): string;
32
+ export interface WorkflowCommandServices {
33
+ readonly registry: Pick<WorkflowRegistry, 'get'>;
34
+ readonly supervisor: Pick<WorkflowSupervisor, 'start' | 'pause' | 'resume' | 'stop' | 'save'>;
35
+ readonly agent: any;
36
+ readonly recorder?: {
37
+ launch?(session: any, start: () => Promise<any>): Promise<any>;
38
+ };
39
+ readonly cwd?: string;
40
+ readonly signal?: AbortSignal;
41
+ }
42
+ /** Execute a parsed command in small standalone fixtures as well as a Host. */
43
+ export declare function executeWorkflowCommand(input: string, services: WorkflowCommandServices): Promise<CommandResult>;
44
+ /** Resolve candidate packaged-skill URLs from source or an installed lib layout. */
45
+ export declare function packagedSkillCandidates(here?: string | URL): readonly URL[];
46
+ /** Resolve the shipped skill asset from source or an installed lib layout. */
47
+ export declare function packagedSkillPath(here?: string | URL): URL;
48
+ /** Split YAML frontmatter from the registered Markdown body. */
49
+ export declare function parsePackagedSkillDocument(text: string): {
50
+ readonly description: string;
51
+ readonly content: string;
52
+ };
53
+ export declare function readPackagedSkillFrom(candidates: readonly URL[]): Promise<string>;
54
+ export declare function readPackagedSkillSyncFrom(candidates: readonly URL[]): string;
55
+ export declare function readPackagedSkill(): Promise<string>;
56
+ export declare function readPackagedSkillSync(): string;
57
+ /** Prefer a future protected binding; stock rc.2 uses its provider rank seam. */
58
+ export declare function registerTrustedWorkflowSkill(ctx: any): Promise<() => void>;
59
+ export declare function registerTrustedWorkflowSkillSync(ctx: any, options?: {
60
+ readonly required?: boolean;
61
+ }): () => unknown;
62
+ /** Mount Host commands and exact-Agent definition aliases. */
63
+ export declare function applyCommands(ctx: any, config?: CommandsConfig): (() => Promise<void>) | undefined;
64
+ export declare const apply: typeof applyCommands;
65
+ export { allocateWorkflowCommandNames };
66
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,550 @@
1
+ import { createUserMessage } from '@deepseek-ai/dsh-llm';
2
+ import { readFileSync } from 'node:fs';
3
+ import { parseWorkflowCommand, WORKFLOW_COMMAND_HELP } from './parser.js';
4
+ import { allocateWorkflowCommandNames } from './aliases.js';
5
+ export * from './parser.js';
6
+ export * from './aliases.js';
7
+ export const name = 'commands';
8
+ export const CommandsConfig = { enabled: true };
9
+ export const COMMAND_SUCCESS = {
10
+ pause: (display) => `Paused workflow "${display}". Open /workflows to resume or stop it.`,
11
+ resume: (display) => `Resumed workflow "${display}". Open /workflows to watch it.`,
12
+ stop: (display) => `Stopped workflow "${display}".`,
13
+ };
14
+ export const CREATE_WORKFLOW_COMMAND_DESCRIPTION = 'Author, smoke-check, and save a new workflow (create-workflow skill)';
15
+ export const WORKFLOWS_COMMAND_DESCRIPTION = 'Open saved workflows and live runs';
16
+ /**
17
+ * The steered user message must be exactly what the user typed. Enforcement
18
+ * (no interview, validate_only, auto-save) lives in the skill content and the
19
+ * tool defaults — not in visible user text.
20
+ */
21
+ export function createWorkflowSteerText(detail) {
22
+ const trimmed = detail.trim();
23
+ return trimmed === '' ? '/create-workflow' : `/create-workflow ${trimmed}`;
24
+ }
25
+ const DEFAULT_SKILL_DESCRIPTION = 'Author, smoke-check, and save a new saved workflow (invoke via /create-workflow).';
26
+ const CREATE_WORKFLOW_PROVIDER = 'workflow-authoring';
27
+ const CREATE_WORKFLOW_RANK = 0;
28
+ const CREATE_WORKFLOW_LOCATOR = Object.freeze({ name: 'create-workflow' });
29
+ function renderThrown(error) {
30
+ try {
31
+ return error instanceof Error ? error.message : String(error);
32
+ }
33
+ catch {
34
+ return '[unrenderable workflow command failure]';
35
+ }
36
+ }
37
+ function cwdOf(agent) {
38
+ const cwd = agent?.session?.header?.cwd;
39
+ return typeof cwd === 'string' && cwd.length > 0 ? { cwd } : {};
40
+ }
41
+ function commandSuccess(text) { return { kind: 'success', text }; }
42
+ function commandError(error) { return { kind: 'error', text: renderThrown(error) }; }
43
+ function officialFromCommandResult(result) {
44
+ return result.isError === true ? { kind: 'error', text: result.content } : commandSuccess(result.content);
45
+ }
46
+ function isAbortError(error, signal) {
47
+ return signal?.aborted === true
48
+ || (typeof error === 'object' && error !== null && error.name === 'AbortError');
49
+ }
50
+ /** Execute a parsed command in small standalone fixtures as well as a Host. */
51
+ export async function executeWorkflowCommand(input, services) {
52
+ const command = parseWorkflowCommand(input);
53
+ if (command.kind === 'empty')
54
+ return { content: WORKFLOW_COMMAND_HELP };
55
+ if (command.kind === 'malformed')
56
+ return { content: command.error, isError: true };
57
+ const signal = services.signal;
58
+ try {
59
+ signal?.throwIfAborted();
60
+ if (command.kind === 'launch') {
61
+ const definition = await services.registry.get(command.name, { cwd: services.cwd ?? cwdOf(services.agent).cwd, signal });
62
+ if (definition === undefined)
63
+ return { content: `no saved workflow named "${command.name}"`, isError: true };
64
+ const start = () => services.supervisor.start({ definition, args: command.args, parent: services.agent, signal });
65
+ const launched = typeof services.recorder?.launch === 'function'
66
+ ? await services.recorder.launch(services.agent.session, start)
67
+ : await start();
68
+ return { content: `Started workflow "${launched.displayName}" in the background. Open /workflows to watch it.` };
69
+ }
70
+ if (command.kind === 'pause') {
71
+ await services.supervisor.pause(command.displayName, services.agent, signal);
72
+ return { content: COMMAND_SUCCESS.pause(command.displayName) };
73
+ }
74
+ if (command.kind === 'resume') {
75
+ await services.supervisor.resume(command.displayName, services.agent, signal);
76
+ return { content: COMMAND_SUCCESS.resume(command.displayName) };
77
+ }
78
+ if (command.kind === 'stop') {
79
+ await services.supervisor.stop(command.displayName, services.agent, signal);
80
+ return { content: COMMAND_SUCCESS.stop(command.displayName) };
81
+ }
82
+ const path = await services.supervisor.save(command.displayName, services.agent, undefined, signal);
83
+ return { content: `Saved workflow "${command.displayName}" to ${path}.` };
84
+ }
85
+ catch (error) {
86
+ return { content: renderThrown(error), isError: true };
87
+ }
88
+ }
89
+ /** Resolve candidate packaged-skill URLs from source or an installed lib layout. */
90
+ export function packagedSkillCandidates(here = import.meta.url) {
91
+ const base = typeof here === 'string' ? new URL(here) : here;
92
+ return [
93
+ new URL('../../skills/create-workflow/SKILL.md', base),
94
+ new URL('../../../skills/create-workflow/SKILL.md', base),
95
+ ];
96
+ }
97
+ /** Resolve the shipped skill asset from source or an installed lib layout. */
98
+ export function packagedSkillPath(here = import.meta.url) {
99
+ return packagedSkillCandidates(here)[baseUsesLibLayout(here) ? 1 : 0];
100
+ }
101
+ function baseUsesLibLayout(here) {
102
+ const path = String(typeof here === 'string' ? here : here.pathname);
103
+ return path.includes('/lib/');
104
+ }
105
+ function validSkill(text) {
106
+ return /^---\s*\n/u.test(text)
107
+ && /^name:\s*create-workflow\s*$/mu.test(text)
108
+ && /\/create-workflow/u.test(text)
109
+ && /^user-invocable:\s*true\s*$/mu.test(text)
110
+ && /^model-invocable:\s*true\s*$/mu.test(text);
111
+ }
112
+ /** Split YAML frontmatter from the registered Markdown body. */
113
+ export function parsePackagedSkillDocument(text) {
114
+ if (!validSkill(text))
115
+ throw new Error('invalid skill');
116
+ const match = /^---\r?\n[\s\S]*?\r?\n---\r?\n([\s\S]*)$/u.exec(text);
117
+ const content = (match?.[1] ?? '').replace(/^\uFEFF/u, '').replace(/^(?:\r?\n)+/u, '');
118
+ const description = text.match(/^description:\s*(.+)$/mu)?.[1]?.trim() || DEFAULT_SKILL_DESCRIPTION;
119
+ return { description, content };
120
+ }
121
+ export async function readPackagedSkillFrom(candidates) {
122
+ const fs = await import('node:fs/promises');
123
+ let last;
124
+ for (const candidate of candidates) {
125
+ try {
126
+ const text = await fs.readFile(candidate, 'utf8');
127
+ if (!validSkill(text))
128
+ throw new Error('invalid skill');
129
+ return text;
130
+ }
131
+ catch (error) {
132
+ last = error;
133
+ }
134
+ }
135
+ throw new Error(`packaged create-workflow skill is missing or invalid: ${renderThrown(last)}`);
136
+ }
137
+ export function readPackagedSkillSyncFrom(candidates) {
138
+ let last;
139
+ for (const candidate of candidates) {
140
+ try {
141
+ const text = readFileSync(candidate, 'utf8');
142
+ if (!validSkill(text))
143
+ throw new Error('invalid skill');
144
+ return text;
145
+ }
146
+ catch (error) {
147
+ last = error;
148
+ }
149
+ }
150
+ throw new Error(`packaged create-workflow skill is missing or invalid: ${renderThrown(last)}`);
151
+ }
152
+ export async function readPackagedSkill() {
153
+ return readPackagedSkillFrom(packagedSkillCandidates());
154
+ }
155
+ export function readPackagedSkillSync() {
156
+ return readPackagedSkillSyncFrom(packagedSkillCandidates());
157
+ }
158
+ function registrationForSkill(text) {
159
+ const parsed = parsePackagedSkillDocument(text);
160
+ return {
161
+ name: 'create-workflow',
162
+ description: parsed.description,
163
+ content: parsed.content,
164
+ source: 'bundled',
165
+ invocation: { modelInvocable: true, userInvocable: true },
166
+ };
167
+ }
168
+ /** Stock rc.2 provider whose rank keeps the product procedure above project/user collisions. */
169
+ function createWorkflowSkillProvider(text) {
170
+ const registration = registrationForSkill(text);
171
+ const definition = Object.freeze({
172
+ ...registration,
173
+ provider: CREATE_WORKFLOW_PROVIDER,
174
+ });
175
+ const candidate = Object.freeze({
176
+ name: definition.name,
177
+ description: definition.description,
178
+ source: definition.source,
179
+ provider: CREATE_WORKFLOW_PROVIDER,
180
+ invocation: definition.invocation,
181
+ rank: CREATE_WORKFLOW_RANK,
182
+ locator: CREATE_WORKFLOW_LOCATOR,
183
+ });
184
+ return Object.freeze({
185
+ name: CREATE_WORKFLOW_PROVIDER,
186
+ list: () => Promise.resolve([candidate]),
187
+ get: (selected) => Promise.resolve(selected === candidate ? definition : undefined),
188
+ });
189
+ }
190
+ function asDisposer(value) {
191
+ if (typeof value === 'function')
192
+ return value;
193
+ if (typeof value?.dispose === 'function') {
194
+ return () => value.dispose();
195
+ }
196
+ return () => undefined;
197
+ }
198
+ /** Prefer a future protected binding; stock rc.2 uses its provider rank seam. */
199
+ export async function registerTrustedWorkflowSkill(ctx) {
200
+ const content = await readPackagedSkill();
201
+ const trusted = ctx?.skills?.registerTrustedPackageSkill;
202
+ if (typeof trusted === 'function') {
203
+ return asDisposer(trusted.call(ctx.skills, registrationForSkill(content), { protectedName: 'create-workflow' }));
204
+ }
205
+ const registerProvider = ctx?.skills?.registerProvider;
206
+ if (typeof registerProvider === 'function') {
207
+ return asDisposer(registerProvider.call(ctx.skills, () => createWorkflowSkillProvider(content)));
208
+ }
209
+ throw new Error('protected packaged skill registration is unavailable');
210
+ }
211
+ export function registerTrustedWorkflowSkillSync(ctx, options = {}) {
212
+ const trusted = ctx?.skills?.registerTrustedPackageSkill;
213
+ if (typeof trusted === 'function') {
214
+ return asDisposer(trusted.call(ctx.skills, registrationForSkill(readPackagedSkillSync()), { protectedName: 'create-workflow' }));
215
+ }
216
+ const registerProvider = ctx?.skills?.registerProvider;
217
+ if (typeof registerProvider === 'function') {
218
+ const content = readPackagedSkillSync();
219
+ return asDisposer(registerProvider.call(ctx.skills, () => createWorkflowSkillProvider(content)));
220
+ }
221
+ if (options.required !== false)
222
+ throw new Error('protected packaged skill registration is unavailable');
223
+ return () => undefined;
224
+ }
225
+ function on(ctx, event, listener) {
226
+ const disposer = ctx?.on?.(event, listener);
227
+ return typeof disposer === 'function' ? disposer : () => undefined;
228
+ }
229
+ function agentList(ctx) {
230
+ const value = ctx?.agents?.list?.();
231
+ return Array.isArray(value) ? value : [];
232
+ }
233
+ function effectiveCommandNames(ctx, agent) {
234
+ const names = new Set();
235
+ const list = ctx?.commands?.list?.(agent);
236
+ if (Array.isArray(list))
237
+ for (const item of list)
238
+ if (typeof item?.name === 'string')
239
+ names.add(item.name);
240
+ return names;
241
+ }
242
+ function occupiedCommandNames(ctx, state) {
243
+ const ownHandlers = new Set([...state.registrations.values()].map(registration => registration.handler));
244
+ const occupied = new Set();
245
+ for (const name of effectiveCommandNames(ctx, state.agent)) {
246
+ const found = ctx?.commands?.find?.(state.agent, name);
247
+ if (found !== undefined && ownHandlers.has(found.handler))
248
+ continue;
249
+ if (found === undefined && [...state.registrations.values()].some(registration => registration.commandName === name))
250
+ continue;
251
+ occupied.add(name);
252
+ }
253
+ return occupied;
254
+ }
255
+ function queueRefresh(ctx, state, supervisor, track) {
256
+ if (state.disposed || state.refreshQueued)
257
+ return;
258
+ state.refreshQueued = true;
259
+ queueMicrotask(() => {
260
+ state.refreshQueued = false;
261
+ if (!state.disposed)
262
+ track(refreshAliases(ctx, state, supervisor));
263
+ });
264
+ }
265
+ function scheduleReconcile(ctx, state, supervisor) {
266
+ if (state.disposed || state.reconcileQueued)
267
+ return;
268
+ state.reconcileQueued = true;
269
+ queueMicrotask(() => {
270
+ state.reconcileQueued = false;
271
+ if (state.disposed)
272
+ return;
273
+ try {
274
+ reconcileAliases(ctx, state, supervisor);
275
+ }
276
+ catch { /* contained: owner inject is probed at attach */ }
277
+ });
278
+ }
279
+ async function refreshAliases(ctx, state, supervisor) {
280
+ state.abort?.abort(new Error('workflow alias refresh superseded'));
281
+ const abort = new AbortController();
282
+ state.abort = abort;
283
+ let definitions;
284
+ try {
285
+ definitions = await ctx.workflows.list({ ...cwdOf(state.agent), signal: abort.signal });
286
+ }
287
+ catch (error) {
288
+ if (abort.signal.aborted || state.disposed || isAbortError(error, abort.signal))
289
+ return;
290
+ ctx?.logger?.warn?.(`workflow alias catalog refresh failed: ${error instanceof Error ? error.message : String(error)}`);
291
+ return;
292
+ }
293
+ if (abort.signal.aborted || state.disposed)
294
+ return;
295
+ state.definitions.clear();
296
+ for (const definition of definitions)
297
+ state.definitions.set(definition.name, definition);
298
+ reconcileAliases(ctx, state, supervisor);
299
+ }
300
+ function reconcileAliases(ctx, state, supervisor) {
301
+ if (state.disposed)
302
+ return;
303
+ const allocations = allocateWorkflowCommandNames([...state.definitions.values()], occupiedCommandNames(ctx, state));
304
+ for (const [canonical, registration] of [...state.registrations]) {
305
+ const definition = state.definitions.get(canonical);
306
+ if (definition !== undefined
307
+ && registration.description === definition.description
308
+ && registration.commandName === allocations.get(canonical))
309
+ continue;
310
+ try {
311
+ void registration.dispose();
312
+ }
313
+ catch { /* contained */ }
314
+ state.registrations.delete(canonical);
315
+ }
316
+ for (const definition of state.definitions.values()) {
317
+ if (state.registrations.has(definition.name))
318
+ continue;
319
+ const alias = allocations.get(definition.name);
320
+ if (alias === undefined)
321
+ continue;
322
+ state.registrations.set(definition.name, makeAlias(ctx, state, supervisor, definition, alias));
323
+ }
324
+ }
325
+ function makeAlias(ctx, state, supervisor, definition, commandName) {
326
+ const handler = async (invocation) => {
327
+ const raw = String(invocation?.rawInput ?? '').trim();
328
+ let args = {};
329
+ if (raw !== '') {
330
+ try {
331
+ const parsed = JSON.parse(raw);
332
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed))
333
+ throw new Error('object');
334
+ args = parsed;
335
+ }
336
+ catch {
337
+ return { kind: 'error', text: `/${commandName} args must be one JSON object (wrap arrays/scalars in a field)` };
338
+ }
339
+ }
340
+ const agent = invocation.agent;
341
+ try {
342
+ const full = await ctx.workflows.get(definition.name, { ...cwdOf(agent), signal: invocation.signal });
343
+ if (full === undefined)
344
+ return { kind: 'error', text: `no saved workflow named "${definition.name}"` };
345
+ const launch = () => supervisor.start({ definition: full, args, parent: agent, signal: invocation.signal });
346
+ const launched = typeof ctx.workflowRunRecorder?.launch === 'function'
347
+ ? await ctx.workflowRunRecorder.launch(agent.session, launch)
348
+ : await launch();
349
+ return commandSuccess(`Started workflow "${launched.displayName}" in the background. Open /workflows to watch it.`);
350
+ }
351
+ catch (error) {
352
+ return commandError(error);
353
+ }
354
+ };
355
+ const contribution = {
356
+ name: commandName,
357
+ description: commandName === definition.name
358
+ ? definition.description
359
+ : `Saved workflow "${definition.name}": ${definition.description}`,
360
+ input: { hint: '[json-args]' },
361
+ handler,
362
+ };
363
+ const owner = state.agent?.ctx;
364
+ const hasFallback = typeof ctx?.commands?.registerFallback === 'function';
365
+ if (hasFallback) {
366
+ if (typeof owner?.inject !== 'function') {
367
+ throw new Error('workflow command aliases require exact-Agent command injection');
368
+ }
369
+ const fiber = owner.inject(['commands'], (registrationCtx) => {
370
+ if (typeof registrationCtx?.commands?.registerFallback !== 'function') {
371
+ throw new Error('workflow command aliases require the official commands.registerFallback seam');
372
+ }
373
+ registrationCtx.commands.registerFallback(contribution);
374
+ });
375
+ const dispose = asDisposer(fiber);
376
+ if (fiber === undefined || (typeof fiber !== 'function' && typeof fiber?.dispose !== 'function')) {
377
+ throw new Error('workflow command aliases require exact-Agent command injection');
378
+ }
379
+ return { commandName, description: definition.description, handler, dispose };
380
+ }
381
+ const register = ctx?.commands?.register;
382
+ if (typeof register !== 'function') {
383
+ throw new Error('workflow command aliases require exact-Agent command injection');
384
+ }
385
+ return {
386
+ commandName,
387
+ description: definition.description,
388
+ handler,
389
+ dispose: asDisposer(register.call(ctx.commands, contribution)),
390
+ };
391
+ }
392
+ /** Mount Host commands and exact-Agent definition aliases. */
393
+ export function applyCommands(ctx, config = {}) {
394
+ if (config.enabled === false)
395
+ return;
396
+ const cleanup = [];
397
+ const commands = ctx?.commands;
398
+ if (typeof commands?.register !== 'function')
399
+ throw new Error('workflow command registry is unavailable');
400
+ const hasFallback = typeof commands.registerFallback === 'function';
401
+ const supervisor = ctx.workflowSupervisor;
402
+ if (config.registerSkill !== false && ctx?.skills?.registerTrustedPackageSkill !== undefined) {
403
+ cleanup.push(asDisposer(registerTrustedWorkflowSkillSync(ctx)));
404
+ }
405
+ const workflowCommand = commands.register({
406
+ name: 'workflow',
407
+ description: 'Launch a saved workflow or pause/resume/stop/save a run',
408
+ input: { hint: '<name> [json-args] | pause|resume|stop|save <display-name>' },
409
+ handler: async (invocation) => {
410
+ try {
411
+ invocation.signal?.throwIfAborted();
412
+ return officialFromCommandResult(await executeWorkflowCommand(String(invocation?.rawInput ?? ''), {
413
+ registry: ctx.workflows,
414
+ supervisor,
415
+ agent: invocation.agent,
416
+ recorder: ctx.workflowRunRecorder,
417
+ signal: invocation.signal,
418
+ }));
419
+ }
420
+ catch (error) {
421
+ return commandError(error);
422
+ }
423
+ },
424
+ });
425
+ cleanup.push(asDisposer(workflowCommand));
426
+ const createCommand = commands.register({
427
+ name: 'create-workflow',
428
+ description: CREATE_WORKFLOW_COMMAND_DESCRIPTION,
429
+ input: { hint: '[what the workflow should do]' },
430
+ handler: (invocation) => {
431
+ try {
432
+ invocation.signal?.throwIfAborted();
433
+ const detail = String(invocation.rawInput ?? '').trim();
434
+ invocation.agent.steer(createUserMessage({
435
+ content: [{ type: 'text', text: createWorkflowSteerText(detail) }],
436
+ source: { kind: 'user' },
437
+ }));
438
+ return commandSuccess('Opened the workflow authoring skill.');
439
+ }
440
+ catch (error) {
441
+ return commandError(error);
442
+ }
443
+ },
444
+ });
445
+ cleanup.push(asDisposer(createCommand));
446
+ const states = new Map();
447
+ const pendingDisposals = new Set();
448
+ const track = (task) => {
449
+ pendingDisposals.add(task.catch(error => {
450
+ if (isAbortError(error))
451
+ return undefined;
452
+ const message = error instanceof Error ? error.message : String(error);
453
+ if (/registerFallback|exact-Agent command injection/u.test(message))
454
+ return undefined;
455
+ throw error;
456
+ }));
457
+ };
458
+ const addAgent = (agent) => {
459
+ if (agent === undefined || states.has(agent))
460
+ return;
461
+ if (!hasFallback) {
462
+ const cwd = cwdOf(agent).cwd;
463
+ if (cwd === undefined)
464
+ return;
465
+ for (const existing of states.keys()) {
466
+ if (cwdOf(existing).cwd === cwd)
467
+ return;
468
+ }
469
+ }
470
+ if (hasFallback) {
471
+ if (typeof agent?.ctx?.inject !== 'function') {
472
+ throw new Error('workflow command aliases require exact-Agent command injection');
473
+ }
474
+ const probe = agent.ctx.inject(['commands'], (registrationCtx) => {
475
+ if (typeof registrationCtx?.commands?.registerFallback !== 'function') {
476
+ throw new Error('workflow command aliases require the official commands.registerFallback seam');
477
+ }
478
+ });
479
+ try {
480
+ void asDisposer(probe)();
481
+ }
482
+ catch { /* contained */ }
483
+ }
484
+ const state = {
485
+ agent,
486
+ registrations: new Map(),
487
+ definitions: new Map(),
488
+ disposed: false,
489
+ refreshQueued: false,
490
+ reconcileQueued: false,
491
+ };
492
+ states.set(agent, state);
493
+ track(refreshAliases(ctx, state, supervisor));
494
+ };
495
+ const removeAgent = (agent) => {
496
+ const state = states.get(agent);
497
+ if (state === undefined)
498
+ return;
499
+ state.disposed = true;
500
+ state.abort?.abort(new Error('workflow alias owner disposed'));
501
+ for (const registration of state.registrations.values()) {
502
+ try {
503
+ const result = registration.dispose();
504
+ if (result !== undefined && typeof result?.then === 'function') {
505
+ const pending = Promise.resolve(result);
506
+ pendingDisposals.add(pending);
507
+ void pending.then(() => pendingDisposals.delete(pending), () => pendingDisposals.delete(pending));
508
+ }
509
+ }
510
+ catch { /* contained */ }
511
+ }
512
+ state.registrations.clear();
513
+ states.delete(agent);
514
+ };
515
+ for (const agent of agentList(ctx))
516
+ addAgent(agent);
517
+ cleanup.push(on(ctx, 'agent/created', event => addAgent(event?.agent ?? event)));
518
+ cleanup.push(on(ctx, 'agent/disposed', event => removeAgent(event?.agent ?? event)));
519
+ cleanup.push(on(ctx, 'workflows/change', () => { for (const state of states.values())
520
+ queueRefresh(ctx, state, supervisor, track); }));
521
+ cleanup.push(on(ctx, 'commands/change', () => { for (const state of states.values())
522
+ scheduleReconcile(ctx, state, supervisor); }));
523
+ let disposed = false;
524
+ let disposal;
525
+ const dispose = () => {
526
+ if (disposal !== undefined)
527
+ return disposal;
528
+ disposed = true;
529
+ disposal = (async () => {
530
+ for (const agent of [...states.keys()])
531
+ removeAgent(agent);
532
+ for (const item of cleanup.splice(0)) {
533
+ try {
534
+ await item();
535
+ }
536
+ catch { /* contained */ }
537
+ }
538
+ await Promise.allSettled([...pendingDisposals]);
539
+ pendingDisposals.clear();
540
+ })();
541
+ return disposal;
542
+ };
543
+ void disposed;
544
+ if (typeof ctx.effect === 'function')
545
+ ctx.effect(() => dispose, 'dsh-workflows: commands');
546
+ return dispose;
547
+ }
548
+ export const apply = applyCommands;
549
+ export { allocateWorkflowCommandNames };
550
+ //# sourceMappingURL=index.js.map