@output.ai/cli 0.5.6 → 0.6.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/commands/agents/init.d.ts +0 -1
- package/dist/commands/agents/init.js +9 -16
- package/dist/commands/agents/init.spec.js +49 -224
- package/dist/commands/workflow/generate.js +2 -2
- package/dist/commands/workflow/plan.js +3 -3
- package/dist/commands/workflow/plan.spec.js +13 -13
- package/dist/services/claude_client.d.ts +4 -4
- package/dist/services/claude_client.integration.test.js +2 -2
- package/dist/services/claude_client.js +7 -7
- package/dist/services/claude_client.spec.js +3 -3
- package/dist/services/coding_agents.d.ts +10 -24
- package/dist/services/coding_agents.js +112 -368
- package/dist/services/coding_agents.spec.js +101 -290
- package/dist/services/project_scaffold.js +3 -3
- package/dist/services/workflow_builder.d.ts +1 -1
- package/dist/services/workflow_builder.js +1 -1
- package/dist/services/workflow_planner.js +1 -2
- package/dist/services/workflow_planner.spec.js +4 -5
- package/dist/templates/agent_instructions/dotclaude/settings.json.template +29 -0
- package/dist/templates/agent_instructions/{AGENTS.md.template → dotoutputai/AGENTS.md.template} +12 -10
- package/dist/utils/claude.d.ts +5 -0
- package/dist/utils/claude.js +19 -0
- package/dist/utils/claude.spec.d.ts +1 -0
- package/dist/utils/claude.spec.js +119 -0
- package/dist/utils/paths.d.ts +0 -4
- package/dist/utils/paths.js +0 -6
- package/package.json +3 -3
- package/dist/templates/agent_instructions/agents/workflow_context_fetcher.md.template +0 -82
- package/dist/templates/agent_instructions/agents/workflow_debugger.md.template +0 -98
- package/dist/templates/agent_instructions/agents/workflow_planner.md.template +0 -113
- package/dist/templates/agent_instructions/agents/workflow_prompt_writer.md.template +0 -595
- package/dist/templates/agent_instructions/agents/workflow_quality.md.template +0 -244
- package/dist/templates/agent_instructions/commands/build_workflow.md.template +0 -290
- package/dist/templates/agent_instructions/commands/debug_workflow.md.template +0 -198
- package/dist/templates/agent_instructions/commands/plan_workflow.md.template +0 -261
- package/dist/templates/agent_instructions/meta/post_flight.md.template +0 -94
- package/dist/templates/agent_instructions/meta/pre_flight.md.template +0 -60
- package/dist/templates/agent_instructions/skills/output-error-direct-io/SKILL.md.template +0 -249
- package/dist/templates/agent_instructions/skills/output-error-http-client/SKILL.md.template +0 -298
- package/dist/templates/agent_instructions/skills/output-error-missing-schemas/SKILL.md.template +0 -265
- package/dist/templates/agent_instructions/skills/output-error-nondeterminism/SKILL.md.template +0 -252
- package/dist/templates/agent_instructions/skills/output-error-try-catch/SKILL.md.template +0 -226
- package/dist/templates/agent_instructions/skills/output-error-zod-import/SKILL.md.template +0 -209
- package/dist/templates/agent_instructions/skills/output-services-check/SKILL.md.template +0 -128
- package/dist/templates/agent_instructions/skills/output-workflow-list/SKILL.md.template +0 -117
- package/dist/templates/agent_instructions/skills/output-workflow-result/SKILL.md.template +0 -199
- package/dist/templates/agent_instructions/skills/output-workflow-run/SKILL.md.template +0 -228
- package/dist/templates/agent_instructions/skills/output-workflow-runs-list/SKILL.md.template +0 -141
- package/dist/templates/agent_instructions/skills/output-workflow-start/SKILL.md.template +0 -201
- package/dist/templates/agent_instructions/skills/output-workflow-status/SKILL.md.template +0 -151
- package/dist/templates/agent_instructions/skills/output-workflow-stop/SKILL.md.template +0 -164
- package/dist/templates/agent_instructions/skills/output-workflow-trace/SKILL.md.template +0 -134
|
@@ -13,7 +13,7 @@ describe('invokePlanWorkflow', () => {
|
|
|
13
13
|
// Clean up environment variables
|
|
14
14
|
delete process.env.ANTHROPIC_API_KEY;
|
|
15
15
|
});
|
|
16
|
-
it('should invoke /plan_workflow slash command with settingSources', async () => {
|
|
16
|
+
it('should invoke /outputai:plan_workflow slash command with settingSources', async () => {
|
|
17
17
|
const { query } = await import('@anthropic-ai/claude-agent-sdk');
|
|
18
18
|
process.env.ANTHROPIC_API_KEY = 'test-key';
|
|
19
19
|
async function* mockIterator() {
|
|
@@ -22,7 +22,7 @@ describe('invokePlanWorkflow', () => {
|
|
|
22
22
|
vi.mocked(query).mockReturnValue(mockIterator());
|
|
23
23
|
await invokePlanWorkflow('Test workflow');
|
|
24
24
|
const calls = vi.mocked(query).mock.calls;
|
|
25
|
-
expect(calls[0]?.[0]?.prompt).toContain('/plan_workflow Test workflow');
|
|
25
|
+
expect(calls[0]?.[0]?.prompt).toContain('/outputai:plan_workflow Test workflow');
|
|
26
26
|
expect(calls[0]?.[0]?.options?.settingSources).toEqual(['user', 'project', 'local']);
|
|
27
27
|
expect(calls[0]?.[0]?.options?.allowedTools).toEqual(['Read', 'Grep', 'WebSearch', 'WebFetch', 'TodoWrite']);
|
|
28
28
|
});
|
|
@@ -36,7 +36,7 @@ describe('invokePlanWorkflow', () => {
|
|
|
36
36
|
const description = 'Build a user authentication system';
|
|
37
37
|
await invokePlanWorkflow(description);
|
|
38
38
|
const calls = vi.mocked(query).mock.calls;
|
|
39
|
-
expect(calls[0]?.[0]?.prompt).toContain(`/plan_workflow ${description}`);
|
|
39
|
+
expect(calls[0]?.[0]?.prompt).toContain(`/outputai:plan_workflow ${description}`);
|
|
40
40
|
expect(calls[0]?.[0]?.options?.settingSources).toEqual(['user', 'project', 'local']);
|
|
41
41
|
});
|
|
42
42
|
it('should return plan output from claude-code', async () => {
|
|
@@ -1,28 +1,11 @@
|
|
|
1
|
-
export interface FileMapping {
|
|
2
|
-
from: string;
|
|
3
|
-
to: string;
|
|
4
|
-
type: 'template' | 'symlink' | 'copy';
|
|
5
|
-
}
|
|
6
|
-
export interface AgentSystemConfig {
|
|
7
|
-
id: string;
|
|
8
|
-
name: string;
|
|
9
|
-
mappings: FileMapping[];
|
|
10
|
-
}
|
|
11
1
|
export interface StructureCheckResult {
|
|
12
|
-
dirExists: boolean;
|
|
13
|
-
missingFiles: string[];
|
|
14
2
|
isComplete: boolean;
|
|
3
|
+
needsInit: boolean;
|
|
15
4
|
}
|
|
16
5
|
export interface InitOptions {
|
|
17
6
|
projectRoot: string;
|
|
18
7
|
force: boolean;
|
|
19
|
-
agentProvider: string;
|
|
20
8
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Agent configuration mappings for different providers
|
|
23
|
-
*/
|
|
24
|
-
export declare const AGENT_CONFIGS: Record<string, AgentSystemConfig>;
|
|
25
|
-
export declare function getRequiredFiles(): string[];
|
|
26
9
|
/**
|
|
27
10
|
* Get the full path to the agent configuration directory
|
|
28
11
|
*/
|
|
@@ -37,14 +20,17 @@ export declare function checkAgentStructure(projectRoot: string): Promise<Struct
|
|
|
37
20
|
*/
|
|
38
21
|
export declare function prepareTemplateVariables(): Record<string, string>;
|
|
39
22
|
/**
|
|
40
|
-
* Initialize agent configuration files
|
|
41
|
-
*
|
|
23
|
+
* Initialize agent configuration files and register Claude Code plugin
|
|
24
|
+
* Creates 3 files:
|
|
25
|
+
* - .outputai/AGENTS.md (from template with Handlebars processing)
|
|
26
|
+
* - .claude/settings.json (static JSON)
|
|
27
|
+
* - CLAUDE.md symlink to .outputai/AGENTS.md
|
|
28
|
+
* Then runs Claude CLI commands to register the plugin marketplace and install the plugin
|
|
42
29
|
*/
|
|
43
30
|
export declare function initializeAgentConfig(options: InitOptions): Promise<void>;
|
|
44
31
|
/**
|
|
45
|
-
* Ensure
|
|
46
|
-
*
|
|
32
|
+
* Ensure OutputAI system is initialized by invoking agents init if needed
|
|
33
|
+
* Creates configuration files and registers Claude Code plugin
|
|
47
34
|
* @param projectRoot - Root directory of the project
|
|
48
|
-
* @throws Error if user declines to initialize or if initialization fails
|
|
49
35
|
*/
|
|
50
|
-
export declare function
|
|
36
|
+
export declare function ensureOutputAISystem(projectRoot: string): Promise<void>;
|
|
@@ -7,284 +7,11 @@ import { access } from 'node:fs/promises';
|
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { join } from 'node:path';
|
|
9
9
|
import { ux } from '@oclif/core';
|
|
10
|
-
import { confirm } from '@inquirer/prompts';
|
|
11
10
|
import { AGENT_CONFIG_DIR } from '#config.js';
|
|
12
11
|
import { getTemplateDir } from '#utils/paths.js';
|
|
12
|
+
import { executeClaudeCommand } from '#utils/claude.js';
|
|
13
13
|
import { processTemplate } from '#utils/template.js';
|
|
14
|
-
|
|
15
|
-
* Agent configuration mappings for different providers
|
|
16
|
-
*/
|
|
17
|
-
export const AGENT_CONFIGS = {
|
|
18
|
-
outputai: {
|
|
19
|
-
id: 'outputai',
|
|
20
|
-
name: 'OutputAI Core Files',
|
|
21
|
-
mappings: [
|
|
22
|
-
{
|
|
23
|
-
type: 'template',
|
|
24
|
-
from: 'AGENTS.md.template',
|
|
25
|
-
to: `${AGENT_CONFIG_DIR}/AGENTS.md`
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
type: 'template',
|
|
29
|
-
from: 'agents/workflow_planner.md.template',
|
|
30
|
-
to: `${AGENT_CONFIG_DIR}/agents/workflow_planner.md`
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
type: 'template',
|
|
34
|
-
from: 'agents/workflow_quality.md.template',
|
|
35
|
-
to: `${AGENT_CONFIG_DIR}/agents/workflow_quality.md`
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
type: 'template',
|
|
39
|
-
from: 'agents/workflow_context_fetcher.md.template',
|
|
40
|
-
to: `${AGENT_CONFIG_DIR}/agents/workflow_context_fetcher.md`
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
type: 'template',
|
|
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`
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
type: 'template',
|
|
54
|
-
from: 'commands/plan_workflow.md.template',
|
|
55
|
-
to: `${AGENT_CONFIG_DIR}/commands/plan_workflow.md`
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
type: 'template',
|
|
59
|
-
from: 'commands/debug_workflow.md.template',
|
|
60
|
-
to: `${AGENT_CONFIG_DIR}/commands/debug_workflow.md`
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
type: 'template',
|
|
64
|
-
from: 'commands/build_workflow.md.template',
|
|
65
|
-
to: `${AGENT_CONFIG_DIR}/commands/build_workflow.md`
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
type: 'template',
|
|
69
|
-
from: 'meta/pre_flight.md.template',
|
|
70
|
-
to: '.outputai/meta/pre_flight.md'
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
type: 'template',
|
|
74
|
-
from: 'meta/post_flight.md.template',
|
|
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`
|
|
152
|
-
}
|
|
153
|
-
]
|
|
154
|
-
},
|
|
155
|
-
'claude-code': {
|
|
156
|
-
id: 'claude-code',
|
|
157
|
-
name: 'Claude Code',
|
|
158
|
-
mappings: [
|
|
159
|
-
{
|
|
160
|
-
type: 'symlink',
|
|
161
|
-
from: `${AGENT_CONFIG_DIR}/AGENTS.md`,
|
|
162
|
-
to: 'CLAUDE.md'
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
type: 'symlink',
|
|
166
|
-
from: `${AGENT_CONFIG_DIR}/agents/workflow_planner.md`,
|
|
167
|
-
to: '.claude/agents/workflow_planner.md'
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
type: 'symlink',
|
|
171
|
-
from: `${AGENT_CONFIG_DIR}/agents/workflow_quality.md`,
|
|
172
|
-
to: '.claude/agents/workflow_quality.md'
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
type: 'symlink',
|
|
176
|
-
from: `${AGENT_CONFIG_DIR}/agents/workflow_context_fetcher.md`,
|
|
177
|
-
to: '.claude/agents/workflow_context_fetcher.md'
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
type: 'symlink',
|
|
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'
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
type: 'symlink',
|
|
191
|
-
from: `${AGENT_CONFIG_DIR}/commands/plan_workflow.md`,
|
|
192
|
-
to: '.claude/commands/plan_workflow.md'
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
type: 'symlink',
|
|
196
|
-
from: `${AGENT_CONFIG_DIR}/commands/debug_workflow.md`,
|
|
197
|
-
to: '.claude/commands/debug_workflow.md'
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
type: 'symlink',
|
|
201
|
-
from: `${AGENT_CONFIG_DIR}/commands/build_workflow.md`,
|
|
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'
|
|
279
|
-
}
|
|
280
|
-
]
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
export function getRequiredFiles() {
|
|
284
|
-
const outputaiFiles = AGENT_CONFIGS.outputai.mappings.map(m => m.to);
|
|
285
|
-
const claudeCodeFiles = AGENT_CONFIGS['claude-code'].mappings.map(m => m.to);
|
|
286
|
-
return [...outputaiFiles, ...claudeCodeFiles];
|
|
287
|
-
}
|
|
14
|
+
const EXPECTED_MARKETPLACE_REPO = 'growthxai/output-claude-plugins';
|
|
288
15
|
/**
|
|
289
16
|
* Get the full path to the agent configuration directory
|
|
290
17
|
*/
|
|
@@ -313,31 +40,38 @@ async function fileExists(filePath) {
|
|
|
313
40
|
return false;
|
|
314
41
|
}
|
|
315
42
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
.
|
|
323
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Validate settings.json content has correct marketplace and plugin configuration
|
|
45
|
+
*/
|
|
46
|
+
async function validateSettingsJson(projectRoot) {
|
|
47
|
+
const settingsPath = join(projectRoot, '.claude/settings.json');
|
|
48
|
+
try {
|
|
49
|
+
const content = await fs.readFile(settingsPath, 'utf-8');
|
|
50
|
+
const settings = JSON.parse(content);
|
|
51
|
+
const marketplaceRepo = settings.extraKnownMarketplaces?.['team-tools']?.source?.repo;
|
|
52
|
+
const pluginEnabled = settings.enabledPlugins?.['outputai@outputai'];
|
|
53
|
+
return marketplaceRepo === EXPECTED_MARKETPLACE_REPO && pluginEnabled === true;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
324
58
|
}
|
|
325
59
|
export async function checkAgentStructure(projectRoot) {
|
|
326
|
-
const
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
missingFiles: requiredFiles,
|
|
332
|
-
isComplete: false
|
|
333
|
-
};
|
|
60
|
+
const outputaiDirExists = await checkAgentConfigDirExists(projectRoot);
|
|
61
|
+
const settingsValid = await validateSettingsJson(projectRoot);
|
|
62
|
+
const claudeMdExists = await fileExists(join(projectRoot, 'CLAUDE.md'));
|
|
63
|
+
if (!settingsValid) {
|
|
64
|
+
ux.warn('.claude/settings.json missing critical configuration.');
|
|
334
65
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}
|
|
66
|
+
if (!claudeMdExists) {
|
|
67
|
+
ux.warn('CLAUDE.md missing.');
|
|
68
|
+
}
|
|
69
|
+
if (!outputaiDirExists) {
|
|
70
|
+
ux.warn('.outputai/ directory missing.');
|
|
71
|
+
}
|
|
72
|
+
const isComplete = outputaiDirExists && settingsValid && claudeMdExists;
|
|
73
|
+
const needsInit = !outputaiDirExists || !settingsValid;
|
|
74
|
+
return { isComplete, needsInit };
|
|
341
75
|
}
|
|
342
76
|
/**
|
|
343
77
|
* Prepare template variables for file generation
|
|
@@ -368,14 +102,24 @@ async function ensureDirectoryExists(dir) {
|
|
|
368
102
|
/**
|
|
369
103
|
* Create a file from a template
|
|
370
104
|
*/
|
|
371
|
-
async function createFromTemplate(
|
|
105
|
+
async function createFromTemplate(templateSubpath, output, variables) {
|
|
372
106
|
const templateDir = getTemplateDir('agent_instructions');
|
|
373
|
-
const templatePath = path.join(templateDir,
|
|
107
|
+
const templatePath = path.join(templateDir, templateSubpath);
|
|
374
108
|
const content = await fs.readFile(templatePath, 'utf-8');
|
|
375
109
|
const processed = processTemplate(content, variables);
|
|
376
110
|
await fs.writeFile(output, processed, 'utf-8');
|
|
377
111
|
ux.stdout(ux.colorize('gray', `Created from template: ${output}`));
|
|
378
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Create a static file (no template processing)
|
|
115
|
+
*/
|
|
116
|
+
async function createStaticFile(templateSubpath, output) {
|
|
117
|
+
const templateDir = getTemplateDir('agent_instructions');
|
|
118
|
+
const templatePath = path.join(templateDir, templateSubpath);
|
|
119
|
+
const content = await fs.readFile(templatePath, 'utf-8');
|
|
120
|
+
await fs.writeFile(output, content, 'utf-8');
|
|
121
|
+
ux.stdout(ux.colorize('gray', `Created file: ${output}`));
|
|
122
|
+
}
|
|
379
123
|
/**
|
|
380
124
|
* Create a symlink, falling back to copying if symlinks are not supported
|
|
381
125
|
*/
|
|
@@ -397,7 +141,6 @@ async function createSymlink(source, target, projectRoot) {
|
|
|
397
141
|
const code = error.code;
|
|
398
142
|
if (code === 'ENOTSUP' || code === 'EPERM') {
|
|
399
143
|
ux.stdout(ux.colorize('gray', `Symlinks not supported, creating copy: ${target}`));
|
|
400
|
-
// Use resolved source path for copying
|
|
401
144
|
const resolvedSource = path.isAbsolute(source) ?
|
|
402
145
|
source :
|
|
403
146
|
path.join(projectRoot, source);
|
|
@@ -409,90 +152,91 @@ async function createSymlink(source, target, projectRoot) {
|
|
|
409
152
|
}
|
|
410
153
|
}
|
|
411
154
|
/**
|
|
412
|
-
*
|
|
155
|
+
* Create .outputai/AGENTS.md file from template
|
|
413
156
|
*/
|
|
414
|
-
async function
|
|
415
|
-
const
|
|
416
|
-
await
|
|
417
|
-
|
|
157
|
+
async function createAgentsMdFile(projectRoot, force, variables) {
|
|
158
|
+
const outputaiDir = join(projectRoot, AGENT_CONFIG_DIR);
|
|
159
|
+
await ensureDirectoryExists(outputaiDir);
|
|
160
|
+
const agentsMdPath = join(outputaiDir, 'AGENTS.md');
|
|
161
|
+
if (force || !await fileExists(agentsMdPath)) {
|
|
162
|
+
await createFromTemplate('dotoutputai/AGENTS.md.template', agentsMdPath, variables);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
ux.warn(`File already exists: ${AGENT_CONFIG_DIR}/AGENTS.md (use --force to overwrite)`);
|
|
166
|
+
}
|
|
418
167
|
}
|
|
419
168
|
/**
|
|
420
|
-
*
|
|
169
|
+
* Create .claude/settings.json file from template
|
|
421
170
|
*/
|
|
422
|
-
async function
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
continue;
|
|
432
|
-
}
|
|
433
|
-
switch (mapping.type) {
|
|
434
|
-
case 'template':
|
|
435
|
-
await createFromTemplate(mapping.from, fullPath, variables);
|
|
436
|
-
break;
|
|
437
|
-
case 'symlink':
|
|
438
|
-
await createSymlink(mapping.from, fullPath, projectRoot);
|
|
439
|
-
break;
|
|
440
|
-
case 'copy':
|
|
441
|
-
await copyFile(mapping.from, fullPath);
|
|
442
|
-
break;
|
|
443
|
-
}
|
|
171
|
+
async function createSettingsFile(projectRoot, force) {
|
|
172
|
+
const claudeDir = join(projectRoot, '.claude');
|
|
173
|
+
await ensureDirectoryExists(claudeDir);
|
|
174
|
+
const settingsPath = join(claudeDir, 'settings.json');
|
|
175
|
+
if (force || !await fileExists(settingsPath)) {
|
|
176
|
+
await createStaticFile('dotclaude/settings.json.template', settingsPath);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
ux.warn('File already exists: .claude/settings.json (use --force to overwrite)');
|
|
444
180
|
}
|
|
445
181
|
}
|
|
446
182
|
/**
|
|
447
|
-
*
|
|
448
|
-
*
|
|
183
|
+
* Create CLAUDE.md symlink pointing to .outputai/AGENTS.md
|
|
184
|
+
* Only checks if CLAUDE.md exists, not AGENTS.md - developers can remove AGENTS.md freely
|
|
449
185
|
*/
|
|
450
|
-
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
186
|
+
async function createClaudeMdSymlink(projectRoot, force) {
|
|
187
|
+
const claudeMdPath = join(projectRoot, 'CLAUDE.md');
|
|
188
|
+
if (force || !await fileExists(claudeMdPath)) {
|
|
189
|
+
await createSymlink(`${AGENT_CONFIG_DIR}/AGENTS.md`, claudeMdPath, projectRoot);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
ux.warn('File already exists: CLAUDE.md (use --force to overwrite)');
|
|
193
|
+
}
|
|
458
194
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
195
|
+
/**
|
|
196
|
+
* Register and update the OutputAI plugin marketplace
|
|
197
|
+
*/
|
|
198
|
+
async function registerPluginMarketplace(projectRoot) {
|
|
199
|
+
ux.stdout(ux.colorize('gray', 'Registering plugin marketplace...'));
|
|
200
|
+
await executeClaudeCommand(['plugin', 'marketplace', 'add', 'growthxai/output-claude-plugins'], projectRoot, { ignoreFailure: true });
|
|
201
|
+
ux.stdout(ux.colorize('gray', 'Updating plugin marketplace...'));
|
|
202
|
+
await executeClaudeCommand(['plugin', 'marketplace', 'update', 'outputai'], projectRoot);
|
|
464
203
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
204
|
+
/**
|
|
205
|
+
* Install the OutputAI plugin
|
|
206
|
+
*/
|
|
207
|
+
async function installOutputAIPlugin(projectRoot) {
|
|
208
|
+
ux.stdout(ux.colorize('gray', 'Installing OutputAI plugin...'));
|
|
209
|
+
await executeClaudeCommand(['plugin', 'install', 'outputai@outputai', '--scope', 'project'], projectRoot);
|
|
471
210
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
211
|
+
/**
|
|
212
|
+
* Initialize agent configuration files and register Claude Code plugin
|
|
213
|
+
* Creates 3 files:
|
|
214
|
+
* - .outputai/AGENTS.md (from template with Handlebars processing)
|
|
215
|
+
* - .claude/settings.json (static JSON)
|
|
216
|
+
* - CLAUDE.md symlink to .outputai/AGENTS.md
|
|
217
|
+
* Then runs Claude CLI commands to register the plugin marketplace and install the plugin
|
|
218
|
+
*/
|
|
219
|
+
export async function initializeAgentConfig(options) {
|
|
220
|
+
const { projectRoot, force } = options;
|
|
221
|
+
const variables = prepareTemplateVariables();
|
|
222
|
+
await createAgentsMdFile(projectRoot, force, variables);
|
|
223
|
+
await createSettingsFile(projectRoot, force);
|
|
224
|
+
await createClaudeMdSymlink(projectRoot, force);
|
|
225
|
+
await registerPluginMarketplace(projectRoot);
|
|
226
|
+
await installOutputAIPlugin(projectRoot);
|
|
475
227
|
}
|
|
476
228
|
/**
|
|
477
|
-
* Ensure
|
|
478
|
-
*
|
|
229
|
+
* Ensure OutputAI system is initialized by invoking agents init if needed
|
|
230
|
+
* Creates configuration files and registers Claude Code plugin
|
|
479
231
|
* @param projectRoot - Root directory of the project
|
|
480
|
-
* @throws Error if user declines to initialize or if initialization fails
|
|
481
232
|
*/
|
|
482
|
-
export async function
|
|
483
|
-
const
|
|
484
|
-
if (
|
|
485
|
-
return;
|
|
486
|
-
}
|
|
487
|
-
if (!structureCheck.dirExists) {
|
|
488
|
-
await initializeAgentStructure(projectRoot, false);
|
|
233
|
+
export async function ensureOutputAISystem(projectRoot) {
|
|
234
|
+
const { isComplete, needsInit } = await checkAgentStructure(projectRoot);
|
|
235
|
+
if (isComplete) {
|
|
489
236
|
return;
|
|
490
237
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
if (!shouldReinit) {
|
|
495
|
-
throw createIncompleteConfigError(structureCheck.missingFiles);
|
|
238
|
+
if (needsInit) {
|
|
239
|
+
ux.warn('Agent configuration is incomplete. Initializing...');
|
|
240
|
+
await initializeAgentConfig({ projectRoot, force: false });
|
|
496
241
|
}
|
|
497
|
-
await initializeAgentStructure(projectRoot, true);
|
|
498
242
|
}
|