@output.ai/cli 0.7.14 → 0.8.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/dist/api/generated/api.d.ts +38 -4
- package/dist/api/generated/api.js +16 -2
- package/dist/assets/docker/docker-compose-dev.yml +13 -16
- package/dist/commands/init.js +1 -1
- package/dist/commands/workflow/generate.js +1 -1
- package/dist/config.d.ts +14 -6
- package/dist/config.js +17 -9
- package/dist/generated/sdk_versions.json +4 -4
- package/dist/services/claude_client.js +3 -2
- package/dist/services/coding_agents.js +5 -5
- package/dist/services/messages.js +3 -3
- package/dist/services/project_scaffold.js +2 -2
- package/dist/services/project_scaffold.spec.js +2 -2
- package/dist/services/workflow_planner.js +2 -2
- package/dist/templates/agent_instructions/dotoutputai/AGENTS.md.template +4 -4
- package/dist/templates/workflow/README.md.template +5 -5
- package/dist/types/trace.d.ts +1 -1
- package/dist/utils/env_loader.js +2 -1
- package/dist/utils/env_loader.spec.js +1 -1
- package/dist/utils/error_handler.js +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Generated by orval v7.20.0 🍺
|
|
3
3
|
* Do not edit manually.
|
|
4
|
-
* Output.ai
|
|
5
|
-
* API for managing and executing
|
|
4
|
+
* Output.ai API
|
|
5
|
+
* API for managing and executing Output.ai workflows
|
|
6
6
|
* OpenAPI spec version: 1.0.0
|
|
7
7
|
*/
|
|
8
8
|
import { type ApiRequestOptions } from '../http_client.js';
|
|
@@ -155,12 +155,27 @@ export type PostWorkflowRunBody = {
|
|
|
155
155
|
/** (Optional) The max time to wait for the execution, defaults to 30s */
|
|
156
156
|
timeout?: number;
|
|
157
157
|
};
|
|
158
|
+
/**
|
|
159
|
+
* The workflow execution status
|
|
160
|
+
*/
|
|
161
|
+
export type PostWorkflowRun200Status = typeof PostWorkflowRun200Status[keyof typeof PostWorkflowRun200Status];
|
|
162
|
+
export declare const PostWorkflowRun200Status: {
|
|
163
|
+
readonly completed: "completed";
|
|
164
|
+
readonly failed: "failed";
|
|
165
|
+
};
|
|
158
166
|
export type PostWorkflowRun200 = {
|
|
159
167
|
/** The workflow execution id */
|
|
160
168
|
workflowId?: string;
|
|
161
|
-
/** The output of the workflow */
|
|
169
|
+
/** The output of the workflow, null if workflow failed */
|
|
162
170
|
output?: unknown;
|
|
163
171
|
trace?: TraceInfo;
|
|
172
|
+
/** The workflow execution status */
|
|
173
|
+
status?: PostWorkflowRun200Status;
|
|
174
|
+
/**
|
|
175
|
+
* Error message if workflow failed, null otherwise
|
|
176
|
+
* @nullable
|
|
177
|
+
*/
|
|
178
|
+
error?: string | null;
|
|
164
179
|
};
|
|
165
180
|
export type PostWorkflowStartBody = {
|
|
166
181
|
/** The name of the workflow to execute */
|
|
@@ -208,12 +223,31 @@ export type PostWorkflowIdTerminate200 = {
|
|
|
208
223
|
terminated?: boolean;
|
|
209
224
|
workflowId?: string;
|
|
210
225
|
};
|
|
226
|
+
/**
|
|
227
|
+
* The workflow execution status
|
|
228
|
+
*/
|
|
229
|
+
export type GetWorkflowIdResult200Status = typeof GetWorkflowIdResult200Status[keyof typeof GetWorkflowIdResult200Status];
|
|
230
|
+
export declare const GetWorkflowIdResult200Status: {
|
|
231
|
+
readonly completed: "completed";
|
|
232
|
+
readonly failed: "failed";
|
|
233
|
+
readonly canceled: "canceled";
|
|
234
|
+
readonly terminated: "terminated";
|
|
235
|
+
readonly timed_out: "timed_out";
|
|
236
|
+
readonly continued: "continued";
|
|
237
|
+
};
|
|
211
238
|
export type GetWorkflowIdResult200 = {
|
|
212
239
|
/** The workflow execution id */
|
|
213
240
|
workflowId?: string;
|
|
214
|
-
/** The result of workflow */
|
|
241
|
+
/** The result of workflow, null if workflow failed */
|
|
215
242
|
output?: unknown;
|
|
216
243
|
trace?: TraceInfo;
|
|
244
|
+
/** The workflow execution status */
|
|
245
|
+
status?: GetWorkflowIdResult200Status;
|
|
246
|
+
/**
|
|
247
|
+
* Error message if workflow failed, null otherwise
|
|
248
|
+
* @nullable
|
|
249
|
+
*/
|
|
250
|
+
error?: string | null;
|
|
217
251
|
};
|
|
218
252
|
export type GetWorkflowIdTraceLog200 = TraceLogRemoteResponse | TraceLogLocalResponse;
|
|
219
253
|
export type GetWorkflowIdTraceLog404 = {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Generated by orval v7.20.0 🍺
|
|
3
3
|
* Do not edit manually.
|
|
4
|
-
* Output.ai
|
|
5
|
-
* API for managing and executing
|
|
4
|
+
* Output.ai API
|
|
5
|
+
* API for managing and executing Output.ai workflows
|
|
6
6
|
* OpenAPI spec version: 1.0.0
|
|
7
7
|
*/
|
|
8
8
|
import { customFetchInstance } from '../http_client.js';
|
|
@@ -25,6 +25,11 @@ export const WorkflowRunInfoStatus = {
|
|
|
25
25
|
continued: 'continued',
|
|
26
26
|
};
|
|
27
27
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
28
|
+
export const PostWorkflowRun200Status = {
|
|
29
|
+
completed: 'completed',
|
|
30
|
+
failed: 'failed',
|
|
31
|
+
};
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
28
33
|
export const GetWorkflowIdStatus200Status = {
|
|
29
34
|
canceled: 'canceled',
|
|
30
35
|
completed: 'completed',
|
|
@@ -35,6 +40,15 @@ export const GetWorkflowIdStatus200Status = {
|
|
|
35
40
|
timed_out: 'timed_out',
|
|
36
41
|
unspecified: 'unspecified',
|
|
37
42
|
};
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
44
|
+
export const GetWorkflowIdResult200Status = {
|
|
45
|
+
completed: 'completed',
|
|
46
|
+
failed: 'failed',
|
|
47
|
+
canceled: 'canceled',
|
|
48
|
+
terminated: 'terminated',
|
|
49
|
+
timed_out: 'timed_out',
|
|
50
|
+
continued: 'continued',
|
|
51
|
+
};
|
|
38
52
|
;
|
|
39
53
|
export const getGetHealthUrl = () => {
|
|
40
54
|
return `/health`;
|
|
@@ -85,13 +85,13 @@ services:
|
|
|
85
85
|
- main
|
|
86
86
|
env_file: ./.env
|
|
87
87
|
environment:
|
|
88
|
-
- PORT=3001
|
|
89
|
-
- CATALOG_ID=${CATALOG_ID:-main}
|
|
90
|
-
- TEMPORAL_ADDRESS=temporal:7233
|
|
91
88
|
- NODE_ENV=development
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
89
|
+
- OUTPUT_API_PORT=3001
|
|
90
|
+
- OUTPUT_CATALOG_ID=${OUTPUT_CATALOG_ID:-main}
|
|
91
|
+
- OUTPUT_AWS_REGION=${AWS_REGION:-us-west-1}
|
|
92
|
+
- OUTPUT_AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-}
|
|
93
|
+
- OUTPUT_AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-}
|
|
94
|
+
- TEMPORAL_ADDRESS=temporal:7233
|
|
95
95
|
ports:
|
|
96
96
|
- '3001:3001'
|
|
97
97
|
|
|
@@ -105,17 +105,14 @@ services:
|
|
|
105
105
|
- main
|
|
106
106
|
env_file: ./.env
|
|
107
107
|
environment:
|
|
108
|
-
-
|
|
109
|
-
-
|
|
110
|
-
-
|
|
108
|
+
- NODE_ENV=development
|
|
109
|
+
- OUTPUT_CATALOG_ID=${OUTPUT_CATALOG_ID:-main}
|
|
110
|
+
- OUTPUT_REDIS_URL=redis://redis:6379
|
|
111
|
+
- OUTPUT_TRACE_LOCAL_ON=${OUTPUT_TRACE_LOCAL_ON:-true}
|
|
112
|
+
- OUTPUT_TRACE_HOST_PATH=${PWD}/logs
|
|
113
|
+
- OUTPUT_TRACE_HTTP_VERBOSE=${OUTPUT_TRACE_HTTP_VERBOSE:-true}
|
|
111
114
|
- TEMPORAL_ADDRESS=temporal:7233
|
|
112
|
-
-
|
|
113
|
-
- TRACE_REMOTE_ON=${TRACE_REMOTE_ON:-}
|
|
114
|
-
- TRACE_REMOTE_S3_BUCKET=${TRACE_REMOTE_S3_BUCKET:-}
|
|
115
|
-
- HOST_TRACE_PATH=${PWD}/logs
|
|
116
|
-
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-}
|
|
117
|
-
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-}
|
|
118
|
-
- AWS_REGION=${AWS_REGION:-us-west-1}
|
|
115
|
+
- NODE_OPTIONS=${NODE_OPTIONS:---max-old-space-size=4096}
|
|
119
116
|
command: >
|
|
120
117
|
sh -c "
|
|
121
118
|
npm run output:worker:install &&
|
package/dist/commands/init.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Args, Command, Flags } from '@oclif/core';
|
|
|
2
2
|
import { UserCancelledError } from '#types/errors.js';
|
|
3
3
|
import { runInit } from '#services/project_scaffold.js';
|
|
4
4
|
export default class Init extends Command {
|
|
5
|
-
static description = 'Initialize a new Output
|
|
5
|
+
static description = 'Initialize a new Output project by scaffolding the complete project structure';
|
|
6
6
|
static examples = [
|
|
7
7
|
'<%= config.bin %> <%= command.id %>',
|
|
8
8
|
'<%= config.bin %> <%= command.id %> my-workflow-project'
|
|
@@ -6,7 +6,7 @@ import { getWorkflowGenerateSuccessMessage } from '#services/messages.js';
|
|
|
6
6
|
import { DEFAULT_OUTPUT_DIRS } from '#utils/paths.js';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
export default class Generate extends Command {
|
|
9
|
-
static description = 'Generate a new Output
|
|
9
|
+
static description = 'Generate a new Output workflow';
|
|
10
10
|
static examples = [
|
|
11
11
|
'<%= config.bin %> <%= command.id %> my-workflow',
|
|
12
12
|
'<%= config.bin %> <%= command.id %> my-workflow --skeleton',
|
package/dist/config.d.ts
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
export declare const config: {
|
|
5
5
|
/**
|
|
6
6
|
* Base URL for the Output.ai API server
|
|
7
|
-
* Can be overridden with
|
|
7
|
+
* Can be overridden with OUTPUT_API_URL environment variable
|
|
8
8
|
*/
|
|
9
9
|
apiUrl: string;
|
|
10
10
|
/**
|
|
11
11
|
* API authentication token
|
|
12
|
-
* Set via
|
|
12
|
+
* Set via OUTPUT_API_AUTH_TOKEN environment variable
|
|
13
13
|
*/
|
|
14
14
|
apiToken: string | undefined;
|
|
15
15
|
/**
|
|
@@ -21,8 +21,16 @@ export declare const config: {
|
|
|
21
21
|
* Can be overridden with DOCKER_SERVICE_NAME environment variable
|
|
22
22
|
*/
|
|
23
23
|
dockerServiceName: string;
|
|
24
|
+
/**
|
|
25
|
+
* Set the debug mode
|
|
26
|
+
*/
|
|
27
|
+
debugMode: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Where the env vars are stored, defaults to `.env`
|
|
30
|
+
*/
|
|
31
|
+
envFile: string;
|
|
32
|
+
/**
|
|
33
|
+
* Agent configuration directory name
|
|
34
|
+
*/
|
|
35
|
+
agentConfigDir: string;
|
|
24
36
|
};
|
|
25
|
-
/**
|
|
26
|
-
* Agent configuration directory name
|
|
27
|
-
*/
|
|
28
|
-
export declare const AGENT_CONFIG_DIR = ".outputai";
|
package/dist/config.js
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
export const config = {
|
|
5
5
|
/**
|
|
6
6
|
* Base URL for the Output.ai API server
|
|
7
|
-
* Can be overridden with
|
|
7
|
+
* Can be overridden with OUTPUT_API_URL environment variable
|
|
8
8
|
*/
|
|
9
|
-
apiUrl: process.env.
|
|
9
|
+
apiUrl: process.env.OUTPUT_API_URL || 'http://localhost:3001',
|
|
10
10
|
/**
|
|
11
11
|
* API authentication token
|
|
12
|
-
* Set via
|
|
12
|
+
* Set via OUTPUT_API_AUTH_TOKEN environment variable
|
|
13
13
|
*/
|
|
14
|
-
apiToken: process.env.
|
|
14
|
+
apiToken: process.env.OUTPUT_API_AUTH_TOKEN,
|
|
15
15
|
/**
|
|
16
16
|
* Default timeout for API requests (in milliseconds)
|
|
17
17
|
*/
|
|
@@ -20,9 +20,17 @@ export const config = {
|
|
|
20
20
|
* Docker Compose project name
|
|
21
21
|
* Can be overridden with DOCKER_SERVICE_NAME environment variable
|
|
22
22
|
*/
|
|
23
|
-
dockerServiceName: process.env.DOCKER_SERVICE_NAME || 'output-sdk'
|
|
23
|
+
dockerServiceName: process.env.DOCKER_SERVICE_NAME || 'output-sdk',
|
|
24
|
+
/**
|
|
25
|
+
* Set the debug mode
|
|
26
|
+
*/
|
|
27
|
+
debugMode: process.env.OUTPUT_DEBUG === 'true',
|
|
28
|
+
/**
|
|
29
|
+
* Where the env vars are stored, defaults to `.env`
|
|
30
|
+
*/
|
|
31
|
+
envFile: process.env.OUTPUT_CLI_ENV || '.env',
|
|
32
|
+
/**
|
|
33
|
+
* Agent configuration directory name
|
|
34
|
+
*/
|
|
35
|
+
agentConfigDir: '.outputai'
|
|
24
36
|
};
|
|
25
|
-
/**
|
|
26
|
-
* Agent configuration directory name
|
|
27
|
-
*/
|
|
28
|
-
export const AGENT_CONFIG_DIR = '.outputai';
|
|
@@ -5,6 +5,7 @@ import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
|
5
5
|
import { ux } from '@oclif/core';
|
|
6
6
|
import * as cliProgress from 'cli-progress';
|
|
7
7
|
import { getErrorMessage, toError } from '#utils/error_utils.js';
|
|
8
|
+
import { config } from '#config.js';
|
|
8
9
|
const ADDITIONAL_INSTRUCTIONS = `
|
|
9
10
|
! IMPORTANT !
|
|
10
11
|
1. Use TodoWrite to track your progress through plan creation.
|
|
@@ -29,7 +30,7 @@ const ADDITIONAL_INSTRUCTIONS_BUILD = `
|
|
|
29
30
|
|
|
30
31
|
2. Follow the implementation plan exactly as specified in the plan file.
|
|
31
32
|
|
|
32
|
-
3. Implement all workflow files following Output
|
|
33
|
+
3. Implement all workflow files following Output.ai patterns and best practices.
|
|
33
34
|
|
|
34
35
|
4. After you mark all todos as complete, provide a summary of what was implemented.
|
|
35
36
|
`;
|
|
@@ -143,7 +144,7 @@ function getProgressUpdate(message) {
|
|
|
143
144
|
};
|
|
144
145
|
}
|
|
145
146
|
function debugMessage(message) {
|
|
146
|
-
if (
|
|
147
|
+
if (!config.debugMode) {
|
|
147
148
|
return;
|
|
148
149
|
}
|
|
149
150
|
ux.stdout(ux.colorize('teal', `[Message]: ${message.type}`));
|
|
@@ -8,7 +8,7 @@ import path from 'node:path';
|
|
|
8
8
|
import { join } from 'node:path';
|
|
9
9
|
import { ux } from '@oclif/core';
|
|
10
10
|
import { confirm } from '@inquirer/prompts';
|
|
11
|
-
import {
|
|
11
|
+
import { config } from '#config.js';
|
|
12
12
|
import { getTemplateDir } from '#utils/paths.js';
|
|
13
13
|
import { executeClaudeCommand } from '#utils/claude.js';
|
|
14
14
|
import { processTemplate } from '#utils/template.js';
|
|
@@ -18,7 +18,7 @@ const EXPECTED_MARKETPLACE_REPO = 'growthxai/output-claude-plugins';
|
|
|
18
18
|
* Get the full path to the agent configuration directory
|
|
19
19
|
*/
|
|
20
20
|
export function getAgentConfigDir(projectRoot) {
|
|
21
|
-
return join(projectRoot,
|
|
21
|
+
return join(projectRoot, config.agentConfigDir);
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* Check if .outputai directory exists
|
|
@@ -157,14 +157,14 @@ async function createSymlink(source, target, projectRoot) {
|
|
|
157
157
|
* Create .outputai/AGENTS.md file from template
|
|
158
158
|
*/
|
|
159
159
|
async function createAgentsMdFile(projectRoot, force, variables) {
|
|
160
|
-
const outputaiDir = join(projectRoot,
|
|
160
|
+
const outputaiDir = join(projectRoot, config.agentConfigDir);
|
|
161
161
|
await ensureDirectoryExists(outputaiDir);
|
|
162
162
|
const agentsMdPath = join(outputaiDir, 'AGENTS.md');
|
|
163
163
|
if (force || !await fileExists(agentsMdPath)) {
|
|
164
164
|
await createFromTemplate('dotoutputai/AGENTS.md.template', agentsMdPath, variables);
|
|
165
165
|
}
|
|
166
166
|
else {
|
|
167
|
-
ux.warn(`File already exists: ${
|
|
167
|
+
ux.warn(`File already exists: ${config.agentConfigDir}/AGENTS.md (use --force to overwrite)`);
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
/**
|
|
@@ -188,7 +188,7 @@ async function createSettingsFile(projectRoot, force) {
|
|
|
188
188
|
async function createClaudeMdSymlink(projectRoot, force) {
|
|
189
189
|
const claudeMdPath = join(projectRoot, 'CLAUDE.md');
|
|
190
190
|
if (force || !await fileExists(claudeMdPath)) {
|
|
191
|
-
await createSymlink(`${
|
|
191
|
+
await createSymlink(`${config.agentConfigDir}/AGENTS.md`, claudeMdPath, projectRoot);
|
|
192
192
|
}
|
|
193
193
|
else {
|
|
194
194
|
ux.warn('File already exists: CLAUDE.md (use --force to overwrite)');
|
|
@@ -199,14 +199,14 @@ ${createOutputBanner()}
|
|
|
199
199
|
|
|
200
200
|
${divider}
|
|
201
201
|
|
|
202
|
-
${ux.colorize('bold', ux.colorize('green', '🎉 SUCCESS!'))} ${ux.colorize('bold', 'Your Output
|
|
202
|
+
${ux.colorize('bold', ux.colorize('green', '🎉 SUCCESS!'))} ${ux.colorize('bold', 'Your Output project has been created')}
|
|
203
203
|
|
|
204
204
|
${divider}
|
|
205
205
|
|
|
206
206
|
${createSectionHeader('PROJECT DETAILS', '📁')}
|
|
207
207
|
|
|
208
208
|
${bulletPoint} ${ux.colorize('white', 'Name:')} ${formatPath(folderName)}
|
|
209
|
-
${bulletPoint} ${ux.colorize('white', 'Type:')} Output
|
|
209
|
+
${bulletPoint} ${ux.colorize('white', 'Type:')} Output Project
|
|
210
210
|
${bulletPoint} ${ux.colorize('white', 'Structure:')} ${formatPath('.outputai/')} (agents), ${formatPath('workflows/')} (implementations)
|
|
211
211
|
|
|
212
212
|
${divider}
|
|
@@ -229,7 +229,7 @@ ${divider}
|
|
|
229
229
|
${ux.colorize('dim', '💡 Tip: Use ')}${formatCommand('npx output workflow plan')}${ux.colorize('dim', ' to design your first custom workflow')}
|
|
230
230
|
${ux.colorize('dim', ' with AI assistance.')}
|
|
231
231
|
|
|
232
|
-
${ux.colorize('green', ux.colorize('bold', 'Happy building with Output
|
|
232
|
+
${ux.colorize('green', ux.colorize('bold', 'Happy building with Output! 🚀'))}
|
|
233
233
|
`;
|
|
234
234
|
};
|
|
235
235
|
export const getWorkflowGenerateSuccessMessage = (workflowName, targetDir, filesCreated) => {
|
|
@@ -62,7 +62,7 @@ const promptForProjectName = async (defaultProjectName) => {
|
|
|
62
62
|
}) || defaultProjectName;
|
|
63
63
|
};
|
|
64
64
|
const generateProjectDescription = (projectName) => {
|
|
65
|
-
return `
|
|
65
|
+
return `AI Agents & Workflows built with Output.ai for ${kebabCase(projectName)}`;
|
|
66
66
|
};
|
|
67
67
|
/**
|
|
68
68
|
* Get project configuration from user input
|
|
@@ -98,7 +98,7 @@ async function scaffoldProjectFiles(projectPath, projectName, description) {
|
|
|
98
98
|
const templateVars = {
|
|
99
99
|
projectName: kebabCase(projectName),
|
|
100
100
|
ProjectName: pascalCase(projectName),
|
|
101
|
-
description: description || `An Output
|
|
101
|
+
description: description || `An Output.ai workflow for ${projectName}`,
|
|
102
102
|
coreVersion: sdkVersions.core,
|
|
103
103
|
llmVersion: sdkVersions.llm,
|
|
104
104
|
httpVersion: sdkVersions.http,
|
|
@@ -48,7 +48,7 @@ describe('project_scaffold', () => {
|
|
|
48
48
|
});
|
|
49
49
|
it('should auto-generate description when folderName provided', async () => {
|
|
50
50
|
const config = await getProjectConfig('test-folder');
|
|
51
|
-
expect(config.description).toBe('
|
|
51
|
+
expect(config.description).toBe('AI Agents & Workflows built with Output.ai for test-folder');
|
|
52
52
|
});
|
|
53
53
|
it('should prompt for project name and folder name when not provided', async () => {
|
|
54
54
|
const { input } = await import('@inquirer/prompts');
|
|
@@ -58,7 +58,7 @@ describe('project_scaffold', () => {
|
|
|
58
58
|
const config = await getProjectConfig();
|
|
59
59
|
expect(config.projectName).toBe('Test Project');
|
|
60
60
|
expect(config.folderName).toBe('test-project');
|
|
61
|
-
expect(config.description).toBe('
|
|
61
|
+
expect(config.description).toBe('AI Agents & Workflows built with Output.ai for test-project');
|
|
62
62
|
expect(input).toHaveBeenCalledTimes(2);
|
|
63
63
|
});
|
|
64
64
|
});
|
|
@@ -2,7 +2,7 @@ import { initializeAgentConfig } from './coding_agents.js';
|
|
|
2
2
|
import { generateText } from '@output.ai/llm';
|
|
3
3
|
import fs from 'node:fs/promises';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import {
|
|
5
|
+
import { config } from '#config.js';
|
|
6
6
|
export async function generatePlanName(description, date = new Date()) {
|
|
7
7
|
const year = date.getFullYear();
|
|
8
8
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
@@ -29,7 +29,7 @@ export async function generatePlanName(description, date = new Date()) {
|
|
|
29
29
|
* @returns Full path to the created PLAN.md file
|
|
30
30
|
*/
|
|
31
31
|
export async function writePlanFile(planName, content, projectRoot) {
|
|
32
|
-
const planDir = path.join(projectRoot,
|
|
32
|
+
const planDir = path.join(projectRoot, config.agentConfigDir, 'plans', planName);
|
|
33
33
|
const planFilePath = path.join(planDir, 'PLAN.md');
|
|
34
34
|
await fs.mkdir(planDir, { recursive: true });
|
|
35
35
|
await fs.writeFile(planFilePath, content, 'utf-8');
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
This project uses Output.ai Framework to build
|
|
5
|
+
This project uses Output.ai Framework to build production-ready AI applications with built-in prompt management, evaluation, observability, and error handling. Developers use it to build AI features like fact checkers, content generators, data extractors, research assistants, and multi-step agents.
|
|
6
6
|
|
|
7
7
|
### Project Overview
|
|
8
8
|
|
|
9
|
-
Each workflow lives in its own folder under `src/workflows/` and follows a consistent structure. Workflows define the orchestration logic, calling steps to perform external operations like API calls, database queries, and LLM inference. The
|
|
9
|
+
Each workflow lives in its own folder under `src/workflows/` and follows a consistent structure. Workflows define the orchestration logic, calling steps to perform external operations like API calls, database queries, and LLM inference. The framework automatically handles retries, timeouts, and reliable execution.
|
|
10
10
|
|
|
11
11
|
### Key Concepts
|
|
12
12
|
|
|
13
|
-
####
|
|
13
|
+
#### Durable Execution powered by Temporal.io
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Output provides durable execution guarantees (built on Temporal.io) - if execution fails mid-run, it resumes from the last successful step rather than restarting. The framework provides high-level abstractions (`workflow`, `step`, `evaluator`) that enforce best practices and provide automatic tracing.
|
|
16
16
|
|
|
17
17
|
#### Single Folder Project Structure
|
|
18
18
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
This
|
|
7
|
+
This was generated using the Output.ai CLI. It provides a starting point for building AI applications with production-ready LLM integration, built-in prompt management, evaluation, and observability.
|
|
8
8
|
|
|
9
9
|
## Files
|
|
10
10
|
|
|
@@ -41,7 +41,7 @@ workflow/
|
|
|
41
41
|
|
|
42
42
|
## Import Rules
|
|
43
43
|
|
|
44
|
-
**Important:** Steps and evaluators are
|
|
44
|
+
**Important:** Steps and evaluators are isolated execution units that cannot call each other.
|
|
45
45
|
|
|
46
46
|
**Steps can import from:**
|
|
47
47
|
- Local utilities (`./utils.ts`, `./utils/*.ts`)
|
|
@@ -105,7 +105,7 @@ Example:
|
|
|
105
105
|
|
|
106
106
|
### Workflow Structure
|
|
107
107
|
|
|
108
|
-
The workflow follows the Output
|
|
108
|
+
The workflow follows the Output.ai conventions:
|
|
109
109
|
|
|
110
110
|
```typescript
|
|
111
111
|
import { workflow, z } from '@output.ai/core';
|
|
@@ -221,7 +221,7 @@ To test your workflow:
|
|
|
221
221
|
|
|
222
222
|
1. Build the parent project containing this workflow
|
|
223
223
|
2. Start the Output worker
|
|
224
|
-
3. Execute the workflow using the Output
|
|
224
|
+
3. Execute the workflow using the Output.ai API
|
|
225
225
|
|
|
226
226
|
Example execution:
|
|
227
227
|
```bash
|
|
@@ -230,5 +230,5 @@ npx output workflow run {{workflowName}} --input '{"prompt": "Hello"}'
|
|
|
230
230
|
|
|
231
231
|
## Resources
|
|
232
232
|
|
|
233
|
-
- [Output
|
|
233
|
+
- [Output.ai Documentation](https://docs.output.ai)
|
|
234
234
|
- [Temporal Documentation](https://docs.temporal.io)
|
package/dist/types/trace.d.ts
CHANGED
|
@@ -107,7 +107,7 @@ export interface TraceStructure {
|
|
|
107
107
|
children?: DebugNode[];
|
|
108
108
|
}
|
|
109
109
|
/**
|
|
110
|
-
* The structure of a workflow trace file generated by Output
|
|
110
|
+
* The structure of a workflow trace file generated by Output.ai workflow runs.
|
|
111
111
|
* This file is written to the local filesystem during workflow execution and contains
|
|
112
112
|
* the complete execution history including timing, inputs, outputs, and any errors.
|
|
113
113
|
*/
|
package/dist/utils/env_loader.js
CHANGED
|
@@ -7,10 +7,11 @@ import { existsSync } from 'node:fs';
|
|
|
7
7
|
import { resolve } from 'node:path';
|
|
8
8
|
import * as dotenv from 'dotenv';
|
|
9
9
|
import debugFactory from 'debug';
|
|
10
|
+
import { config } from '#config.js';
|
|
10
11
|
const debug = debugFactory('output-cli:env-loader');
|
|
11
12
|
export function loadEnvironment() {
|
|
12
13
|
const cwd = process.cwd();
|
|
13
|
-
const envFile =
|
|
14
|
+
const envFile = config.envFile;
|
|
14
15
|
const envPath = resolve(cwd, envFile);
|
|
15
16
|
if (!existsSync(envPath)) {
|
|
16
17
|
debug(`Warning: Env file not found: ${envPath}`);
|
|
@@ -25,7 +25,7 @@ describe('loadEnvironment', () => {
|
|
|
25
25
|
process.env.OUTPUT_CLI_ENV = '.env.prod';
|
|
26
26
|
const expectedPath = resolve(mockCwd, '.env.prod');
|
|
27
27
|
vi.mocked(existsSync).mockReturnValue(true);
|
|
28
|
-
vi.mocked(dotenv.config).mockReturnValue({ parsed: {
|
|
28
|
+
vi.mocked(dotenv.config).mockReturnValue({ parsed: { OUTPUT_API_URL: 'https://prod.api.com' } });
|
|
29
29
|
const { loadEnvironment } = await import('./env_loader.js');
|
|
30
30
|
loadEnvironment();
|
|
31
31
|
expect(dotenv.config).toHaveBeenCalledWith({ path: expectedPath });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { config } from '#config.js';
|
|
2
2
|
const DEFAULT_MESSAGES = {
|
|
3
3
|
ECONNREFUSED: `Connection refused to ${config.apiUrl}. Is the API server running?`,
|
|
4
|
-
401: 'Authentication failed. Check your
|
|
4
|
+
401: 'Authentication failed. Check your OUTPUT_API_AUTH_TOKEN.',
|
|
5
5
|
404: 'Resource not found.',
|
|
6
6
|
500: 'Server error.',
|
|
7
7
|
UNKNOWN: 'An unknown error occurred.'
|