@studio-foundation/cli 0.3.0-beta.1
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/ARCHITECTURE.md +40 -0
- package/LICENSE +663 -0
- package/README.md +165 -0
- package/dist/commands/api.d.ts +16 -0
- package/dist/commands/api.d.ts.map +1 -0
- package/dist/commands/api.js +118 -0
- package/dist/commands/api.js.map +1 -0
- package/dist/commands/config.d.ts +32 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +390 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/init.d.ts +93 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +728 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +22 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/integrations.d.ts +14 -0
- package/dist/commands/integrations.d.ts.map +1 -0
- package/dist/commands/integrations.js +282 -0
- package/dist/commands/integrations.js.map +1 -0
- package/dist/commands/list.d.ts +9 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +161 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/logs.d.ts +7 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +98 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/ollama.d.ts +6 -0
- package/dist/commands/ollama.d.ts.map +1 -0
- package/dist/commands/ollama.js +161 -0
- package/dist/commands/ollama.js.map +1 -0
- package/dist/commands/project.d.ts +38 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +137 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/registry/audit.d.ts +13 -0
- package/dist/commands/registry/audit.d.ts.map +1 -0
- package/dist/commands/registry/audit.js +65 -0
- package/dist/commands/registry/audit.js.map +1 -0
- package/dist/commands/registry/index.d.ts +3 -0
- package/dist/commands/registry/index.d.ts.map +1 -0
- package/dist/commands/registry/index.js +53 -0
- package/dist/commands/registry/index.js.map +1 -0
- package/dist/commands/registry/install.d.ts +17 -0
- package/dist/commands/registry/install.d.ts.map +1 -0
- package/dist/commands/registry/install.js +153 -0
- package/dist/commands/registry/install.js.map +1 -0
- package/dist/commands/registry/publish.d.ts +8 -0
- package/dist/commands/registry/publish.d.ts.map +1 -0
- package/dist/commands/registry/publish.js +94 -0
- package/dist/commands/registry/publish.js.map +1 -0
- package/dist/commands/registry/remove.d.ts +8 -0
- package/dist/commands/registry/remove.d.ts.map +1 -0
- package/dist/commands/registry/remove.js +82 -0
- package/dist/commands/registry/remove.js.map +1 -0
- package/dist/commands/registry/search.d.ts +9 -0
- package/dist/commands/registry/search.d.ts.map +1 -0
- package/dist/commands/registry/search.js +68 -0
- package/dist/commands/registry/search.js.map +1 -0
- package/dist/commands/registry/sync.d.ts +8 -0
- package/dist/commands/registry/sync.d.ts.map +1 -0
- package/dist/commands/registry/sync.js +19 -0
- package/dist/commands/registry/sync.js.map +1 -0
- package/dist/commands/registry/update.d.ts +15 -0
- package/dist/commands/registry/update.d.ts.map +1 -0
- package/dist/commands/registry/update.js +48 -0
- package/dist/commands/registry/update.js.map +1 -0
- package/dist/commands/replay.d.ts +36 -0
- package/dist/commands/replay.d.ts.map +1 -0
- package/dist/commands/replay.js +453 -0
- package/dist/commands/replay.js.map +1 -0
- package/dist/commands/run.d.ts +18 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +406 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +144 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/template/index.d.ts +2 -0
- package/dist/commands/template/index.d.ts.map +1 -0
- package/dist/commands/template/index.js +57 -0
- package/dist/commands/template/index.js.map +1 -0
- package/dist/commands/template/validate.d.ts +8 -0
- package/dist/commands/template/validate.d.ts.map +1 -0
- package/dist/commands/template/validate.js +135 -0
- package/dist/commands/template/validate.js.map +1 -0
- package/dist/commands/templates.d.ts +14 -0
- package/dist/commands/templates.d.ts.map +1 -0
- package/dist/commands/templates.js +86 -0
- package/dist/commands/templates.js.map +1 -0
- package/dist/commands/tools.d.ts +12 -0
- package/dist/commands/tools.d.ts.map +1 -0
- package/dist/commands/tools.js +200 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/users.d.ts +4 -0
- package/dist/commands/users.d.ts.map +1 -0
- package/dist/commands/users.js +123 -0
- package/dist/commands/users.js.map +1 -0
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +39 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +64 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +178 -0
- package/dist/index.js.map +1 -0
- package/dist/models-cache.d.ts +13 -0
- package/dist/models-cache.d.ts.map +1 -0
- package/dist/models-cache.js +106 -0
- package/dist/models-cache.js.map +1 -0
- package/dist/output/file-changes.d.ts +15 -0
- package/dist/output/file-changes.d.ts.map +1 -0
- package/dist/output/file-changes.js +77 -0
- package/dist/output/file-changes.js.map +1 -0
- package/dist/output/formatter.d.ts +6 -0
- package/dist/output/formatter.d.ts.map +1 -0
- package/dist/output/formatter.js +70 -0
- package/dist/output/formatter.js.map +1 -0
- package/dist/output/formatters.d.ts +42 -0
- package/dist/output/formatters.d.ts.map +1 -0
- package/dist/output/formatters.js +280 -0
- package/dist/output/formatters.js.map +1 -0
- package/dist/output/logger.d.ts +3 -0
- package/dist/output/logger.d.ts.map +1 -0
- package/dist/output/logger.js +15 -0
- package/dist/output/logger.js.map +1 -0
- package/dist/output/parallel-progress.d.ts +33 -0
- package/dist/output/parallel-progress.d.ts.map +1 -0
- package/dist/output/parallel-progress.js +85 -0
- package/dist/output/parallel-progress.js.map +1 -0
- package/dist/output/progress.d.ts +32 -0
- package/dist/output/progress.d.ts.map +1 -0
- package/dist/output/progress.js +393 -0
- package/dist/output/progress.js.map +1 -0
- package/dist/provider-validator.d.ts +15 -0
- package/dist/provider-validator.d.ts.map +1 -0
- package/dist/provider-validator.js +85 -0
- package/dist/provider-validator.js.map +1 -0
- package/dist/registry/cache.d.ts +10 -0
- package/dist/registry/cache.d.ts.map +1 -0
- package/dist/registry/cache.js +36 -0
- package/dist/registry/cache.js.map +1 -0
- package/dist/registry/client.d.ts +19 -0
- package/dist/registry/client.d.ts.map +1 -0
- package/dist/registry/client.js +63 -0
- package/dist/registry/client.js.map +1 -0
- package/dist/registry/lockfile.d.ts +17 -0
- package/dist/registry/lockfile.d.ts.map +1 -0
- package/dist/registry/lockfile.js +61 -0
- package/dist/registry/lockfile.js.map +1 -0
- package/dist/registry/resolver.d.ts +13 -0
- package/dist/registry/resolver.d.ts.map +1 -0
- package/dist/registry/resolver.js +79 -0
- package/dist/registry/resolver.js.map +1 -0
- package/dist/registry/types.d.ts +59 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +14 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/run-logger.d.ts +8 -0
- package/dist/run-logger.d.ts.map +1 -0
- package/dist/run-logger.js +53 -0
- package/dist/run-logger.js.map +1 -0
- package/dist/run-store-factory.d.ts +9 -0
- package/dist/run-store-factory.d.ts.map +1 -0
- package/dist/run-store-factory.js +26 -0
- package/dist/run-store-factory.js.map +1 -0
- package/dist/studio-dir.d.ts +7 -0
- package/dist/studio-dir.d.ts.map +1 -0
- package/dist/studio-dir.js +27 -0
- package/dist/studio-dir.js.map +1 -0
- package/dist/utils/input-wizard.d.ts +4 -0
- package/dist/utils/input-wizard.d.ts.map +1 -0
- package/dist/utils/input-wizard.js +56 -0
- package/dist/utils/input-wizard.js.map +1 -0
- package/dist/utils/placeholders.d.ts +6 -0
- package/dist/utils/placeholders.d.ts.map +1 -0
- package/dist/utils/placeholders.js +12 -0
- package/dist/utils/placeholders.js.map +1 -0
- package/package.json +43 -0
- package/src/commands/api.ts +126 -0
- package/src/commands/config.ts +433 -0
- package/src/commands/init.ts +879 -0
- package/src/commands/install.ts +23 -0
- package/src/commands/integrations.ts +332 -0
- package/src/commands/list.ts +197 -0
- package/src/commands/logs.ts +119 -0
- package/src/commands/ollama.ts +168 -0
- package/src/commands/project.ts +167 -0
- package/src/commands/registry/audit.ts +87 -0
- package/src/commands/registry/index.ts +63 -0
- package/src/commands/registry/install.ts +222 -0
- package/src/commands/registry/publish.ts +112 -0
- package/src/commands/registry/remove.ts +89 -0
- package/src/commands/registry/search.ts +93 -0
- package/src/commands/registry/sync.ts +24 -0
- package/src/commands/registry/update.ts +63 -0
- package/src/commands/replay.ts +559 -0
- package/src/commands/run.ts +454 -0
- package/src/commands/status.ts +163 -0
- package/src/commands/template/index.ts +59 -0
- package/src/commands/template/validate.ts +175 -0
- package/src/commands/templates.ts +99 -0
- package/src/commands/tools.ts +227 -0
- package/src/commands/users.ts +127 -0
- package/src/commands/validate.ts +46 -0
- package/src/config.ts +101 -0
- package/src/index.ts +201 -0
- package/src/models-cache.ts +127 -0
- package/src/output/file-changes.ts +97 -0
- package/src/output/formatter.ts +85 -0
- package/src/output/formatters.ts +303 -0
- package/src/output/logger.ts +18 -0
- package/src/output/parallel-progress.ts +103 -0
- package/src/output/progress.ts +414 -0
- package/src/provider-validator.ts +109 -0
- package/src/registry/cache.ts +46 -0
- package/src/registry/client.ts +84 -0
- package/src/registry/lockfile.ts +68 -0
- package/src/registry/resolver.ts +113 -0
- package/src/registry/types.ts +66 -0
- package/src/run-logger.ts +66 -0
- package/src/run-store-factory.ts +30 -0
- package/src/studio-dir.ts +28 -0
- package/src/utils/input-wizard.ts +73 -0
- package/src/utils/placeholders.ts +10 -0
- package/templates/.studiorc.yaml +16 -0
- package/templates/projects/blank/metadata.json +7 -0
- package/templates/studio-config.yaml +14 -0
- package/tests/__stubs__/studio-runner.ts +104 -0
- package/tests/commands/api.test.ts +110 -0
- package/tests/commands/config.test.ts +221 -0
- package/tests/commands/init.test.ts +919 -0
- package/tests/commands/install.test.ts +52 -0
- package/tests/commands/integrations.test.ts +158 -0
- package/tests/commands/ollama.test.ts +139 -0
- package/tests/commands/project.test.ts +179 -0
- package/tests/commands/registry/audit.test.ts +56 -0
- package/tests/commands/registry/install.test.ts +200 -0
- package/tests/commands/registry/publish.test.ts +56 -0
- package/tests/commands/registry/remove.test.ts +103 -0
- package/tests/commands/registry/search.test.ts +44 -0
- package/tests/commands/registry/sync.test.ts +37 -0
- package/tests/commands/registry/update.test.ts +62 -0
- package/tests/commands/replay.test.ts +283 -0
- package/tests/commands/template/validate.test.ts +150 -0
- package/tests/commands/templates.test.ts +42 -0
- package/tests/commands/tools.test.ts +106 -0
- package/tests/config.test.ts +142 -0
- package/tests/formatter.test.ts +158 -0
- package/tests/integration/sigint.test.ts +188 -0
- package/tests/models-cache.test.ts +250 -0
- package/tests/output/file-changes.test.ts +178 -0
- package/tests/output/formatters.test.ts +448 -0
- package/tests/output/progress-spinner.test.ts +232 -0
- package/tests/output/progress-timer.test.ts +230 -0
- package/tests/provider-validator.test.ts +182 -0
- package/tests/registry/cache.test.ts +66 -0
- package/tests/registry/client.test.ts +70 -0
- package/tests/registry/lockfile.test.ts +87 -0
- package/tests/registry/resolver.test.ts +122 -0
- package/tests/run-logger-events.test.ts +326 -0
- package/tests/run-logger.test.ts +64 -0
- package/tests/run-store-factory.test.ts +51 -0
- package/tests/studio-dir.test.ts +31 -0
- package/tests/utils/input-wizard.test.ts +153 -0
- package/tests/utils/placeholders.test.ts +36 -0
- package/tsconfig.json +24 -0
- package/vitest.config.ts +20 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { resolve, dirname } from 'node:path';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { REGISTRY_RAW_BASE, REGISTRY_API_BASE } from './types.js';
|
|
5
|
+
export class RegistryClient {
|
|
6
|
+
async fetchIndex() {
|
|
7
|
+
const res = await fetch(`${REGISTRY_RAW_BASE}/index.json`);
|
|
8
|
+
if (!res.ok)
|
|
9
|
+
throw new Error(`Failed to fetch registry index: HTTP ${res.status}`);
|
|
10
|
+
return res.json();
|
|
11
|
+
}
|
|
12
|
+
async fetchMetadata(type, name) {
|
|
13
|
+
const res = await fetch(`${REGISTRY_RAW_BASE}/${type}s/${name}/metadata.json`);
|
|
14
|
+
if (!res.ok)
|
|
15
|
+
throw new Error(`Package '${name}' not found in registry`);
|
|
16
|
+
return res.json();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Download a single-file package (tool, pipeline, integration, agent, skill).
|
|
20
|
+
* Returns { destPath, sha256 }.
|
|
21
|
+
*/
|
|
22
|
+
async downloadFile(type, name, filename, destDir) {
|
|
23
|
+
const url = `${REGISTRY_RAW_BASE}/${type}s/${name}/${filename}`;
|
|
24
|
+
const res = await fetch(url);
|
|
25
|
+
if (!res.ok)
|
|
26
|
+
throw new Error(`Failed to download ${filename}: HTTP ${res.status}`);
|
|
27
|
+
const content = await res.text();
|
|
28
|
+
const destPath = resolve(destDir, filename);
|
|
29
|
+
await mkdir(destDir, { recursive: true });
|
|
30
|
+
await writeFile(destPath, content);
|
|
31
|
+
const sha256 = createHash('sha256').update(content).digest('hex');
|
|
32
|
+
return { destPath, sha256 };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Download a directory package (template, plugin) via GitHub API.
|
|
36
|
+
* Returns SHA256 of all file contents concatenated (sorted by path).
|
|
37
|
+
*/
|
|
38
|
+
async downloadDirectory(type, name, remotePath, localDestDir) {
|
|
39
|
+
const res = await fetch(`${REGISTRY_API_BASE}/contents/${type}s/${name}/${remotePath}`, { headers: { Accept: 'application/vnd.github+json' } });
|
|
40
|
+
if (!res.ok)
|
|
41
|
+
throw new Error(`Failed to list directory: HTTP ${res.status}`);
|
|
42
|
+
const items = (await res.json());
|
|
43
|
+
const hash = createHash('sha256');
|
|
44
|
+
const sortedItems = [...items].sort((a, b) => a.path.localeCompare(b.path));
|
|
45
|
+
for (const item of sortedItems) {
|
|
46
|
+
const localPath = resolve(localDestDir, item.name);
|
|
47
|
+
if (item.type === 'dir') {
|
|
48
|
+
await this.downloadDirectory(type, name, `${remotePath}/${item.name}`, localPath);
|
|
49
|
+
}
|
|
50
|
+
else if (item.download_url) {
|
|
51
|
+
const fileRes = await fetch(item.download_url);
|
|
52
|
+
if (!fileRes.ok)
|
|
53
|
+
throw new Error(`Failed to download ${item.path}`);
|
|
54
|
+
const content = await fileRes.text();
|
|
55
|
+
await mkdir(dirname(localPath), { recursive: true });
|
|
56
|
+
await writeFile(localPath, content);
|
|
57
|
+
hash.update(item.path + content);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return hash.digest('hex');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/registry/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Lockfile, LockfileEntry } from './types.js';
|
|
2
|
+
export declare class RegistryLockfile {
|
|
3
|
+
private lockPath;
|
|
4
|
+
private studioDir;
|
|
5
|
+
constructor(studioDir: string);
|
|
6
|
+
read(): Promise<Lockfile>;
|
|
7
|
+
private write;
|
|
8
|
+
add(name: string, entry: LockfileEntry): Promise<void>;
|
|
9
|
+
remove(name: string): Promise<void>;
|
|
10
|
+
get(name: string): Promise<LockfileEntry | null>;
|
|
11
|
+
list(): Promise<Array<{
|
|
12
|
+
name: string;
|
|
13
|
+
} & LockfileEntry>>;
|
|
14
|
+
addRequiredBy(name: string, requiredBy: string): Promise<void>;
|
|
15
|
+
removeRequiredBy(name: string, requiredBy: string): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=lockfile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../../src/registry/lockfile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE1D,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,EAAE,MAAM;IAKvB,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC;YASjB,KAAK;IAKb,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAKhD,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,CAAC,CAAC;IAKxD,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW9D,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAOxE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
export class RegistryLockfile {
|
|
4
|
+
lockPath;
|
|
5
|
+
studioDir;
|
|
6
|
+
constructor(studioDir) {
|
|
7
|
+
this.studioDir = studioDir;
|
|
8
|
+
this.lockPath = resolve(studioDir, 'registry.lock.json');
|
|
9
|
+
}
|
|
10
|
+
async read() {
|
|
11
|
+
try {
|
|
12
|
+
const raw = await readFile(this.lockPath, 'utf8');
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return { installed: {} };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async write(data) {
|
|
20
|
+
await mkdir(this.studioDir, { recursive: true });
|
|
21
|
+
await writeFile(this.lockPath, JSON.stringify(data, null, 2) + '\n');
|
|
22
|
+
}
|
|
23
|
+
async add(name, entry) {
|
|
24
|
+
const data = await this.read();
|
|
25
|
+
data.installed[name] = entry;
|
|
26
|
+
await this.write(data);
|
|
27
|
+
}
|
|
28
|
+
async remove(name) {
|
|
29
|
+
const data = await this.read();
|
|
30
|
+
delete data.installed[name];
|
|
31
|
+
await this.write(data);
|
|
32
|
+
}
|
|
33
|
+
async get(name) {
|
|
34
|
+
const data = await this.read();
|
|
35
|
+
return data.installed[name] ?? null;
|
|
36
|
+
}
|
|
37
|
+
async list() {
|
|
38
|
+
const data = await this.read();
|
|
39
|
+
return Object.entries(data.installed).map(([name, entry]) => ({ name, ...entry }));
|
|
40
|
+
}
|
|
41
|
+
async addRequiredBy(name, requiredBy) {
|
|
42
|
+
const data = await this.read();
|
|
43
|
+
const entry = data.installed[name];
|
|
44
|
+
if (!entry)
|
|
45
|
+
return;
|
|
46
|
+
const existing = entry.required_by ?? [];
|
|
47
|
+
if (!existing.includes(requiredBy)) {
|
|
48
|
+
data.installed[name] = { ...entry, required_by: [...existing, requiredBy] };
|
|
49
|
+
await this.write(data);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async removeRequiredBy(name, requiredBy) {
|
|
53
|
+
const data = await this.read();
|
|
54
|
+
const entry = data.installed[name];
|
|
55
|
+
if (!entry)
|
|
56
|
+
return;
|
|
57
|
+
data.installed[name] = { ...entry, required_by: (entry.required_by ?? []).filter(r => r !== requiredBy) };
|
|
58
|
+
await this.write(data);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=lockfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../../src/registry/lockfile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PackageMetadata, PackageType, RegistryIndex, Lockfile } from './types.js';
|
|
2
|
+
export interface DependencyNode {
|
|
3
|
+
name: string;
|
|
4
|
+
type: PackageType;
|
|
5
|
+
}
|
|
6
|
+
export interface ResolvedGraph {
|
|
7
|
+
required: DependencyNode[];
|
|
8
|
+
recommended: DependencyNode[];
|
|
9
|
+
}
|
|
10
|
+
type MetadataFetcher = (name: string) => Promise<PackageMetadata>;
|
|
11
|
+
export declare function resolveDependencies(rootPackageName: string, meta: PackageMetadata, index: RegistryIndex, _lockfile: Lockfile, fetchMeta: MetadataFetcher): Promise<ResolvedGraph>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/registry/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAuB,MAAM,YAAY,CAAC;AAE7G,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AA8BlE,wBAAsB,mBAAmB,CACvC,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,QAAQ,EACnB,SAAS,EAAE,eAAe,GACzB,OAAO,CAAC,aAAa,CAAC,CAgExB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Extract all dependency names (regardless of whether they're in the index) for cycle detection. */
|
|
2
|
+
function depNames(deps, kind) {
|
|
3
|
+
const names = [];
|
|
4
|
+
for (const [, spec] of Object.entries(deps)) {
|
|
5
|
+
const arr = spec[kind] ?? [];
|
|
6
|
+
names.push(...arr);
|
|
7
|
+
}
|
|
8
|
+
return names;
|
|
9
|
+
}
|
|
10
|
+
function flattenDeps(deps, kind, index) {
|
|
11
|
+
const nodes = [];
|
|
12
|
+
for (const [, spec] of Object.entries(deps)) {
|
|
13
|
+
const names = spec[kind] ?? [];
|
|
14
|
+
for (const name of names) {
|
|
15
|
+
const entry = index.packages.find(p => p.name === name);
|
|
16
|
+
if (entry) {
|
|
17
|
+
nodes.push({ name, type: entry.type });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return nodes;
|
|
22
|
+
}
|
|
23
|
+
export async function resolveDependencies(rootPackageName, meta, index, _lockfile, fetchMeta) {
|
|
24
|
+
const resolved = new Map();
|
|
25
|
+
const visiting = new Set();
|
|
26
|
+
// Track the root package so cycles back to it are detected
|
|
27
|
+
visiting.add(rootPackageName);
|
|
28
|
+
async function visit(name, pkgMeta) {
|
|
29
|
+
if (visiting.has(name)) {
|
|
30
|
+
throw new Error(`Circular dependency detected: ${name} is part of a cycle`);
|
|
31
|
+
}
|
|
32
|
+
if (resolved.has(name))
|
|
33
|
+
return;
|
|
34
|
+
visiting.add(name);
|
|
35
|
+
if (pkgMeta.dependencies) {
|
|
36
|
+
// Check for cycles on all required names (even those not in index)
|
|
37
|
+
for (const depName of depNames(pkgMeta.dependencies, 'required')) {
|
|
38
|
+
if (visiting.has(depName)) {
|
|
39
|
+
throw new Error(`Circular dependency detected: ${depName} is part of a cycle`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const requiredNodes = flattenDeps(pkgMeta.dependencies, 'required', index);
|
|
43
|
+
for (const node of requiredNodes) {
|
|
44
|
+
if (!resolved.has(node.name)) {
|
|
45
|
+
const subMeta = await fetchMeta(node.name);
|
|
46
|
+
await visit(node.name, subMeta);
|
|
47
|
+
if (!resolved.has(node.name)) {
|
|
48
|
+
resolved.set(node.name, node);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
visiting.delete(name);
|
|
54
|
+
}
|
|
55
|
+
if (meta.dependencies) {
|
|
56
|
+
// Check for cycles at the first level too (root → dep that cycles back to root)
|
|
57
|
+
for (const depName of depNames(meta.dependencies, 'required')) {
|
|
58
|
+
if (visiting.has(depName)) {
|
|
59
|
+
throw new Error(`Circular dependency detected: ${depName} is part of a cycle`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const firstLevelRequired = flattenDeps(meta.dependencies, 'required', index);
|
|
63
|
+
for (const node of firstLevelRequired) {
|
|
64
|
+
const subMeta = await fetchMeta(node.name);
|
|
65
|
+
await visit(node.name, subMeta);
|
|
66
|
+
if (!resolved.has(node.name)) {
|
|
67
|
+
resolved.set(node.name, node);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const recommended = meta.dependencies
|
|
72
|
+
? flattenDeps(meta.dependencies, 'recommended', index)
|
|
73
|
+
: [];
|
|
74
|
+
return {
|
|
75
|
+
required: Array.from(resolved.values()),
|
|
76
|
+
recommended,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/registry/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export type PackageType = 'tool' | 'template' | 'pipeline' | 'integration' | 'agent' | 'plugin' | 'skill';
|
|
2
|
+
export interface PackageEntry {
|
|
3
|
+
name: string;
|
|
4
|
+
type: PackageType;
|
|
5
|
+
version: string;
|
|
6
|
+
description: string;
|
|
7
|
+
author: string;
|
|
8
|
+
license: string;
|
|
9
|
+
tags: string[];
|
|
10
|
+
studio_version: string | null;
|
|
11
|
+
downloads: number;
|
|
12
|
+
}
|
|
13
|
+
export interface RegistryIndex {
|
|
14
|
+
generated_at: string;
|
|
15
|
+
version: string;
|
|
16
|
+
packages: PackageEntry[];
|
|
17
|
+
}
|
|
18
|
+
export interface PackageDependencies {
|
|
19
|
+
tools?: {
|
|
20
|
+
required?: string[];
|
|
21
|
+
recommended?: string[];
|
|
22
|
+
};
|
|
23
|
+
agents?: {
|
|
24
|
+
required?: string[];
|
|
25
|
+
recommended?: string[];
|
|
26
|
+
};
|
|
27
|
+
skills?: {
|
|
28
|
+
required?: string[];
|
|
29
|
+
recommended?: string[];
|
|
30
|
+
};
|
|
31
|
+
templates?: {
|
|
32
|
+
required?: string[];
|
|
33
|
+
recommended?: string[];
|
|
34
|
+
};
|
|
35
|
+
pipelines?: {
|
|
36
|
+
required?: string[];
|
|
37
|
+
recommended?: string[];
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export interface PackageMetadata extends PackageEntry {
|
|
41
|
+
requires_binaries?: string[];
|
|
42
|
+
dependencies?: PackageDependencies;
|
|
43
|
+
}
|
|
44
|
+
export interface LockfileEntry {
|
|
45
|
+
version: string;
|
|
46
|
+
type: PackageType;
|
|
47
|
+
installed_at: string;
|
|
48
|
+
sha256: string;
|
|
49
|
+
required_by?: string[];
|
|
50
|
+
}
|
|
51
|
+
export interface Lockfile {
|
|
52
|
+
installed: Record<string, LockfileEntry>;
|
|
53
|
+
}
|
|
54
|
+
/** Where packages get installed relative to the project's .studio/ dir */
|
|
55
|
+
export declare const INSTALL_DIRS: Record<PackageType, string>;
|
|
56
|
+
export declare const REGISTRY_REPO = "PipStudio/studio-community";
|
|
57
|
+
export declare const REGISTRY_RAW_BASE = "https://raw.githubusercontent.com/PipStudio/studio-community/main";
|
|
58
|
+
export declare const REGISTRY_API_BASE = "https://api.github.com/repos/PipStudio/studio-community";
|
|
59
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,UAAU,GACV,UAAU,GACV,aAAa,GACb,OAAO,GACP,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAM;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5D,MAAM,CAAC,EAAK;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5D,MAAM,CAAC,EAAK;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5D,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5D,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC7D;AAED,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAC1C;AAED,0EAA0E;AAC1E,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAQpD,CAAC;AAEF,eAAO,MAAM,aAAa,+BAA+B,CAAC;AAC1D,eAAO,MAAM,iBAAiB,sEAA4D,CAAC;AAC3F,eAAO,MAAM,iBAAiB,4DAAkD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Where packages get installed relative to the project's .studio/ dir */
|
|
2
|
+
export const INSTALL_DIRS = {
|
|
3
|
+
tool: 'tools',
|
|
4
|
+
template: 'projects',
|
|
5
|
+
pipeline: 'pipelines',
|
|
6
|
+
integration: 'integrations',
|
|
7
|
+
agent: 'agents',
|
|
8
|
+
plugin: 'plugins',
|
|
9
|
+
skill: 'skills',
|
|
10
|
+
};
|
|
11
|
+
export const REGISTRY_REPO = 'PipStudio/studio-community';
|
|
12
|
+
export const REGISTRY_RAW_BASE = `https://raw.githubusercontent.com/${REGISTRY_REPO}/main`;
|
|
13
|
+
export const REGISTRY_API_BASE = `https://api.github.com/repos/${REGISTRY_REPO}`;
|
|
14
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAoDA,0EAA0E;AAC1E,MAAM,CAAC,MAAM,YAAY,GAAgC;IACvD,IAAI,EAAE,OAAO;IACb,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,WAAW;IACrB,WAAW,EAAE,cAAc;IAC3B,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,QAAQ;CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,4BAA4B,CAAC;AAC1D,MAAM,CAAC,MAAM,iBAAiB,GAAG,qCAAqC,aAAa,OAAO,CAAC;AAC3F,MAAM,CAAC,MAAM,iBAAiB,GAAG,gCAAgC,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface RunLogger {
|
|
2
|
+
start(runId: string, pipeline: string): void;
|
|
3
|
+
log(payload: Record<string, unknown>): void;
|
|
4
|
+
close(): Promise<void>;
|
|
5
|
+
getLogPath(): string;
|
|
6
|
+
}
|
|
7
|
+
export declare function createRunLogger(cwd?: string): RunLogger;
|
|
8
|
+
//# sourceMappingURL=run-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-logger.d.ts","sourceRoot":"","sources":["../src/run-logger.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,UAAU,IAAI,MAAM,CAAC;CACtB;AAED,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,SAAS,CA4CtE"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createWriteStream, mkdirSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
const RUNS_DIR = '.studio/runs';
|
|
4
|
+
function runIdShort(runId) {
|
|
5
|
+
return runId.slice(0, 8);
|
|
6
|
+
}
|
|
7
|
+
function dateForFilename() {
|
|
8
|
+
const iso = new Date().toISOString();
|
|
9
|
+
return iso.slice(0, 16).replace(/(\d{2}):(\d{2})$/, '$1h$2m');
|
|
10
|
+
}
|
|
11
|
+
export function createRunLogger(cwd = process.cwd()) {
|
|
12
|
+
let logPath = '';
|
|
13
|
+
let stream = null;
|
|
14
|
+
let shortRunId = '';
|
|
15
|
+
return {
|
|
16
|
+
start(runId, pipeline) {
|
|
17
|
+
shortRunId = runIdShort(runId);
|
|
18
|
+
const date = dateForFilename();
|
|
19
|
+
const base = resolve(cwd, RUNS_DIR);
|
|
20
|
+
logPath = resolve(base, `${date}-${pipeline}-${shortRunId}.jsonl`);
|
|
21
|
+
mkdirSync(base, { recursive: true });
|
|
22
|
+
stream = createWriteStream(logPath, { flags: 'a' });
|
|
23
|
+
},
|
|
24
|
+
log(payload) {
|
|
25
|
+
const line = {
|
|
26
|
+
ts: new Date().toISOString(),
|
|
27
|
+
...payload,
|
|
28
|
+
run_id: payload.run_id !== undefined ? runIdShort(String(payload.run_id)) : shortRunId,
|
|
29
|
+
};
|
|
30
|
+
const out = JSON.stringify(line) + '\n';
|
|
31
|
+
if (stream?.writable) {
|
|
32
|
+
stream.write(out);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
close() {
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
if (stream) {
|
|
38
|
+
stream.end(() => {
|
|
39
|
+
stream = null;
|
|
40
|
+
resolve();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
resolve();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
getLogPath() {
|
|
49
|
+
return logPath;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=run-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-logger.js","sourceRoot":"","sources":["../src/run-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,QAAQ,GAAG,cAAc,CAAC;AAEhC,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AAChE,CAAC;AASD,MAAM,UAAU,eAAe,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACzD,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,MAAM,GAAgD,IAAI,CAAC;IAC/D,IAAI,UAAU,GAAG,EAAE,CAAC;IAEpB,OAAO;QACL,KAAK,CAAC,KAAa,EAAE,QAAgB;YACnC,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YACpC,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,QAAQ,IAAI,UAAU,QAAQ,CAAC,CAAC;YACnE,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACrC,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACtD,CAAC;QAED,GAAG,CAAC,OAAgC;YAClC,MAAM,IAAI,GAA4B;gBACpC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC5B,GAAG,OAAO;gBACV,MAAM,EAAE,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU;aACvF,CAAC;YACF,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACxC,IAAI,MAAM,EAAE,QAAQ,EAAE,CAAC;gBACrB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;QAED,KAAK;YACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;wBACd,MAAM,GAAG,IAAI,CAAC;wBACd,OAAO,EAAE,CAAC;oBACZ,CAAC,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,UAAU;YACR,OAAO,OAAO,CAAC;QACjB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { StudioConfig } from './config.js';
|
|
2
|
+
import type { AnyRunStore } from '@studio-foundation/engine';
|
|
3
|
+
/**
|
|
4
|
+
* Create the production RunStore from config.
|
|
5
|
+
* Returns AnyRunStore (sync RunStore or async AsyncRunStore) based on config.db.type.
|
|
6
|
+
* Defaults to SQLite when no db config is present.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createRunStore(config: StudioConfig): Promise<AnyRunStore>;
|
|
9
|
+
//# sourceMappingURL=run-store-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-store-factory.d.ts","sourceRoot":"","sources":["../src/run-store-factory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAkB/E"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { mkdirSync } from 'node:fs';
|
|
3
|
+
import { SQLiteRunStore, InMemoryRunStore, PgRunStore } from '@studio-foundation/engine';
|
|
4
|
+
/**
|
|
5
|
+
* Create the production RunStore from config.
|
|
6
|
+
* Returns AnyRunStore (sync RunStore or async AsyncRunStore) based on config.db.type.
|
|
7
|
+
* Defaults to SQLite when no db config is present.
|
|
8
|
+
*/
|
|
9
|
+
export async function createRunStore(config) {
|
|
10
|
+
const dbType = config.db?.type ?? 'sqlite';
|
|
11
|
+
if (dbType === 'inmemory') {
|
|
12
|
+
return new InMemoryRunStore();
|
|
13
|
+
}
|
|
14
|
+
if (dbType === 'postgres') {
|
|
15
|
+
const url = config.db?.url;
|
|
16
|
+
if (!url)
|
|
17
|
+
throw new Error('db.url is required when db.type is postgres');
|
|
18
|
+
return new PgRunStore(url);
|
|
19
|
+
}
|
|
20
|
+
// Default: sqlite
|
|
21
|
+
const studioDir = config.resolvedStudioDir ?? join(process.cwd(), '.studio');
|
|
22
|
+
mkdirSync(join(studioDir, 'runs'), { recursive: true });
|
|
23
|
+
const dbPath = join(studioDir, 'runs', 'runs.db');
|
|
24
|
+
return new SQLiteRunStore(dbPath);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=run-store-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-store-factory.js","sourceRoot":"","sources":["../src/run-store-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAGzF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAoB;IACvD,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,IAAI,IAAI,QAAQ,CAAC;IAE3C,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QAC1B,OAAO,IAAI,gBAAgB,EAAE,CAAC;IAChC,CAAC;IAED,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC;QAC3B,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACzE,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,kBAAkB;IAClB,MAAM,SAAS,GAAG,MAAM,CAAC,iBAAiB,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IAC7E,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IAClD,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walk up the directory tree from `startDir` looking for a `.studio/` directory.
|
|
3
|
+
* Like git looking for `.git/`.
|
|
4
|
+
* Returns the absolute path to `.studio/`, or null if not found.
|
|
5
|
+
*/
|
|
6
|
+
export declare function findStudioDir(startDir: string): Promise<string | null>;
|
|
7
|
+
//# sourceMappingURL=studio-dir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-dir.d.ts","sourceRoot":"","sources":["../src/studio-dir.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmB5E"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { access } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Walk up the directory tree from `startDir` looking for a `.studio/` directory.
|
|
5
|
+
* Like git looking for `.git/`.
|
|
6
|
+
* Returns the absolute path to `.studio/`, or null if not found.
|
|
7
|
+
*/
|
|
8
|
+
export async function findStudioDir(startDir) {
|
|
9
|
+
let current = resolve(startDir);
|
|
10
|
+
while (true) {
|
|
11
|
+
const candidate = join(current, '.studio');
|
|
12
|
+
try {
|
|
13
|
+
await access(candidate);
|
|
14
|
+
return candidate;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// not found here, go up
|
|
18
|
+
}
|
|
19
|
+
const parent = dirname(current);
|
|
20
|
+
if (parent === current) {
|
|
21
|
+
// Reached filesystem root
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
current = parent;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=studio-dir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-dir.js","sourceRoot":"","sources":["../src/studio-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,IAAI,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEhC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;YACxB,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,0BAA0B;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { InputSchema } from '@studio-foundation/contracts';
|
|
2
|
+
export declare function validateInputSchema(raw: unknown): InputSchema;
|
|
3
|
+
export declare function collectStructuredInput(schema: InputSchema): Promise<Record<string, unknown>>;
|
|
4
|
+
//# sourceMappingURL=input-wizard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-wizard.d.ts","sourceRoot":"","sources":["../../src/utils/input-wizard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEhE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CA0B7D;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAuClC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { input } from '@inquirer/prompts';
|
|
2
|
+
export function validateInputSchema(raw) {
|
|
3
|
+
const schema = raw;
|
|
4
|
+
if (!Array.isArray(schema?.fields) || schema.fields.length === 0) {
|
|
5
|
+
throw new Error('input_schema must have at least one field');
|
|
6
|
+
}
|
|
7
|
+
for (const field of schema.fields) {
|
|
8
|
+
const name = field.name ?? '(unnamed)';
|
|
9
|
+
if (!field.prompt || typeof field.prompt !== 'string' || !field.prompt.trim()) {
|
|
10
|
+
throw new Error(`Field '${name}' must have a non-empty 'prompt'`);
|
|
11
|
+
}
|
|
12
|
+
if (field.type !== 'text' && field.type !== 'array') {
|
|
13
|
+
throw new Error(`Field '${name}' has invalid type '${field.type}'. Must be 'text' or 'array'`);
|
|
14
|
+
}
|
|
15
|
+
if (field.type === 'array' && field.items !== 'text') {
|
|
16
|
+
throw new Error(`Array field '${name}' must have items: 'text'`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return raw;
|
|
20
|
+
}
|
|
21
|
+
export async function collectStructuredInput(schema) {
|
|
22
|
+
const result = {};
|
|
23
|
+
for (const field of schema.fields) {
|
|
24
|
+
if (field.type === 'text') {
|
|
25
|
+
result[field.name] = await input({
|
|
26
|
+
message: field.prompt,
|
|
27
|
+
required: field.required,
|
|
28
|
+
default: field.default,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
else if (field.type === 'array') {
|
|
32
|
+
const items = [];
|
|
33
|
+
let index = 1;
|
|
34
|
+
while (true) {
|
|
35
|
+
const value = await input({
|
|
36
|
+
message: `${field.prompt} (${index})`,
|
|
37
|
+
required: index === 1 && field.required,
|
|
38
|
+
default: '',
|
|
39
|
+
});
|
|
40
|
+
if (value === '') {
|
|
41
|
+
if (index === 1 && field.required) {
|
|
42
|
+
console.log('At least one value required.');
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
items.push(value);
|
|
48
|
+
index++;
|
|
49
|
+
}
|
|
50
|
+
result[field.name] = items;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
console.log('\n✓ Input collected\n');
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=input-wizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-wizard.js","sourceRoot":"","sources":["../../src/utils/input-wizard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG1C,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,MAAM,MAAM,GAAG,GAA8B,CAAC;IAE9C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAe,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,WAAW,CAAC;QAEvC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YAC9E,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,kCAAkC,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,uBAAuB,KAAK,CAAC,IAAI,8BAA8B,CAC9E,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,2BAA2B,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,OAAO,GAAkB,CAAC;AAC5B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAmB;IAEnB,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,KAAK,CAAC;gBAC/B,OAAO,EAAE,KAAK,CAAC,MAAM;gBACrB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAClC,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,KAAK,GAAG,CAAC,CAAC;YAEd,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC;oBACxB,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,KAAK,KAAK,GAAG;oBACrC,QAAQ,EAAE,KAAK,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ;oBACvC,OAAO,EAAE,EAAE;iBACZ,CAAC,CAAC;gBAEH,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;oBACjB,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;wBAClC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;wBAC5C,SAAS;oBACX,CAAC;oBACD,MAAM;gBACR,CAAC;gBAED,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAClB,KAAK,EAAE,CAAC;YACV,CAAC;YAED,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replace {{ALL_CAPS}} placeholders in `content` with values from `vars`.
|
|
3
|
+
* Throws if any placeholder has no corresponding entry in `vars`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function applyPlaceholders(content: string, vars: Record<string, string>): string;
|
|
6
|
+
//# sourceMappingURL=placeholders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"placeholders.d.ts","sourceRoot":"","sources":["../../src/utils/placeholders.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAKvF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replace {{ALL_CAPS}} placeholders in `content` with values from `vars`.
|
|
3
|
+
* Throws if any placeholder has no corresponding entry in `vars`.
|
|
4
|
+
*/
|
|
5
|
+
export function applyPlaceholders(content, vars) {
|
|
6
|
+
return content.replace(/\{\{([A-Z][A-Z0-9_]*)\}\}/g, (match, key) => {
|
|
7
|
+
if (key in vars)
|
|
8
|
+
return vars[key];
|
|
9
|
+
throw new Error(`Unresolved placeholder: ${match}`);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=placeholders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"placeholders.js","sourceRoot":"","sources":["../../src/utils/placeholders.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,IAA4B;IAC7E,OAAO,OAAO,CAAC,OAAO,CAAC,4BAA4B,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAClE,IAAI,GAAG,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC"}
|