@compilr-dev/sdk 0.29.5 → 0.29.7
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/actions/index.d.ts +1 -2
- package/dist/actions/index.js +10 -2
- package/dist/actions/resolver.d.ts +0 -4
- package/dist/actions/resolver.js +0 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/platform/file-anchor-service.d.ts +73 -1
- package/dist/platform/file-anchor-service.js +133 -0
- package/dist/platform/services.d.ts +15 -0
- package/package.json +1 -1
- package/dist/actions/registry.d.ts +0 -17
- package/dist/actions/registry.js +0 -161
package/dist/actions/index.d.ts
CHANGED
|
@@ -25,5 +25,4 @@
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
export type { ActionContext, ActionDefinition } from './types.js';
|
|
28
|
-
export {
|
|
29
|
-
export { resolveActionPrompt, buildContextSummary, getSuggestedRole } from './resolver.js';
|
|
28
|
+
export { resolveActionPrompt, buildContextSummary } from './resolver.js';
|
package/dist/actions/index.js
CHANGED
|
@@ -25,6 +25,14 @@
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
// Registry
|
|
28
|
-
|
|
28
|
+
/*
|
|
29
|
+
⚠️ ACTION_REGISTRY IS GONE — superseded, not merely unused. `MACRO_META_REGISTRY` replaced it
|
|
30
|
+
during the macro rename and is a strict superset (55 entries against 14, every id present). The
|
|
31
|
+
old one kept an IPC handler and a preload binding alive that nothing called, which made it look
|
|
32
|
+
like the action source and cost a wrong assumption in the Projects plan.
|
|
33
|
+
|
|
34
|
+
`resolveActionPrompt` never read it: it resolves by skill NAME from the array it is given, so
|
|
35
|
+
the live path was never coupled to the dead one.
|
|
36
|
+
*/
|
|
29
37
|
// Resolver
|
|
30
|
-
export { resolveActionPrompt, buildContextSummary
|
|
38
|
+
export { resolveActionPrompt, buildContextSummary } from './resolver.js';
|
|
@@ -23,7 +23,3 @@ export declare function resolveActionPrompt(actionId: string, context: ActionCon
|
|
|
23
23
|
* Used by the ActionCard component to show a brief description.
|
|
24
24
|
*/
|
|
25
25
|
export declare function buildContextSummary(context: ActionContext): string;
|
|
26
|
-
/**
|
|
27
|
-
* Get the suggested agent role for an action.
|
|
28
|
-
*/
|
|
29
|
-
export declare function getSuggestedRole(actionId: string): string | undefined;
|
package/dist/actions/resolver.js
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Used by both CLI and desktop to turn user actions into agent prompts.
|
|
9
9
|
*/
|
|
10
|
-
import { getActionById } from './registry.js';
|
|
11
10
|
/**
|
|
12
11
|
* Resolve an action + context into a final prompt for the agent.
|
|
13
12
|
*
|
|
@@ -99,9 +98,3 @@ export function buildContextSummary(context) {
|
|
|
99
98
|
}
|
|
100
99
|
return '';
|
|
101
100
|
}
|
|
102
|
-
/**
|
|
103
|
-
* Get the suggested agent role for an action.
|
|
104
|
-
*/
|
|
105
|
-
export function getSuggestedRole(actionId) {
|
|
106
|
-
return getActionById(actionId)?.suggestedRole;
|
|
107
|
-
}
|
package/dist/index.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ export type { MacroListEntry, BuildMacroListOptions } from './skills/index.js';
|
|
|
87
87
|
export { generateSkillCatalog, toCatalogEntry, createLoadSkillTool } from './skills/index.js';
|
|
88
88
|
export type { SkillCatalogEntry, SkillSource } from './skills/index.js';
|
|
89
89
|
export { platformMacros, designMacro, sketchMacro, prdMacro, refineMacro, refineItemMacro, architectureMacro, sessionNotesMacro, buildMacro, scaffoldMacro, outlineMacro, literatureReviewMacro, draftSectionMacro, peerReviewMacro, researchScaffoldMacro, businessVisionMacro, marketAnalysisMacro, competitorAnalysisMacro, financialModelMacro, pitchOutlineMacro, businessReviewMacro, brandSetupMacro, contentStrategyMacro, contentCalendarMacro, createContentMacro, contentReviewMacro, curriculumDesignMacro, lessonPlanMacro, assessmentDesignMacro, courseReviewMacro, bookOutlineMacro, characterDesignMacro, plotThreadsMacro, sceneBreakdownMacro, bookReviewMacro, } from './skills/index.js';
|
|
90
|
-
export {
|
|
90
|
+
export { resolveActionPrompt, buildContextSummary } from './actions/index.js';
|
|
91
91
|
export type { ActionContext, ActionDefinition } from './actions/index.js';
|
|
92
92
|
export { PROJECT_TYPES, getProjectTypeConfig, getEnrichedProjectTypeConfig, getProjectTypesByCategory, generalConfig, softwareConfig, researchConfig, businessPlanConfig, contentConfig, techDocsConfig, courseConfig, MACRO_META_REGISTRY, resolveActionMeta, getRelevantMacros, getMacroMeta, getAllMacroMeta, } from './project-types/index.js';
|
|
93
93
|
export type { ActionMeta, MacroMeta, MacroCategory, MacroCapabilities, } from './project-types/index.js';
|
package/dist/index.js
CHANGED
|
@@ -166,7 +166,7 @@ export { platformMacros, designMacro, sketchMacro, prdMacro, refineMacro, refine
|
|
|
166
166
|
// =============================================================================
|
|
167
167
|
// Contextual Actions (skill invocations with context)
|
|
168
168
|
// =============================================================================
|
|
169
|
-
export {
|
|
169
|
+
export { resolveActionPrompt, buildContextSummary } from './actions/index.js';
|
|
170
170
|
// =============================================================================
|
|
171
171
|
// Project Types
|
|
172
172
|
// =============================================================================
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* └── project-{id}.json # Per-project anchors
|
|
11
11
|
*/
|
|
12
12
|
import { AnchorManager } from '@compilr-dev/agents';
|
|
13
|
-
import type { Anchor, AnchorInput, AnchorQueryOptions } from '@compilr-dev/agents';
|
|
13
|
+
import type { Anchor, AnchorInput, AnchorPriority, AnchorQueryOptions } from '@compilr-dev/agents';
|
|
14
14
|
import type { IAnchorService } from './services.js';
|
|
15
15
|
export interface ProjectAnchorStoreConfig {
|
|
16
16
|
/** Directory for anchor JSON files (e.g. ~/.compilr-dev/anchors/) */
|
|
@@ -36,6 +36,55 @@ export declare class ProjectAnchorStore {
|
|
|
36
36
|
addAnchor(input: AnchorInput & {
|
|
37
37
|
projectId?: string;
|
|
38
38
|
}): Anchor;
|
|
39
|
+
/**
|
|
40
|
+
* Find an anchor by id, and say which file holds it.
|
|
41
|
+
*
|
|
42
|
+
* Searches the active project's manager then the global one — the same two the UI lists, and
|
|
43
|
+
* the same order `toService().remove` already uses. It deliberately does not sweep
|
|
44
|
+
* `this.managers`: those are lazily cached, so which ones exist depends on what happened
|
|
45
|
+
* earlier in the session, and the answer would drift with it.
|
|
46
|
+
*
|
|
47
|
+
* The null check on `currentProjectId` is defensive rather than behavioural — `String(null)`
|
|
48
|
+
* would key an empty manager and the lookup would fall through to global with the same
|
|
49
|
+
* result, and `loadPersistent` writes nothing for a file that does not exist. It is here so
|
|
50
|
+
* the intent is legible, not because a test can tell the difference. Mutating it away leaves
|
|
51
|
+
* every test green, and that is correct.
|
|
52
|
+
*/
|
|
53
|
+
findAnchor(id: string, currentProjectId?: string | null): {
|
|
54
|
+
anchor: Anchor;
|
|
55
|
+
projectKey: string | null;
|
|
56
|
+
} | undefined;
|
|
57
|
+
/** Remove an anchor by id from whichever file holds it. */
|
|
58
|
+
removeAnchorById(id: string, currentProjectId?: string | null): {
|
|
59
|
+
removed: boolean;
|
|
60
|
+
scope?: 'global' | 'project';
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Edit an anchor in place, keeping its id.
|
|
64
|
+
*
|
|
65
|
+
* ⚠️ WHY THE ID MATTERS. Without this the caller has to remove and re-add, which mints a new
|
|
66
|
+
* id — an open tab would then point at an anchor that no longer exists, and the row would
|
|
67
|
+
* jump in the list. `AnchorInput` accepts an id, so the re-add reuses the old one and both
|
|
68
|
+
* stay put.
|
|
69
|
+
*
|
|
70
|
+
* ⚠️ CHANGING SCOPE IS A MOVE BETWEEN FILES, not a field edit. Global anchors live in
|
|
71
|
+
* `global.json` and project ones in `project-<id>.json`, so switching "applies to" removes
|
|
72
|
+
* from one manager and adds to the other. The id survives that too.
|
|
73
|
+
*
|
|
74
|
+
* ⚠️ `createdAt` IS RESET, deliberately. `AnchorManager.add` always stamps `new Date()` and
|
|
75
|
+
* its `savePersistent` is private, so the only ways to keep the original are to mutate a
|
|
76
|
+
* stored object behind the manager's back or to widen `AnchorInput` in @compilr-dev/agents.
|
|
77
|
+
* Nothing displays `createdAt`; it is read only by the two eviction tie-breakers
|
|
78
|
+
* (`makeRoom`, `removeOldestLowPriority`), so on an edited anchor it now means "last edited"
|
|
79
|
+
* and that anchor is evicted last under budget pressure. Built-ins keep `new Date(0)` because
|
|
80
|
+
* they cannot be edited at all. See F-4.
|
|
81
|
+
*/
|
|
82
|
+
updateAnchor(id: string, patch: {
|
|
83
|
+
content?: string;
|
|
84
|
+
priority?: AnchorPriority;
|
|
85
|
+
tags?: string[];
|
|
86
|
+
scope?: 'global' | 'project';
|
|
87
|
+
}, currentProjectId?: string | null): Anchor | undefined;
|
|
39
88
|
/** Get all anchors across all cached managers. */
|
|
40
89
|
getAllAnchors(options?: AnchorQueryOptions): Anchor[];
|
|
41
90
|
/** Clear all anchors for a project and delete the persistence file. */
|
|
@@ -53,6 +102,29 @@ export declare class ProjectAnchorStore {
|
|
|
53
102
|
projectCounts: Map<string, number>;
|
|
54
103
|
totalTokens: number;
|
|
55
104
|
};
|
|
105
|
+
/**
|
|
106
|
+
* Usage against the caps, per file.
|
|
107
|
+
*
|
|
108
|
+
* ⚠️ THE CAPS ARE PER FILE, NOT COMBINED. Each `AnchorManager` enforces `maxAnchors` and
|
|
109
|
+
* `maxTokens` on its own store, so global.json and project-<id>.json each get the full
|
|
110
|
+
* budget. A single meter summing the two and measuring it against one cap would read half
|
|
111
|
+
* full at the moment an `anchor_add` starts evicting — which is the opposite of the point,
|
|
112
|
+
* since the meter exists to show the limit before it bites.
|
|
113
|
+
*
|
|
114
|
+
* Both are returned and the caller shows the fuller one.
|
|
115
|
+
*/
|
|
116
|
+
getUsage(projectId?: string | null): {
|
|
117
|
+
global: {
|
|
118
|
+
anchors: number;
|
|
119
|
+
tokens: number;
|
|
120
|
+
};
|
|
121
|
+
project: {
|
|
122
|
+
anchors: number;
|
|
123
|
+
tokens: number;
|
|
124
|
+
} | null;
|
|
125
|
+
maxAnchors: number;
|
|
126
|
+
maxTokens: number;
|
|
127
|
+
};
|
|
56
128
|
/** Clear all cached managers (useful for testing or refresh). */
|
|
57
129
|
clearCache(): void;
|
|
58
130
|
/** Create an IAnchorService implementation for use with createPlatformTools(). */
|
|
@@ -52,6 +52,89 @@ export class ProjectAnchorStore {
|
|
|
52
52
|
const manager = this.getManager(input.projectId ?? null);
|
|
53
53
|
return manager.add(input);
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Find an anchor by id, and say which file holds it.
|
|
57
|
+
*
|
|
58
|
+
* Searches the active project's manager then the global one — the same two the UI lists, and
|
|
59
|
+
* the same order `toService().remove` already uses. It deliberately does not sweep
|
|
60
|
+
* `this.managers`: those are lazily cached, so which ones exist depends on what happened
|
|
61
|
+
* earlier in the session, and the answer would drift with it.
|
|
62
|
+
*
|
|
63
|
+
* The null check on `currentProjectId` is defensive rather than behavioural — `String(null)`
|
|
64
|
+
* would key an empty manager and the lookup would fall through to global with the same
|
|
65
|
+
* result, and `loadPersistent` writes nothing for a file that does not exist. It is here so
|
|
66
|
+
* the intent is legible, not because a test can tell the difference. Mutating it away leaves
|
|
67
|
+
* every test green, and that is correct.
|
|
68
|
+
*/
|
|
69
|
+
findAnchor(id, currentProjectId) {
|
|
70
|
+
if (currentProjectId != null && currentProjectId !== '') {
|
|
71
|
+
const projectManager = this.getManager(currentProjectId);
|
|
72
|
+
const anchor = projectManager.get(id);
|
|
73
|
+
if (anchor)
|
|
74
|
+
return { anchor, projectKey: currentProjectId };
|
|
75
|
+
}
|
|
76
|
+
const anchor = this.getGlobalManager().get(id);
|
|
77
|
+
return anchor ? { anchor, projectKey: null } : undefined;
|
|
78
|
+
}
|
|
79
|
+
/** Remove an anchor by id from whichever file holds it. */
|
|
80
|
+
removeAnchorById(id, currentProjectId) {
|
|
81
|
+
const found = this.findAnchor(id, currentProjectId);
|
|
82
|
+
if (!found)
|
|
83
|
+
return { removed: false };
|
|
84
|
+
const removed = this.getManager(found.projectKey).remove(id);
|
|
85
|
+
return { removed, scope: found.projectKey === null ? 'global' : 'project' };
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Edit an anchor in place, keeping its id.
|
|
89
|
+
*
|
|
90
|
+
* ⚠️ WHY THE ID MATTERS. Without this the caller has to remove and re-add, which mints a new
|
|
91
|
+
* id — an open tab would then point at an anchor that no longer exists, and the row would
|
|
92
|
+
* jump in the list. `AnchorInput` accepts an id, so the re-add reuses the old one and both
|
|
93
|
+
* stay put.
|
|
94
|
+
*
|
|
95
|
+
* ⚠️ CHANGING SCOPE IS A MOVE BETWEEN FILES, not a field edit. Global anchors live in
|
|
96
|
+
* `global.json` and project ones in `project-<id>.json`, so switching "applies to" removes
|
|
97
|
+
* from one manager and adds to the other. The id survives that too.
|
|
98
|
+
*
|
|
99
|
+
* ⚠️ `createdAt` IS RESET, deliberately. `AnchorManager.add` always stamps `new Date()` and
|
|
100
|
+
* its `savePersistent` is private, so the only ways to keep the original are to mutate a
|
|
101
|
+
* stored object behind the manager's back or to widen `AnchorInput` in @compilr-dev/agents.
|
|
102
|
+
* Nothing displays `createdAt`; it is read only by the two eviction tie-breakers
|
|
103
|
+
* (`makeRoom`, `removeOldestLowPriority`), so on an edited anchor it now means "last edited"
|
|
104
|
+
* and that anchor is evicted last under budget pressure. Built-ins keep `new Date(0)` because
|
|
105
|
+
* they cannot be edited at all. See F-4.
|
|
106
|
+
*/
|
|
107
|
+
updateAnchor(id, patch, currentProjectId) {
|
|
108
|
+
const found = this.findAnchor(id, currentProjectId);
|
|
109
|
+
if (!found)
|
|
110
|
+
return undefined;
|
|
111
|
+
const { anchor, projectKey } = found;
|
|
112
|
+
let targetKey = projectKey;
|
|
113
|
+
if (patch.scope !== undefined) {
|
|
114
|
+
if (patch.scope === 'project') {
|
|
115
|
+
if (currentProjectId == null || currentProjectId === '') {
|
|
116
|
+
throw new Error('Cannot scope an anchor to a project: no active project. Use scope: "global" instead.');
|
|
117
|
+
}
|
|
118
|
+
targetKey = currentProjectId;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
targetKey = null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Remove first: re-adding the same id into the same manager would otherwise be an
|
|
125
|
+
// overwrite whose budget accounting counts the content twice.
|
|
126
|
+
this.getManager(projectKey).remove(id);
|
|
127
|
+
return this.getManager(targetKey).add({
|
|
128
|
+
id,
|
|
129
|
+
content: patch.content ?? anchor.content,
|
|
130
|
+
priority: patch.priority ?? anchor.priority,
|
|
131
|
+
scope: anchor.scope,
|
|
132
|
+
tags: patch.tags ?? anchor.tags,
|
|
133
|
+
metadata: anchor.metadata,
|
|
134
|
+
expiresAt: anchor.expiresAt,
|
|
135
|
+
projectId: targetKey ?? undefined,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
55
138
|
/** Get all anchors across all cached managers. */
|
|
56
139
|
getAllAnchors(options) {
|
|
57
140
|
const all = [];
|
|
@@ -127,6 +210,30 @@ export class ProjectAnchorStore {
|
|
|
127
210
|
totalTokens,
|
|
128
211
|
};
|
|
129
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Usage against the caps, per file.
|
|
215
|
+
*
|
|
216
|
+
* ⚠️ THE CAPS ARE PER FILE, NOT COMBINED. Each `AnchorManager` enforces `maxAnchors` and
|
|
217
|
+
* `maxTokens` on its own store, so global.json and project-<id>.json each get the full
|
|
218
|
+
* budget. A single meter summing the two and measuring it against one cap would read half
|
|
219
|
+
* full at the moment an `anchor_add` starts evicting — which is the opposite of the point,
|
|
220
|
+
* since the meter exists to show the limit before it bites.
|
|
221
|
+
*
|
|
222
|
+
* Both are returned and the caller shows the fuller one.
|
|
223
|
+
*/
|
|
224
|
+
getUsage(projectId) {
|
|
225
|
+
const globalManager = this.getGlobalManager();
|
|
226
|
+
const hasProject = projectId != null && projectId !== '';
|
|
227
|
+
const projectManager = hasProject ? this.getManager(projectId) : null;
|
|
228
|
+
return {
|
|
229
|
+
global: { anchors: globalManager.size, tokens: globalManager.getTotalTokens() },
|
|
230
|
+
project: projectManager === null
|
|
231
|
+
? null
|
|
232
|
+
: { anchors: projectManager.size, tokens: projectManager.getTotalTokens() },
|
|
233
|
+
maxAnchors: this.config.maxAnchors ?? 50,
|
|
234
|
+
maxTokens: this.config.maxTokens ?? 4000,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
130
237
|
/** Clear all cached managers (useful for testing or refresh). */
|
|
131
238
|
clearCache() {
|
|
132
239
|
this.managers.clear();
|
|
@@ -164,6 +271,32 @@ export class ProjectAnchorStore {
|
|
|
164
271
|
tags: anchor.tags,
|
|
165
272
|
});
|
|
166
273
|
},
|
|
274
|
+
update: (id, patch) => {
|
|
275
|
+
const projId = this.config.getCurrentProjectId();
|
|
276
|
+
const updated = this.updateAnchor(id, patch, projId == null ? null : String(projId));
|
|
277
|
+
if (!updated)
|
|
278
|
+
return Promise.resolve(null);
|
|
279
|
+
return Promise.resolve({
|
|
280
|
+
id: updated.id,
|
|
281
|
+
content: updated.content,
|
|
282
|
+
priority: updated.priority,
|
|
283
|
+
scope: updated.projectId === undefined ? 'global' : 'project',
|
|
284
|
+
tags: updated.tags,
|
|
285
|
+
});
|
|
286
|
+
},
|
|
287
|
+
get: (id) => {
|
|
288
|
+
const projId = this.config.getCurrentProjectId();
|
|
289
|
+
const found = this.findAnchor(id, projId == null ? null : String(projId));
|
|
290
|
+
if (!found)
|
|
291
|
+
return Promise.resolve(null);
|
|
292
|
+
return Promise.resolve({
|
|
293
|
+
id: found.anchor.id,
|
|
294
|
+
content: found.anchor.content,
|
|
295
|
+
priority: found.anchor.priority,
|
|
296
|
+
scope: found.projectKey === null ? 'global' : 'project',
|
|
297
|
+
tags: found.anchor.tags,
|
|
298
|
+
});
|
|
299
|
+
},
|
|
167
300
|
remove: (id) => {
|
|
168
301
|
let removed = false;
|
|
169
302
|
let scope;
|
|
@@ -23,6 +23,21 @@ export interface IAnchorService {
|
|
|
23
23
|
removed: boolean;
|
|
24
24
|
scope?: string;
|
|
25
25
|
}>;
|
|
26
|
+
/**
|
|
27
|
+
* Edit an anchor in place, keeping its id.
|
|
28
|
+
*
|
|
29
|
+
* Optional so existing hosts are unaffected. Without it a caller has to remove and re-add,
|
|
30
|
+
* which mints a new id — anything holding the old one (an open tab, a row in a list) is then
|
|
31
|
+
* pointing at an anchor that no longer exists.
|
|
32
|
+
*/
|
|
33
|
+
update?(id: string, patch: {
|
|
34
|
+
content?: string;
|
|
35
|
+
priority?: AnchorPriority;
|
|
36
|
+
tags?: string[];
|
|
37
|
+
scope?: 'global' | 'project';
|
|
38
|
+
}): Promise<AnchorData | null>;
|
|
39
|
+
/** One anchor by id, or null. */
|
|
40
|
+
get?(id: string): Promise<AnchorData | null>;
|
|
26
41
|
list(options?: {
|
|
27
42
|
scope?: 'global' | 'project' | 'all';
|
|
28
43
|
priority?: AnchorPriority;
|
package/package.json
CHANGED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Action Registry — Defines which actions are available and where.
|
|
3
|
-
*
|
|
4
|
-
* Each action maps to a skill (from platformMacros/builtinSkills)
|
|
5
|
-
* but adds UI metadata: icon, label, category, applicable contexts,
|
|
6
|
-
* and suggested agent role.
|
|
7
|
-
*/
|
|
8
|
-
import type { ActionDefinition } from './types.js';
|
|
9
|
-
export declare const ACTION_REGISTRY: ActionDefinition[];
|
|
10
|
-
/**
|
|
11
|
-
* Get actions applicable to a given context type.
|
|
12
|
-
*/
|
|
13
|
-
export declare function getActionsForContext(contextType: 'project' | 'workitem' | 'document'): ActionDefinition[];
|
|
14
|
-
/**
|
|
15
|
-
* Get an action definition by ID.
|
|
16
|
-
*/
|
|
17
|
-
export declare function getActionById(id: string): ActionDefinition | undefined;
|
package/dist/actions/registry.js
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Action Registry — Defines which actions are available and where.
|
|
3
|
-
*
|
|
4
|
-
* Each action maps to a skill (from platformMacros/builtinSkills)
|
|
5
|
-
* but adds UI metadata: icon, label, category, applicable contexts,
|
|
6
|
-
* and suggested agent role.
|
|
7
|
-
*/
|
|
8
|
-
export const ACTION_REGISTRY = [
|
|
9
|
-
// ─── Project-level actions ─────────────────────────────────────────────
|
|
10
|
-
{
|
|
11
|
-
id: 'design',
|
|
12
|
-
label: 'Design App',
|
|
13
|
-
description: 'Describe an idea, get a full application design',
|
|
14
|
-
icon: 'Wand2',
|
|
15
|
-
applicableTo: ['project'],
|
|
16
|
-
category: 'design',
|
|
17
|
-
// BA owns requirements: the 'ba' role (analyst profile) has both
|
|
18
|
-
// backlog_write and documents, so it can complete the full /design action
|
|
19
|
-
// (create work items + write the PRD). The architect profile lacks
|
|
20
|
-
// backlog_write and cannot create the backlog.
|
|
21
|
-
suggestedRole: 'ba',
|
|
22
|
-
needsInput: true,
|
|
23
|
-
inputPrompt: 'What would you like to design?',
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
id: 'sketch',
|
|
27
|
-
label: 'Quick Sketch',
|
|
28
|
-
description: 'Quickly sketch out an idea or concept',
|
|
29
|
-
icon: 'Pencil',
|
|
30
|
-
applicableTo: ['project'],
|
|
31
|
-
category: 'design',
|
|
32
|
-
needsInput: true,
|
|
33
|
-
inputPrompt: 'What would you like to sketch?',
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
id: 'prd',
|
|
37
|
-
label: 'Write PRD',
|
|
38
|
-
description: 'Create a product requirements document',
|
|
39
|
-
icon: 'FileText',
|
|
40
|
-
applicableTo: ['project'],
|
|
41
|
-
// PRD is artifact-authoring (requirements), grouped with design/architecture
|
|
42
|
-
// rather than backlog-breakdown 'planning' (refine/refine-item).
|
|
43
|
-
category: 'design',
|
|
44
|
-
// Requirements work → Business Analyst, not PM. The 'ba' role (analyst
|
|
45
|
-
// profile) is purpose-built for requirements gathering and has the
|
|
46
|
-
// documents tools needed to author the PRD.
|
|
47
|
-
suggestedRole: 'ba',
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
id: 'architecture',
|
|
51
|
-
label: 'Architecture',
|
|
52
|
-
description: 'Design the system architecture',
|
|
53
|
-
icon: 'Network',
|
|
54
|
-
applicableTo: ['project'],
|
|
55
|
-
category: 'design',
|
|
56
|
-
suggestedRole: 'architect',
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
id: 'scaffold',
|
|
60
|
-
label: 'Scaffold',
|
|
61
|
-
description: 'Generate project code from the app model',
|
|
62
|
-
icon: 'Layers',
|
|
63
|
-
applicableTo: ['project'],
|
|
64
|
-
category: 'development',
|
|
65
|
-
suggestedRole: 'developer',
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
id: 'session-notes',
|
|
69
|
-
label: 'Session Notes',
|
|
70
|
-
description: 'Summarize what was accomplished in this session',
|
|
71
|
-
icon: 'StickyNote',
|
|
72
|
-
applicableTo: ['project'],
|
|
73
|
-
category: 'documentation',
|
|
74
|
-
},
|
|
75
|
-
// ─── Work item actions ─────────────────────────────────────────────────
|
|
76
|
-
{
|
|
77
|
-
id: 'refine',
|
|
78
|
-
label: 'Refine',
|
|
79
|
-
description: 'Break down into smaller tasks',
|
|
80
|
-
icon: 'RefreshCw',
|
|
81
|
-
applicableTo: ['project', 'workitem'],
|
|
82
|
-
category: 'planning',
|
|
83
|
-
suggestedRole: 'pm',
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
id: 'refine-item',
|
|
87
|
-
label: 'Refine Item',
|
|
88
|
-
description: 'Add detail and acceptance criteria to this item',
|
|
89
|
-
icon: 'RefreshCw',
|
|
90
|
-
applicableTo: ['workitem'],
|
|
91
|
-
category: 'planning',
|
|
92
|
-
suggestedRole: 'pm',
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
id: 'build',
|
|
96
|
-
label: 'Build',
|
|
97
|
-
description: 'Implement this work item',
|
|
98
|
-
icon: 'Hammer',
|
|
99
|
-
applicableTo: ['workitem'],
|
|
100
|
-
category: 'development',
|
|
101
|
-
suggestedRole: 'developer',
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
id: 'code-review',
|
|
105
|
-
label: 'Code Review',
|
|
106
|
-
description: 'Review code for quality and correctness',
|
|
107
|
-
icon: 'Search',
|
|
108
|
-
applicableTo: ['project', 'workitem'],
|
|
109
|
-
category: 'development',
|
|
110
|
-
suggestedRole: 'qa',
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
id: 'debug',
|
|
114
|
-
label: 'Debug',
|
|
115
|
-
description: 'Debug an issue or error',
|
|
116
|
-
icon: 'Bug',
|
|
117
|
-
applicableTo: ['project', 'workitem'],
|
|
118
|
-
category: 'development',
|
|
119
|
-
suggestedRole: 'developer',
|
|
120
|
-
},
|
|
121
|
-
// ─── Document actions ──────────────────────────────────────────────────
|
|
122
|
-
{
|
|
123
|
-
id: 'explain',
|
|
124
|
-
label: 'Explain',
|
|
125
|
-
description: 'Explain this code or document',
|
|
126
|
-
icon: 'BookOpen',
|
|
127
|
-
applicableTo: ['document', 'workitem'],
|
|
128
|
-
category: 'documentation',
|
|
129
|
-
},
|
|
130
|
-
// ─── Analysis actions ──────────────────────────────────────────────────
|
|
131
|
-
{
|
|
132
|
-
id: 'security-review',
|
|
133
|
-
label: 'Security Review',
|
|
134
|
-
description: 'Review for security vulnerabilities',
|
|
135
|
-
icon: 'Shield',
|
|
136
|
-
applicableTo: ['project'],
|
|
137
|
-
category: 'analysis',
|
|
138
|
-
suggestedRole: 'security',
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
id: 'refactor',
|
|
142
|
-
label: 'Refactor',
|
|
143
|
-
description: 'Improve code quality without changing behavior',
|
|
144
|
-
icon: 'Scissors',
|
|
145
|
-
applicableTo: ['project', 'workitem'],
|
|
146
|
-
category: 'development',
|
|
147
|
-
suggestedRole: 'developer',
|
|
148
|
-
},
|
|
149
|
-
];
|
|
150
|
-
/**
|
|
151
|
-
* Get actions applicable to a given context type.
|
|
152
|
-
*/
|
|
153
|
-
export function getActionsForContext(contextType) {
|
|
154
|
-
return ACTION_REGISTRY.filter((a) => a.applicableTo.includes(contextType));
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Get an action definition by ID.
|
|
158
|
-
*/
|
|
159
|
-
export function getActionById(id) {
|
|
160
|
-
return ACTION_REGISTRY.find((a) => a.id === id);
|
|
161
|
-
}
|