@compilr-dev/sdk 0.11.0 → 0.12.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/index.d.ts CHANGED
@@ -64,8 +64,8 @@ export { detectProject, suggestProjectType, detectCommon } from './detection/ind
64
64
  export type { DetectProjectOptions, DetectionResult, ContentSummary } from './detection/index.js';
65
65
  export { createGuideTool, SHARED_GUIDE_ENTRIES, searchGuideEntries, topicToGuideEntry, } from './guide/index.js';
66
66
  export type { GuideEntry, ContentTopic, ContentSection, GuideToolConfig } from './guide/index.js';
67
- export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createImageTools, ProjectAnchorStore, } from './platform/index.js';
68
- export type { ProjectAnchorStoreConfig, ImageToolsConfig, ImageResizer } from './platform/index.js';
67
+ export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createImageTools, ProjectAnchorStore, FileArtifactService, } from './platform/index.js';
68
+ export type { ProjectAnchorStoreConfig, FileArtifactServiceConfig, ImageToolsConfig, ImageResizer, } from './platform/index.js';
69
69
  export { STEP_ORDER, GUIDED_STEP_CRITERIA, getNextStep, isValidTransition, getStepCriteria, formatStepDisplay, getStepNumber, } from './platform/index.js';
70
70
  export type { CustomSkill, CompilrSkillExtension, ForkedFromMarker, SkillEligibilityContext, SkillCollision, SkillDiffLine, SkillValidationIssue, ScopeConfig, SkillResolution, } from './skills/index.js';
71
71
  export { RESERVED_SKILL_NAMES, isReservedSkillName, parseSkillMarkdown, loadSkillsFromDir, resolveLayeredSkills, resolveSkillsForAgent, detectCollisions, formatCollisionWarnings, diffForkVsUpstream, buildForkContent, buildNewSkillContent, validateSkill as validateSkillQuality, getSkillsDir, getSkillFolder, getSkillFile, ensureSkillsDir, isValidSkillName, getScopeConfigPath, readSkillScopeConfig, readSkillScopeConfigSync, writeSkillScopeConfig, getSkillBindings, resolveSkillBinding, } from './skills/index.js';
package/dist/index.js CHANGED
@@ -147,7 +147,7 @@ export { createGuideTool, SHARED_GUIDE_ENTRIES, searchGuideEntries, topicToGuide
147
147
  // =============================================================================
148
148
  // Platform Tools (runtime — createPlatformTools factory + individual factories)
149
149
  // =============================================================================
150
- export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createImageTools, ProjectAnchorStore, } from './platform/index.js';
150
+ export { createPlatformTools, createProjectTools, createWorkItemTools, createDocumentTools, createPlanTools, createBacklogTools, createAnchorTools, createArtifactTools, createEpisodeTools, createImageTools, ProjectAnchorStore, FileArtifactService, } from './platform/index.js';
151
151
  // =============================================================================
152
152
  // Platform Workflow (pure step-criteria logic)
153
153
  // =============================================================================
@@ -0,0 +1,55 @@
1
+ /**
2
+ * FileArtifactService — file-backed IArtifactService shared by CLI and Desktop.
3
+ *
4
+ * Both hosts previously hand-rolled identical artifact CRUD on top of the SDK's
5
+ * ArtifactStore, reading/writing the SAME file:
6
+ * {sessionsDir}/{global | project-<id>}/artifacts/artifacts.json
7
+ * This consolidates that logic next to FileEpisodeStore / ProjectAnchorStore.
8
+ *
9
+ * Each operation does a fresh load → mutate → save (the file is the source of
10
+ * truth, shared per-project across terminals), matching the prior behavior.
11
+ *
12
+ * Hosts wire in:
13
+ * - getProjectId: resolved per call, so the service follows project switches
14
+ * - onSaved (optional): fired after a create/update persists — the CLI uses it
15
+ * to record team activity; Desktop omits it
16
+ * - onError (optional): load/save failures, so each host logs as it sees fit
17
+ */
18
+ import type { IArtifactService, ArtifactData, ArtifactSummaryData, ArtifactType } from './services.js';
19
+ export interface FileArtifactServiceConfig {
20
+ /** Sessions root, e.g. ~/.compilr-dev/sessions */
21
+ sessionsDir: string;
22
+ /** Active project id (null = global), resolved on every call. */
23
+ getProjectId: () => number | null;
24
+ /** Fired after a successful create/update persists. */
25
+ onSaved?: (artifact: ArtifactData, isUpdate: boolean) => void;
26
+ /** Fired on a load/save failure (host decides how to log). */
27
+ onError?: (err: unknown, op: 'load' | 'save') => void;
28
+ }
29
+ export declare class FileArtifactService implements IArtifactService {
30
+ private readonly config;
31
+ constructor(config: FileArtifactServiceConfig);
32
+ private artifactsDir;
33
+ private dataFile;
34
+ /** Load the artifact store for a project from disk (empty store if absent). */
35
+ private loadStore;
36
+ /** Persist the artifact store for a project to disk. */
37
+ private saveStore;
38
+ save(input: {
39
+ name: string;
40
+ type: ArtifactType;
41
+ content: string;
42
+ summary?: string;
43
+ agent?: string;
44
+ }): Promise<{
45
+ artifact: ArtifactData;
46
+ isUpdate: boolean;
47
+ }>;
48
+ getByName(name: string): Promise<ArtifactData | null>;
49
+ list(options?: {
50
+ type?: ArtifactType;
51
+ agent?: string;
52
+ search?: string;
53
+ }): Promise<ArtifactSummaryData[]>;
54
+ delete(name: string): Promise<ArtifactData | null>;
55
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * FileArtifactService — file-backed IArtifactService shared by CLI and Desktop.
3
+ *
4
+ * Both hosts previously hand-rolled identical artifact CRUD on top of the SDK's
5
+ * ArtifactStore, reading/writing the SAME file:
6
+ * {sessionsDir}/{global | project-<id>}/artifacts/artifacts.json
7
+ * This consolidates that logic next to FileEpisodeStore / ProjectAnchorStore.
8
+ *
9
+ * Each operation does a fresh load → mutate → save (the file is the source of
10
+ * truth, shared per-project across terminals), matching the prior behavior.
11
+ *
12
+ * Hosts wire in:
13
+ * - getProjectId: resolved per call, so the service follows project switches
14
+ * - onSaved (optional): fired after a create/update persists — the CLI uses it
15
+ * to record team activity; Desktop omits it
16
+ * - onError (optional): load/save failures, so each host logs as it sees fit
17
+ */
18
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
19
+ import { join } from 'path';
20
+ import { ArtifactStore } from '../team/artifacts.js';
21
+ function toArtifactData(a) {
22
+ return {
23
+ id: a.id,
24
+ name: a.name,
25
+ agent: a.agent,
26
+ type: a.type,
27
+ content: a.content,
28
+ summary: a.summary,
29
+ version: a.version,
30
+ createdAt: a.createdAt,
31
+ updatedAt: a.updatedAt,
32
+ };
33
+ }
34
+ export class FileArtifactService {
35
+ config;
36
+ constructor(config) {
37
+ this.config = config;
38
+ }
39
+ artifactsDir(projectId) {
40
+ const projectDir = projectId === null
41
+ ? join(this.config.sessionsDir, 'global')
42
+ : join(this.config.sessionsDir, `project-${String(projectId)}`);
43
+ return join(projectDir, 'artifacts');
44
+ }
45
+ dataFile(projectId) {
46
+ return join(this.artifactsDir(projectId), 'artifacts.json');
47
+ }
48
+ /** Load the artifact store for a project from disk (empty store if absent). */
49
+ loadStore(projectId) {
50
+ const store = new ArtifactStore();
51
+ const file = this.dataFile(projectId);
52
+ if (!existsSync(file))
53
+ return store;
54
+ try {
55
+ const data = JSON.parse(readFileSync(file, 'utf-8'));
56
+ store.restore(data);
57
+ }
58
+ catch (err) {
59
+ // Corrupt/unreadable — start fresh rather than crash the tool call.
60
+ this.config.onError?.(err, 'load');
61
+ }
62
+ return store;
63
+ }
64
+ /** Persist the artifact store for a project to disk. */
65
+ saveStore(projectId, store) {
66
+ const dir = this.artifactsDir(projectId);
67
+ if (!existsSync(dir))
68
+ mkdirSync(dir, { recursive: true });
69
+ try {
70
+ writeFileSync(this.dataFile(projectId), JSON.stringify(store.serialize(), null, 2), 'utf-8');
71
+ }
72
+ catch (err) {
73
+ this.config.onError?.(err, 'save');
74
+ }
75
+ }
76
+ save(input) {
77
+ const projectId = this.config.getProjectId();
78
+ const store = this.loadStore(projectId);
79
+ const agentId = input.agent ?? 'default';
80
+ const existing = store.getByName(input.name);
81
+ if (existing) {
82
+ const updated = store.update(existing.id, {
83
+ content: input.content,
84
+ summary: input.summary,
85
+ type: input.type,
86
+ });
87
+ if (!updated)
88
+ throw new Error(`Failed to update artifact "${input.name}"`);
89
+ this.saveStore(projectId, store);
90
+ const artifact = toArtifactData(updated);
91
+ this.config.onSaved?.(artifact, true);
92
+ return Promise.resolve({ artifact, isUpdate: true });
93
+ }
94
+ const created = store.create({
95
+ name: input.name,
96
+ agent: agentId,
97
+ type: input.type,
98
+ content: input.content,
99
+ summary: input.summary,
100
+ });
101
+ this.saveStore(projectId, store);
102
+ const artifact = toArtifactData(created);
103
+ this.config.onSaved?.(artifact, false);
104
+ return Promise.resolve({ artifact, isUpdate: false });
105
+ }
106
+ getByName(name) {
107
+ const store = this.loadStore(this.config.getProjectId());
108
+ const a = store.getByName(name);
109
+ return Promise.resolve(a ? toArtifactData(a) : null);
110
+ }
111
+ list(options) {
112
+ const store = this.loadStore(this.config.getProjectId());
113
+ let items = options?.search ? store.search(options.search) : store.list();
114
+ if (options?.type)
115
+ items = items.filter((a) => a.type === options.type);
116
+ if (options?.agent)
117
+ items = items.filter((a) => a.agent === options.agent);
118
+ const summaries = items.map((a) => ({
119
+ id: a.id,
120
+ name: a.name,
121
+ agent: a.agent,
122
+ type: a.type,
123
+ summary: a.summary,
124
+ version: a.version,
125
+ updatedAt: a.updatedAt,
126
+ }));
127
+ return Promise.resolve(summaries);
128
+ }
129
+ delete(name) {
130
+ const projectId = this.config.getProjectId();
131
+ const store = this.loadStore(projectId);
132
+ const a = store.getByName(name);
133
+ if (!a)
134
+ return Promise.resolve(null);
135
+ if (!store.delete(a.id))
136
+ return Promise.resolve(null);
137
+ this.saveStore(projectId, store);
138
+ return Promise.resolve(toArtifactData(a));
139
+ }
140
+ }
@@ -11,5 +11,7 @@ export { createSQLiteRepositories, SQLiteProjectRepository, SQLiteWorkItemReposi
11
11
  export type { SQLiteRepositories, CreateSQLiteRepositoriesOptions, ProjectDeleteHooks, ProjectRecord, WorkItemRecord, ProjectDocumentRecord, WorkItemCommentRecord, } from './sqlite/index.js';
12
12
  export { ProjectAnchorStore } from './file-anchor-service.js';
13
13
  export type { ProjectAnchorStoreConfig } from './file-anchor-service.js';
14
+ export { FileArtifactService } from './file-artifact-service.js';
15
+ export type { FileArtifactServiceConfig } from './file-artifact-service.js';
14
16
  export { STEP_ORDER, GUIDED_STEP_CRITERIA, getNextStep, isValidTransition, getStepCriteria, formatStepDisplay, getStepNumber, } from './workflow.js';
15
17
  export type { StepCriteria } from './workflow.js';
@@ -7,5 +7,7 @@ export { createPlatformTools, createProjectTools, createWorkItemTools, createDoc
7
7
  export { createSQLiteRepositories, SQLiteProjectRepository, SQLiteWorkItemRepository, SQLiteDocumentRepository, SQLitePlanRepository, SQLiteCommentRepository, getDatabase, closeDatabase, closeAllDatabases, databaseExists, SCHEMA_VERSION, SCHEMA_SQL, } from './sqlite/index.js';
8
8
  // File-based anchor service (shared by CLI and Desktop)
9
9
  export { ProjectAnchorStore } from './file-anchor-service.js';
10
+ // File-based artifact service (shared by CLI and Desktop)
11
+ export { FileArtifactService } from './file-artifact-service.js';
10
12
  // Workflow (pure step-criteria logic)
11
13
  export { STEP_ORDER, GUIDED_STEP_CRITERIA, getNextStep, isValidTransition, getStepCriteria, formatStepDisplay, getStepNumber, } from './workflow.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compilr-dev/sdk",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Universal agent runtime for building AI-powered applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",