prjct-cli 0.45.0 → 0.45.3
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/CHANGELOG.md +75 -0
- package/bin/prjct.ts +117 -10
- package/core/__tests__/agentic/memory-system.test.ts +39 -26
- package/core/__tests__/agentic/plan-mode.test.ts +64 -46
- package/core/__tests__/agentic/prompt-builder.test.ts +14 -14
- package/core/__tests__/services/project-index.test.ts +353 -0
- package/core/__tests__/types/fs.test.ts +3 -3
- package/core/__tests__/utils/date-helper.test.ts +10 -10
- package/core/__tests__/utils/output.test.ts +9 -6
- package/core/__tests__/utils/project-commands.test.ts +5 -6
- package/core/agentic/agent-router.ts +9 -10
- package/core/agentic/chain-of-thought.ts +16 -4
- package/core/agentic/command-executor.ts +66 -40
- package/core/agentic/context-builder.ts +8 -5
- package/core/agentic/ground-truth.ts +15 -9
- package/core/agentic/index.ts +145 -152
- package/core/agentic/loop-detector.ts +40 -11
- package/core/agentic/memory-system.ts +98 -35
- package/core/agentic/orchestrator-executor.ts +135 -71
- package/core/agentic/plan-mode.ts +46 -16
- package/core/agentic/prompt-builder.ts +108 -42
- package/core/agentic/services.ts +10 -9
- package/core/agentic/skill-loader.ts +9 -15
- package/core/agentic/smart-context.ts +129 -79
- package/core/agentic/template-executor.ts +13 -12
- package/core/agentic/template-loader.ts +7 -4
- package/core/agentic/tool-registry.ts +16 -13
- package/core/agents/index.ts +1 -1
- package/core/agents/performance.ts +10 -27
- package/core/ai-tools/formatters.ts +8 -6
- package/core/ai-tools/generator.ts +4 -4
- package/core/ai-tools/index.ts +1 -1
- package/core/ai-tools/registry.ts +21 -11
- package/core/bus/bus.ts +23 -16
- package/core/bus/index.ts +2 -2
- package/core/cli/linear.ts +3 -5
- package/core/cli/start.ts +28 -25
- package/core/commands/analysis.ts +58 -39
- package/core/commands/analytics.ts +52 -44
- package/core/commands/base.ts +15 -13
- package/core/commands/cleanup.ts +6 -13
- package/core/commands/command-data.ts +28 -4
- package/core/commands/commands.ts +57 -24
- package/core/commands/context.ts +4 -4
- package/core/commands/design.ts +3 -10
- package/core/commands/index.ts +5 -8
- package/core/commands/maintenance.ts +7 -4
- package/core/commands/planning.ts +179 -56
- package/core/commands/register.ts +13 -9
- package/core/commands/registry.ts +15 -14
- package/core/commands/setup.ts +26 -14
- package/core/commands/shipping.ts +11 -16
- package/core/commands/snapshots.ts +16 -32
- package/core/commands/uninstall.ts +541 -0
- package/core/commands/workflow.ts +24 -28
- package/core/constants/index.ts +10 -22
- package/core/context/generator.ts +82 -33
- package/core/context-tools/files-tool.ts +18 -19
- package/core/context-tools/imports-tool.ts +13 -33
- package/core/context-tools/index.ts +29 -54
- package/core/context-tools/recent-tool.ts +16 -22
- package/core/context-tools/signatures-tool.ts +17 -26
- package/core/context-tools/summary-tool.ts +20 -22
- package/core/context-tools/token-counter.ts +25 -20
- package/core/context-tools/types.ts +5 -5
- package/core/domain/agent-generator.ts +7 -5
- package/core/domain/agent-loader.ts +2 -2
- package/core/domain/analyzer.ts +19 -16
- package/core/domain/architecture-generator.ts +6 -3
- package/core/domain/context-estimator.ts +3 -4
- package/core/domain/snapshot-manager.ts +25 -22
- package/core/domain/task-stack.ts +24 -14
- package/core/errors.ts +1 -1
- package/core/events/events.ts +2 -4
- package/core/events/index.ts +1 -2
- package/core/index.ts +28 -16
- package/core/infrastructure/agent-detector.ts +3 -3
- package/core/infrastructure/ai-provider.ts +23 -20
- package/core/infrastructure/author-detector.ts +16 -10
- package/core/infrastructure/capability-installer.ts +2 -2
- package/core/infrastructure/claude-agent.ts +6 -6
- package/core/infrastructure/command-installer.ts +22 -17
- package/core/infrastructure/config-manager.ts +18 -14
- package/core/infrastructure/editors-config.ts +8 -4
- package/core/infrastructure/path-manager.ts +8 -6
- package/core/infrastructure/permission-manager.ts +20 -17
- package/core/infrastructure/setup.ts +42 -38
- package/core/infrastructure/update-checker.ts +5 -5
- package/core/integrations/issue-tracker/enricher.ts +8 -19
- package/core/integrations/issue-tracker/index.ts +2 -2
- package/core/integrations/issue-tracker/manager.ts +15 -15
- package/core/integrations/issue-tracker/types.ts +5 -22
- package/core/integrations/jira/client.ts +67 -59
- package/core/integrations/jira/index.ts +11 -14
- package/core/integrations/jira/mcp-adapter.ts +5 -10
- package/core/integrations/jira/service.ts +10 -10
- package/core/integrations/linear/client.ts +27 -18
- package/core/integrations/linear/index.ts +9 -12
- package/core/integrations/linear/service.ts +11 -11
- package/core/integrations/linear/sync.ts +8 -8
- package/core/outcomes/analyzer.ts +5 -18
- package/core/outcomes/index.ts +2 -2
- package/core/outcomes/recorder.ts +3 -3
- package/core/plugin/builtin/webhook.ts +19 -15
- package/core/plugin/hooks.ts +29 -21
- package/core/plugin/index.ts +7 -7
- package/core/plugin/loader.ts +19 -19
- package/core/plugin/registry.ts +12 -23
- package/core/schemas/agents.ts +1 -1
- package/core/schemas/analysis.ts +1 -1
- package/core/schemas/enriched-task.ts +62 -49
- package/core/schemas/ideas.ts +13 -13
- package/core/schemas/index.ts +17 -27
- package/core/schemas/issues.ts +40 -25
- package/core/schemas/metrics.ts +25 -25
- package/core/schemas/outcomes.ts +70 -62
- package/core/schemas/permissions.ts +15 -12
- package/core/schemas/prd.ts +27 -14
- package/core/schemas/project.ts +3 -3
- package/core/schemas/roadmap.ts +47 -34
- package/core/schemas/schemas.ts +3 -4
- package/core/schemas/shipped.ts +3 -3
- package/core/schemas/state.ts +43 -29
- package/core/server/index.ts +5 -6
- package/core/server/routes-extended.ts +68 -72
- package/core/server/routes.ts +3 -3
- package/core/server/server.ts +31 -26
- package/core/services/agent-generator.ts +237 -0
- package/core/services/agent-service.ts +2 -2
- package/core/services/breakdown-service.ts +2 -4
- package/core/services/context-generator.ts +299 -0
- package/core/services/context-selector.ts +420 -0
- package/core/services/doctor-service.ts +426 -0
- package/core/services/file-categorizer.ts +448 -0
- package/core/services/file-scorer.ts +270 -0
- package/core/services/git-analyzer.ts +267 -0
- package/core/services/index.ts +27 -10
- package/core/services/memory-service.ts +3 -4
- package/core/services/project-index.ts +911 -0
- package/core/services/project-service.ts +4 -4
- package/core/services/skill-installer.ts +14 -17
- package/core/services/skill-lock.ts +3 -3
- package/core/services/skill-service.ts +12 -6
- package/core/services/stack-detector.ts +245 -0
- package/core/services/sync-service.ts +87 -345
- package/core/services/watch-service.ts +294 -0
- package/core/session/compaction.ts +23 -31
- package/core/session/index.ts +11 -5
- package/core/session/log-migration.ts +3 -3
- package/core/session/metrics.ts +19 -14
- package/core/session/session-log-manager.ts +12 -17
- package/core/session/task-session-manager.ts +25 -25
- package/core/session/utils.ts +1 -1
- package/core/storage/ideas-storage.ts +41 -57
- package/core/storage/index-storage.ts +514 -0
- package/core/storage/index.ts +41 -17
- package/core/storage/metrics-storage.ts +39 -34
- package/core/storage/queue-storage.ts +35 -45
- package/core/storage/shipped-storage.ts +17 -20
- package/core/storage/state-storage.ts +50 -30
- package/core/storage/storage-manager.ts +6 -6
- package/core/storage/storage.ts +18 -15
- package/core/sync/auth-config.ts +3 -3
- package/core/sync/index.ts +13 -19
- package/core/sync/oauth-handler.ts +3 -3
- package/core/sync/sync-client.ts +4 -9
- package/core/sync/sync-manager.ts +12 -14
- package/core/types/commands.ts +42 -7
- package/core/types/index.ts +284 -305
- package/core/types/integrations.ts +3 -3
- package/core/types/storage.ts +14 -14
- package/core/types/utils.ts +3 -3
- package/core/utils/agent-stream.ts +3 -1
- package/core/utils/animations.ts +14 -11
- package/core/utils/branding.ts +7 -7
- package/core/utils/cache.ts +1 -3
- package/core/utils/collection-filters.ts +3 -15
- package/core/utils/date-helper.ts +2 -7
- package/core/utils/file-helper.ts +13 -8
- package/core/utils/jsonl-helper.ts +13 -10
- package/core/utils/keychain.ts +4 -8
- package/core/utils/logger.ts +1 -1
- package/core/utils/next-steps.ts +3 -3
- package/core/utils/output.ts +58 -11
- package/core/utils/project-commands.ts +6 -6
- package/core/utils/project-credentials.ts +5 -12
- package/core/utils/runtime.ts +2 -2
- package/core/utils/session-helper.ts +3 -4
- package/core/utils/version.ts +3 -3
- package/core/wizard/index.ts +13 -0
- package/core/wizard/onboarding.ts +633 -0
- package/core/workflow/state-machine.ts +7 -7
- package/dist/bin/prjct.mjs +18755 -15574
- package/dist/core/infrastructure/command-installer.js +86 -79
- package/dist/core/infrastructure/editors-config.js +6 -6
- package/dist/core/infrastructure/setup.js +246 -225
- package/dist/core/utils/version.js +9 -9
- package/package.json +11 -12
- package/scripts/build.js +3 -3
- package/scripts/postinstall.js +2 -2
- package/templates/mcp-config.json +6 -1
- package/templates/permissions/permissive.jsonc +1 -1
- package/templates/permissions/strict.jsonc +5 -9
- package/templates/global/docs/agents.md +0 -88
- package/templates/global/docs/architecture.md +0 -103
- package/templates/global/docs/commands.md +0 -96
- package/templates/global/docs/validation.md +0 -95
|
@@ -10,26 +10,26 @@
|
|
|
10
10
|
|
|
11
11
|
import { agentPerformanceTracker } from '../agents'
|
|
12
12
|
import { outcomeAnalyzer } from '../outcomes'
|
|
13
|
-
import type { TaskType } from '../types'
|
|
14
13
|
import type {
|
|
15
14
|
ContextDomain,
|
|
16
|
-
|
|
17
|
-
FullContext,
|
|
15
|
+
DomainAnalysis,
|
|
18
16
|
FilteredContext,
|
|
17
|
+
FullContext,
|
|
18
|
+
SmartContextProjectState,
|
|
19
19
|
StackInfo,
|
|
20
|
-
|
|
20
|
+
TaskType,
|
|
21
21
|
} from '../types'
|
|
22
22
|
|
|
23
23
|
// Re-export types for convenience
|
|
24
24
|
export type {
|
|
25
|
-
ContextDomain,
|
|
26
|
-
FullContext,
|
|
27
|
-
FilteredContext,
|
|
28
25
|
AgentInfo,
|
|
26
|
+
ContextDomain,
|
|
29
27
|
FeatureInfo,
|
|
28
|
+
FilteredContext,
|
|
29
|
+
FilterMetrics,
|
|
30
|
+
FullContext,
|
|
30
31
|
PatternInfo,
|
|
31
32
|
StackInfo,
|
|
32
|
-
FilterMetrics,
|
|
33
33
|
} from '../types'
|
|
34
34
|
|
|
35
35
|
// Local type alias for backward compatibility
|
|
@@ -47,38 +47,105 @@ class SmartContext {
|
|
|
47
47
|
|
|
48
48
|
// Frontend indicators
|
|
49
49
|
const frontendKeywords = [
|
|
50
|
-
'ui',
|
|
51
|
-
'
|
|
52
|
-
'
|
|
50
|
+
'ui',
|
|
51
|
+
'component',
|
|
52
|
+
'react',
|
|
53
|
+
'vue',
|
|
54
|
+
'angular',
|
|
55
|
+
'css',
|
|
56
|
+
'style',
|
|
57
|
+
'button',
|
|
58
|
+
'form',
|
|
59
|
+
'modal',
|
|
60
|
+
'layout',
|
|
61
|
+
'responsive',
|
|
62
|
+
'animation',
|
|
63
|
+
'dom',
|
|
64
|
+
'html',
|
|
65
|
+
'frontend',
|
|
66
|
+
'fe',
|
|
67
|
+
'client',
|
|
68
|
+
'browser',
|
|
69
|
+
'jsx',
|
|
70
|
+
'tsx',
|
|
53
71
|
]
|
|
54
72
|
|
|
55
73
|
// Backend indicators
|
|
56
74
|
const backendKeywords = [
|
|
57
|
-
'api',
|
|
58
|
-
'
|
|
59
|
-
'
|
|
75
|
+
'api',
|
|
76
|
+
'server',
|
|
77
|
+
'database',
|
|
78
|
+
'db',
|
|
79
|
+
'endpoint',
|
|
80
|
+
'route',
|
|
81
|
+
'handler',
|
|
82
|
+
'controller',
|
|
83
|
+
'service',
|
|
84
|
+
'repository',
|
|
85
|
+
'model',
|
|
86
|
+
'query',
|
|
87
|
+
'backend',
|
|
88
|
+
'be',
|
|
89
|
+
'rest',
|
|
90
|
+
'graphql',
|
|
91
|
+
'prisma',
|
|
92
|
+
'sql',
|
|
93
|
+
'redis',
|
|
94
|
+
'auth',
|
|
60
95
|
]
|
|
61
96
|
|
|
62
97
|
// DevOps indicators
|
|
63
98
|
const devopsKeywords = [
|
|
64
|
-
'deploy',
|
|
65
|
-
'
|
|
66
|
-
'
|
|
99
|
+
'deploy',
|
|
100
|
+
'docker',
|
|
101
|
+
'kubernetes',
|
|
102
|
+
'k8s',
|
|
103
|
+
'ci',
|
|
104
|
+
'cd',
|
|
105
|
+
'pipeline',
|
|
106
|
+
'terraform',
|
|
107
|
+
'ansible',
|
|
108
|
+
'aws',
|
|
109
|
+
'gcp',
|
|
110
|
+
'azure',
|
|
111
|
+
'config',
|
|
112
|
+
'nginx',
|
|
113
|
+
'devops',
|
|
114
|
+
'infrastructure',
|
|
115
|
+
'monitoring',
|
|
116
|
+
'logging',
|
|
117
|
+
'build',
|
|
67
118
|
]
|
|
68
119
|
|
|
69
120
|
// Docs indicators
|
|
70
121
|
const docsKeywords = [
|
|
71
|
-
'document',
|
|
72
|
-
'
|
|
122
|
+
'document',
|
|
123
|
+
'docs',
|
|
124
|
+
'readme',
|
|
125
|
+
'changelog',
|
|
126
|
+
'comment',
|
|
127
|
+
'jsdoc',
|
|
128
|
+
'tutorial',
|
|
129
|
+
'guide',
|
|
130
|
+
'explain',
|
|
131
|
+
'describe',
|
|
132
|
+
'markdown',
|
|
73
133
|
]
|
|
74
134
|
|
|
75
135
|
// Testing indicators
|
|
76
136
|
const testingKeywords = [
|
|
77
|
-
'test',
|
|
137
|
+
'test',
|
|
138
|
+
'spec',
|
|
78
139
|
// JS/TS
|
|
79
|
-
'bun',
|
|
140
|
+
'bun',
|
|
141
|
+
'bun test',
|
|
142
|
+
'jest',
|
|
143
|
+
'mocha',
|
|
144
|
+
'cypress',
|
|
145
|
+
'playwright',
|
|
80
146
|
// Python
|
|
81
|
-
'pytest',
|
|
147
|
+
'pytest',
|
|
148
|
+
'unittest',
|
|
82
149
|
// Go
|
|
83
150
|
'go test',
|
|
84
151
|
// Rust
|
|
@@ -86,17 +153,24 @@ class SmartContext {
|
|
|
86
153
|
// .NET
|
|
87
154
|
'dotnet test',
|
|
88
155
|
// Java
|
|
89
|
-
'mvn test',
|
|
90
|
-
'
|
|
156
|
+
'mvn test',
|
|
157
|
+
'gradle test',
|
|
158
|
+
'gradlew test',
|
|
159
|
+
'e2e',
|
|
160
|
+
'unit',
|
|
161
|
+
'integration',
|
|
162
|
+
'coverage',
|
|
163
|
+
'mock',
|
|
164
|
+
'fixture',
|
|
91
165
|
]
|
|
92
166
|
|
|
93
167
|
// Count matches
|
|
94
168
|
const scores: Record<ContextDomain, number> = {
|
|
95
|
-
frontend: frontendKeywords.filter(k => lower.includes(k)).length,
|
|
96
|
-
backend: backendKeywords.filter(k => lower.includes(k)).length,
|
|
97
|
-
devops: devopsKeywords.filter(k => lower.includes(k)).length,
|
|
98
|
-
docs: docsKeywords.filter(k => lower.includes(k)).length,
|
|
99
|
-
testing: testingKeywords.filter(k => lower.includes(k)).length,
|
|
169
|
+
frontend: frontendKeywords.filter((k) => lower.includes(k)).length,
|
|
170
|
+
backend: backendKeywords.filter((k) => lower.includes(k)).length,
|
|
171
|
+
devops: devopsKeywords.filter((k) => lower.includes(k)).length,
|
|
172
|
+
docs: docsKeywords.filter((k) => lower.includes(k)).length,
|
|
173
|
+
testing: testingKeywords.filter((k) => lower.includes(k)).length,
|
|
100
174
|
general: 0,
|
|
101
175
|
}
|
|
102
176
|
|
|
@@ -135,29 +209,26 @@ class SmartContext {
|
|
|
135
209
|
const relevantDomains = [taskDomain, ...secondary, 'general']
|
|
136
210
|
|
|
137
211
|
// Filter agents
|
|
138
|
-
const filteredAgents = fullContext.agents.filter(
|
|
139
|
-
|
|
212
|
+
const filteredAgents = fullContext.agents.filter((agent) =>
|
|
213
|
+
relevantDomains.includes(agent.domain)
|
|
140
214
|
)
|
|
141
215
|
|
|
142
216
|
// Enrich with performance data
|
|
143
217
|
for (const agent of filteredAgents) {
|
|
144
|
-
const perf = await agentPerformanceTracker.getAgentPerformance(
|
|
145
|
-
projectId,
|
|
146
|
-
agent.name
|
|
147
|
-
)
|
|
218
|
+
const perf = await agentPerformanceTracker.getAgentPerformance(projectId, agent.name)
|
|
148
219
|
if (perf) {
|
|
149
220
|
agent.successRate = perf.successRate
|
|
150
221
|
}
|
|
151
222
|
}
|
|
152
223
|
|
|
153
224
|
// Filter roadmap
|
|
154
|
-
const filteredRoadmap = fullContext.roadmap.filter(
|
|
155
|
-
feature
|
|
225
|
+
const filteredRoadmap = fullContext.roadmap.filter((feature) =>
|
|
226
|
+
feature.relatedTo.some((domain) => relevantDomains.includes(domain))
|
|
156
227
|
)
|
|
157
228
|
|
|
158
229
|
// Filter patterns
|
|
159
|
-
const filteredPatterns = fullContext.patterns.filter(
|
|
160
|
-
|
|
230
|
+
const filteredPatterns = fullContext.patterns.filter((pattern) =>
|
|
231
|
+
relevantDomains.includes(pattern.domain)
|
|
161
232
|
)
|
|
162
233
|
|
|
163
234
|
// Get relevant patterns from outcomes
|
|
@@ -248,19 +319,8 @@ class SmartContext {
|
|
|
248
319
|
/infra/i,
|
|
249
320
|
/k8s/i,
|
|
250
321
|
],
|
|
251
|
-
docs: [
|
|
252
|
-
|
|
253
|
-
/docs?\//i,
|
|
254
|
-
/readme/i,
|
|
255
|
-
/changelog/i,
|
|
256
|
-
],
|
|
257
|
-
testing: [
|
|
258
|
-
/\.(test|spec)\./i,
|
|
259
|
-
/tests?\//i,
|
|
260
|
-
/__tests__\//i,
|
|
261
|
-
/e2e\//i,
|
|
262
|
-
/fixtures?\//i,
|
|
263
|
-
],
|
|
322
|
+
docs: [/\.(md|mdx|rst|txt)$/i, /docs?\//i, /readme/i, /changelog/i],
|
|
323
|
+
testing: [/\.(test|spec)\./i, /tests?\//i, /__tests__\//i, /e2e\//i, /fixtures?\//i],
|
|
264
324
|
general: [],
|
|
265
325
|
}
|
|
266
326
|
|
|
@@ -270,19 +330,15 @@ class SmartContext {
|
|
|
270
330
|
}
|
|
271
331
|
|
|
272
332
|
// Always include config files
|
|
273
|
-
const configPatterns = [
|
|
274
|
-
/package\.json$/,
|
|
275
|
-
/tsconfig\.json$/,
|
|
276
|
-
/\.config\.(ts|js)$/,
|
|
277
|
-
]
|
|
333
|
+
const configPatterns = [/package\.json$/, /tsconfig\.json$/, /\.config\.(ts|js)$/]
|
|
278
334
|
|
|
279
|
-
return files.filter(file => {
|
|
335
|
+
return files.filter((file) => {
|
|
280
336
|
// Include if matches domain patterns
|
|
281
|
-
if (domainPatterns.some(p => p.test(file))) {
|
|
337
|
+
if (domainPatterns.some((p) => p.test(file))) {
|
|
282
338
|
return true
|
|
283
339
|
}
|
|
284
340
|
// Include config files
|
|
285
|
-
if (configPatterns.some(p => p.test(file))) {
|
|
341
|
+
if (configPatterns.some((p) => p.test(file))) {
|
|
286
342
|
return true
|
|
287
343
|
}
|
|
288
344
|
return false
|
|
@@ -292,14 +348,16 @@ class SmartContext {
|
|
|
292
348
|
/**
|
|
293
349
|
* Estimate context size in approximate tokens.
|
|
294
350
|
*/
|
|
295
|
-
private estimateSize(
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
351
|
+
private estimateSize(
|
|
352
|
+
context: Partial<{
|
|
353
|
+
agents: unknown[]
|
|
354
|
+
roadmap: unknown[]
|
|
355
|
+
patterns: unknown[]
|
|
356
|
+
stack: unknown
|
|
357
|
+
files: string[]
|
|
358
|
+
state: unknown
|
|
359
|
+
}>
|
|
360
|
+
): number {
|
|
303
361
|
let size = 0
|
|
304
362
|
|
|
305
363
|
// Rough estimates: each item ~50 tokens, files ~10 tokens each
|
|
@@ -349,22 +407,14 @@ class SmartContext {
|
|
|
349
407
|
const taskType = this.contextDomainToTaskType(domainAnalysis.primary)
|
|
350
408
|
|
|
351
409
|
// Get agent suggestion
|
|
352
|
-
const agentSuggestion = await agentPerformanceTracker.suggestAgent(
|
|
353
|
-
projectId,
|
|
354
|
-
taskType
|
|
355
|
-
)
|
|
410
|
+
const agentSuggestion = await agentPerformanceTracker.suggestAgent(projectId, taskType)
|
|
356
411
|
|
|
357
412
|
// Get duration estimate
|
|
358
|
-
const durationEstimate = await outcomeAnalyzer.suggestEstimate(
|
|
359
|
-
projectId,
|
|
360
|
-
taskType
|
|
361
|
-
)
|
|
413
|
+
const durationEstimate = await outcomeAnalyzer.suggestEstimate(projectId, taskType)
|
|
362
414
|
|
|
363
415
|
// Get relevant patterns
|
|
364
416
|
const patterns = await outcomeAnalyzer.detectPatterns(projectId)
|
|
365
|
-
const relevantPatterns = patterns
|
|
366
|
-
.slice(0, 3)
|
|
367
|
-
.map(p => p.description)
|
|
417
|
+
const relevantPatterns = patterns.slice(0, 3).map((p) => p.description)
|
|
368
418
|
|
|
369
419
|
return {
|
|
370
420
|
domain: domainAnalysis.primary,
|
|
@@ -9,9 +9,8 @@
|
|
|
9
9
|
* @version 1.0.0
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import fs from 'fs/promises'
|
|
13
|
-
import path from 'path'
|
|
14
|
-
import os from 'os'
|
|
12
|
+
import fs from 'node:fs/promises'
|
|
13
|
+
import path from 'node:path'
|
|
15
14
|
import configManager from '../infrastructure/config-manager'
|
|
16
15
|
import pathManager from '../infrastructure/path-manager'
|
|
17
16
|
import { isNotFoundError } from '../types/fs'
|
|
@@ -119,7 +118,7 @@ export class TemplateExecutor {
|
|
|
119
118
|
agentsDir: path.join(globalPath, 'agents'),
|
|
120
119
|
skillsDir: activeProvider.skillsDir,
|
|
121
120
|
stateJson: path.join(globalPath, 'storage', 'state.json'),
|
|
122
|
-
}
|
|
121
|
+
},
|
|
123
122
|
}
|
|
124
123
|
}
|
|
125
124
|
|
|
@@ -141,7 +140,7 @@ export class TemplateExecutor {
|
|
|
141
140
|
const projectId = await this.getProjectId(projectPath)
|
|
142
141
|
const agentsDir = path.join(pathManager.getGlobalProjectPath(projectId), 'agents')
|
|
143
142
|
const files = await fs.readdir(agentsDir)
|
|
144
|
-
return files.some(f => f.endsWith('.md'))
|
|
143
|
+
return files.some((f) => f.endsWith('.md'))
|
|
145
144
|
} catch (error) {
|
|
146
145
|
if (isNotFoundError(error)) return false
|
|
147
146
|
return false
|
|
@@ -156,9 +155,7 @@ export class TemplateExecutor {
|
|
|
156
155
|
const projectId = await this.getProjectId(projectPath)
|
|
157
156
|
const agentsDir = path.join(pathManager.getGlobalProjectPath(projectId), 'agents')
|
|
158
157
|
const files = await fs.readdir(agentsDir)
|
|
159
|
-
return files
|
|
160
|
-
.filter(f => f.endsWith('.md'))
|
|
161
|
-
.map(f => f.replace('.md', ''))
|
|
158
|
+
return files.filter((f) => f.endsWith('.md')).map((f) => f.replace('.md', ''))
|
|
162
159
|
} catch {
|
|
163
160
|
return []
|
|
164
161
|
}
|
|
@@ -199,7 +196,9 @@ You are executing a prjct command as ${context.agentName}. Follow the template-f
|
|
|
199
196
|
|
|
200
197
|
2. **Check if orchestration is needed**
|
|
201
198
|
- This command ${requiresOrchestration ? 'REQUIRES' : 'does NOT require'} orchestration
|
|
202
|
-
${
|
|
199
|
+
${
|
|
200
|
+
requiresOrchestration
|
|
201
|
+
? `
|
|
203
202
|
3. **Orchestration steps:**
|
|
204
203
|
- Read: ${context.paths.orchestrator}
|
|
205
204
|
- Read: ${context.paths.repoAnalysis} to understand project technologies
|
|
@@ -217,11 +216,13 @@ You are executing a prjct command as ${context.agentName}. Follow the template-f
|
|
|
217
216
|
|
|
218
217
|
- Check if task should be fragmented (read: ${context.paths.taskFragmentation})
|
|
219
218
|
- If agents loaded, check their skills and load from ${context.paths.skillsDir}
|
|
220
|
-
`
|
|
219
|
+
`
|
|
220
|
+
: `
|
|
221
221
|
3. **Simple execution:**
|
|
222
222
|
- Execute the command template directly
|
|
223
223
|
- No agent routing needed
|
|
224
|
-
`
|
|
224
|
+
`
|
|
225
|
+
}
|
|
225
226
|
|
|
226
227
|
4. **Execute the command template** with full context
|
|
227
228
|
|
|
@@ -258,7 +259,7 @@ When fragmenting tasks:
|
|
|
258
259
|
return {
|
|
259
260
|
prompt,
|
|
260
261
|
context,
|
|
261
|
-
requiresOrchestration
|
|
262
|
+
requiresOrchestration,
|
|
262
263
|
}
|
|
263
264
|
}
|
|
264
265
|
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* @module agentic/template-loader
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import fs from 'fs/promises'
|
|
9
|
-
import path from 'path'
|
|
8
|
+
import fs from 'node:fs/promises'
|
|
9
|
+
import path from 'node:path'
|
|
10
10
|
import { TemplateError } from '../errors'
|
|
11
11
|
import type { Frontmatter, ParsedTemplate } from '../types'
|
|
12
12
|
|
|
@@ -53,7 +53,10 @@ export function parseFrontmatter(content: string): ParsedTemplate {
|
|
|
53
53
|
|
|
54
54
|
// Parse arrays
|
|
55
55
|
if (value.startsWith('[') && value.endsWith(']')) {
|
|
56
|
-
frontmatter[key.trim()] = value
|
|
56
|
+
frontmatter[key.trim()] = value
|
|
57
|
+
.slice(1, -1)
|
|
58
|
+
.split(',')
|
|
59
|
+
.map((v) => v.trim())
|
|
57
60
|
} else {
|
|
58
61
|
// Remove quotes if present
|
|
59
62
|
frontmatter[key.trim()] = value.replace(/^["']|["']$/g, '')
|
|
@@ -108,5 +111,5 @@ export default {
|
|
|
108
111
|
load,
|
|
109
112
|
parseFrontmatter,
|
|
110
113
|
getAllowedTools,
|
|
111
|
-
clearCache
|
|
114
|
+
clearCache,
|
|
112
115
|
}
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* @version 1.0.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import { promisify } from 'util'
|
|
9
|
+
import { exec } from 'node:child_process'
|
|
10
|
+
import fs from 'node:fs/promises'
|
|
11
|
+
import { promisify } from 'node:util'
|
|
12
12
|
import type { ToolFunction, ToolRegistryInterface } from '../types'
|
|
13
13
|
|
|
14
14
|
// Re-export types for convenience
|
|
@@ -83,18 +83,21 @@ toolRegistry.register('Write', async (filePath: unknown, content: unknown): Prom
|
|
|
83
83
|
})
|
|
84
84
|
|
|
85
85
|
// Execute bash command
|
|
86
|
-
toolRegistry.register(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
86
|
+
toolRegistry.register(
|
|
87
|
+
'Bash',
|
|
88
|
+
async (command: unknown): Promise<{ stdout: string; stderr: string }> => {
|
|
89
|
+
try {
|
|
90
|
+
const { stdout, stderr } = await execAsync(command as string)
|
|
91
|
+
return { stdout, stderr }
|
|
92
|
+
} catch (error) {
|
|
93
|
+
const err = error as { stdout?: string; stderr?: string; message?: string }
|
|
94
|
+
return {
|
|
95
|
+
stdout: err.stdout || '',
|
|
96
|
+
stderr: err.stderr || err.message || 'Command failed',
|
|
97
|
+
}
|
|
95
98
|
}
|
|
96
99
|
}
|
|
97
|
-
|
|
100
|
+
)
|
|
98
101
|
|
|
99
102
|
// Get current timestamp
|
|
100
103
|
toolRegistry.register('GetTimestamp', async (): Promise<string> => {
|
package/core/agents/index.ts
CHANGED
|
@@ -5,16 +5,16 @@
|
|
|
5
5
|
* Enables learning which agent works best for which task type.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import path from 'path'
|
|
9
|
-
import * as fileHelper from '../utils/file-helper'
|
|
8
|
+
import path from 'node:path'
|
|
10
9
|
import pathManager from '../infrastructure/path-manager'
|
|
11
10
|
import type {
|
|
12
11
|
AgentPerformance,
|
|
13
|
-
AgentTaskRecord,
|
|
14
|
-
AgentSuggestion,
|
|
15
12
|
AgentPerformanceSummary,
|
|
13
|
+
AgentSuggestion,
|
|
14
|
+
AgentTaskRecord,
|
|
16
15
|
TaskType,
|
|
17
16
|
} from '../types'
|
|
17
|
+
import * as fileHelper from '../utils/file-helper'
|
|
18
18
|
|
|
19
19
|
const PERFORMANCE_DIR = 'analysis'
|
|
20
20
|
const PERFORMANCE_FILE = 'agent-performance.json'
|
|
@@ -94,10 +94,7 @@ export class AgentPerformanceTracker {
|
|
|
94
94
|
return []
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
const data = await fileHelper.readJson<{ agents: AgentPerformance[] }>(
|
|
98
|
-
perfPath,
|
|
99
|
-
{ agents: [] }
|
|
100
|
-
)
|
|
97
|
+
const data = await fileHelper.readJson<{ agents: AgentPerformance[] }>(perfPath, { agents: [] })
|
|
101
98
|
return data?.agents ?? []
|
|
102
99
|
}
|
|
103
100
|
|
|
@@ -115,17 +112,11 @@ export class AgentPerformanceTracker {
|
|
|
115
112
|
/**
|
|
116
113
|
* Update performance summary after a task completion.
|
|
117
114
|
*/
|
|
118
|
-
private async updatePerformance(
|
|
119
|
-
projectId: string,
|
|
120
|
-
record: AgentTaskRecord
|
|
121
|
-
): Promise<void> {
|
|
115
|
+
private async updatePerformance(projectId: string, record: AgentTaskRecord): Promise<void> {
|
|
122
116
|
const perfPath = this.getPerformancePath(projectId)
|
|
123
117
|
await fileHelper.ensureDir(path.dirname(perfPath))
|
|
124
118
|
|
|
125
|
-
const data = await fileHelper.readJson<{ agents: AgentPerformance[] }>(
|
|
126
|
-
perfPath,
|
|
127
|
-
{ agents: [] }
|
|
128
|
-
)
|
|
119
|
+
const data = await fileHelper.readJson<{ agents: AgentPerformance[] }>(perfPath, { agents: [] })
|
|
129
120
|
|
|
130
121
|
if (!data) return
|
|
131
122
|
|
|
@@ -279,10 +270,7 @@ export class AgentPerformanceTracker {
|
|
|
279
270
|
/**
|
|
280
271
|
* Suggest the best agent for a task type.
|
|
281
272
|
*/
|
|
282
|
-
async suggestAgent(
|
|
283
|
-
projectId: string,
|
|
284
|
-
taskType: TaskType
|
|
285
|
-
): Promise<AgentSuggestion | null> {
|
|
273
|
+
async suggestAgent(projectId: string, taskType: TaskType): Promise<AgentSuggestion | null> {
|
|
286
274
|
const allPerf = await this.getAllPerformance(projectId)
|
|
287
275
|
|
|
288
276
|
if (allPerf.length === 0) {
|
|
@@ -308,9 +296,7 @@ export class AgentPerformanceTracker {
|
|
|
308
296
|
}
|
|
309
297
|
|
|
310
298
|
// Fallback to most experienced agent
|
|
311
|
-
const byExperience = [...allPerf].sort(
|
|
312
|
-
(a, b) => b.tasksCompleted - a.tasksCompleted
|
|
313
|
-
)
|
|
299
|
+
const byExperience = [...allPerf].sort((a, b) => b.tasksCompleted - a.tasksCompleted)
|
|
314
300
|
const fallback = byExperience[0]
|
|
315
301
|
|
|
316
302
|
return {
|
|
@@ -364,10 +350,7 @@ export class AgentPerformanceTracker {
|
|
|
364
350
|
'design',
|
|
365
351
|
'other',
|
|
366
352
|
]
|
|
367
|
-
const byTaskType: Record<TaskType, string | null> = {} as Record<
|
|
368
|
-
TaskType,
|
|
369
|
-
string | null
|
|
370
|
-
>
|
|
353
|
+
const byTaskType: Record<TaskType, string | null> = {} as Record<TaskType, string | null>
|
|
371
354
|
|
|
372
355
|
for (const taskType of taskTypes) {
|
|
373
356
|
const best = allPerf.find((a) => a.bestFor.includes(taskType))
|
|
@@ -41,7 +41,7 @@ export interface ProjectContext {
|
|
|
41
41
|
* Format context for Claude Code (CLAUDE.md)
|
|
42
42
|
* Detailed markdown with full context
|
|
43
43
|
*/
|
|
44
|
-
export function formatForClaude(ctx: ProjectContext,
|
|
44
|
+
export function formatForClaude(ctx: ProjectContext, _config: AIToolConfig): string {
|
|
45
45
|
return `# ${ctx.name} - Project Rules
|
|
46
46
|
<!-- projectId: ${ctx.projectId} -->
|
|
47
47
|
<!-- Generated: ${new Date().toISOString()} -->
|
|
@@ -117,7 +117,7 @@ Load from \`~/.prjct-cli/projects/${ctx.projectId}/agents/\`:
|
|
|
117
117
|
* Format context for Cursor (.cursorrules)
|
|
118
118
|
* Concise rules format, optimized for inline suggestions
|
|
119
119
|
*/
|
|
120
|
-
export function formatForCursor(ctx: ProjectContext,
|
|
120
|
+
export function formatForCursor(ctx: ProjectContext, _config: AIToolConfig): string {
|
|
121
121
|
const rules: string[] = []
|
|
122
122
|
|
|
123
123
|
// Project identity
|
|
@@ -164,7 +164,7 @@ export function formatForCursor(ctx: ProjectContext, config: AIToolConfig): stri
|
|
|
164
164
|
* Format context for GitHub Copilot (.github/copilot-instructions.md)
|
|
165
165
|
* Minimal bullet points
|
|
166
166
|
*/
|
|
167
|
-
export function formatForCopilot(ctx: ProjectContext,
|
|
167
|
+
export function formatForCopilot(ctx: ProjectContext, _config: AIToolConfig): string {
|
|
168
168
|
const lines: string[] = []
|
|
169
169
|
|
|
170
170
|
lines.push('# Copilot Instructions')
|
|
@@ -197,7 +197,7 @@ export function formatForCopilot(ctx: ProjectContext, config: AIToolConfig): str
|
|
|
197
197
|
* Format context for Windsurf (.windsurfrules)
|
|
198
198
|
* Optimized for Cascade AI with flow-based suggestions
|
|
199
199
|
*/
|
|
200
|
-
export function formatForWindsurf(ctx: ProjectContext,
|
|
200
|
+
export function formatForWindsurf(ctx: ProjectContext, _config: AIToolConfig): string {
|
|
201
201
|
const rules: string[] = []
|
|
202
202
|
|
|
203
203
|
// Project identity
|
|
@@ -242,7 +242,7 @@ export function formatForWindsurf(ctx: ProjectContext, config: AIToolConfig): st
|
|
|
242
242
|
* Format context for Continue.dev (.continue/config.json)
|
|
243
243
|
* JSON config with system message and context providers
|
|
244
244
|
*/
|
|
245
|
-
export function formatForContinue(ctx: ProjectContext,
|
|
245
|
+
export function formatForContinue(ctx: ProjectContext, _config: AIToolConfig): string {
|
|
246
246
|
const systemMessage = [
|
|
247
247
|
`You are working on ${ctx.name}, a ${ctx.projectType} ${ctx.ecosystem} project.`,
|
|
248
248
|
'',
|
|
@@ -289,7 +289,9 @@ export function formatForContinue(ctx: ProjectContext, config: AIToolConfig): st
|
|
|
289
289
|
/**
|
|
290
290
|
* Get formatter function for a tool
|
|
291
291
|
*/
|
|
292
|
-
export function getFormatter(
|
|
292
|
+
export function getFormatter(
|
|
293
|
+
toolId: string
|
|
294
|
+
): ((ctx: ProjectContext, config: AIToolConfig) => string) | null {
|
|
293
295
|
const formatters: Record<string, (ctx: ProjectContext, config: AIToolConfig) => string> = {
|
|
294
296
|
claude: formatForClaude,
|
|
295
297
|
cursor: formatForCursor,
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* Each tool gets context in its preferred format.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import fs from 'fs/promises'
|
|
9
|
-
import path from 'path'
|
|
10
|
-
import { AI_TOOLS, DEFAULT_AI_TOOLS, getAIToolConfig, type AIToolConfig } from './registry'
|
|
8
|
+
import fs from 'node:fs/promises'
|
|
9
|
+
import path from 'node:path'
|
|
11
10
|
import { getFormatter, type ProjectContext } from './formatters'
|
|
11
|
+
import { AI_TOOLS, type AIToolConfig, DEFAULT_AI_TOOLS, getAIToolConfig } from './registry'
|
|
12
12
|
|
|
13
13
|
export interface GenerateResult {
|
|
14
14
|
toolId: string
|
|
@@ -111,7 +111,7 @@ export function getOutputFiles(
|
|
|
111
111
|
toolIds: string[] = DEFAULT_AI_TOOLS
|
|
112
112
|
): { toolId: string; file: string; location: 'repo' | 'global' }[] {
|
|
113
113
|
return toolIds
|
|
114
|
-
.map(id => {
|
|
114
|
+
.map((id) => {
|
|
115
115
|
const config = AI_TOOLS[id]
|
|
116
116
|
if (!config) return null
|
|
117
117
|
return {
|