@output.ai/cli 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -8
- package/dist/api/generated/api.d.ts +66 -0
- package/dist/api/generated/api.js +26 -0
- package/dist/assets/docker/docker-compose-dev.yml +9 -2
- package/dist/commands/workflow/runs/list.d.ts +14 -0
- package/dist/commands/workflow/runs/list.js +104 -0
- package/dist/services/coding_agents.js +180 -8
- package/dist/services/coding_agents.spec.js +54 -11
- package/dist/services/workflow_runs.d.ts +14 -0
- package/dist/services/workflow_runs.js +24 -0
- package/dist/templates/agent_instructions/AGENTS.md.template +13 -7
- package/dist/templates/agent_instructions/agents/{context_fetcher.md.template → workflow_context_fetcher.md.template} +1 -1
- package/dist/templates/agent_instructions/agents/workflow_debugger.md.template +98 -0
- package/dist/templates/agent_instructions/agents/workflow_planner.md.template +3 -3
- package/dist/templates/agent_instructions/agents/{prompt_writer.md.template → workflow_prompt_writer.md.template} +1 -1
- package/dist/templates/agent_instructions/agents/workflow_quality.md.template +2 -2
- package/dist/templates/agent_instructions/commands/build_workflow.md.template +2 -2
- package/dist/templates/agent_instructions/commands/debug_workflow.md.template +198 -0
- package/dist/templates/agent_instructions/commands/plan_workflow.md.template +2 -2
- package/dist/templates/agent_instructions/skills/output-error-direct-io/SKILL.md.template +249 -0
- package/dist/templates/agent_instructions/skills/output-error-http-client/SKILL.md.template +298 -0
- package/dist/templates/agent_instructions/skills/output-error-missing-schemas/SKILL.md.template +265 -0
- package/dist/templates/agent_instructions/skills/output-error-nondeterminism/SKILL.md.template +252 -0
- package/dist/templates/agent_instructions/skills/output-error-try-catch/SKILL.md.template +226 -0
- package/dist/templates/agent_instructions/skills/output-error-zod-import/SKILL.md.template +209 -0
- package/dist/templates/agent_instructions/skills/output-services-check/SKILL.md.template +128 -0
- package/dist/templates/agent_instructions/skills/output-workflow-list/SKILL.md.template +117 -0
- package/dist/templates/agent_instructions/skills/output-workflow-result/SKILL.md.template +199 -0
- package/dist/templates/agent_instructions/skills/output-workflow-run/SKILL.md.template +228 -0
- package/dist/templates/agent_instructions/skills/output-workflow-runs-list/SKILL.md.template +141 -0
- package/dist/templates/agent_instructions/skills/output-workflow-start/SKILL.md.template +201 -0
- package/dist/templates/agent_instructions/skills/output-workflow-status/SKILL.md.template +151 -0
- package/dist/templates/agent_instructions/skills/output-workflow-stop/SKILL.md.template +164 -0
- package/dist/templates/agent_instructions/skills/output-workflow-trace/SKILL.md.template +134 -0
- package/dist/templates/project/README.md.template +1 -1
- package/dist/templates/project/package.json.template +3 -2
- package/dist/utils/date_formatter.d.ts +15 -0
- package/dist/utils/date_formatter.js +31 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,11 +5,7 @@ Command-line interface for creating and running Output Framework workflows.
|
|
|
5
5
|
[](https://www.npmjs.com/package/@output.ai/cli)
|
|
6
6
|
[](https://docs.output.ai/packages/cli)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npm install -g @output.ai/cli
|
|
12
|
-
```
|
|
8
|
+
> **Full Documentation**: For detailed command options, flags, and examples, see the [CLI Reference](https://docs.output.ai/packages/cli).
|
|
13
9
|
|
|
14
10
|
## Quick Start
|
|
15
11
|
|
|
@@ -35,11 +31,13 @@ output workflow run simple --input '{"question": "who is ada lovelace?"}'
|
|
|
35
31
|
| `output workflow plan` | Generate a workflow plan from description |
|
|
36
32
|
| `output workflow generate` | Generate a workflow from plan |
|
|
37
33
|
| `output workflow list` | List available workflows |
|
|
34
|
+
| `output workflow runs list` | List recent workflow runs |
|
|
38
35
|
| `output workflow run` | Execute a workflow synchronously |
|
|
39
36
|
| `output workflow start` | Start a workflow asynchronously |
|
|
40
37
|
| `output workflow status` | Get workflow execution status |
|
|
41
38
|
| `output workflow result` | Get workflow execution result |
|
|
42
39
|
| `output workflow stop` | Stop a workflow execution |
|
|
40
|
+
| `output workflow debug` | Display workflow execution trace |
|
|
43
41
|
|
|
44
42
|
## Development Services
|
|
45
43
|
|
|
@@ -53,7 +51,7 @@ Running `output dev` starts:
|
|
|
53
51
|
|
|
54
52
|
## Documentation
|
|
55
53
|
|
|
56
|
-
For comprehensive documentation
|
|
54
|
+
For comprehensive documentation including all command flags and detailed examples:
|
|
57
55
|
|
|
58
|
-
- [CLI Reference](https://docs.output.ai/packages/cli)
|
|
59
|
-
- [Getting Started](https://docs.output.ai/quickstart)
|
|
56
|
+
- [CLI Reference](https://docs.output.ai/packages/cli) - Complete command documentation
|
|
57
|
+
- [Getting Started](https://docs.output.ai/quickstart) - Project setup guide
|
|
@@ -54,6 +54,39 @@ export interface TraceInfo {
|
|
|
54
54
|
/** File destinations for trace data */
|
|
55
55
|
destinations?: TraceInfoDestinations;
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Current run status
|
|
59
|
+
*/
|
|
60
|
+
export type WorkflowRunInfoStatus = typeof WorkflowRunInfoStatus[keyof typeof WorkflowRunInfoStatus];
|
|
61
|
+
export declare const WorkflowRunInfoStatus: {
|
|
62
|
+
readonly running: "running";
|
|
63
|
+
readonly completed: "completed";
|
|
64
|
+
readonly failed: "failed";
|
|
65
|
+
readonly canceled: "canceled";
|
|
66
|
+
readonly terminated: "terminated";
|
|
67
|
+
readonly timed_out: "timed_out";
|
|
68
|
+
readonly continued: "continued";
|
|
69
|
+
};
|
|
70
|
+
export interface WorkflowRunInfo {
|
|
71
|
+
/** Unique identifier for this run */
|
|
72
|
+
workflowId?: string;
|
|
73
|
+
/** Name of the workflow definition */
|
|
74
|
+
workflowType?: string;
|
|
75
|
+
/** Current run status */
|
|
76
|
+
status?: WorkflowRunInfoStatus;
|
|
77
|
+
/** ISO 8601 timestamp of run start */
|
|
78
|
+
startedAt?: string;
|
|
79
|
+
/**
|
|
80
|
+
* ISO 8601 timestamp of completion, or null if still running
|
|
81
|
+
* @nullable
|
|
82
|
+
*/
|
|
83
|
+
completedAt?: string | null;
|
|
84
|
+
}
|
|
85
|
+
export interface WorkflowRunsResponse {
|
|
86
|
+
runs?: WorkflowRunInfo[];
|
|
87
|
+
/** Total number of runs returned */
|
|
88
|
+
count?: number;
|
|
89
|
+
}
|
|
57
90
|
export type PostWorkflowRunBody = {
|
|
58
91
|
/** The name of the workflow to execute */
|
|
59
92
|
workflowName: string;
|
|
@@ -124,6 +157,18 @@ export type GetWorkflowCatalog200 = {
|
|
|
124
157
|
/** Each workflow available in this catalog */
|
|
125
158
|
workflows?: Workflow[];
|
|
126
159
|
};
|
|
160
|
+
export type GetWorkflowRunsParams = {
|
|
161
|
+
/**
|
|
162
|
+
* Filter by workflow type/name
|
|
163
|
+
*/
|
|
164
|
+
workflowType?: string;
|
|
165
|
+
/**
|
|
166
|
+
* Maximum number of runs to return
|
|
167
|
+
* @minimum 1
|
|
168
|
+
* @maximum 1000
|
|
169
|
+
*/
|
|
170
|
+
limit?: number;
|
|
171
|
+
};
|
|
127
172
|
export type PostWorkflowIdFeedbackBody = {
|
|
128
173
|
/** The payload to send to the workflow */
|
|
129
174
|
payload?: unknown;
|
|
@@ -254,6 +299,27 @@ export type getWorkflowCatalogResponseSuccess = (getWorkflowCatalogResponse200)
|
|
|
254
299
|
export type getWorkflowCatalogResponse = (getWorkflowCatalogResponseSuccess);
|
|
255
300
|
export declare const getGetWorkflowCatalogUrl: () => string;
|
|
256
301
|
export declare const getWorkflowCatalog: (options?: ApiRequestOptions) => Promise<getWorkflowCatalogResponse>;
|
|
302
|
+
/**
|
|
303
|
+
* Returns a list of workflow runs with optional filtering by workflow type
|
|
304
|
+
* @summary List workflow runs
|
|
305
|
+
*/
|
|
306
|
+
export type getWorkflowRunsResponse200 = {
|
|
307
|
+
data: WorkflowRunsResponse;
|
|
308
|
+
status: 200;
|
|
309
|
+
};
|
|
310
|
+
export type getWorkflowRunsResponse400 = {
|
|
311
|
+
data: void;
|
|
312
|
+
status: 400;
|
|
313
|
+
};
|
|
314
|
+
export type getWorkflowRunsResponseSuccess = (getWorkflowRunsResponse200) & {
|
|
315
|
+
headers: Headers;
|
|
316
|
+
};
|
|
317
|
+
export type getWorkflowRunsResponseError = (getWorkflowRunsResponse400) & {
|
|
318
|
+
headers: Headers;
|
|
319
|
+
};
|
|
320
|
+
export type getWorkflowRunsResponse = (getWorkflowRunsResponseSuccess | getWorkflowRunsResponseError);
|
|
321
|
+
export declare const getGetWorkflowRunsUrl: (params?: GetWorkflowRunsParams) => string;
|
|
322
|
+
export declare const getWorkflowRuns: (params?: GetWorkflowRunsParams, options?: ApiRequestOptions) => Promise<getWorkflowRunsResponse>;
|
|
257
323
|
/**
|
|
258
324
|
* @summary Send feedback to a payload
|
|
259
325
|
*/
|
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { customFetchInstance } from '../http_client.js';
|
|
9
9
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
10
|
+
export const WorkflowRunInfoStatus = {
|
|
11
|
+
running: 'running',
|
|
12
|
+
completed: 'completed',
|
|
13
|
+
failed: 'failed',
|
|
14
|
+
canceled: 'canceled',
|
|
15
|
+
terminated: 'terminated',
|
|
16
|
+
timed_out: 'timed_out',
|
|
17
|
+
continued: 'continued',
|
|
18
|
+
};
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
10
20
|
export const GetWorkflowIdStatus200Status = {
|
|
11
21
|
canceled: 'canceled',
|
|
12
22
|
completed: 'completed',
|
|
@@ -98,6 +108,22 @@ export const getWorkflowCatalog = async (options) => {
|
|
|
98
108
|
method: 'GET'
|
|
99
109
|
});
|
|
100
110
|
};
|
|
111
|
+
export const getGetWorkflowRunsUrl = (params) => {
|
|
112
|
+
const normalizedParams = new URLSearchParams();
|
|
113
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
114
|
+
if (value !== undefined) {
|
|
115
|
+
normalizedParams.append(key, value === null ? 'null' : value.toString());
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
const stringifiedParams = normalizedParams.toString();
|
|
119
|
+
return stringifiedParams.length > 0 ? `/workflow/runs?${stringifiedParams}` : `/workflow/runs`;
|
|
120
|
+
};
|
|
121
|
+
export const getWorkflowRuns = async (params, options) => {
|
|
122
|
+
return customFetchInstance(getGetWorkflowRunsUrl(params), {
|
|
123
|
+
...options,
|
|
124
|
+
method: 'GET'
|
|
125
|
+
});
|
|
126
|
+
};
|
|
101
127
|
;
|
|
102
128
|
export const getPostWorkflowIdFeedbackUrl = (id) => {
|
|
103
129
|
return `/workflow/${id}/feedback`;
|
|
@@ -80,7 +80,6 @@ services:
|
|
|
80
80
|
temporal:
|
|
81
81
|
condition: service_healthy
|
|
82
82
|
image: growthxteam/output-api:latest
|
|
83
|
-
pull_policy: always
|
|
84
83
|
networks:
|
|
85
84
|
- main
|
|
86
85
|
environment:
|
|
@@ -106,7 +105,15 @@ services:
|
|
|
106
105
|
- TEMPORAL_ADDRESS=temporal:7233
|
|
107
106
|
- TRACE_LOCAL_ON=true
|
|
108
107
|
- HOST_TRACE_PATH=${PWD}/logs
|
|
109
|
-
command:
|
|
108
|
+
command: >
|
|
109
|
+
sh -c "
|
|
110
|
+
npm run output:worker:install &&
|
|
111
|
+
echo 'Installed dependencies' &&
|
|
112
|
+
npm run output:worker:build &&
|
|
113
|
+
echo 'Built worker' &&
|
|
114
|
+
npm run output:worker:start &&
|
|
115
|
+
echo 'Started worker'
|
|
116
|
+
"
|
|
110
117
|
working_dir: /app
|
|
111
118
|
volumes:
|
|
112
119
|
- ./:/app
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class WorkflowRunsList extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
workflowName: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
limit: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
format: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
catch(error: Error): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import Table from 'cli-table3';
|
|
3
|
+
import { fetchWorkflowRuns } from '#services/workflow_runs.js';
|
|
4
|
+
import { formatDate, formatDurationFromTimestamps } from '#utils/date_formatter.js';
|
|
5
|
+
import { handleApiError } from '#utils/error_handler.js';
|
|
6
|
+
const OUTPUT_FORMAT = {
|
|
7
|
+
TABLE: 'table',
|
|
8
|
+
JSON: 'json',
|
|
9
|
+
TEXT: 'text'
|
|
10
|
+
};
|
|
11
|
+
function createRunsTable(runs) {
|
|
12
|
+
const table = new Table({
|
|
13
|
+
head: ['Workflow ID', 'Type', 'Status', 'Started', 'Duration'],
|
|
14
|
+
colWidths: [40, 20, 12, 22, 10],
|
|
15
|
+
wordWrap: true,
|
|
16
|
+
style: {
|
|
17
|
+
head: ['cyan']
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
runs.forEach(run => {
|
|
21
|
+
table.push([
|
|
22
|
+
run.workflowId || '-',
|
|
23
|
+
run.workflowType || '-',
|
|
24
|
+
run.status || '-',
|
|
25
|
+
formatDate(run.startedAt),
|
|
26
|
+
formatDurationFromTimestamps(run.startedAt || '', run.completedAt)
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
return table.toString();
|
|
30
|
+
}
|
|
31
|
+
function formatRunsAsText(runs) {
|
|
32
|
+
if (runs.length === 0) {
|
|
33
|
+
return 'No workflow runs found.';
|
|
34
|
+
}
|
|
35
|
+
return runs.map(run => {
|
|
36
|
+
const duration = formatDurationFromTimestamps(run.startedAt || '', run.completedAt);
|
|
37
|
+
return `${run.workflowId} (${run.workflowType}) - ${run.status} [${duration}]`;
|
|
38
|
+
}).join('\n');
|
|
39
|
+
}
|
|
40
|
+
function formatRunsAsJson(runs) {
|
|
41
|
+
return JSON.stringify(runs, null, 2);
|
|
42
|
+
}
|
|
43
|
+
function formatRuns(runs, format) {
|
|
44
|
+
if (format === OUTPUT_FORMAT.JSON) {
|
|
45
|
+
return formatRunsAsJson(runs);
|
|
46
|
+
}
|
|
47
|
+
if (format === OUTPUT_FORMAT.TABLE) {
|
|
48
|
+
return createRunsTable(runs);
|
|
49
|
+
}
|
|
50
|
+
return formatRunsAsText(runs);
|
|
51
|
+
}
|
|
52
|
+
export default class WorkflowRunsList extends Command {
|
|
53
|
+
static description = 'List workflow runs with optional filtering by workflow type';
|
|
54
|
+
static examples = [
|
|
55
|
+
'<%= config.bin %> <%= command.id %>',
|
|
56
|
+
'<%= config.bin %> <%= command.id %> simple',
|
|
57
|
+
'<%= config.bin %> <%= command.id %> simple --limit 10',
|
|
58
|
+
'<%= config.bin %> <%= command.id %> --format json',
|
|
59
|
+
'<%= config.bin %> <%= command.id %> --format table'
|
|
60
|
+
];
|
|
61
|
+
static args = {
|
|
62
|
+
workflowName: Args.string({
|
|
63
|
+
description: 'Filter by workflow type/name',
|
|
64
|
+
required: false
|
|
65
|
+
})
|
|
66
|
+
};
|
|
67
|
+
static flags = {
|
|
68
|
+
limit: Flags.integer({
|
|
69
|
+
char: 'l',
|
|
70
|
+
description: 'Maximum number of runs to return',
|
|
71
|
+
default: 100
|
|
72
|
+
}),
|
|
73
|
+
format: Flags.string({
|
|
74
|
+
char: 'f',
|
|
75
|
+
description: 'Output format',
|
|
76
|
+
options: [OUTPUT_FORMAT.TABLE, OUTPUT_FORMAT.JSON, OUTPUT_FORMAT.TEXT],
|
|
77
|
+
default: OUTPUT_FORMAT.TABLE
|
|
78
|
+
})
|
|
79
|
+
};
|
|
80
|
+
async run() {
|
|
81
|
+
const { args, flags } = await this.parse(WorkflowRunsList);
|
|
82
|
+
const { runs, count } = await fetchWorkflowRuns({
|
|
83
|
+
workflowType: args.workflowName,
|
|
84
|
+
limit: flags.limit
|
|
85
|
+
});
|
|
86
|
+
if (runs.length === 0) {
|
|
87
|
+
const filterMsg = args.workflowName ? ` for workflow type "${args.workflowName}"` : '';
|
|
88
|
+
this.log(`No workflow runs found${filterMsg}.`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const output = formatRuns(runs, flags.format);
|
|
92
|
+
this.log(output);
|
|
93
|
+
if (flags.format !== OUTPUT_FORMAT.JSON) {
|
|
94
|
+
const filterMsg = args.workflowName ? ` of type "${args.workflowName}"` : '';
|
|
95
|
+
this.log(`\nFound ${count} run(s)${filterMsg}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async catch(error) {
|
|
99
|
+
return handleApiError(error, (...args) => this.error(...args), {
|
|
100
|
+
400: 'Invalid parameters provided.',
|
|
101
|
+
503: 'Workflow service temporarily unavailable.'
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -36,19 +36,29 @@ export const AGENT_CONFIGS = {
|
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
type: 'template',
|
|
39
|
-
from: 'agents/
|
|
40
|
-
to: `${AGENT_CONFIG_DIR}/agents/
|
|
39
|
+
from: 'agents/workflow_context_fetcher.md.template',
|
|
40
|
+
to: `${AGENT_CONFIG_DIR}/agents/workflow_context_fetcher.md`
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
type: 'template',
|
|
44
|
-
from: 'agents/
|
|
45
|
-
to: `${AGENT_CONFIG_DIR}/agents/
|
|
44
|
+
from: 'agents/workflow_prompt_writer.md.template',
|
|
45
|
+
to: `${AGENT_CONFIG_DIR}/agents/workflow_prompt_writer.md`
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: 'template',
|
|
49
|
+
from: 'agents/workflow_debugger.md.template',
|
|
50
|
+
to: `${AGENT_CONFIG_DIR}/agents/workflow_debugger.md`
|
|
46
51
|
},
|
|
47
52
|
{
|
|
48
53
|
type: 'template',
|
|
49
54
|
from: 'commands/plan_workflow.md.template',
|
|
50
55
|
to: `${AGENT_CONFIG_DIR}/commands/plan_workflow.md`
|
|
51
56
|
},
|
|
57
|
+
{
|
|
58
|
+
type: 'template',
|
|
59
|
+
from: 'commands/debug_workflow.md.template',
|
|
60
|
+
to: `${AGENT_CONFIG_DIR}/commands/debug_workflow.md`
|
|
61
|
+
},
|
|
52
62
|
{
|
|
53
63
|
type: 'template',
|
|
54
64
|
from: 'commands/build_workflow.md.template',
|
|
@@ -63,6 +73,82 @@ export const AGENT_CONFIGS = {
|
|
|
63
73
|
type: 'template',
|
|
64
74
|
from: 'meta/post_flight.md.template',
|
|
65
75
|
to: '.outputai/meta/post_flight.md'
|
|
76
|
+
},
|
|
77
|
+
// Skills (all at top level - no nesting allowed)
|
|
78
|
+
{
|
|
79
|
+
type: 'template',
|
|
80
|
+
from: 'skills/output-services-check/SKILL.md.template',
|
|
81
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-services-check/SKILL.md`
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
type: 'template',
|
|
85
|
+
from: 'skills/output-workflow-trace/SKILL.md.template',
|
|
86
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-workflow-trace/SKILL.md`
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
type: 'template',
|
|
90
|
+
from: 'skills/output-workflow-list/SKILL.md.template',
|
|
91
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-workflow-list/SKILL.md`
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: 'template',
|
|
95
|
+
from: 'skills/output-workflow-runs-list/SKILL.md.template',
|
|
96
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-workflow-runs-list/SKILL.md`
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
type: 'template',
|
|
100
|
+
from: 'skills/output-workflow-run/SKILL.md.template',
|
|
101
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-workflow-run/SKILL.md`
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: 'template',
|
|
105
|
+
from: 'skills/output-workflow-start/SKILL.md.template',
|
|
106
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-workflow-start/SKILL.md`
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: 'template',
|
|
110
|
+
from: 'skills/output-workflow-status/SKILL.md.template',
|
|
111
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-workflow-status/SKILL.md`
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: 'template',
|
|
115
|
+
from: 'skills/output-workflow-result/SKILL.md.template',
|
|
116
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-workflow-result/SKILL.md`
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
type: 'template',
|
|
120
|
+
from: 'skills/output-workflow-stop/SKILL.md.template',
|
|
121
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-workflow-stop/SKILL.md`
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
type: 'template',
|
|
125
|
+
from: 'skills/output-error-zod-import/SKILL.md.template',
|
|
126
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-error-zod-import/SKILL.md`
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'template',
|
|
130
|
+
from: 'skills/output-error-nondeterminism/SKILL.md.template',
|
|
131
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-error-nondeterminism/SKILL.md`
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
type: 'template',
|
|
135
|
+
from: 'skills/output-error-try-catch/SKILL.md.template',
|
|
136
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-error-try-catch/SKILL.md`
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
type: 'template',
|
|
140
|
+
from: 'skills/output-error-missing-schemas/SKILL.md.template',
|
|
141
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-error-missing-schemas/SKILL.md`
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
type: 'template',
|
|
145
|
+
from: 'skills/output-error-direct-io/SKILL.md.template',
|
|
146
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-error-direct-io/SKILL.md`
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
type: 'template',
|
|
150
|
+
from: 'skills/output-error-http-client/SKILL.md.template',
|
|
151
|
+
to: `${AGENT_CONFIG_DIR}/skills/output-error-http-client/SKILL.md`
|
|
66
152
|
}
|
|
67
153
|
]
|
|
68
154
|
},
|
|
@@ -87,23 +173,109 @@ export const AGENT_CONFIGS = {
|
|
|
87
173
|
},
|
|
88
174
|
{
|
|
89
175
|
type: 'symlink',
|
|
90
|
-
from: `${AGENT_CONFIG_DIR}/agents/
|
|
91
|
-
to: '.claude/agents/
|
|
176
|
+
from: `${AGENT_CONFIG_DIR}/agents/workflow_context_fetcher.md`,
|
|
177
|
+
to: '.claude/agents/workflow_context_fetcher.md'
|
|
92
178
|
},
|
|
93
179
|
{
|
|
94
180
|
type: 'symlink',
|
|
95
|
-
from: `${AGENT_CONFIG_DIR}/agents/
|
|
96
|
-
to: '.claude/agents/
|
|
181
|
+
from: `${AGENT_CONFIG_DIR}/agents/workflow_prompt_writer.md`,
|
|
182
|
+
to: '.claude/agents/workflow_prompt_writer.md'
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
type: 'symlink',
|
|
186
|
+
from: `${AGENT_CONFIG_DIR}/agents/workflow_debugger.md`,
|
|
187
|
+
to: '.claude/agents/workflow_debugger.md'
|
|
97
188
|
},
|
|
98
189
|
{
|
|
99
190
|
type: 'symlink',
|
|
100
191
|
from: `${AGENT_CONFIG_DIR}/commands/plan_workflow.md`,
|
|
101
192
|
to: '.claude/commands/plan_workflow.md'
|
|
102
193
|
},
|
|
194
|
+
{
|
|
195
|
+
type: 'symlink',
|
|
196
|
+
from: `${AGENT_CONFIG_DIR}/commands/debug_workflow.md`,
|
|
197
|
+
to: '.claude/commands/debug_workflow.md'
|
|
198
|
+
},
|
|
103
199
|
{
|
|
104
200
|
type: 'symlink',
|
|
105
201
|
from: `${AGENT_CONFIG_DIR}/commands/build_workflow.md`,
|
|
106
202
|
to: '.claude/commands/build_workflow.md'
|
|
203
|
+
},
|
|
204
|
+
// Skills Symlinks (all at top level - no nesting allowed)
|
|
205
|
+
{
|
|
206
|
+
type: 'symlink',
|
|
207
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-services-check/SKILL.md`,
|
|
208
|
+
to: '.claude/skills/output-services-check/SKILL.md'
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
type: 'symlink',
|
|
212
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-workflow-trace/SKILL.md`,
|
|
213
|
+
to: '.claude/skills/output-workflow-trace/SKILL.md'
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
type: 'symlink',
|
|
217
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-workflow-list/SKILL.md`,
|
|
218
|
+
to: '.claude/skills/output-workflow-list/SKILL.md'
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
type: 'symlink',
|
|
222
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-workflow-runs-list/SKILL.md`,
|
|
223
|
+
to: '.claude/skills/output-workflow-runs-list/SKILL.md'
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
type: 'symlink',
|
|
227
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-workflow-run/SKILL.md`,
|
|
228
|
+
to: '.claude/skills/output-workflow-run/SKILL.md'
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
type: 'symlink',
|
|
232
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-workflow-start/SKILL.md`,
|
|
233
|
+
to: '.claude/skills/output-workflow-start/SKILL.md'
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
type: 'symlink',
|
|
237
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-workflow-status/SKILL.md`,
|
|
238
|
+
to: '.claude/skills/output-workflow-status/SKILL.md'
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
type: 'symlink',
|
|
242
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-workflow-result/SKILL.md`,
|
|
243
|
+
to: '.claude/skills/output-workflow-result/SKILL.md'
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
type: 'symlink',
|
|
247
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-workflow-stop/SKILL.md`,
|
|
248
|
+
to: '.claude/skills/output-workflow-stop/SKILL.md'
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
type: 'symlink',
|
|
252
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-error-zod-import/SKILL.md`,
|
|
253
|
+
to: '.claude/skills/output-error-zod-import/SKILL.md'
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
type: 'symlink',
|
|
257
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-error-nondeterminism/SKILL.md`,
|
|
258
|
+
to: '.claude/skills/output-error-nondeterminism/SKILL.md'
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
type: 'symlink',
|
|
262
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-error-try-catch/SKILL.md`,
|
|
263
|
+
to: '.claude/skills/output-error-try-catch/SKILL.md'
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
type: 'symlink',
|
|
267
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-error-missing-schemas/SKILL.md`,
|
|
268
|
+
to: '.claude/skills/output-error-missing-schemas/SKILL.md'
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
type: 'symlink',
|
|
272
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-error-direct-io/SKILL.md`,
|
|
273
|
+
to: '.claude/skills/output-error-direct-io/SKILL.md'
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
type: 'symlink',
|
|
277
|
+
from: `${AGENT_CONFIG_DIR}/skills/output-error-http-client/SKILL.md`,
|
|
278
|
+
to: '.claude/skills/output-error-http-client/SKILL.md'
|
|
107
279
|
}
|
|
108
280
|
]
|
|
109
281
|
}
|
|
@@ -33,17 +33,23 @@ describe('coding_agents service', () => {
|
|
|
33
33
|
expect(files).toContain('CLAUDE.md');
|
|
34
34
|
expect(files).toContain('.claude/agents/workflow_planner.md');
|
|
35
35
|
expect(files).toContain('.claude/commands/plan_workflow.md');
|
|
36
|
+
// Spot check skill files (all at top level - no nesting)
|
|
37
|
+
expect(files).toContain('.outputai/skills/output-services-check/SKILL.md');
|
|
38
|
+
expect(files).toContain('.outputai/skills/output-workflow-list/SKILL.md');
|
|
39
|
+
expect(files).toContain('.outputai/skills/output-error-zod-import/SKILL.md');
|
|
40
|
+
expect(files).toContain('.claude/skills/output-workflow-trace/SKILL.md');
|
|
41
|
+
expect(files).toContain('.claude/skills/output-workflow-run/SKILL.md');
|
|
42
|
+
expect(files).toContain('.claude/skills/output-error-nondeterminism/SKILL.md');
|
|
36
43
|
});
|
|
37
44
|
it('should include both outputai and claude-code files', () => {
|
|
38
45
|
const files = getRequiredFiles();
|
|
39
46
|
const expectedCount = AGENT_CONFIGS.outputai.mappings.length +
|
|
40
47
|
AGENT_CONFIGS['claude-code'].mappings.length;
|
|
41
48
|
expect(files.length).toBe(expectedCount);
|
|
42
|
-
expect(files.length).toBe(16);
|
|
43
49
|
});
|
|
44
50
|
it('should have outputai files with .outputai prefix', () => {
|
|
45
51
|
const files = getRequiredFiles();
|
|
46
|
-
const outputaiFiles = files.slice(0,
|
|
52
|
+
const outputaiFiles = files.slice(0, 26);
|
|
47
53
|
outputaiFiles.forEach(file => {
|
|
48
54
|
expect(file).toMatch(/^\.outputai\//);
|
|
49
55
|
});
|
|
@@ -78,19 +84,56 @@ describe('coding_agents service', () => {
|
|
|
78
84
|
'.outputai/AGENTS.md',
|
|
79
85
|
'.outputai/agents/workflow_planner.md',
|
|
80
86
|
'.outputai/agents/workflow_quality.md',
|
|
81
|
-
'.outputai/agents/
|
|
82
|
-
'.outputai/agents/
|
|
87
|
+
'.outputai/agents/workflow_context_fetcher.md',
|
|
88
|
+
'.outputai/agents/workflow_prompt_writer.md',
|
|
89
|
+
'.outputai/agents/workflow_debugger.md',
|
|
83
90
|
'.outputai/commands/plan_workflow.md',
|
|
91
|
+
'.outputai/commands/debug_workflow.md',
|
|
84
92
|
'.outputai/commands/build_workflow.md',
|
|
85
93
|
'.outputai/meta/pre_flight.md',
|
|
86
94
|
'.outputai/meta/post_flight.md',
|
|
95
|
+
// Skills (all at top level - no nesting allowed)
|
|
96
|
+
'.outputai/skills/output-services-check/SKILL.md',
|
|
97
|
+
'.outputai/skills/output-workflow-trace/SKILL.md',
|
|
98
|
+
'.outputai/skills/output-workflow-list/SKILL.md',
|
|
99
|
+
'.outputai/skills/output-workflow-runs-list/SKILL.md',
|
|
100
|
+
'.outputai/skills/output-workflow-run/SKILL.md',
|
|
101
|
+
'.outputai/skills/output-workflow-start/SKILL.md',
|
|
102
|
+
'.outputai/skills/output-workflow-status/SKILL.md',
|
|
103
|
+
'.outputai/skills/output-workflow-result/SKILL.md',
|
|
104
|
+
'.outputai/skills/output-workflow-stop/SKILL.md',
|
|
105
|
+
'.outputai/skills/output-error-zod-import/SKILL.md',
|
|
106
|
+
'.outputai/skills/output-error-nondeterminism/SKILL.md',
|
|
107
|
+
'.outputai/skills/output-error-try-catch/SKILL.md',
|
|
108
|
+
'.outputai/skills/output-error-missing-schemas/SKILL.md',
|
|
109
|
+
'.outputai/skills/output-error-direct-io/SKILL.md',
|
|
110
|
+
'.outputai/skills/output-error-http-client/SKILL.md',
|
|
111
|
+
// Claude-code symlinks
|
|
87
112
|
'CLAUDE.md',
|
|
88
113
|
'.claude/agents/workflow_planner.md',
|
|
89
114
|
'.claude/agents/workflow_quality.md',
|
|
90
|
-
'.claude/agents/
|
|
91
|
-
'.claude/agents/
|
|
115
|
+
'.claude/agents/workflow_context_fetcher.md',
|
|
116
|
+
'.claude/agents/workflow_prompt_writer.md',
|
|
117
|
+
'.claude/agents/workflow_debugger.md',
|
|
92
118
|
'.claude/commands/plan_workflow.md',
|
|
93
|
-
'.claude/commands/
|
|
119
|
+
'.claude/commands/debug_workflow.md',
|
|
120
|
+
'.claude/commands/build_workflow.md',
|
|
121
|
+
// Claude-code skill symlinks (all at top level - no nesting allowed)
|
|
122
|
+
'.claude/skills/output-services-check/SKILL.md',
|
|
123
|
+
'.claude/skills/output-workflow-trace/SKILL.md',
|
|
124
|
+
'.claude/skills/output-workflow-list/SKILL.md',
|
|
125
|
+
'.claude/skills/output-workflow-runs-list/SKILL.md',
|
|
126
|
+
'.claude/skills/output-workflow-run/SKILL.md',
|
|
127
|
+
'.claude/skills/output-workflow-start/SKILL.md',
|
|
128
|
+
'.claude/skills/output-workflow-status/SKILL.md',
|
|
129
|
+
'.claude/skills/output-workflow-result/SKILL.md',
|
|
130
|
+
'.claude/skills/output-workflow-stop/SKILL.md',
|
|
131
|
+
'.claude/skills/output-error-zod-import/SKILL.md',
|
|
132
|
+
'.claude/skills/output-error-nondeterminism/SKILL.md',
|
|
133
|
+
'.claude/skills/output-error-try-catch/SKILL.md',
|
|
134
|
+
'.claude/skills/output-error-missing-schemas/SKILL.md',
|
|
135
|
+
'.claude/skills/output-error-direct-io/SKILL.md',
|
|
136
|
+
'.claude/skills/output-error-http-client/SKILL.md'
|
|
94
137
|
],
|
|
95
138
|
isComplete: false
|
|
96
139
|
});
|
|
@@ -104,7 +147,7 @@ describe('coding_agents service', () => {
|
|
|
104
147
|
missingFiles: [],
|
|
105
148
|
isComplete: true
|
|
106
149
|
});
|
|
107
|
-
expect(access).toHaveBeenCalledTimes(
|
|
150
|
+
expect(access).toHaveBeenCalledTimes(51); // dir + 26 outputai + 24 claude-code
|
|
108
151
|
});
|
|
109
152
|
it('should return missing files when some files do not exist', async () => {
|
|
110
153
|
const missingFiles = new Set([
|
|
@@ -180,10 +223,10 @@ describe('coding_agents service', () => {
|
|
|
180
223
|
force: false,
|
|
181
224
|
agentProvider: 'claude-code'
|
|
182
225
|
});
|
|
183
|
-
// Should create outputai files (
|
|
226
|
+
// Should create outputai files (26 templates)
|
|
184
227
|
expect(fs.writeFile).toHaveBeenCalledWith(expect.stringContaining('AGENTS.md'), expect.any(String), 'utf-8');
|
|
185
|
-
// Should create symlinks (
|
|
186
|
-
expect(fs.symlink).toHaveBeenCalledTimes(
|
|
228
|
+
// Should create symlinks (24 symlinks for claude-code)
|
|
229
|
+
expect(fs.symlink).toHaveBeenCalledTimes(24);
|
|
187
230
|
});
|
|
188
231
|
it('should skip existing files when force is false', async () => {
|
|
189
232
|
// Mock some files exist
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow runs service for fetching workflow run data from the API
|
|
3
|
+
*/
|
|
4
|
+
import { type WorkflowRunInfo } from '#api/generated/api.js';
|
|
5
|
+
export type WorkflowRun = WorkflowRunInfo;
|
|
6
|
+
export interface WorkflowRunsResult {
|
|
7
|
+
runs: WorkflowRun[];
|
|
8
|
+
count: number;
|
|
9
|
+
}
|
|
10
|
+
export interface FetchWorkflowRunsOptions {
|
|
11
|
+
workflowType?: string;
|
|
12
|
+
limit?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function fetchWorkflowRuns(options?: FetchWorkflowRunsOptions): Promise<WorkflowRunsResult>;
|