@compilr-dev/cli 0.5.1 → 0.5.2

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.
Files changed (40) hide show
  1. package/LICENSE +108 -0
  2. package/README.md +2 -2
  3. package/dist/.tsbuildinfo.app +1 -1
  4. package/dist/.tsbuildinfo.data +1 -1
  5. package/dist/.tsbuildinfo.domain +1 -1
  6. package/dist/.tsbuildinfo.foundation +1 -1
  7. package/dist/commands-v2/handlers/context.js +20 -0
  8. package/dist/commands-v2/handlers/project.js +52 -9
  9. package/dist/compilr-diff-companion.vsix +0 -0
  10. package/dist/db/repositories/document-repository.js +1 -0
  11. package/dist/db/schema.d.ts +1 -1
  12. package/dist/repl-helpers.js +2 -0
  13. package/dist/repl-v2.js +16 -5
  14. package/dist/tool-names.d.ts +5 -0
  15. package/dist/tool-names.js +12 -0
  16. package/dist/tools/db-tools.d.ts +6 -1
  17. package/dist/tools/db-tools.js +6 -2
  18. package/dist/tools/meta-tools.d.ts +1 -1
  19. package/dist/tools/platform-adapter.d.ts +6 -0
  20. package/dist/tools/platform-adapter.js +10 -0
  21. package/dist/tools.js +3 -1
  22. package/dist/ui/constants/labels.js +1 -0
  23. package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +1 -0
  24. package/dist/ui/overlay/impl/workflow-overlay-v2.js +5 -3
  25. package/dist/ui/tool-formatters.js +190 -6
  26. package/package.json +5 -4
  27. package/dist/tools/anchor-tools.d.ts +0 -31
  28. package/dist/tools/anchor-tools.js +0 -255
  29. package/dist/tools/artifact-tools.d.ts +0 -42
  30. package/dist/tools/artifact-tools.js +0 -328
  31. package/dist/tools/backlog-wrappers.d.ts +0 -56
  32. package/dist/tools/backlog-wrappers.js +0 -353
  33. package/dist/tools/document-db.d.ts +0 -43
  34. package/dist/tools/document-db.js +0 -220
  35. package/dist/tools/plan-tools.d.ts +0 -54
  36. package/dist/tools/plan-tools.js +0 -338
  37. package/dist/tools/recall-work-tool.d.ts +0 -18
  38. package/dist/tools/recall-work-tool.js +0 -82
  39. package/dist/tools/workitem-db.d.ts +0 -135
  40. package/dist/tools/workitem-db.js +0 -730
@@ -16,6 +16,7 @@
16
16
  * - recall-work-tool.ts (1 tool)
17
17
  */
18
18
  import { createPlatformTools, } from '@compilr-dev/sdk';
19
+ import { createFactoryTools } from '@compilr-dev/factory';
19
20
  import { projectRepository, workItemRepository, documentRepository, planRepository, } from '../db/repositories/index.js';
20
21
  import { getCurrentProject, setCurrentProject } from './project-db.js';
21
22
  import { awardFirstProject, awardWorkItemCompletion } from '../games/coins.js';
@@ -392,3 +393,12 @@ const config = {
392
393
  * - 1 episode tool (recall_work)
393
394
  */
394
395
  export const allPlatformTools = createPlatformTools(config);
396
+ /**
397
+ * All 5 factory tools from @compilr-dev/factory:
398
+ * - 3 model tools (app_model_get, app_model_update, app_model_validate)
399
+ * - 2 factory tools (factory_scaffold, factory_list_toolkits)
400
+ */
401
+ export const allFactoryTools = createFactoryTools({
402
+ context,
403
+ cwd: process.cwd(),
404
+ });
package/dist/tools.js CHANGED
@@ -127,7 +127,7 @@ import { delegationStatusTool } from './tools/delegation-status.js';
127
127
  import { handoffTool } from './tools/handoff.js';
128
128
  import { guideTool } from './tools/guide-tool.js';
129
129
  // DB tools for project, work item, document, plan, backlog, anchor, artifact, and episode management
130
- import { allDbTools } from './tools/db-tools.js';
130
+ import { allDbTools, allFactoryTools } from './tools/db-tools.js';
131
131
  // Meta-tools for dynamic tool loading
132
132
  import { initializeMetaToolRegistry, generateToolIndex, getMetaToolCount, META_TOOLS_SYSTEM_PROMPT_PREFIX, setMetaToolFilter, getRegisteredMetaTools, createMetaToolFallback, getToolInfoTool, } from './tools/meta-tools.js';
133
133
  // Re-export for use in agent.ts
@@ -212,6 +212,8 @@ const META_REGISTRY_TOOLS = [
212
212
  getComplexityTool,
213
213
  // DB tools (project, workitem, document, plan, backlog, anchor, artifact, episode)
214
214
  ...allDbTools,
215
+ // Factory tools (app_model_get, app_model_update, app_model_validate, factory_scaffold, factory_list_toolkits)
216
+ ...allFactoryTools,
215
217
  // Delegation status (coordinator query)
216
218
  delegationStatusTool,
217
219
  ];
@@ -22,6 +22,7 @@ export const DOC_TYPE_LABELS = {
22
22
  'design': 'DESIGN',
23
23
  'notes': 'NOTES',
24
24
  'plan': 'PLAN',
25
+ 'app-model': 'MODEL',
25
26
  };
26
27
  // =============================================================================
27
28
  // Plan Status Labels
@@ -24,6 +24,7 @@ interface ProjectStats {
24
24
  hasPrd: boolean;
25
25
  hasArchDocs: boolean;
26
26
  hasScaffold: boolean;
27
+ hasModel: boolean;
27
28
  }
28
29
  interface ActionItem {
29
30
  label: string;
@@ -53,7 +53,7 @@ const PHASES = [
53
53
  id: 'scaffold',
54
54
  name: 'Scaffold',
55
55
  command: '/scaffold',
56
- description: 'Create project foundation',
56
+ description: 'Create project foundation (auto-generates if model available)',
57
57
  isComplete: (_project, stats) => stats.hasScaffold,
58
58
  isActive: (_project, stats) => stats.totalItems >= 3 && !stats.hasScaffold,
59
59
  },
@@ -82,6 +82,7 @@ function getProjectStats(project) {
82
82
  const docs = documentRepository.listByProject(project.id);
83
83
  const hasPrd = docs.some(d => d.docType === 'prd');
84
84
  const hasArchDocs = docs.some(d => d.docType === 'architecture');
85
+ const hasModel = docs.some(d => d.docType === 'app-model');
85
86
  const hasScaffold = items.some(i => i.title.toLowerCase().includes('scaffold') && i.status === 'completed') || project.metadata?.scaffolded === true;
86
87
  return {
87
88
  totalItems: items.length,
@@ -90,6 +91,7 @@ function getProjectStats(project) {
90
91
  hasPrd,
91
92
  hasArchDocs,
92
93
  hasScaffold,
94
+ hasModel,
93
95
  };
94
96
  }
95
97
  function buildActionsItems(project, stats) {
@@ -130,9 +132,9 @@ function buildActionsItems(project, stats) {
130
132
  }
131
133
  if (stats.totalItems > 0 && !stats.hasScaffold) {
132
134
  actions.push({
133
- label: 'Scaffold Project',
135
+ label: stats.hasModel ? 'Generate from Model' : 'Scaffold Project',
134
136
  command: '/scaffold',
135
- description: 'Create project foundation',
137
+ description: stats.hasModel ? 'Auto-generate from Application Model' : 'Create project foundation',
136
138
  enabled: true,
137
139
  });
138
140
  }
@@ -130,6 +130,21 @@ export function formatToolResult(toolName, result) {
130
130
  else if (toolLower.startsWith('artifact_')) {
131
131
  ({ content, summary } = formatArtifact(toolLower, innerResult));
132
132
  }
133
+ else if (toolLower === 'app_model_get') {
134
+ ({ content, summary } = formatAppModelGet(innerResult));
135
+ }
136
+ else if (toolLower === 'app_model_update') {
137
+ ({ content, summary } = formatAppModelUpdate(innerResult));
138
+ }
139
+ else if (toolLower === 'app_model_validate') {
140
+ ({ content, summary } = formatAppModelValidate(innerResult));
141
+ }
142
+ else if (toolLower === 'factory_scaffold') {
143
+ ({ content, summary } = formatFactoryScaffold(innerResult));
144
+ }
145
+ else if (toolLower === 'factory_list_toolkits') {
146
+ ({ content, summary } = formatFactoryListToolkits(innerResult));
147
+ }
133
148
  else if (toolLower === 'list_tools') {
134
149
  ({ content, summary } = formatListTools(innerResult));
135
150
  }
@@ -973,14 +988,22 @@ function formatListTools(result) {
973
988
  return { content: '', summary: count ? `${String(count)} tools available` : 'No tools' };
974
989
  }
975
990
  function formatGetToolInfo(result) {
991
+ // Compact schema format (SDK 0.1.15+): result is a string like "tool_name(...)\n description"
992
+ if (typeof result === 'string') {
993
+ // Extract tool name from signature line: "tool_name(params...)"
994
+ const parenIdx = result.indexOf('(');
995
+ const toolName = parenIdx > 0 ? result.slice(0, parenIdx) : null;
996
+ if (toolName) {
997
+ return { content: '', summary: `Schema: ${toolName}` };
998
+ }
999
+ return { content: '', summary: result.split('\n')[0].slice(0, 80) };
1000
+ }
1001
+ // Legacy object format: { name, description, parameters }
976
1002
  const name = result.name;
977
- const description = result.description;
978
- if (name && description) {
979
- // First sentence of description
980
- const firstSentence = description.split('.')[0].slice(0, 60);
981
- return { content: '', summary: `${name}: ${firstSentence}` };
1003
+ if (name) {
1004
+ return { content: '', summary: `Schema: ${name}` };
982
1005
  }
983
- return { content: '', summary: name || 'Tool info' };
1006
+ return { content: '', summary: 'Tool info' };
984
1007
  }
985
1008
  function formatDelegateBackground(result) {
986
1009
  const delegated = result.delegated;
@@ -1002,6 +1025,167 @@ function formatDelegate(result) {
1002
1025
  const message = result.message;
1003
1026
  return { content: '', summary: message || 'Delegated' };
1004
1027
  }
1028
+ // =============================================================================
1029
+ // Factory Tool Formatters
1030
+ // =============================================================================
1031
+ /**
1032
+ * Unwrap the use_tool envelope to get the actual tool result.
1033
+ * use_tool wraps as: { tool, status, message, result: { success, result: actualData } }
1034
+ */
1035
+ function unwrapToolResult(result) {
1036
+ const inner = result.result;
1037
+ if (inner && typeof inner === 'object' && !Array.isArray(inner)) {
1038
+ const innerObj = inner;
1039
+ // If wrapped by use_tool, the actual data is in innerObj.result
1040
+ if (innerObj.result && typeof innerObj.result === 'object' && !Array.isArray(innerObj.result)) {
1041
+ return innerObj.result;
1042
+ }
1043
+ return innerObj;
1044
+ }
1045
+ return result;
1046
+ }
1047
+ function formatAppModelGet(result) {
1048
+ const data = unwrapToolResult(result);
1049
+ // No model exists
1050
+ if (data.exists === false) {
1051
+ const message = data.message;
1052
+ return { content: '', summary: message || 'No Application Model found' };
1053
+ }
1054
+ // Summary scope
1055
+ if (data.entityCount !== undefined) {
1056
+ const name = data.name || '?';
1057
+ const entityCount = data.entityCount;
1058
+ const toolkit = data.toolkit || '?';
1059
+ const revision = data.revision;
1060
+ const entities = data.entities;
1061
+ const summary = `${name} — ${String(entityCount)} entities, toolkit: ${toolkit}${revision !== undefined ? `, rev ${String(revision)}` : ''}`;
1062
+ const lines = [];
1063
+ if (entities?.length) {
1064
+ for (const e of entities) {
1065
+ const rels = e.relationshipCount > 0 ? `, ${String(e.relationshipCount)} rel` : '';
1066
+ lines.push(` ${e.name} (${String(e.fieldCount)} fields, ${e.views.join('/')})${rels}`);
1067
+ }
1068
+ }
1069
+ const features = data.features;
1070
+ if (features) {
1071
+ const enabled = Object.entries(features).filter(([, v]) => v).map(([k]) => k);
1072
+ if (enabled.length)
1073
+ lines.push(`Features: ${enabled.join(', ')}`);
1074
+ }
1075
+ return { content: lines.join('\n'), summary };
1076
+ }
1077
+ // Single entity scope
1078
+ if (data.entity && typeof data.entity === 'object') {
1079
+ const entity = data.entity;
1080
+ const name = entity.name || '?';
1081
+ const fields = entity.fields;
1082
+ const rels = entity.relationships;
1083
+ const summary = `Entity: ${name} (${String(fields?.length ?? 0)} fields)`;
1084
+ const lines = [];
1085
+ if (fields?.length) {
1086
+ lines.push('Fields:');
1087
+ for (const f of fields)
1088
+ lines.push(` ${f.name}: ${f.type}`);
1089
+ }
1090
+ if (rels?.length) {
1091
+ lines.push('Relationships:');
1092
+ for (const r of rels)
1093
+ lines.push(` ${r.type} → ${r.target}`);
1094
+ }
1095
+ return { content: lines.join('\n'), summary };
1096
+ }
1097
+ // Section scopes (identity, features, layout, theme, techStack)
1098
+ const section = data.identity ?? data.features ?? data.layout ?? data.theme ?? data.techStack;
1099
+ if (section && typeof section === 'object') {
1100
+ const entries = Object.entries(section);
1101
+ const summary = entries.map(([k, v]) => `${k}: ${String(v)}`).join(', ');
1102
+ return { content: '', summary: truncate(summary, 80) };
1103
+ }
1104
+ // Full model fallback
1105
+ const message = data.message;
1106
+ return { content: '', summary: message || 'Application Model' };
1107
+ }
1108
+ function formatAppModelUpdate(result) {
1109
+ const data = unwrapToolResult(result);
1110
+ const op = data.op || '';
1111
+ const revision = data.revision;
1112
+ const message = data.message;
1113
+ const revInfo = revision !== undefined ? ` (rev ${String(revision)})` : '';
1114
+ const summary = message || `${op} applied${revInfo}`;
1115
+ return { content: '', summary: truncate(summary, 80) };
1116
+ }
1117
+ function formatAppModelValidate(result) {
1118
+ const data = unwrapToolResult(result);
1119
+ const valid = data.valid;
1120
+ const errors = data.errors;
1121
+ const revision = data.revision;
1122
+ if (valid) {
1123
+ return { content: '', summary: `Model valid${revision !== undefined ? ` (rev ${String(revision)})` : ''}` };
1124
+ }
1125
+ const errorCount = errors?.length ?? 0;
1126
+ const summary = `${String(errorCount)} validation error(s)`;
1127
+ const lines = errors?.slice(0, 10).map((e) => `${e.path || '?'}: ${e.message || 'error'}`) ?? [];
1128
+ if (errorCount > 10)
1129
+ lines.push(`... and ${String(errorCount - 10)} more`);
1130
+ return { content: lines.join('\n'), summary };
1131
+ }
1132
+ function formatFactoryScaffold(result) {
1133
+ const data = unwrapToolResult(result);
1134
+ const toolkit = data.toolkit || '?';
1135
+ const fileCount = data.fileCount;
1136
+ const files = data.files;
1137
+ const dryRun = data.dryRun;
1138
+ const warnings = data.warnings;
1139
+ const message = data.message;
1140
+ const mode = dryRun ? 'Dry run' : 'Generated';
1141
+ const summary = message || `${mode}: ${String(fileCount ?? 0)} files (${toolkit})`;
1142
+ // Build detailed content with file listing
1143
+ const lines = [];
1144
+ if (files?.length) {
1145
+ // Group files by directory
1146
+ const dirs = new Map();
1147
+ for (const f of files) {
1148
+ const parts = f.split('/');
1149
+ const dir = parts.length > 1 ? parts.slice(0, -1).join('/') : '.';
1150
+ const file = parts[parts.length - 1];
1151
+ const existing = dirs.get(dir);
1152
+ if (existing) {
1153
+ existing.push(file);
1154
+ }
1155
+ else {
1156
+ dirs.set(dir, [file]);
1157
+ }
1158
+ }
1159
+ for (const [dir, dirFiles] of dirs) {
1160
+ lines.push(`${dir}/`);
1161
+ for (const f of dirFiles)
1162
+ lines.push(` ${f}`);
1163
+ }
1164
+ }
1165
+ if (warnings?.length) {
1166
+ lines.push('');
1167
+ lines.push('Warnings:');
1168
+ for (const w of warnings)
1169
+ lines.push(` ! ${w}`);
1170
+ }
1171
+ return { content: lines.join('\n'), summary };
1172
+ }
1173
+ function formatFactoryListToolkits(result) {
1174
+ const data = unwrapToolResult(result);
1175
+ const count = data.count;
1176
+ const toolkits = data.toolkits;
1177
+ if (!toolkits?.length) {
1178
+ return { content: '', summary: 'No toolkits available' };
1179
+ }
1180
+ const summary = `${String(count ?? toolkits.length)} toolkit(s)`;
1181
+ const lines = toolkits.map((t) => {
1182
+ const name = t.name || t.id || '?';
1183
+ const desc = t.description ? ` — ${t.description}` : '';
1184
+ const sections = t.requiredSections?.length ? `\n Requires: ${t.requiredSections.join(', ')}` : '';
1185
+ return `${name}${desc}${sections}`;
1186
+ });
1187
+ return { content: lines.join('\n'), summary };
1188
+ }
1005
1189
  function formatGeneric(result) {
1006
1190
  const content = typeof result.content === 'string'
1007
1191
  ? result.content
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compilr-dev/cli",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "AI-powered coding assistant CLI using @compilr-dev/agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -35,7 +35,7 @@
35
35
  "terminal"
36
36
  ],
37
37
  "author": "Carmelo Scozzola",
38
- "license": "MIT",
38
+ "license": "FSL-1.1-MIT",
39
39
  "repository": {
40
40
  "type": "git",
41
41
  "url": "git+https://github.com/compilr-dev/cli.git"
@@ -54,10 +54,11 @@
54
54
  },
55
55
  "dependencies": {
56
56
  "@anthropic-ai/sdk": "^0.74.0",
57
- "@compilr-dev/agents": "^0.3.16",
57
+ "@compilr-dev/agents": "^0.3.20",
58
58
  "@compilr-dev/agents-coding": "^1.0.2",
59
59
  "@compilr-dev/editor-core": "^0.0.2",
60
- "@compilr-dev/sdk": "^0.1.11",
60
+ "@compilr-dev/factory": "^0.1.4",
61
+ "@compilr-dev/sdk": "^0.1.16",
61
62
  "@compilr-dev/ui-core": "^0.0.1",
62
63
  "@modelcontextprotocol/sdk": "^1.23.0",
63
64
  "better-sqlite3": "^12.5.0",
@@ -1,31 +0,0 @@
1
- /**
2
- * Anchor Tools - Agent tools for managing anchors
3
- *
4
- * Provides anchor_add and anchor_remove tools that allow
5
- * the agent to add critical context that survives compaction.
6
- */
7
- interface AnchorAddInput {
8
- /** The anchor content - critical information to preserve */
9
- content: string;
10
- /** Priority level: 'critical' | 'safety' | 'info' (default: 'info') */
11
- priority?: 'critical' | 'safety' | 'info';
12
- /** Scope: 'global' or 'project' (default: 'project' if active project, else 'global') */
13
- scope?: 'global' | 'project';
14
- /** Tags for categorization */
15
- tags?: string[];
16
- }
17
- interface AnchorRemoveInput {
18
- /** ID of the anchor to remove */
19
- id: string;
20
- }
21
- interface AnchorListInput {
22
- /** Filter by scope: 'global' | 'project' | 'all' (default: 'all') */
23
- scope?: 'global' | 'project' | 'all';
24
- /** Filter by priority */
25
- priority?: 'critical' | 'safety' | 'info';
26
- }
27
- export declare const anchorAddTool: import("@compilr-dev/sdk").Tool<AnchorAddInput>;
28
- export declare const anchorRemoveTool: import("@compilr-dev/sdk").Tool<AnchorRemoveInput>;
29
- export declare const anchorListTool: import("@compilr-dev/sdk").Tool<AnchorListInput>;
30
- export declare const allAnchorTools: (import("@compilr-dev/sdk").Tool<AnchorAddInput> | import("@compilr-dev/sdk").Tool<AnchorRemoveInput>)[];
31
- export {};
@@ -1,255 +0,0 @@
1
- /**
2
- * Anchor Tools - Agent tools for managing anchors
3
- *
4
- * Provides anchor_add and anchor_remove tools that allow
5
- * the agent to add critical context that survives compaction.
6
- */
7
- import { defineTool } from '@compilr-dev/sdk';
8
- import { getGlobalAnchorManager, getAnchorManager, } from '../anchors/index.js';
9
- import { getActiveProject } from './project-db.js';
10
- // =============================================================================
11
- // anchor_add Tool
12
- // =============================================================================
13
- export const anchorAddTool = defineTool({
14
- name: 'anchor_add',
15
- description: 'Add critical information that must survive context compaction. ' +
16
- 'Use this for: project context, important decisions, user preferences, ' +
17
- 'architectural constraints, or any information that should persist across the entire conversation. ' +
18
- 'Anchors are always included at the top of the context window.',
19
- inputSchema: {
20
- type: 'object',
21
- properties: {
22
- content: {
23
- type: 'string',
24
- description: 'The critical information to preserve. Keep it concise but complete.',
25
- },
26
- priority: {
27
- type: 'string',
28
- enum: ['critical', 'safety', 'info'],
29
- description: 'Priority level. "critical" for must-never-forget info (user preferences, key constraints), ' +
30
- '"safety" for safety-related context, "info" for general helpful context.',
31
- },
32
- scope: {
33
- type: 'string',
34
- enum: ['global', 'project'],
35
- description: 'Scope for the anchor. "global" persists across all projects, ' +
36
- '"project" is specific to the current project (requires active project).',
37
- },
38
- tags: {
39
- type: 'array',
40
- items: { type: 'string' },
41
- description: 'Optional tags for categorization (e.g., ["architecture", "decision"])',
42
- },
43
- },
44
- required: ['content'],
45
- },
46
- execute: (input) => {
47
- try {
48
- // Validate content
49
- if (!input.content || input.content.trim().length === 0) {
50
- return Promise.resolve({
51
- success: false,
52
- error: 'Anchor content is required and cannot be empty',
53
- });
54
- }
55
- const content = input.content.trim();
56
- const priority = input.priority ?? 'info';
57
- const activeProject = getActiveProject();
58
- // Determine scope
59
- let scope = input.scope;
60
- if (!scope) {
61
- scope = activeProject ? 'project' : 'global';
62
- }
63
- // Validate project scope
64
- if (scope === 'project' && !activeProject) {
65
- return Promise.resolve({
66
- success: false,
67
- error: 'Cannot add project-scoped anchor: no active project. Use scope: "global" instead.',
68
- });
69
- }
70
- // Get project ID for project-scoped anchors (validated above that activeProject exists)
71
- const projectId = scope === 'project' && activeProject
72
- ? String(activeProject.id)
73
- : undefined;
74
- // Get the appropriate manager
75
- const manager = scope === 'global'
76
- ? getGlobalAnchorManager()
77
- : getAnchorManager(projectId ?? '');
78
- // Add the anchor
79
- const anchor = manager.add({
80
- content,
81
- priority,
82
- scope: 'persistent', // Anchors persist across sessions
83
- tags: input.tags,
84
- projectId,
85
- });
86
- return Promise.resolve({
87
- success: true,
88
- result: {
89
- id: anchor.id,
90
- content: anchor.content,
91
- priority: anchor.priority,
92
- scope: scope,
93
- tags: anchor.tags,
94
- message: `Anchor added successfully (${scope} scope, ${priority} priority)`,
95
- },
96
- });
97
- }
98
- catch (err) {
99
- return Promise.resolve({
100
- success: false,
101
- error: `Failed to add anchor: ${err instanceof Error ? err.message : String(err)}`,
102
- });
103
- }
104
- },
105
- });
106
- // =============================================================================
107
- // anchor_remove Tool
108
- // =============================================================================
109
- export const anchorRemoveTool = defineTool({
110
- name: 'anchor_remove',
111
- description: 'Remove an anchor by its ID. Use this to clean up outdated or no longer relevant anchors. ' +
112
- 'Use anchor_list first to see available anchors and their IDs.',
113
- inputSchema: {
114
- type: 'object',
115
- properties: {
116
- id: {
117
- type: 'string',
118
- description: 'The ID of the anchor to remove',
119
- },
120
- },
121
- required: ['id'],
122
- },
123
- execute: (input) => {
124
- try {
125
- if (!input.id || input.id.trim().length === 0) {
126
- return Promise.resolve({
127
- success: false,
128
- error: 'Anchor ID is required',
129
- });
130
- }
131
- const id = input.id.trim();
132
- const activeProject = getActiveProject();
133
- // Try to remove from project anchors first, then global
134
- let removed = false;
135
- let scope = 'unknown';
136
- if (activeProject) {
137
- const projectManager = getAnchorManager(String(activeProject.id));
138
- if (projectManager.has(id)) {
139
- removed = projectManager.remove(id);
140
- scope = 'project';
141
- }
142
- }
143
- if (!removed) {
144
- const globalManager = getGlobalAnchorManager();
145
- if (globalManager.has(id)) {
146
- removed = globalManager.remove(id);
147
- scope = 'global';
148
- }
149
- }
150
- if (!removed) {
151
- return Promise.resolve({
152
- success: false,
153
- error: `Anchor with ID "${id}" not found`,
154
- });
155
- }
156
- return Promise.resolve({
157
- success: true,
158
- result: {
159
- id,
160
- scope,
161
- message: `Anchor removed successfully (was ${scope} scope)`,
162
- },
163
- });
164
- }
165
- catch (err) {
166
- return Promise.resolve({
167
- success: false,
168
- error: `Failed to remove anchor: ${err instanceof Error ? err.message : String(err)}`,
169
- });
170
- }
171
- },
172
- });
173
- // =============================================================================
174
- // anchor_list Tool
175
- // =============================================================================
176
- export const anchorListTool = defineTool({
177
- name: 'anchor_list',
178
- description: 'List all anchors. Returns anchor IDs, content, priority, and scope. ' +
179
- 'Use this to see what persistent context is available before adding or removing anchors.',
180
- inputSchema: {
181
- type: 'object',
182
- properties: {
183
- scope: {
184
- type: 'string',
185
- enum: ['global', 'project', 'all'],
186
- description: 'Filter by scope: "global", "project", or "all" (default: "all")',
187
- },
188
- priority: {
189
- type: 'string',
190
- enum: ['critical', 'safety', 'info'],
191
- description: 'Filter by priority level',
192
- },
193
- },
194
- },
195
- execute: (input) => {
196
- try {
197
- const activeProject = getActiveProject();
198
- const scope = input.scope ?? 'all';
199
- const anchors = [];
200
- // Collect global anchors
201
- if (scope === 'global' || scope === 'all') {
202
- const globalManager = getGlobalAnchorManager();
203
- const globalAnchors = globalManager.getAll({ priority: input.priority });
204
- for (const anchor of globalAnchors) {
205
- anchors.push({
206
- id: anchor.id,
207
- content: anchor.content,
208
- priority: anchor.priority,
209
- scope: 'global',
210
- tags: anchor.tags,
211
- });
212
- }
213
- }
214
- // Collect project anchors
215
- if ((scope === 'project' || scope === 'all') && activeProject) {
216
- const projectManager = getAnchorManager(String(activeProject.id));
217
- const projectAnchors = projectManager.getAll({ priority: input.priority });
218
- for (const anchor of projectAnchors) {
219
- anchors.push({
220
- id: anchor.id,
221
- content: anchor.content,
222
- priority: anchor.priority,
223
- scope: 'project',
224
- tags: anchor.tags,
225
- });
226
- }
227
- }
228
- // Sort by priority (critical first)
229
- const priorityOrder = { critical: 0, safety: 1, info: 2 };
230
- anchors.sort((a, b) => {
231
- const pa = priorityOrder[a.priority] ?? 2;
232
- const pb = priorityOrder[b.priority] ?? 2;
233
- return pa - pb;
234
- });
235
- return Promise.resolve({
236
- success: true,
237
- result: {
238
- count: anchors.length,
239
- activeProject: activeProject?.displayName ?? null,
240
- anchors,
241
- },
242
- });
243
- }
244
- catch (err) {
245
- return Promise.resolve({
246
- success: false,
247
- error: `Failed to list anchors: ${err instanceof Error ? err.message : String(err)}`,
248
- });
249
- }
250
- },
251
- });
252
- // =============================================================================
253
- // Export all anchor tools
254
- // =============================================================================
255
- export const allAnchorTools = [anchorAddTool, anchorRemoveTool, anchorListTool];
@@ -1,42 +0,0 @@
1
- /**
2
- * Artifact Tools
3
- *
4
- * Tools for managing team artifacts - named pieces of work that agents
5
- * can publish and reference across the team.
6
- *
7
- * Artifact types:
8
- * - design: Architecture, API specs, data models
9
- * - plan: Sprint plans, task breakdowns, timelines
10
- * - review: Code reviews, security audits, feedback
11
- * - decision: Architectural decisions, trade-off analysis
12
- * - note: General notes, meeting summaries
13
- */
14
- export declare const artifactSaveTool: import("@compilr-dev/sdk").Tool<{
15
- name: string;
16
- type: string;
17
- content: string;
18
- summary?: string;
19
- agent?: string;
20
- }>;
21
- export declare const artifactGetTool: import("@compilr-dev/sdk").Tool<{
22
- name: string;
23
- }>;
24
- export declare const artifactListTool: import("@compilr-dev/sdk").Tool<{
25
- type?: string;
26
- agent?: string;
27
- search?: string;
28
- }>;
29
- export declare const artifactDeleteTool: import("@compilr-dev/sdk").Tool<{
30
- name: string;
31
- }>;
32
- export declare const allArtifactTools: (import("@compilr-dev/sdk").Tool<{
33
- name: string;
34
- type: string;
35
- content: string;
36
- summary?: string;
37
- agent?: string;
38
- }> | import("@compilr-dev/sdk").Tool<{
39
- type?: string;
40
- agent?: string;
41
- search?: string;
42
- }>)[];