@agimon-ai/doompi-workflow 0.0.1-alpha.71 → 0.0.1-alpha.73

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.
@@ -1,2 +1,2 @@
1
- const e=require("../services/workflowLaunchCommand/index.cjs"),t=require("../services/workflowResource/index.cjs"),n=require("../services/webWorkflowCatalog/index.cjs"),r=require("../services/workflowCatalogDeps/index.cjs"),i=require("../services/workflowRuns/index.cjs"),a=require("../services/workflowWatcher/index.cjs"),o=require("../types/webWorkflows.cjs");let s=require("@agimon-ai/workflow-mcp"),c=require("zod"),l=require("@agimon-ai/doompi-minor-mode");const u=`@agimon-ai/doompi-workflow`,d=`workflow`,f=`list_workflows`,p=`launch_workflow`,m=`workflow_run`;function h(e){let t=[];if(typeof e==`object`&&e&&`content`in e&&Array.isArray(e.content))for(let n of e.content){if(typeof n!=`object`||!n||!(`type`in n))continue;let e=n;e.type===`text`&&typeof e.text==`string`?t.push({type:`text`,text:e.text}):e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`&&t.push({type:`image`,data:e.data,mimeType:e.mimeType})}return t.length===0&&t.push({type:`text`,text:JSON.stringify(e,null,2)}),{content:t,details:e}}function g(g,_){if(_.context.directEvents===void 0)throw Error(`Workflow headless facet requires the session direct event bus.`);let v=_.context.directEvents,y=n.createWorkflowCatalogReader(r.defaultCatalogDeps()),b=async e=>{let t=i.presentWorkflowRuns(a.readWorkflowRuns({environment:e.environment}).filter(t=>i.runBelongsToSession(t,e.sessionId)).map(e=>e.view),Date.now());v.publish(o.WORKFLOW_RUNS_TYPE,e.sessionId,{runs:t});try{v.publish(o.WORKFLOW_CATALOG_TYPE,e.sessionId,{cwd:e.cwd,workflows:n.presentWorkflowCatalog(await y.read(e.cwd))})}catch(t){let n=t instanceof Error?t.message:String(t);v.publish(o.WORKFLOW_CATALOG_TYPE,e.sessionId,{cwd:e.cwd,workflows:[],warning:n})}},x=(0,s.createEmbeddedWorkflowFeature)(),S=x.createListStatusesTool({recordFilter:e=>{let t=g.context.sessionId;return e.env?.PI_SESSION_ID===void 0||e.env.PI_SESSION_ID===t}}),C,w,T=()=>(g.context.selection.state?.[`minor-mode`]??[]).includes(d),E=()=>{let e=T();return{activation:e?`active`:`inactive`,condition:`ready`,...e?{detail:`workflow tools available`}:{},actions:[{id:`activate`,enabled:!e,...e?{disabledReason:`Workflow mode is active.`}:{}},{id:`deactivate`,enabled:e,...e?{}:{disabledReason:`Workflow mode is inactive.`}}]}},D=async e=>{let t=(g.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==d);await g.changeSelection({axis:`state`,key:`minor-mode`,values:e?[...t,d]:t}),w?.publish()};return w=(0,l.defineMinorMode)({descriptor:{source:u,id:d,label:`Workflow`,description:`Workflow discovery, launch, inspection, control, and recovery tools.`,order:20,actions:[{id:`activate`,label:`Activate`,description:`Enable workflow tools for this session.`,contexts:[`headless`],parameters:[]},{id:`deactivate`,label:`Deactivate`,description:`Disable workflow tools without stopping active runs.`,contexts:[`headless`],parameters:[]}]},state:E,async handleAction(e,t,n,r){if(r.signal.throwIfAborted(),t===`activate`)return await D(!0),{message:`Workflow mode activated.`};if(t===`deactivate`)return await D(!1),{message:`Workflow mode deactivated.`};throw Error(`Unknown workflow mode action: ${t}`)}}).createOwner(void 0),{services:[(0,l.serverMinorModes)([w])],toolRestrictions:[{when:{state:{"minor-mode":d}},allowedTools:[f,p,m]}],hooks:[{event:`tool_execution_end`,handle:async(e,t)=>{await b(t)}},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},event:`session_shutdown`,handle:()=>{C?.dispose(),C=void 0}}],resources:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`doompi-author-workflow`,kind:`skill`,read:()=>t.readWorkflowSkill(`doompi-author-workflow`)},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`doompi-use-workflow`,kind:`skill`,read:()=>t.readWorkflowSkill(`doompi-use-workflow`)},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`workflow-recovery`,kind:`skill`,read:()=>t.readWorkflowSkill(`workflow-recovery`)}],activities:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:u,async start(e){return C=x.createRunControl({}),await C.start(),await b(e),()=>{C?.dispose(),C=void 0}}}],tools:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:f,label:`List Workflows`,description:`List workflow definitions available in this repository.`,parameters:c.z.toJSONSchema(x.listWorkflowsTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),h(await x.listWorkflowsTool.execute(t))}},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:p,label:`Launch Workflow`,description:`Start a workflow run and return its recorded launch result.`,parameters:c.z.toJSONSchema(x.runTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),h(await x.runTool.execute(t))}},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:m,label:`Workflow Run`,description:`Inspect the status of a workflow run or request cooperative control.`,parameters:{type:`object`,properties:{action:{type:`string`,enum:[`status`,`pause`,`resume`,`stop`]},runKey:{type:`string`,minLength:1},workspace:{type:`string`},reason:{type:`string`},expectedRunId:{type:`string`}},required:[`action`,`runKey`],additionalProperties:!1},executionMode:`serial`,async execute(e,t,n){n?.throwIfAborted();let r=t;return r.action===`status`?h(await S.execute({workspace:r.workspace,pageSize:100})):C?typeof r.expectedRunId!=`string`||r.expectedRunId.length===0?h({error:`expectedRunId is required for workflow control.`}):h(r.action===`pause`?await C.pause(r.runKey,r.expectedRunId,r.workspace,r.reason):r.action===`resume`?await C.resume(r.runKey,r.expectedRunId,r.workspace):await C.stop(r.runKey,r.expectedRunId,r.workspace,r.reason)):h({error:`Workflow activity is not active.`})}}],commands:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`workflow-launch`,description:`Launch a workflow from a slash command.`,async execute(t,n){let r=e.parseWorkflowLaunchCommand(t);if(`error`in r){await n.client.notify({body:r.error,level:`error`});return}let i=h(await x.runTool.execute({workflowPath:r.workflow,...r.runner===void 0?{}:{runner:r.runner},...Object.keys(r.inputs).length===0?{}:{inputs:r.inputs},...r.prompt===void 0?{}:{prompt:r.prompt}})).content.find(e=>e.type===`text`);await n.client.notify({body:i?.type===`text`?i.text:`Workflow launch requested.`,level:`info`})}}],onDispose(){C?.dispose(),C=void 0}}}exports.createWorkflowServerRuntime=g;
1
+ const e=require("../services/workflowLaunchCommand/index.cjs"),t=require("../services/workflowResource/index.cjs"),n=require("../services/webWorkflowCatalog/index.cjs"),r=require("../services/workflowCatalogDeps/index.cjs"),i=require("../services/workflowRuns/index.cjs"),a=require("../services/workflowWatcher/index.cjs"),o=require("../types/webWorkflows.cjs");let s=require("@agimon-ai/workflow-mcp"),c=require("zod"),l=require("@agimon-ai/doompi-minor-mode");const u=`@agimon-ai/doompi-workflow`,d=`workflow`,f=`list_workflows`,p=`launch_workflow`,m=`workflow_run`;function h(e){let t=[];if(typeof e==`object`&&e&&`content`in e&&Array.isArray(e.content))for(let n of e.content){if(typeof n!=`object`||!n||!(`type`in n))continue;let e=n;e.type===`text`&&typeof e.text==`string`?t.push({type:`text`,text:e.text}):e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`&&t.push({type:`image`,data:e.data,mimeType:e.mimeType})}return t.length===0&&t.push({type:`text`,text:JSON.stringify(e,null,2)}),{content:t,details:e}}function g(g,_){if(_.context.directEvents===void 0)throw Error(`Workflow headless facet requires the session direct event bus.`);let v=_.context.directEvents,y=n.createWorkflowCatalogReader(r.defaultCatalogDeps()),b=async e=>{let t=i.presentWorkflowRuns(a.readWorkflowRuns({environment:e.environment}).filter(t=>i.runBelongsToSession(t,e.sessionId)).map(e=>e.view),Date.now());v.publish(o.WORKFLOW_RUNS_TYPE,e.sessionId,{runs:t});try{v.publish(o.WORKFLOW_CATALOG_TYPE,e.sessionId,{cwd:e.cwd,workflows:n.presentWorkflowCatalog(await y.read(e.cwd))})}catch(t){let n=t instanceof Error?t.message:String(t);v.publish(o.WORKFLOW_CATALOG_TYPE,e.sessionId,{cwd:e.cwd,workflows:[],warning:n})}},x=(0,s.createEmbeddedWorkflowFeature)(),S,C,w=()=>(g.context.selection.state?.[`minor-mode`]??[]).includes(d),T=()=>{let e=w();return{activation:e?`active`:`inactive`,condition:`ready`,...e?{detail:`workflow tools available`}:{},actions:[{id:`activate`,enabled:!e,...e?{disabledReason:`Workflow mode is active.`}:{}},{id:`deactivate`,enabled:e,...e?{}:{disabledReason:`Workflow mode is inactive.`}}]}},E=async e=>{let t=(g.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==d);await g.changeSelection({axis:`state`,key:`minor-mode`,values:e?[...t,d]:t}),C?.publish()};return C=(0,l.defineMinorMode)({descriptor:{source:u,id:d,label:`Workflow`,description:`Workflow discovery, launch, inspection, control, and recovery tools.`,order:20,actions:[{id:`activate`,label:`Activate`,description:`Enable workflow tools for this session.`,contexts:[`headless`],parameters:[]},{id:`deactivate`,label:`Deactivate`,description:`Disable workflow tools without stopping active runs.`,contexts:[`headless`],parameters:[]}]},state:T,async handleAction(e,t,n,r){if(r.signal.throwIfAborted(),t===`activate`)return await E(!0),{message:`Workflow mode activated.`};if(t===`deactivate`)return await E(!1),{message:`Workflow mode deactivated.`};throw Error(`Unknown workflow mode action: ${t}`)}}).createOwner(void 0),{services:[(0,l.serverMinorModes)([C])],toolRestrictions:[{when:{state:{"minor-mode":d}},allowedTools:[f,p,m]}],hooks:[{event:`tool_execution_end`,handle:async(e,t)=>{await b(t)}},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},event:`session_shutdown`,handle:()=>{S?.dispose(),S=void 0}}],resources:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`doompi-author-workflow`,kind:`skill`,read:()=>t.readWorkflowSkill(`doompi-author-workflow`)},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`doompi-use-workflow`,kind:`skill`,read:()=>t.readWorkflowSkill(`doompi-use-workflow`)},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`workflow-recovery`,kind:`skill`,read:()=>t.readWorkflowSkill(`workflow-recovery`)}],activities:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:u,async start(e){return S=x.createRunControl({}),await S.start(),await b(e),()=>{S?.dispose(),S=void 0}}}],tools:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:f,label:`List Workflows`,description:`List workflow definitions available in this repository.`,parameters:c.z.toJSONSchema(x.listWorkflowsTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),h(await x.listWorkflowsTool.execute(t))}},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:p,label:`Launch Workflow`,description:`Start a workflow run and return its recorded launch result.`,parameters:c.z.toJSONSchema(x.runTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),h(await x.runTool.execute(t))}},{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:m,label:`Workflow Run`,description:`Inspect the status of a workflow run or request cooperative control.`,parameters:{type:`object`,properties:{action:{type:`string`,enum:[`status`,`pause`,`resume`,`stop`]},runKey:{type:`string`,minLength:1},workspace:{type:`string`},reason:{type:`string`},expectedRunId:{type:`string`}},required:[`action`,`runKey`],additionalProperties:!1},executionMode:`serial`,async execute(e,t,n){n?.throwIfAborted();let r=t,o=a.readWorkflowRuns({environment:g.context.environment}).filter(e=>i.runBelongsToSession(e,g.context.sessionId)&&e.view.runKey===r.runKey&&(r.workspace===void 0||e.view.workspace===r.workspace));if(o.length!==1)return{...h({error:o.length===0?`Workflow run was not found in this session.`:`Specify the workspace for this run key.`}),isError:!0};let s=o[0].view;return r.action===`status`?h(s):S?typeof r.expectedRunId!=`string`||r.expectedRunId.length===0?h({error:`expectedRunId is required for workflow control.`}):h(r.action===`pause`?await S.pause(r.runKey,r.expectedRunId,r.workspace,r.reason):r.action===`resume`?await S.resume(r.runKey,r.expectedRunId,r.workspace):await S.stop(r.runKey,r.expectedRunId,r.workspace,r.reason)):h({error:`Workflow activity is not active.`})}}],commands:[{when:{state:{"minor-mode":d},attribution:{kind:`minor`,mode:d}},name:`workflow-launch`,description:`Launch a workflow from a slash command.`,async execute(t,n){let r=e.parseWorkflowLaunchCommand(t);if(`error`in r){await n.client.notify({body:r.error,level:`error`});return}let i=h(await x.runTool.execute({workflowPath:r.workflow,...r.runner===void 0?{}:{runner:r.runner},...Object.keys(r.inputs).length===0?{}:{inputs:r.inputs},...r.prompt===void 0?{}:{prompt:r.prompt}})).content.find(e=>e.type===`text`);await n.client.notify({body:i?.type===`text`?i.text:`Workflow launch requested.`,level:`info`})}}],onDispose(){S?.dispose(),S=void 0}}}exports.createWorkflowServerRuntime=g;
2
2
  //# sourceMappingURL=serverRuntime.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"serverRuntime.cjs","names":["createWorkflowCatalogReader","defaultCatalogDeps","presentWorkflowRuns","readWorkflowRuns","runBelongsToSession","WORKFLOW_RUNS_TYPE","WORKFLOW_CATALOG_TYPE","presentWorkflowCatalog","createEmbeddedWorkflowFeature","defineMinorMode","serverMinorModes","skill","z","parseWorkflowLaunchCommand"],"sources":["../../../src/controllers/serverRuntime.ts"],"sourcesContent":["import {\n type DoomHeadlessExecutionContext,\n type DoomHeadlessContent,\n type DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\nimport { createEmbeddedWorkflowFeature } from '@agimon-ai/workflow-mcp';\nimport { z } from 'zod';\n\nimport { createWorkflowCatalogReader, presentWorkflowCatalog } from '../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../services/workflowCatalogDeps';\nimport { parseWorkflowLaunchCommand } from '../services/workflowLaunchCommand';\nimport { readWorkflowSkill as skill } from '../services/workflowResource';\nimport { presentWorkflowRuns, runBelongsToSession } from '../services/workflowRuns';\nimport { readWorkflowRuns } from '../services/workflowWatcher';\nimport { WORKFLOW_CATALOG_TYPE, WORKFLOW_RUNS_TYPE } from '../types/webWorkflows';\n\nconst SOURCE = '@agimon-ai/doompi-workflow';\nconst WORKFLOW_MODE_ID = 'workflow';\nconst LIST_TOOL = 'list_workflows';\nconst LAUNCH_TOOL = 'launch_workflow';\nconst RUN_TOOL = 'workflow_run';\n\nfunction callResult(value: unknown): DoomHeadlessToolResult {\n const content: DoomHeadlessContent[] = [];\n if (typeof value === 'object' && value !== null && 'content' in value && Array.isArray(value.content)) {\n for (const item of value.content) {\n if (typeof item !== 'object' || item === null || !('type' in item)) continue;\n const record = item as Record<string, unknown>;\n if (record.type === 'text' && typeof record.text === 'string') content.push({ type: 'text', text: record.text });\n else if (record.type === 'image' && typeof record.data === 'string' && typeof record.mimeType === 'string') {\n content.push({ type: 'image', data: record.data, mimeType: record.mimeType });\n }\n }\n }\n if (content.length === 0) content.push({ type: 'text', text: JSON.stringify(value, null, 2) });\n return { content, details: value };\n}\n\nimport { type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { type DoomServerHostService, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nexport function createWorkflowServerRuntime(\n host: DoomHeadlessHostService,\n serverHost: DoomServerHostService,\n): DoomServerSessionPlugin {\n if (serverHost.context.directEvents === undefined)\n throw new Error('Workflow headless facet requires the session direct event bus.');\n const directEvents = serverHost.context.directEvents;\n const catalogReader = createWorkflowCatalogReader(defaultCatalogDeps());\n const publishLifecycle = async (executionContext: typeof host.context): Promise<void> => {\n const runs = presentWorkflowRuns(\n readWorkflowRuns({ environment: executionContext.environment })\n .filter((run) => runBelongsToSession(run, executionContext.sessionId))\n .map((run) => run.view),\n Date.now(),\n );\n directEvents.publish(WORKFLOW_RUNS_TYPE, executionContext.sessionId, { runs });\n try {\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: presentWorkflowCatalog(await catalogReader.read(executionContext.cwd)),\n });\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: [],\n warning,\n });\n }\n };\n const feature = createEmbeddedWorkflowFeature();\n const statuses = feature.createListStatusesTool({\n recordFilter: (record) => {\n const sessionId = host.context.sessionId;\n return record.env?.PI_SESSION_ID === undefined || record.env.PI_SESSION_ID === sessionId;\n },\n });\n let control: ReturnType<typeof feature.createRunControl> | undefined;\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(WORKFLOW_MODE_ID);\n const modeState = (): MinorModeState => {\n const active = modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: 'ready',\n ...(active ? { detail: 'workflow tools available' } : {}),\n actions: [\n { id: 'activate', enabled: !active, ...(!active ? {} : { disabledReason: 'Workflow mode is active.' }) },\n { id: 'deactivate', enabled: active, ...(active ? {} : { disabledReason: 'Workflow mode is inactive.' }) },\n ],\n };\n };\n const selectMode = async (enabled: boolean): Promise<void> => {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== WORKFLOW_MODE_ID);\n await host.changeSelection({\n axis: 'state',\n key: 'minor-mode',\n values: enabled ? [...modes, WORKFLOW_MODE_ID] : modes,\n });\n modeOwner?.publish();\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: WORKFLOW_MODE_ID,\n label: 'Workflow',\n description: 'Workflow discovery, launch, inspection, control, and recovery tools.',\n order: 20,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Enable workflow tools for this session.',\n contexts: ['headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Disable workflow tools without stopping active runs.',\n contexts: ['headless'],\n parameters: [],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, _argumentsValue, execution) {\n execution.signal.throwIfAborted();\n if (actionId === 'activate') {\n await selectMode(true);\n return { message: 'Workflow mode activated.' };\n }\n if (actionId === 'deactivate') {\n await selectMode(false);\n return { message: 'Workflow mode deactivated.' };\n }\n throw new Error(`Unknown workflow mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [serverMinorModes([modeOwner])],\n toolRestrictions: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID } },\n allowedTools: [LIST_TOOL, LAUNCH_TOOL, RUN_TOOL],\n },\n ],\n hooks: [\n {\n event: 'tool_execution_end',\n handle: async (_event, executionContext) => {\n await publishLifecycle(executionContext);\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n event: 'session_shutdown',\n handle: () => {\n control?.dispose();\n control = undefined;\n },\n },\n ],\n resources: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-author-workflow',\n kind: 'skill',\n read: () => skill('doompi-author-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-use-workflow',\n kind: 'skill',\n read: () => skill('doompi-use-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-recovery',\n kind: 'skill',\n read: () => skill('workflow-recovery'),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: SOURCE,\n async start(executionContext) {\n control = feature.createRunControl({});\n await control.start();\n await publishLifecycle(executionContext);\n return () => {\n control?.dispose();\n control = undefined;\n };\n },\n },\n ],\n tools: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LIST_TOOL,\n label: 'List Workflows',\n description: 'List workflow definitions available in this repository.',\n parameters: z.toJSONSchema(feature.listWorkflowsTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(\n await feature.listWorkflowsTool.execute(\n parameters as Parameters<typeof feature.listWorkflowsTool.execute>[0],\n ),\n );\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LAUNCH_TOOL,\n label: 'Launch Workflow',\n description: 'Start a workflow run and return its recorded launch result.',\n parameters: z.toJSONSchema(feature.runTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(await feature.runTool.execute(parameters as Parameters<typeof feature.runTool.execute>[0]));\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: RUN_TOOL,\n label: 'Workflow Run',\n description: 'Inspect the status of a workflow run or request cooperative control.',\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['status', 'pause', 'resume', 'stop'] },\n runKey: { type: 'string', minLength: 1 },\n workspace: { type: 'string' },\n reason: { type: 'string' },\n expectedRunId: { type: 'string' },\n },\n required: ['action', 'runKey'],\n additionalProperties: false,\n },\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n const input = parameters as unknown as {\n action: 'status' | 'pause' | 'resume' | 'stop';\n runKey: string;\n workspace?: string;\n reason?: string;\n expectedRunId?: string;\n };\n if (input.action === 'status')\n return callResult(await statuses.execute({ workspace: input.workspace, pageSize: 100 }));\n if (!control) return callResult({ error: 'Workflow activity is not active.' });\n if (typeof input.expectedRunId !== 'string' || input.expectedRunId.length === 0) {\n return callResult({ error: 'expectedRunId is required for workflow control.' });\n }\n const request =\n input.action === 'pause'\n ? await control.pause(input.runKey, input.expectedRunId, input.workspace, input.reason)\n : input.action === 'resume'\n ? await control.resume(input.runKey, input.expectedRunId, input.workspace)\n : await control.stop(input.runKey, input.expectedRunId, input.workspace, input.reason);\n return callResult(request);\n },\n },\n ],\n commands: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-launch',\n description: 'Launch a workflow from a slash command.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n const parsed = parseWorkflowLaunchCommand(args);\n if ('error' in parsed) {\n await execution.client.notify({ body: parsed.error, level: 'error' });\n return;\n }\n const result = await feature.runTool.execute({\n workflowPath: parsed.workflow,\n ...(parsed.runner === undefined ? {} : { runner: parsed.runner }),\n ...(Object.keys(parsed.inputs).length === 0 ? {} : { inputs: parsed.inputs }),\n ...(parsed.prompt === undefined ? {} : { prompt: parsed.prompt }),\n });\n const rendered = callResult(result).content.find((entry) => entry.type === 'text');\n await execution.client.notify({\n body: rendered?.type === 'text' ? rendered.text : 'Workflow launch requested.',\n level: 'info',\n });\n },\n },\n ],\n onDispose() {\n control?.dispose();\n control = undefined;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"serverRuntime.cjs","names":["createWorkflowCatalogReader","defaultCatalogDeps","presentWorkflowRuns","readWorkflowRuns","runBelongsToSession","WORKFLOW_RUNS_TYPE","WORKFLOW_CATALOG_TYPE","presentWorkflowCatalog","createEmbeddedWorkflowFeature","defineMinorMode","serverMinorModes","skill","z","parseWorkflowLaunchCommand"],"sources":["../../../src/controllers/serverRuntime.ts"],"sourcesContent":["import {\n type DoomHeadlessExecutionContext,\n type DoomHeadlessContent,\n type DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\nimport { createEmbeddedWorkflowFeature } from '@agimon-ai/workflow-mcp';\nimport { z } from 'zod';\n\nimport { createWorkflowCatalogReader, presentWorkflowCatalog } from '../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../services/workflowCatalogDeps';\nimport { parseWorkflowLaunchCommand } from '../services/workflowLaunchCommand';\nimport { readWorkflowSkill as skill } from '../services/workflowResource';\nimport { presentWorkflowRuns, runBelongsToSession } from '../services/workflowRuns';\nimport { readWorkflowRuns } from '../services/workflowWatcher';\nimport { WORKFLOW_CATALOG_TYPE, WORKFLOW_RUNS_TYPE } from '../types/webWorkflows';\n\nconst SOURCE = '@agimon-ai/doompi-workflow';\nconst WORKFLOW_MODE_ID = 'workflow';\nconst LIST_TOOL = 'list_workflows';\nconst LAUNCH_TOOL = 'launch_workflow';\nconst RUN_TOOL = 'workflow_run';\n\nfunction callResult(value: unknown): DoomHeadlessToolResult {\n const content: DoomHeadlessContent[] = [];\n if (typeof value === 'object' && value !== null && 'content' in value && Array.isArray(value.content)) {\n for (const item of value.content) {\n if (typeof item !== 'object' || item === null || !('type' in item)) continue;\n const record = item as Record<string, unknown>;\n if (record.type === 'text' && typeof record.text === 'string') content.push({ type: 'text', text: record.text });\n else if (record.type === 'image' && typeof record.data === 'string' && typeof record.mimeType === 'string') {\n content.push({ type: 'image', data: record.data, mimeType: record.mimeType });\n }\n }\n }\n if (content.length === 0) content.push({ type: 'text', text: JSON.stringify(value, null, 2) });\n return { content, details: value };\n}\n\nimport { type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { type DoomServerHostService, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nexport function createWorkflowServerRuntime(\n host: DoomHeadlessHostService,\n serverHost: DoomServerHostService,\n): DoomServerSessionPlugin {\n if (serverHost.context.directEvents === undefined)\n throw new Error('Workflow headless facet requires the session direct event bus.');\n const directEvents = serverHost.context.directEvents;\n const catalogReader = createWorkflowCatalogReader(defaultCatalogDeps());\n const publishLifecycle = async (executionContext: typeof host.context): Promise<void> => {\n const runs = presentWorkflowRuns(\n readWorkflowRuns({ environment: executionContext.environment })\n .filter((run) => runBelongsToSession(run, executionContext.sessionId))\n .map((run) => run.view),\n Date.now(),\n );\n directEvents.publish(WORKFLOW_RUNS_TYPE, executionContext.sessionId, { runs });\n try {\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: presentWorkflowCatalog(await catalogReader.read(executionContext.cwd)),\n });\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: [],\n warning,\n });\n }\n };\n const feature = createEmbeddedWorkflowFeature();\n let control: ReturnType<typeof feature.createRunControl> | undefined;\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(WORKFLOW_MODE_ID);\n const modeState = (): MinorModeState => {\n const active = modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: 'ready',\n ...(active ? { detail: 'workflow tools available' } : {}),\n actions: [\n { id: 'activate', enabled: !active, ...(!active ? {} : { disabledReason: 'Workflow mode is active.' }) },\n { id: 'deactivate', enabled: active, ...(active ? {} : { disabledReason: 'Workflow mode is inactive.' }) },\n ],\n };\n };\n const selectMode = async (enabled: boolean): Promise<void> => {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== WORKFLOW_MODE_ID);\n await host.changeSelection({\n axis: 'state',\n key: 'minor-mode',\n values: enabled ? [...modes, WORKFLOW_MODE_ID] : modes,\n });\n modeOwner?.publish();\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: WORKFLOW_MODE_ID,\n label: 'Workflow',\n description: 'Workflow discovery, launch, inspection, control, and recovery tools.',\n order: 20,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Enable workflow tools for this session.',\n contexts: ['headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Disable workflow tools without stopping active runs.',\n contexts: ['headless'],\n parameters: [],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, _argumentsValue, execution) {\n execution.signal.throwIfAborted();\n if (actionId === 'activate') {\n await selectMode(true);\n return { message: 'Workflow mode activated.' };\n }\n if (actionId === 'deactivate') {\n await selectMode(false);\n return { message: 'Workflow mode deactivated.' };\n }\n throw new Error(`Unknown workflow mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [serverMinorModes([modeOwner])],\n toolRestrictions: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID } },\n allowedTools: [LIST_TOOL, LAUNCH_TOOL, RUN_TOOL],\n },\n ],\n hooks: [\n {\n event: 'tool_execution_end',\n handle: async (_event, executionContext) => {\n await publishLifecycle(executionContext);\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n event: 'session_shutdown',\n handle: () => {\n control?.dispose();\n control = undefined;\n },\n },\n ],\n resources: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-author-workflow',\n kind: 'skill',\n read: () => skill('doompi-author-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-use-workflow',\n kind: 'skill',\n read: () => skill('doompi-use-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-recovery',\n kind: 'skill',\n read: () => skill('workflow-recovery'),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: SOURCE,\n async start(executionContext) {\n control = feature.createRunControl({});\n await control.start();\n await publishLifecycle(executionContext);\n return () => {\n control?.dispose();\n control = undefined;\n };\n },\n },\n ],\n tools: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LIST_TOOL,\n label: 'List Workflows',\n description: 'List workflow definitions available in this repository.',\n parameters: z.toJSONSchema(feature.listWorkflowsTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(\n await feature.listWorkflowsTool.execute(\n parameters as Parameters<typeof feature.listWorkflowsTool.execute>[0],\n ),\n );\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LAUNCH_TOOL,\n label: 'Launch Workflow',\n description: 'Start a workflow run and return its recorded launch result.',\n parameters: z.toJSONSchema(feature.runTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(await feature.runTool.execute(parameters as Parameters<typeof feature.runTool.execute>[0]));\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: RUN_TOOL,\n label: 'Workflow Run',\n description: 'Inspect the status of a workflow run or request cooperative control.',\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['status', 'pause', 'resume', 'stop'] },\n runKey: { type: 'string', minLength: 1 },\n workspace: { type: 'string' },\n reason: { type: 'string' },\n expectedRunId: { type: 'string' },\n },\n required: ['action', 'runKey'],\n additionalProperties: false,\n },\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n const input = parameters as unknown as {\n action: 'status' | 'pause' | 'resume' | 'stop';\n runKey: string;\n workspace?: string;\n reason?: string;\n expectedRunId?: string;\n };\n const runs = readWorkflowRuns({ environment: host.context.environment }).filter(\n (run) =>\n runBelongsToSession(run, host.context.sessionId) &&\n run.view.runKey === input.runKey &&\n (input.workspace === undefined || run.view.workspace === input.workspace),\n );\n if (runs.length !== 1)\n return {\n ...callResult({\n error:\n runs.length === 0\n ? 'Workflow run was not found in this session.'\n : 'Specify the workspace for this run key.',\n }),\n isError: true,\n };\n const run = runs[0]!.view;\n if (input.action === 'status') return callResult(run);\n if (!control) return callResult({ error: 'Workflow activity is not active.' });\n if (typeof input.expectedRunId !== 'string' || input.expectedRunId.length === 0) {\n return callResult({ error: 'expectedRunId is required for workflow control.' });\n }\n const request =\n input.action === 'pause'\n ? await control.pause(input.runKey, input.expectedRunId, input.workspace, input.reason)\n : input.action === 'resume'\n ? await control.resume(input.runKey, input.expectedRunId, input.workspace)\n : await control.stop(input.runKey, input.expectedRunId, input.workspace, input.reason);\n return callResult(request);\n },\n },\n ],\n commands: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-launch',\n description: 'Launch a workflow from a slash command.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n const parsed = parseWorkflowLaunchCommand(args);\n if ('error' in parsed) {\n await execution.client.notify({ body: parsed.error, level: 'error' });\n return;\n }\n const result = await feature.runTool.execute({\n workflowPath: parsed.workflow,\n ...(parsed.runner === undefined ? {} : { runner: parsed.runner }),\n ...(Object.keys(parsed.inputs).length === 0 ? {} : { inputs: parsed.inputs }),\n ...(parsed.prompt === undefined ? {} : { prompt: parsed.prompt }),\n });\n const rendered = callResult(result).content.find((entry) => entry.type === 'text');\n await execution.client.notify({\n body: rendered?.type === 'text' ? rendered.text : 'Workflow launch requested.',\n level: 'info',\n });\n },\n },\n ],\n onDispose() {\n control?.dispose();\n control = undefined;\n },\n };\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{parseWorkflowLaunchCommand as e}from"../services/workflowLaunchCommand/index.mjs";import{readWorkflowSkill as t}from"../services/workflowResource/index.mjs";import{createWorkflowCatalogReader as n,presentWorkflowCatalog as r}from"../services/webWorkflowCatalog/index.mjs";import{defaultCatalogDeps as i}from"../services/workflowCatalogDeps/index.mjs";import{presentWorkflowRuns as a,runBelongsToSession as o}from"../services/workflowRuns/index.mjs";import{readWorkflowRuns as s}from"../services/workflowWatcher/index.mjs";import{WORKFLOW_CATALOG_TYPE as c,WORKFLOW_RUNS_TYPE as l}from"../types/webWorkflows.mjs";import{createEmbeddedWorkflowFeature as u}from"@agimon-ai/workflow-mcp";import{z as d}from"zod";import{defineMinorMode as f,serverMinorModes as p}from"@agimon-ai/doompi-minor-mode";const m=`@agimon-ai/doompi-workflow`,h=`workflow`,g=`list_workflows`,_=`launch_workflow`,v=`workflow_run`;function y(e){let t=[];if(typeof e==`object`&&e&&`content`in e&&Array.isArray(e.content))for(let n of e.content){if(typeof n!=`object`||!n||!(`type`in n))continue;let e=n;e.type===`text`&&typeof e.text==`string`?t.push({type:`text`,text:e.text}):e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`&&t.push({type:`image`,data:e.data,mimeType:e.mimeType})}return t.length===0&&t.push({type:`text`,text:JSON.stringify(e,null,2)}),{content:t,details:e}}function b(b,x){if(x.context.directEvents===void 0)throw Error(`Workflow headless facet requires the session direct event bus.`);let S=x.context.directEvents,C=n(i()),w=async e=>{let t=a(s({environment:e.environment}).filter(t=>o(t,e.sessionId)).map(e=>e.view),Date.now());S.publish(l,e.sessionId,{runs:t});try{S.publish(c,e.sessionId,{cwd:e.cwd,workflows:r(await C.read(e.cwd))})}catch(t){let n=t instanceof Error?t.message:String(t);S.publish(c,e.sessionId,{cwd:e.cwd,workflows:[],warning:n})}},T=u(),E=T.createListStatusesTool({recordFilter:e=>{let t=b.context.sessionId;return e.env?.PI_SESSION_ID===void 0||e.env.PI_SESSION_ID===t}}),D,O,k=()=>(b.context.selection.state?.[`minor-mode`]??[]).includes(h),A=()=>{let e=k();return{activation:e?`active`:`inactive`,condition:`ready`,...e?{detail:`workflow tools available`}:{},actions:[{id:`activate`,enabled:!e,...e?{disabledReason:`Workflow mode is active.`}:{}},{id:`deactivate`,enabled:e,...e?{}:{disabledReason:`Workflow mode is inactive.`}}]}},j=async e=>{let t=(b.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==h);await b.changeSelection({axis:`state`,key:`minor-mode`,values:e?[...t,h]:t}),O?.publish()};return O=f({descriptor:{source:m,id:h,label:`Workflow`,description:`Workflow discovery, launch, inspection, control, and recovery tools.`,order:20,actions:[{id:`activate`,label:`Activate`,description:`Enable workflow tools for this session.`,contexts:[`headless`],parameters:[]},{id:`deactivate`,label:`Deactivate`,description:`Disable workflow tools without stopping active runs.`,contexts:[`headless`],parameters:[]}]},state:A,async handleAction(e,t,n,r){if(r.signal.throwIfAborted(),t===`activate`)return await j(!0),{message:`Workflow mode activated.`};if(t===`deactivate`)return await j(!1),{message:`Workflow mode deactivated.`};throw Error(`Unknown workflow mode action: ${t}`)}}).createOwner(void 0),{services:[p([O])],toolRestrictions:[{when:{state:{"minor-mode":h}},allowedTools:[g,_,v]}],hooks:[{event:`tool_execution_end`,handle:async(e,t)=>{await w(t)}},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},event:`session_shutdown`,handle:()=>{D?.dispose(),D=void 0}}],resources:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`doompi-author-workflow`,kind:`skill`,read:()=>t(`doompi-author-workflow`)},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`doompi-use-workflow`,kind:`skill`,read:()=>t(`doompi-use-workflow`)},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`workflow-recovery`,kind:`skill`,read:()=>t(`workflow-recovery`)}],activities:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:m,async start(e){return D=T.createRunControl({}),await D.start(),await w(e),()=>{D?.dispose(),D=void 0}}}],tools:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:g,label:`List Workflows`,description:`List workflow definitions available in this repository.`,parameters:d.toJSONSchema(T.listWorkflowsTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),y(await T.listWorkflowsTool.execute(t))}},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:_,label:`Launch Workflow`,description:`Start a workflow run and return its recorded launch result.`,parameters:d.toJSONSchema(T.runTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),y(await T.runTool.execute(t))}},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:v,label:`Workflow Run`,description:`Inspect the status of a workflow run or request cooperative control.`,parameters:{type:`object`,properties:{action:{type:`string`,enum:[`status`,`pause`,`resume`,`stop`]},runKey:{type:`string`,minLength:1},workspace:{type:`string`},reason:{type:`string`},expectedRunId:{type:`string`}},required:[`action`,`runKey`],additionalProperties:!1},executionMode:`serial`,async execute(e,t,n){n?.throwIfAborted();let r=t;return r.action===`status`?y(await E.execute({workspace:r.workspace,pageSize:100})):D?typeof r.expectedRunId!=`string`||r.expectedRunId.length===0?y({error:`expectedRunId is required for workflow control.`}):y(r.action===`pause`?await D.pause(r.runKey,r.expectedRunId,r.workspace,r.reason):r.action===`resume`?await D.resume(r.runKey,r.expectedRunId,r.workspace):await D.stop(r.runKey,r.expectedRunId,r.workspace,r.reason)):y({error:`Workflow activity is not active.`})}}],commands:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`workflow-launch`,description:`Launch a workflow from a slash command.`,async execute(t,n){let r=e(t);if(`error`in r){await n.client.notify({body:r.error,level:`error`});return}let i=y(await T.runTool.execute({workflowPath:r.workflow,...r.runner===void 0?{}:{runner:r.runner},...Object.keys(r.inputs).length===0?{}:{inputs:r.inputs},...r.prompt===void 0?{}:{prompt:r.prompt}})).content.find(e=>e.type===`text`);await n.client.notify({body:i?.type===`text`?i.text:`Workflow launch requested.`,level:`info`})}}],onDispose(){D?.dispose(),D=void 0}}}export{b as createWorkflowServerRuntime};
1
+ import{parseWorkflowLaunchCommand as e}from"../services/workflowLaunchCommand/index.mjs";import{readWorkflowSkill as t}from"../services/workflowResource/index.mjs";import{createWorkflowCatalogReader as n,presentWorkflowCatalog as r}from"../services/webWorkflowCatalog/index.mjs";import{defaultCatalogDeps as i}from"../services/workflowCatalogDeps/index.mjs";import{presentWorkflowRuns as a,runBelongsToSession as o}from"../services/workflowRuns/index.mjs";import{readWorkflowRuns as s}from"../services/workflowWatcher/index.mjs";import{WORKFLOW_CATALOG_TYPE as c,WORKFLOW_RUNS_TYPE as l}from"../types/webWorkflows.mjs";import{createEmbeddedWorkflowFeature as u}from"@agimon-ai/workflow-mcp";import{z as d}from"zod";import{defineMinorMode as f,serverMinorModes as p}from"@agimon-ai/doompi-minor-mode";const m=`@agimon-ai/doompi-workflow`,h=`workflow`,g=`list_workflows`,_=`launch_workflow`,v=`workflow_run`;function y(e){let t=[];if(typeof e==`object`&&e&&`content`in e&&Array.isArray(e.content))for(let n of e.content){if(typeof n!=`object`||!n||!(`type`in n))continue;let e=n;e.type===`text`&&typeof e.text==`string`?t.push({type:`text`,text:e.text}):e.type===`image`&&typeof e.data==`string`&&typeof e.mimeType==`string`&&t.push({type:`image`,data:e.data,mimeType:e.mimeType})}return t.length===0&&t.push({type:`text`,text:JSON.stringify(e,null,2)}),{content:t,details:e}}function b(b,x){if(x.context.directEvents===void 0)throw Error(`Workflow headless facet requires the session direct event bus.`);let S=x.context.directEvents,C=n(i()),w=async e=>{let t=a(s({environment:e.environment}).filter(t=>o(t,e.sessionId)).map(e=>e.view),Date.now());S.publish(l,e.sessionId,{runs:t});try{S.publish(c,e.sessionId,{cwd:e.cwd,workflows:r(await C.read(e.cwd))})}catch(t){let n=t instanceof Error?t.message:String(t);S.publish(c,e.sessionId,{cwd:e.cwd,workflows:[],warning:n})}},T=u(),E,D,O=()=>(b.context.selection.state?.[`minor-mode`]??[]).includes(h),k=()=>{let e=O();return{activation:e?`active`:`inactive`,condition:`ready`,...e?{detail:`workflow tools available`}:{},actions:[{id:`activate`,enabled:!e,...e?{disabledReason:`Workflow mode is active.`}:{}},{id:`deactivate`,enabled:e,...e?{}:{disabledReason:`Workflow mode is inactive.`}}]}},A=async e=>{let t=(b.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==h);await b.changeSelection({axis:`state`,key:`minor-mode`,values:e?[...t,h]:t}),D?.publish()};return D=f({descriptor:{source:m,id:h,label:`Workflow`,description:`Workflow discovery, launch, inspection, control, and recovery tools.`,order:20,actions:[{id:`activate`,label:`Activate`,description:`Enable workflow tools for this session.`,contexts:[`headless`],parameters:[]},{id:`deactivate`,label:`Deactivate`,description:`Disable workflow tools without stopping active runs.`,contexts:[`headless`],parameters:[]}]},state:k,async handleAction(e,t,n,r){if(r.signal.throwIfAborted(),t===`activate`)return await A(!0),{message:`Workflow mode activated.`};if(t===`deactivate`)return await A(!1),{message:`Workflow mode deactivated.`};throw Error(`Unknown workflow mode action: ${t}`)}}).createOwner(void 0),{services:[p([D])],toolRestrictions:[{when:{state:{"minor-mode":h}},allowedTools:[g,_,v]}],hooks:[{event:`tool_execution_end`,handle:async(e,t)=>{await w(t)}},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},event:`session_shutdown`,handle:()=>{E?.dispose(),E=void 0}}],resources:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`doompi-author-workflow`,kind:`skill`,read:()=>t(`doompi-author-workflow`)},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`doompi-use-workflow`,kind:`skill`,read:()=>t(`doompi-use-workflow`)},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`workflow-recovery`,kind:`skill`,read:()=>t(`workflow-recovery`)}],activities:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:m,async start(e){return E=T.createRunControl({}),await E.start(),await w(e),()=>{E?.dispose(),E=void 0}}}],tools:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:g,label:`List Workflows`,description:`List workflow definitions available in this repository.`,parameters:d.toJSONSchema(T.listWorkflowsTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),y(await T.listWorkflowsTool.execute(t))}},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:_,label:`Launch Workflow`,description:`Start a workflow run and return its recorded launch result.`,parameters:d.toJSONSchema(T.runTool.getInputSchema()),executionMode:`serial`,async execute(e,t,n){return n?.throwIfAborted(),y(await T.runTool.execute(t))}},{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:v,label:`Workflow Run`,description:`Inspect the status of a workflow run or request cooperative control.`,parameters:{type:`object`,properties:{action:{type:`string`,enum:[`status`,`pause`,`resume`,`stop`]},runKey:{type:`string`,minLength:1},workspace:{type:`string`},reason:{type:`string`},expectedRunId:{type:`string`}},required:[`action`,`runKey`],additionalProperties:!1},executionMode:`serial`,async execute(e,t,n){n?.throwIfAborted();let r=t,i=s({environment:b.context.environment}).filter(e=>o(e,b.context.sessionId)&&e.view.runKey===r.runKey&&(r.workspace===void 0||e.view.workspace===r.workspace));if(i.length!==1)return{...y({error:i.length===0?`Workflow run was not found in this session.`:`Specify the workspace for this run key.`}),isError:!0};let a=i[0].view;return r.action===`status`?y(a):E?typeof r.expectedRunId!=`string`||r.expectedRunId.length===0?y({error:`expectedRunId is required for workflow control.`}):y(r.action===`pause`?await E.pause(r.runKey,r.expectedRunId,r.workspace,r.reason):r.action===`resume`?await E.resume(r.runKey,r.expectedRunId,r.workspace):await E.stop(r.runKey,r.expectedRunId,r.workspace,r.reason)):y({error:`Workflow activity is not active.`})}}],commands:[{when:{state:{"minor-mode":h},attribution:{kind:`minor`,mode:h}},name:`workflow-launch`,description:`Launch a workflow from a slash command.`,async execute(t,n){let r=e(t);if(`error`in r){await n.client.notify({body:r.error,level:`error`});return}let i=y(await T.runTool.execute({workflowPath:r.workflow,...r.runner===void 0?{}:{runner:r.runner},...Object.keys(r.inputs).length===0?{}:{inputs:r.inputs},...r.prompt===void 0?{}:{prompt:r.prompt}})).content.find(e=>e.type===`text`);await n.client.notify({body:i?.type===`text`?i.text:`Workflow launch requested.`,level:`info`})}}],onDispose(){E?.dispose(),E=void 0}}}export{b as createWorkflowServerRuntime};
2
2
  //# sourceMappingURL=serverRuntime.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"serverRuntime.mjs","names":["skill"],"sources":["../../../src/controllers/serverRuntime.ts"],"sourcesContent":["import {\n type DoomHeadlessExecutionContext,\n type DoomHeadlessContent,\n type DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\nimport { createEmbeddedWorkflowFeature } from '@agimon-ai/workflow-mcp';\nimport { z } from 'zod';\n\nimport { createWorkflowCatalogReader, presentWorkflowCatalog } from '../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../services/workflowCatalogDeps';\nimport { parseWorkflowLaunchCommand } from '../services/workflowLaunchCommand';\nimport { readWorkflowSkill as skill } from '../services/workflowResource';\nimport { presentWorkflowRuns, runBelongsToSession } from '../services/workflowRuns';\nimport { readWorkflowRuns } from '../services/workflowWatcher';\nimport { WORKFLOW_CATALOG_TYPE, WORKFLOW_RUNS_TYPE } from '../types/webWorkflows';\n\nconst SOURCE = '@agimon-ai/doompi-workflow';\nconst WORKFLOW_MODE_ID = 'workflow';\nconst LIST_TOOL = 'list_workflows';\nconst LAUNCH_TOOL = 'launch_workflow';\nconst RUN_TOOL = 'workflow_run';\n\nfunction callResult(value: unknown): DoomHeadlessToolResult {\n const content: DoomHeadlessContent[] = [];\n if (typeof value === 'object' && value !== null && 'content' in value && Array.isArray(value.content)) {\n for (const item of value.content) {\n if (typeof item !== 'object' || item === null || !('type' in item)) continue;\n const record = item as Record<string, unknown>;\n if (record.type === 'text' && typeof record.text === 'string') content.push({ type: 'text', text: record.text });\n else if (record.type === 'image' && typeof record.data === 'string' && typeof record.mimeType === 'string') {\n content.push({ type: 'image', data: record.data, mimeType: record.mimeType });\n }\n }\n }\n if (content.length === 0) content.push({ type: 'text', text: JSON.stringify(value, null, 2) });\n return { content, details: value };\n}\n\nimport { type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { type DoomServerHostService, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nexport function createWorkflowServerRuntime(\n host: DoomHeadlessHostService,\n serverHost: DoomServerHostService,\n): DoomServerSessionPlugin {\n if (serverHost.context.directEvents === undefined)\n throw new Error('Workflow headless facet requires the session direct event bus.');\n const directEvents = serverHost.context.directEvents;\n const catalogReader = createWorkflowCatalogReader(defaultCatalogDeps());\n const publishLifecycle = async (executionContext: typeof host.context): Promise<void> => {\n const runs = presentWorkflowRuns(\n readWorkflowRuns({ environment: executionContext.environment })\n .filter((run) => runBelongsToSession(run, executionContext.sessionId))\n .map((run) => run.view),\n Date.now(),\n );\n directEvents.publish(WORKFLOW_RUNS_TYPE, executionContext.sessionId, { runs });\n try {\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: presentWorkflowCatalog(await catalogReader.read(executionContext.cwd)),\n });\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: [],\n warning,\n });\n }\n };\n const feature = createEmbeddedWorkflowFeature();\n const statuses = feature.createListStatusesTool({\n recordFilter: (record) => {\n const sessionId = host.context.sessionId;\n return record.env?.PI_SESSION_ID === undefined || record.env.PI_SESSION_ID === sessionId;\n },\n });\n let control: ReturnType<typeof feature.createRunControl> | undefined;\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(WORKFLOW_MODE_ID);\n const modeState = (): MinorModeState => {\n const active = modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: 'ready',\n ...(active ? { detail: 'workflow tools available' } : {}),\n actions: [\n { id: 'activate', enabled: !active, ...(!active ? {} : { disabledReason: 'Workflow mode is active.' }) },\n { id: 'deactivate', enabled: active, ...(active ? {} : { disabledReason: 'Workflow mode is inactive.' }) },\n ],\n };\n };\n const selectMode = async (enabled: boolean): Promise<void> => {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== WORKFLOW_MODE_ID);\n await host.changeSelection({\n axis: 'state',\n key: 'minor-mode',\n values: enabled ? [...modes, WORKFLOW_MODE_ID] : modes,\n });\n modeOwner?.publish();\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: WORKFLOW_MODE_ID,\n label: 'Workflow',\n description: 'Workflow discovery, launch, inspection, control, and recovery tools.',\n order: 20,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Enable workflow tools for this session.',\n contexts: ['headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Disable workflow tools without stopping active runs.',\n contexts: ['headless'],\n parameters: [],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, _argumentsValue, execution) {\n execution.signal.throwIfAborted();\n if (actionId === 'activate') {\n await selectMode(true);\n return { message: 'Workflow mode activated.' };\n }\n if (actionId === 'deactivate') {\n await selectMode(false);\n return { message: 'Workflow mode deactivated.' };\n }\n throw new Error(`Unknown workflow mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [serverMinorModes([modeOwner])],\n toolRestrictions: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID } },\n allowedTools: [LIST_TOOL, LAUNCH_TOOL, RUN_TOOL],\n },\n ],\n hooks: [\n {\n event: 'tool_execution_end',\n handle: async (_event, executionContext) => {\n await publishLifecycle(executionContext);\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n event: 'session_shutdown',\n handle: () => {\n control?.dispose();\n control = undefined;\n },\n },\n ],\n resources: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-author-workflow',\n kind: 'skill',\n read: () => skill('doompi-author-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-use-workflow',\n kind: 'skill',\n read: () => skill('doompi-use-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-recovery',\n kind: 'skill',\n read: () => skill('workflow-recovery'),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: SOURCE,\n async start(executionContext) {\n control = feature.createRunControl({});\n await control.start();\n await publishLifecycle(executionContext);\n return () => {\n control?.dispose();\n control = undefined;\n };\n },\n },\n ],\n tools: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LIST_TOOL,\n label: 'List Workflows',\n description: 'List workflow definitions available in this repository.',\n parameters: z.toJSONSchema(feature.listWorkflowsTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(\n await feature.listWorkflowsTool.execute(\n parameters as Parameters<typeof feature.listWorkflowsTool.execute>[0],\n ),\n );\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LAUNCH_TOOL,\n label: 'Launch Workflow',\n description: 'Start a workflow run and return its recorded launch result.',\n parameters: z.toJSONSchema(feature.runTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(await feature.runTool.execute(parameters as Parameters<typeof feature.runTool.execute>[0]));\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: RUN_TOOL,\n label: 'Workflow Run',\n description: 'Inspect the status of a workflow run or request cooperative control.',\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['status', 'pause', 'resume', 'stop'] },\n runKey: { type: 'string', minLength: 1 },\n workspace: { type: 'string' },\n reason: { type: 'string' },\n expectedRunId: { type: 'string' },\n },\n required: ['action', 'runKey'],\n additionalProperties: false,\n },\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n const input = parameters as unknown as {\n action: 'status' | 'pause' | 'resume' | 'stop';\n runKey: string;\n workspace?: string;\n reason?: string;\n expectedRunId?: string;\n };\n if (input.action === 'status')\n return callResult(await statuses.execute({ workspace: input.workspace, pageSize: 100 }));\n if (!control) return callResult({ error: 'Workflow activity is not active.' });\n if (typeof input.expectedRunId !== 'string' || input.expectedRunId.length === 0) {\n return callResult({ error: 'expectedRunId is required for workflow control.' });\n }\n const request =\n input.action === 'pause'\n ? await control.pause(input.runKey, input.expectedRunId, input.workspace, input.reason)\n : input.action === 'resume'\n ? await control.resume(input.runKey, input.expectedRunId, input.workspace)\n : await control.stop(input.runKey, input.expectedRunId, input.workspace, input.reason);\n return callResult(request);\n },\n },\n ],\n commands: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-launch',\n description: 'Launch a workflow from a slash command.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n const parsed = parseWorkflowLaunchCommand(args);\n if ('error' in parsed) {\n await execution.client.notify({ body: parsed.error, level: 'error' });\n return;\n }\n const result = await feature.runTool.execute({\n workflowPath: parsed.workflow,\n ...(parsed.runner === undefined ? {} : { runner: parsed.runner }),\n ...(Object.keys(parsed.inputs).length === 0 ? {} : { inputs: parsed.inputs }),\n ...(parsed.prompt === undefined ? {} : { prompt: parsed.prompt }),\n });\n const rendered = callResult(result).content.find((entry) => entry.type === 'text');\n await execution.client.notify({\n body: rendered?.type === 'text' ? rendered.text : 'Workflow launch requested.',\n level: 'info',\n });\n },\n },\n ],\n onDispose() {\n control?.dispose();\n control = undefined;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"serverRuntime.mjs","names":["skill"],"sources":["../../../src/controllers/serverRuntime.ts"],"sourcesContent":["import {\n type DoomHeadlessExecutionContext,\n type DoomHeadlessContent,\n type DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\nimport { createEmbeddedWorkflowFeature } from '@agimon-ai/workflow-mcp';\nimport { z } from 'zod';\n\nimport { createWorkflowCatalogReader, presentWorkflowCatalog } from '../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../services/workflowCatalogDeps';\nimport { parseWorkflowLaunchCommand } from '../services/workflowLaunchCommand';\nimport { readWorkflowSkill as skill } from '../services/workflowResource';\nimport { presentWorkflowRuns, runBelongsToSession } from '../services/workflowRuns';\nimport { readWorkflowRuns } from '../services/workflowWatcher';\nimport { WORKFLOW_CATALOG_TYPE, WORKFLOW_RUNS_TYPE } from '../types/webWorkflows';\n\nconst SOURCE = '@agimon-ai/doompi-workflow';\nconst WORKFLOW_MODE_ID = 'workflow';\nconst LIST_TOOL = 'list_workflows';\nconst LAUNCH_TOOL = 'launch_workflow';\nconst RUN_TOOL = 'workflow_run';\n\nfunction callResult(value: unknown): DoomHeadlessToolResult {\n const content: DoomHeadlessContent[] = [];\n if (typeof value === 'object' && value !== null && 'content' in value && Array.isArray(value.content)) {\n for (const item of value.content) {\n if (typeof item !== 'object' || item === null || !('type' in item)) continue;\n const record = item as Record<string, unknown>;\n if (record.type === 'text' && typeof record.text === 'string') content.push({ type: 'text', text: record.text });\n else if (record.type === 'image' && typeof record.data === 'string' && typeof record.mimeType === 'string') {\n content.push({ type: 'image', data: record.data, mimeType: record.mimeType });\n }\n }\n }\n if (content.length === 0) content.push({ type: 'text', text: JSON.stringify(value, null, 2) });\n return { content, details: value };\n}\n\nimport { type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { type DoomServerHostService, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nexport function createWorkflowServerRuntime(\n host: DoomHeadlessHostService,\n serverHost: DoomServerHostService,\n): DoomServerSessionPlugin {\n if (serverHost.context.directEvents === undefined)\n throw new Error('Workflow headless facet requires the session direct event bus.');\n const directEvents = serverHost.context.directEvents;\n const catalogReader = createWorkflowCatalogReader(defaultCatalogDeps());\n const publishLifecycle = async (executionContext: typeof host.context): Promise<void> => {\n const runs = presentWorkflowRuns(\n readWorkflowRuns({ environment: executionContext.environment })\n .filter((run) => runBelongsToSession(run, executionContext.sessionId))\n .map((run) => run.view),\n Date.now(),\n );\n directEvents.publish(WORKFLOW_RUNS_TYPE, executionContext.sessionId, { runs });\n try {\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: presentWorkflowCatalog(await catalogReader.read(executionContext.cwd)),\n });\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: [],\n warning,\n });\n }\n };\n const feature = createEmbeddedWorkflowFeature();\n let control: ReturnType<typeof feature.createRunControl> | undefined;\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(WORKFLOW_MODE_ID);\n const modeState = (): MinorModeState => {\n const active = modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: 'ready',\n ...(active ? { detail: 'workflow tools available' } : {}),\n actions: [\n { id: 'activate', enabled: !active, ...(!active ? {} : { disabledReason: 'Workflow mode is active.' }) },\n { id: 'deactivate', enabled: active, ...(active ? {} : { disabledReason: 'Workflow mode is inactive.' }) },\n ],\n };\n };\n const selectMode = async (enabled: boolean): Promise<void> => {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== WORKFLOW_MODE_ID);\n await host.changeSelection({\n axis: 'state',\n key: 'minor-mode',\n values: enabled ? [...modes, WORKFLOW_MODE_ID] : modes,\n });\n modeOwner?.publish();\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: WORKFLOW_MODE_ID,\n label: 'Workflow',\n description: 'Workflow discovery, launch, inspection, control, and recovery tools.',\n order: 20,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Enable workflow tools for this session.',\n contexts: ['headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Disable workflow tools without stopping active runs.',\n contexts: ['headless'],\n parameters: [],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, _argumentsValue, execution) {\n execution.signal.throwIfAborted();\n if (actionId === 'activate') {\n await selectMode(true);\n return { message: 'Workflow mode activated.' };\n }\n if (actionId === 'deactivate') {\n await selectMode(false);\n return { message: 'Workflow mode deactivated.' };\n }\n throw new Error(`Unknown workflow mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [serverMinorModes([modeOwner])],\n toolRestrictions: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID } },\n allowedTools: [LIST_TOOL, LAUNCH_TOOL, RUN_TOOL],\n },\n ],\n hooks: [\n {\n event: 'tool_execution_end',\n handle: async (_event, executionContext) => {\n await publishLifecycle(executionContext);\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n event: 'session_shutdown',\n handle: () => {\n control?.dispose();\n control = undefined;\n },\n },\n ],\n resources: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-author-workflow',\n kind: 'skill',\n read: () => skill('doompi-author-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-use-workflow',\n kind: 'skill',\n read: () => skill('doompi-use-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-recovery',\n kind: 'skill',\n read: () => skill('workflow-recovery'),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: SOURCE,\n async start(executionContext) {\n control = feature.createRunControl({});\n await control.start();\n await publishLifecycle(executionContext);\n return () => {\n control?.dispose();\n control = undefined;\n };\n },\n },\n ],\n tools: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LIST_TOOL,\n label: 'List Workflows',\n description: 'List workflow definitions available in this repository.',\n parameters: z.toJSONSchema(feature.listWorkflowsTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(\n await feature.listWorkflowsTool.execute(\n parameters as Parameters<typeof feature.listWorkflowsTool.execute>[0],\n ),\n );\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LAUNCH_TOOL,\n label: 'Launch Workflow',\n description: 'Start a workflow run and return its recorded launch result.',\n parameters: z.toJSONSchema(feature.runTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n return callResult(await feature.runTool.execute(parameters as Parameters<typeof feature.runTool.execute>[0]));\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: RUN_TOOL,\n label: 'Workflow Run',\n description: 'Inspect the status of a workflow run or request cooperative control.',\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['status', 'pause', 'resume', 'stop'] },\n runKey: { type: 'string', minLength: 1 },\n workspace: { type: 'string' },\n reason: { type: 'string' },\n expectedRunId: { type: 'string' },\n },\n required: ['action', 'runKey'],\n additionalProperties: false,\n },\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n const input = parameters as unknown as {\n action: 'status' | 'pause' | 'resume' | 'stop';\n runKey: string;\n workspace?: string;\n reason?: string;\n expectedRunId?: string;\n };\n const runs = readWorkflowRuns({ environment: host.context.environment }).filter(\n (run) =>\n runBelongsToSession(run, host.context.sessionId) &&\n run.view.runKey === input.runKey &&\n (input.workspace === undefined || run.view.workspace === input.workspace),\n );\n if (runs.length !== 1)\n return {\n ...callResult({\n error:\n runs.length === 0\n ? 'Workflow run was not found in this session.'\n : 'Specify the workspace for this run key.',\n }),\n isError: true,\n };\n const run = runs[0]!.view;\n if (input.action === 'status') return callResult(run);\n if (!control) return callResult({ error: 'Workflow activity is not active.' });\n if (typeof input.expectedRunId !== 'string' || input.expectedRunId.length === 0) {\n return callResult({ error: 'expectedRunId is required for workflow control.' });\n }\n const request =\n input.action === 'pause'\n ? await control.pause(input.runKey, input.expectedRunId, input.workspace, input.reason)\n : input.action === 'resume'\n ? await control.resume(input.runKey, input.expectedRunId, input.workspace)\n : await control.stop(input.runKey, input.expectedRunId, input.workspace, input.reason);\n return callResult(request);\n },\n },\n ],\n commands: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-launch',\n description: 'Launch a workflow from a slash command.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n const parsed = parseWorkflowLaunchCommand(args);\n if ('error' in parsed) {\n await execution.client.notify({ body: parsed.error, level: 'error' });\n return;\n }\n const result = await feature.runTool.execute({\n workflowPath: parsed.workflow,\n ...(parsed.runner === undefined ? {} : { runner: parsed.runner }),\n ...(Object.keys(parsed.inputs).length === 0 ? {} : { inputs: parsed.inputs }),\n ...(parsed.prompt === undefined ? {} : { prompt: parsed.prompt }),\n });\n const rendered = callResult(result).content.find((entry) => entry.type === 'text');\n await execution.client.notify({\n body: rendered?.type === 'text' ? rendered.text : 'Workflow launch requested.',\n level: 'info',\n });\n },\n },\n ],\n onDispose() {\n control?.dispose();\n control = undefined;\n },\n };\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("@agimon-ai/doompi-core/package-api"),exports.WORKFLOW_API_BASE_PATH=`workflow`,exports.WORKFLOW_SCREEN_EVENT=`screen`;
1
+ exports.WORKFLOW_API_BASE_PATH=`workflow`,exports.WORKFLOW_SCREEN_EVENT=`screen`;
2
2
  //# sourceMappingURL=webWorkflowTerminal.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"webWorkflowTerminal.cjs","names":[],"sources":["../../../src/types/webWorkflowTerminal.ts"],"sourcesContent":["/**\n * The wire contract between this package's hub API and its cockpit client:\n * one run's terminal, and the files its run directory holds.\n *\n * Both halves of the cockpit import these names, so the route strings and the\n * event names live here rather than being spelled twice.\n */\n\nimport { DOOM_HUB_API_SESSION_QUERY_PARAM } from '@agimon-ai/doompi-core/package-api';\n\n/** Segment this package's API is mounted under, below /api/plugin/. */\nexport const WORKFLOW_API_BASE_PATH = 'workflow';\n/** Host query parameter that selects the focused session's hub API bundle. */\nexport const WORKFLOW_HUB_SESSION_QUERY_PARAM = DOOM_HUB_API_SESSION_QUERY_PARAM;\n\n/** The SSE event name the screen stream writes. */\nexport const WORKFLOW_SCREEN_EVENT = 'screen';\n\n/** Where a run's routes live, below the mount every hub-scoped package API shares. */\nexport function workflowRunPath(workspace: string, runKey: string): string {\n return `/api/global/plugin/${WORKFLOW_API_BASE_PATH}/runs/${encodeURIComponent(workspace)}/${encodeURIComponent(runKey)}`;\n}\n\n/** What a surface may do with one run's terminal, and why anything is missing. */\nexport interface WorkflowTerminalCapabilitiesView {\n readable: boolean;\n writable: boolean;\n resizable: boolean;\n reason?: string;\n}\n\n/** One frame of a run's terminal, as the stream pushes it. */\nexport interface WorkflowScreenEvent {\n /** The visible screen, newest line last, carrying the colour the run printed. */\n lines: string[];\n capabilities: WorkflowTerminalCapabilitiesView;\n /** True once the run has settled, after which the stream ends. */\n ended?: boolean;\n}\n\n/** Answer to taking or releasing the keyboard for one run. */\nexport interface WorkflowControlResponse {\n /** True when this caller now holds the keyboard. */\n held: boolean;\n /** The token later writes must carry; absent when control was refused or released. */\n token?: string;\n /** Why control was refused, worded for a reader. */\n reason?: string;\n}\n\n/** Answer after a settled run and its directory have been permanently removed. */\nexport interface WorkflowDeleteResponse {\n deleted: true;\n}\n\n/** How a declared run-directory entry compares with what is on disk. */\nexport type WorkflowArtifactState = 'written' | 'empty' | 'pending' | 'unreadable';\n\n/** One file or directory in a run's own folder. */\nexport interface WorkflowArtifactView {\n /** Path relative to the run directory, which is also the read route's parameter. */\n path: string;\n kind: 'file' | 'directory';\n /** What the workflow says this file is for; empty for a file it never declared. */\n description: string;\n /** The jobs the workflow says write it. */\n producedBy: string[];\n /** True when the workflow's run-directory block names this entry. */\n declared: boolean;\n state: WorkflowArtifactState;\n /** Bytes on disk, absent until the file exists. */\n size?: number;\n /** ISO 8601 of the last write, absent until the file exists. */\n modifiedAt?: string;\n}\n\nexport interface WorkflowArtifactsResponse {\n /** Absolute path of the run's own directory, which the reader may want to open. */\n runDir: string;\n /** What the workflow says the directory is for. */\n description: string;\n artifacts: WorkflowArtifactView[];\n}\n\n/** One artifact's metadata and optional text, as the viewer tab reads it. */\nexport interface WorkflowArtifactContentResponse {\n path: string;\n size: number;\n modifiedAt: string;\n /** Media type inferred from the file extension by the trusted hub. Absent on older hubs. */\n mimeType?: string;\n /** Present for text formats; binary files are streamed from the raw route instead. */\n text?: string;\n /** True when textual content was longer than the reader's byte budget. */\n truncated: boolean;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"webWorkflowTerminal.cjs","names":[],"sources":["../../../src/types/webWorkflowTerminal.ts"],"sourcesContent":["/**\n * The wire contract between this package's hub API and its cockpit client:\n * one run's terminal, and the files its run directory holds.\n *\n * Both halves of the cockpit import these names, so the route strings and the\n * event names live here rather than being spelled twice.\n */\n\n/** Segment this package's API is mounted under, below /api/plugins/. */\nexport const WORKFLOW_API_BASE_PATH = 'workflow';\n\n/** The SSE event name the screen stream writes. */\nexport const WORKFLOW_SCREEN_EVENT = 'screen';\n\n/** Where a run's routes live, below the mount every hub-scoped package API shares. */\nexport function workflowRunPath(workspace: string, runKey: string): string {\n return `/api/plugins/${WORKFLOW_API_BASE_PATH}/runs/${encodeURIComponent(workspace)}/${encodeURIComponent(runKey)}`;\n}\n\n/** What a surface may do with one run's terminal, and why anything is missing. */\nexport interface WorkflowTerminalCapabilitiesView {\n readable: boolean;\n writable: boolean;\n resizable: boolean;\n reason?: string;\n}\n\n/** One frame of a run's terminal, as the stream pushes it. */\nexport interface WorkflowScreenEvent {\n /** The visible screen, newest line last, carrying the colour the run printed. */\n lines: string[];\n capabilities: WorkflowTerminalCapabilitiesView;\n /** True once the run has settled, after which the stream ends. */\n ended?: boolean;\n}\n\n/** Answer to taking or releasing the keyboard for one run. */\nexport interface WorkflowControlResponse {\n /** True when this caller now holds the keyboard. */\n held: boolean;\n /** The token later writes must carry; absent when control was refused or released. */\n token?: string;\n /** Why control was refused, worded for a reader. */\n reason?: string;\n}\n\n/** Answer after a settled run and its directory have been permanently removed. */\nexport interface WorkflowDeleteResponse {\n deleted: true;\n}\n\n/** How a declared run-directory entry compares with what is on disk. */\nexport type WorkflowArtifactState = 'written' | 'empty' | 'pending' | 'unreadable';\n\n/** One file or directory in a run's own folder. */\nexport interface WorkflowArtifactView {\n /** Path relative to the run directory, which is also the read route's parameter. */\n path: string;\n kind: 'file' | 'directory';\n /** What the workflow says this file is for; empty for a file it never declared. */\n description: string;\n /** The jobs the workflow says write it. */\n producedBy: string[];\n /** True when the workflow's run-directory block names this entry. */\n declared: boolean;\n state: WorkflowArtifactState;\n /** Bytes on disk, absent until the file exists. */\n size?: number;\n /** ISO 8601 of the last write, absent until the file exists. */\n modifiedAt?: string;\n}\n\nexport interface WorkflowArtifactsResponse {\n /** Absolute path of the run's own directory, which the reader may want to open. */\n runDir: string;\n /** What the workflow says the directory is for. */\n description: string;\n artifacts: WorkflowArtifactView[];\n}\n\n/** One artifact's metadata and optional text, as the viewer tab reads it. */\nexport interface WorkflowArtifactContentResponse {\n path: string;\n size: number;\n modifiedAt: string;\n /** Media type inferred from the file extension by the trusted hub. Absent on older hubs. */\n mimeType?: string;\n /** Present for text formats; binary files are streamed from the raw route instead. */\n text?: string;\n /** True when textual content was longer than the reader's byte budget. */\n truncated: boolean;\n}\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
- import"@agimon-ai/doompi-core/package-api";const e=`workflow`,t=`screen`;export{e as WORKFLOW_API_BASE_PATH,t as WORKFLOW_SCREEN_EVENT};
1
+ const e=`workflow`,t=`screen`;export{e as WORKFLOW_API_BASE_PATH,t as WORKFLOW_SCREEN_EVENT};
2
2
  //# sourceMappingURL=webWorkflowTerminal.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"webWorkflowTerminal.mjs","names":[],"sources":["../../../src/types/webWorkflowTerminal.ts"],"sourcesContent":["/**\n * The wire contract between this package's hub API and its cockpit client:\n * one run's terminal, and the files its run directory holds.\n *\n * Both halves of the cockpit import these names, so the route strings and the\n * event names live here rather than being spelled twice.\n */\n\nimport { DOOM_HUB_API_SESSION_QUERY_PARAM } from '@agimon-ai/doompi-core/package-api';\n\n/** Segment this package's API is mounted under, below /api/plugin/. */\nexport const WORKFLOW_API_BASE_PATH = 'workflow';\n/** Host query parameter that selects the focused session's hub API bundle. */\nexport const WORKFLOW_HUB_SESSION_QUERY_PARAM = DOOM_HUB_API_SESSION_QUERY_PARAM;\n\n/** The SSE event name the screen stream writes. */\nexport const WORKFLOW_SCREEN_EVENT = 'screen';\n\n/** Where a run's routes live, below the mount every hub-scoped package API shares. */\nexport function workflowRunPath(workspace: string, runKey: string): string {\n return `/api/global/plugin/${WORKFLOW_API_BASE_PATH}/runs/${encodeURIComponent(workspace)}/${encodeURIComponent(runKey)}`;\n}\n\n/** What a surface may do with one run's terminal, and why anything is missing. */\nexport interface WorkflowTerminalCapabilitiesView {\n readable: boolean;\n writable: boolean;\n resizable: boolean;\n reason?: string;\n}\n\n/** One frame of a run's terminal, as the stream pushes it. */\nexport interface WorkflowScreenEvent {\n /** The visible screen, newest line last, carrying the colour the run printed. */\n lines: string[];\n capabilities: WorkflowTerminalCapabilitiesView;\n /** True once the run has settled, after which the stream ends. */\n ended?: boolean;\n}\n\n/** Answer to taking or releasing the keyboard for one run. */\nexport interface WorkflowControlResponse {\n /** True when this caller now holds the keyboard. */\n held: boolean;\n /** The token later writes must carry; absent when control was refused or released. */\n token?: string;\n /** Why control was refused, worded for a reader. */\n reason?: string;\n}\n\n/** Answer after a settled run and its directory have been permanently removed. */\nexport interface WorkflowDeleteResponse {\n deleted: true;\n}\n\n/** How a declared run-directory entry compares with what is on disk. */\nexport type WorkflowArtifactState = 'written' | 'empty' | 'pending' | 'unreadable';\n\n/** One file or directory in a run's own folder. */\nexport interface WorkflowArtifactView {\n /** Path relative to the run directory, which is also the read route's parameter. */\n path: string;\n kind: 'file' | 'directory';\n /** What the workflow says this file is for; empty for a file it never declared. */\n description: string;\n /** The jobs the workflow says write it. */\n producedBy: string[];\n /** True when the workflow's run-directory block names this entry. */\n declared: boolean;\n state: WorkflowArtifactState;\n /** Bytes on disk, absent until the file exists. */\n size?: number;\n /** ISO 8601 of the last write, absent until the file exists. */\n modifiedAt?: string;\n}\n\nexport interface WorkflowArtifactsResponse {\n /** Absolute path of the run's own directory, which the reader may want to open. */\n runDir: string;\n /** What the workflow says the directory is for. */\n description: string;\n artifacts: WorkflowArtifactView[];\n}\n\n/** One artifact's metadata and optional text, as the viewer tab reads it. */\nexport interface WorkflowArtifactContentResponse {\n path: string;\n size: number;\n modifiedAt: string;\n /** Media type inferred from the file extension by the trusted hub. Absent on older hubs. */\n mimeType?: string;\n /** Present for text formats; binary files are streamed from the raw route instead. */\n text?: string;\n /** True when textual content was longer than the reader's byte budget. */\n truncated: boolean;\n}\n"],"mappings":"2CAWA,MAAa,EAAyB,WAKzB,EAAwB"}
1
+ {"version":3,"file":"webWorkflowTerminal.mjs","names":[],"sources":["../../../src/types/webWorkflowTerminal.ts"],"sourcesContent":["/**\n * The wire contract between this package's hub API and its cockpit client:\n * one run's terminal, and the files its run directory holds.\n *\n * Both halves of the cockpit import these names, so the route strings and the\n * event names live here rather than being spelled twice.\n */\n\n/** Segment this package's API is mounted under, below /api/plugins/. */\nexport const WORKFLOW_API_BASE_PATH = 'workflow';\n\n/** The SSE event name the screen stream writes. */\nexport const WORKFLOW_SCREEN_EVENT = 'screen';\n\n/** Where a run's routes live, below the mount every hub-scoped package API shares. */\nexport function workflowRunPath(workspace: string, runKey: string): string {\n return `/api/plugins/${WORKFLOW_API_BASE_PATH}/runs/${encodeURIComponent(workspace)}/${encodeURIComponent(runKey)}`;\n}\n\n/** What a surface may do with one run's terminal, and why anything is missing. */\nexport interface WorkflowTerminalCapabilitiesView {\n readable: boolean;\n writable: boolean;\n resizable: boolean;\n reason?: string;\n}\n\n/** One frame of a run's terminal, as the stream pushes it. */\nexport interface WorkflowScreenEvent {\n /** The visible screen, newest line last, carrying the colour the run printed. */\n lines: string[];\n capabilities: WorkflowTerminalCapabilitiesView;\n /** True once the run has settled, after which the stream ends. */\n ended?: boolean;\n}\n\n/** Answer to taking or releasing the keyboard for one run. */\nexport interface WorkflowControlResponse {\n /** True when this caller now holds the keyboard. */\n held: boolean;\n /** The token later writes must carry; absent when control was refused or released. */\n token?: string;\n /** Why control was refused, worded for a reader. */\n reason?: string;\n}\n\n/** Answer after a settled run and its directory have been permanently removed. */\nexport interface WorkflowDeleteResponse {\n deleted: true;\n}\n\n/** How a declared run-directory entry compares with what is on disk. */\nexport type WorkflowArtifactState = 'written' | 'empty' | 'pending' | 'unreadable';\n\n/** One file or directory in a run's own folder. */\nexport interface WorkflowArtifactView {\n /** Path relative to the run directory, which is also the read route's parameter. */\n path: string;\n kind: 'file' | 'directory';\n /** What the workflow says this file is for; empty for a file it never declared. */\n description: string;\n /** The jobs the workflow says write it. */\n producedBy: string[];\n /** True when the workflow's run-directory block names this entry. */\n declared: boolean;\n state: WorkflowArtifactState;\n /** Bytes on disk, absent until the file exists. */\n size?: number;\n /** ISO 8601 of the last write, absent until the file exists. */\n modifiedAt?: string;\n}\n\nexport interface WorkflowArtifactsResponse {\n /** Absolute path of the run's own directory, which the reader may want to open. */\n runDir: string;\n /** What the workflow says the directory is for. */\n description: string;\n artifacts: WorkflowArtifactView[];\n}\n\n/** One artifact's metadata and optional text, as the viewer tab reads it. */\nexport interface WorkflowArtifactContentResponse {\n path: string;\n size: number;\n modifiedAt: string;\n /** Media type inferred from the file extension by the trusted hub. Absent on older hubs. */\n mimeType?: string;\n /** Present for text formats; binary files are streamed from the raw route instead. */\n text?: string;\n /** True when textual content was longer than the reader's byte budget. */\n truncated: boolean;\n}\n"],"mappings":"AASA,MAAa,EAAyB,WAGzB,EAAwB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-workflow",
3
- "version": "0.0.1-alpha.71",
3
+ "version": "0.0.1-alpha.73",
4
4
  "description": "GitHub Actions-style workflow graphs, artifacts, recovery, and asynchronous runs for DoomPi.",
5
5
  "keywords": [
6
6
  "ai",
@@ -64,30 +64,30 @@
64
64
  "access": "public"
65
65
  },
66
66
  "dependencies": {
67
- "@agimon-ai/workflow-mcp": "0.23.19",
67
+ "@agimon-ai/doompi-core": "0.0.1-alpha.72",
68
+ "@agimon-ai/doompi-minor-mode": "0.0.1-alpha.72",
69
+ "@agimon-ai/doompi-telemetry": "0.0.1-alpha.69",
70
+ "@agimon-ai/doompi-ui": "0.0.1-alpha.72",
71
+ "@agimon-ai/doompi-web-components": "0.0.1-alpha.30",
72
+ "@agimon-ai/doompi-web-security": "0.0.1-alpha.32",
73
+ "@agimon-ai/workflow-mcp": "0.23.26",
68
74
  "@deepseek-ai/cordis": "4.0.2",
69
75
  "@modelcontextprotocol/sdk": "1.30.0",
70
- "hono": "4.13.5",
71
- "typebox": "1.3.25",
72
- "zod": "4.5.4",
73
- "@agimon-ai/doompi-minor-mode": "0.0.1-alpha.70",
74
- "@agimon-ai/doompi-core": "0.0.1-alpha.70",
75
- "@agimon-ai/doompi-telemetry": "0.0.1-alpha.68",
76
- "@agimon-ai/doompi-web-components": "0.0.1-alpha.29",
77
- "@agimon-ai/doompi-ui": "0.0.1-alpha.70",
78
- "@agimon-ai/doompi-web-security": "0.0.1-alpha.31"
76
+ "hono": "4.13.7",
77
+ "typebox": "1.3.30",
78
+ "zod": "4.6.2"
79
79
  },
80
80
  "devDependencies": {
81
81
  "@earendil-works/pi-coding-agent": "0.85.1",
82
82
  "@earendil-works/pi-tui": "0.85.1",
83
83
  "@tanstack/react-store": "0.11.1",
84
84
  "@tanstack/store": "0.11.1",
85
- "@types/node": "26.4.1",
86
- "@types/react": "19.2.18",
87
- "@types/react-dom": "19.2.7",
85
+ "@types/node": "26.5.1",
86
+ "@types/react": "19.3.0",
87
+ "@types/react-dom": "19.3.0",
88
88
  "@vitest/coverage-v8": "5.0.0",
89
- "react": "19.2.8",
90
- "react-dom": "19.2.8",
89
+ "react": "19.3.0",
90
+ "react-dom": "19.3.0",
91
91
  "tsdown": "0.23.0",
92
92
  "typescript": "7.0.2",
93
93
  "vitest": "5.0.0"
@@ -6,19 +6,15 @@
6
6
  * event names live here rather than being spelled twice.
7
7
  */
8
8
 
9
- import { DOOM_HUB_API_SESSION_QUERY_PARAM } from '@agimon-ai/doompi-core/package-api';
10
-
11
- /** Segment this package's API is mounted under, below /api/plugin/. */
9
+ /** Segment this package's API is mounted under, below /api/plugins/. */
12
10
  export const WORKFLOW_API_BASE_PATH = 'workflow';
13
- /** Host query parameter that selects the focused session's hub API bundle. */
14
- export const WORKFLOW_HUB_SESSION_QUERY_PARAM = DOOM_HUB_API_SESSION_QUERY_PARAM;
15
11
 
16
12
  /** The SSE event name the screen stream writes. */
17
13
  export const WORKFLOW_SCREEN_EVENT = 'screen';
18
14
 
19
15
  /** Where a run's routes live, below the mount every hub-scoped package API shares. */
20
16
  export function workflowRunPath(workspace: string, runKey: string): string {
21
- return `/api/global/plugin/${WORKFLOW_API_BASE_PATH}/runs/${encodeURIComponent(workspace)}/${encodeURIComponent(runKey)}`;
17
+ return `/api/plugins/${WORKFLOW_API_BASE_PATH}/runs/${encodeURIComponent(workspace)}/${encodeURIComponent(runKey)}`;
22
18
  }
23
19
 
24
20
  /** What a surface may do with one run's terminal, and why anything is missing. */
@@ -1,3 +1,4 @@
1
+ import { sessionApiPath } from '@agimon-ai/doompi-core/web';
1
2
  import { sealedTransport } from '@agimon-ai/doompi-web-security/browser';
2
3
 
3
4
  import {
@@ -21,7 +22,7 @@ const JSON_HEADERS = { 'content-type': 'application/json' };
21
22
 
22
23
  function sessionUrl(path: string, sessionId?: string | null): string {
23
24
  if (sessionId === undefined || sessionId === null) return path;
24
- return path.replace('/api/global/plugin/', `/api/sessions/${encodeURIComponent(sessionId)}/plugin/`);
25
+ return path.replace('/api/plugins/', `${sessionApiPath(sessionId)}/plugins/`);
25
26
  }
26
27
  function isRecord(value: unknown): value is Record<string, unknown> {
27
28
  return typeof value === 'object' && value !== null && !Array.isArray(value);