@martin0309205/prism 0.1.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.
Files changed (51) hide show
  1. package/README.md +87 -0
  2. package/assets/systemd/prism@.service +21 -0
  3. package/dist/artifacts.d.ts +9 -0
  4. package/dist/artifacts.js +77 -0
  5. package/dist/artifacts.js.map +1 -0
  6. package/dist/cli/commands/daemon.d.ts +2 -0
  7. package/dist/cli/commands/daemon.js +90 -0
  8. package/dist/cli/commands/daemon.js.map +1 -0
  9. package/dist/cli/commands/doctor.d.ts +2 -0
  10. package/dist/cli/commands/doctor.js +69 -0
  11. package/dist/cli/commands/doctor.js.map +1 -0
  12. package/dist/cli/commands/generate.d.ts +2 -0
  13. package/dist/cli/commands/generate.js +89 -0
  14. package/dist/cli/commands/generate.js.map +1 -0
  15. package/dist/cli/commands/onboard.d.ts +2 -0
  16. package/dist/cli/commands/onboard.js +131 -0
  17. package/dist/cli/commands/onboard.js.map +1 -0
  18. package/dist/cli/commands/serve.d.ts +2 -0
  19. package/dist/cli/commands/serve.js +51 -0
  20. package/dist/cli/commands/serve.js.map +1 -0
  21. package/dist/cli/commands/update.d.ts +2 -0
  22. package/dist/cli/commands/update.js +38 -0
  23. package/dist/cli/commands/update.js.map +1 -0
  24. package/dist/cli/index.d.ts +2 -0
  25. package/dist/cli/index.js +29 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/config.d.ts +34 -0
  28. package/dist/config.js +88 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/daemon.d.ts +16 -0
  31. package/dist/daemon.js +72 -0
  32. package/dist/daemon.js.map +1 -0
  33. package/dist/index.d.ts +4 -0
  34. package/dist/index.js +3 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/instances.d.ts +2 -0
  37. package/dist/instances.js +16 -0
  38. package/dist/instances.js.map +1 -0
  39. package/dist/logger.d.ts +9 -0
  40. package/dist/logger.js +23 -0
  41. package/dist/logger.js.map +1 -0
  42. package/dist/runner.d.ts +19 -0
  43. package/dist/runner.js +89 -0
  44. package/dist/runner.js.map +1 -0
  45. package/dist/surfaces/http.d.ts +12 -0
  46. package/dist/surfaces/http.js +96 -0
  47. package/dist/surfaces/http.js.map +1 -0
  48. package/dist/surfaces/slack.d.ts +9 -0
  49. package/dist/surfaces/slack.js +123 -0
  50. package/dist/surfaces/slack.js.map +1 -0
  51. package/package.json +51 -0
@@ -0,0 +1,51 @@
1
+ import { loadConfig, loadEnvFile } from '../../config.js';
2
+ import { createLogger } from '../../logger.js';
3
+ import { startHttpServer } from '../../surfaces/http.js';
4
+ import { startSlackServer } from '../../surfaces/slack.js';
5
+ export function serveCmd(program) {
6
+ program
7
+ .command('serve')
8
+ .description('Start the configured surfaces (HTTP + Slack) for an instance.')
9
+ .option('-i, --instance <name>', 'prism instance to run', 'default')
10
+ .option('--http-only', 'start only the HTTP surface')
11
+ .option('--slack-only', 'start only the Slack surface')
12
+ .option('--public-base-url <url>', 'public base URL for artifact links (HTTP)', '')
13
+ .action(async (opts) => {
14
+ const config = loadConfig(opts.instance);
15
+ const env = loadEnvFile(opts.instance);
16
+ const logger = createLogger(config.logging.level);
17
+ // expose loaded env vars to claude subprocess via process.env
18
+ for (const [k, v] of Object.entries(env)) {
19
+ if (process.env[k] == null)
20
+ process.env[k] = v;
21
+ }
22
+ const runSlack = config.surfaces.slack.enabled && !opts.httpOnly;
23
+ const runHttp = config.surfaces.http.enabled && !opts.slackOnly;
24
+ const shutdownHandlers = [];
25
+ if (runHttp) {
26
+ const app = await startHttpServer({
27
+ config,
28
+ env,
29
+ logger,
30
+ public_base_url: opts.publicBaseUrl || undefined,
31
+ });
32
+ shutdownHandlers.push(async () => { await app.close(); });
33
+ }
34
+ if (runSlack) {
35
+ const app = await startSlackServer({ config, env, logger });
36
+ shutdownHandlers.push(async () => { await app.stop(); });
37
+ }
38
+ if (!runHttp && !runSlack) {
39
+ logger.warn('serve.nothing_enabled');
40
+ process.exit(0);
41
+ }
42
+ const shutdown = async (sig) => {
43
+ logger.info('serve.shutdown', { sig });
44
+ await Promise.allSettled(shutdownHandlers.map((h) => h()));
45
+ process.exit(0);
46
+ };
47
+ process.on('SIGINT', () => void shutdown('SIGINT'));
48
+ process.on('SIGTERM', () => void shutdown('SIGTERM'));
49
+ });
50
+ }
51
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/cli/commands/serve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function updateCmd(program: Command): void;
@@ -0,0 +1,38 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { listInstances } from '../../instances.js';
3
+ export function updateCmd(program) {
4
+ program
5
+ .command('update')
6
+ .description('Pull the latest prism version from npm and restart all installed services.')
7
+ .option('--no-restart', 'skip restarting systemd services')
8
+ .option('--version <ver>', 'specific version to install', 'latest')
9
+ .action((opts) => {
10
+ const target = `prism@${opts.version}`;
11
+ process.stderr.write(`[prism] installing ${target}...\n`);
12
+ const install = spawnSync('npm', ['install', '-g', target], { stdio: 'inherit' });
13
+ if (install.status !== 0) {
14
+ process.stderr.write(`[prism] npm install failed\n`);
15
+ process.exit(install.status ?? 1);
16
+ }
17
+ if (!opts.restart)
18
+ return;
19
+ if (process.platform !== 'linux') {
20
+ process.stderr.write(`[prism] skipping service restart (not Linux)\n`);
21
+ return;
22
+ }
23
+ const instances = listInstances();
24
+ if (instances.length === 0) {
25
+ process.stderr.write(`[prism] no instances configured, nothing to restart\n`);
26
+ return;
27
+ }
28
+ for (const inst of instances) {
29
+ const unit = `prism@${inst}.service`;
30
+ process.stderr.write(`[prism] restarting ${unit}...\n`);
31
+ const r = spawnSync('systemctl', ['--user', 'restart', unit], { stdio: 'inherit' });
32
+ if (r.status !== 0) {
33
+ process.stderr.write(`[prism] failed to restart ${unit} (continuing)\n`);
34
+ }
35
+ }
36
+ });
37
+ }
38
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/cli/commands/update.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,UAAU,SAAS,CAAC,OAAgB;IACxC,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,4EAA4E,CAAC;SACzF,MAAM,CAAC,cAAc,EAAE,kCAAkC,CAAC;SAC1D,MAAM,CAAC,iBAAiB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;SAClE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QACf,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;QACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,MAAM,OAAO,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAClF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;YACrD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAE1B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;YACvE,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;QAClC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;YAC9E,OAAO;QACT,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,SAAS,IAAI,UAAU,CAAC;YACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,IAAI,OAAO,CAAC,CAAC;YACxD,MAAM,CAAC,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACpF,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,IAAI,iBAAiB,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { readFileSync } from 'node:fs';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { dirname, resolve } from 'node:path';
6
+ import { generateCmd } from './commands/generate.js';
7
+ import { onboardCmd } from './commands/onboard.js';
8
+ import { doctorCmd } from './commands/doctor.js';
9
+ import { serveCmd } from './commands/serve.js';
10
+ import { updateCmd } from './commands/update.js';
11
+ import { daemonCmd } from './commands/daemon.js';
12
+ const here = dirname(fileURLToPath(import.meta.url));
13
+ const pkg = JSON.parse(readFileSync(resolve(here, '..', '..', 'package.json'), 'utf8'));
14
+ const program = new Command();
15
+ program
16
+ .name('prism')
17
+ .description('Thin connector around Claude Code: Slack/HTTP/CLI surfaces that ship the files Claude creates.')
18
+ .version(pkg.version);
19
+ generateCmd(program);
20
+ serveCmd(program);
21
+ onboardCmd(program);
22
+ doctorCmd(program);
23
+ daemonCmd(program);
24
+ updateCmd(program);
25
+ program.parseAsync(process.argv).catch((err) => {
26
+ console.error(err instanceof Error ? err.message : String(err));
27
+ process.exit(1);
28
+ });
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAwB,CAAC;AAE/G,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,gGAAgG,CAAC;KAC7G,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAExB,WAAW,CAAC,OAAO,CAAC,CAAC;AACrB,QAAQ,CAAC,OAAO,CAAC,CAAC;AAClB,UAAU,CAAC,OAAO,CAAC,CAAC;AACpB,SAAS,CAAC,OAAO,CAAC,CAAC;AACnB,SAAS,CAAC,OAAO,CAAC,CAAC;AACnB,SAAS,CAAC,OAAO,CAAC,CAAC;AAEnB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,34 @@
1
+ export interface PrismConfig {
2
+ instance: string;
3
+ surfaces: {
4
+ slack: {
5
+ enabled: boolean;
6
+ allowlist_channels?: string[];
7
+ };
8
+ http: {
9
+ enabled: boolean;
10
+ bind: string;
11
+ port: number;
12
+ };
13
+ cli: {
14
+ enabled: boolean;
15
+ };
16
+ };
17
+ claude: {
18
+ bin: string;
19
+ timeout_ms: number;
20
+ workdir_root: string;
21
+ };
22
+ artifacts: {
23
+ retention_days: number;
24
+ dir?: string;
25
+ };
26
+ logging: {
27
+ level: 'debug' | 'info' | 'warn' | 'error';
28
+ decision_log: boolean;
29
+ };
30
+ }
31
+ export declare function defaultConfig(instance?: string): PrismConfig;
32
+ export declare function instanceRoot(instance?: string): string;
33
+ export declare function loadConfig(instance?: string): PrismConfig;
34
+ export declare function loadEnvFile(instance?: string): Record<string, string>;
package/dist/config.js ADDED
@@ -0,0 +1,88 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { parse as parseYaml } from 'yaml';
5
+ export function defaultConfig(instance = 'default') {
6
+ return {
7
+ instance,
8
+ surfaces: {
9
+ slack: { enabled: false, allowlist_channels: [] },
10
+ http: { enabled: true, bind: '127.0.0.1', port: 18790 },
11
+ cli: { enabled: true },
12
+ },
13
+ claude: {
14
+ bin: 'claude',
15
+ timeout_ms: 600_000,
16
+ workdir_root: '/tmp',
17
+ },
18
+ artifacts: {
19
+ retention_days: 7,
20
+ },
21
+ logging: {
22
+ level: 'info',
23
+ decision_log: true,
24
+ },
25
+ };
26
+ }
27
+ export function instanceRoot(instance = 'default') {
28
+ return join(homedir(), '.prism', 'instances', instance);
29
+ }
30
+ export function loadConfig(instance = 'default') {
31
+ const root = instanceRoot(instance);
32
+ const configPath = join(root, 'config.yaml');
33
+ const base = defaultConfig(instance);
34
+ if (!existsSync(configPath))
35
+ return base;
36
+ const raw = readFileSync(configPath, 'utf8');
37
+ const parsed = parseYaml(raw);
38
+ if (!parsed)
39
+ return base;
40
+ return mergeDeep(base, parsed);
41
+ }
42
+ export function loadEnvFile(instance = 'default') {
43
+ const path = join(instanceRoot(instance), '.env');
44
+ if (!existsSync(path))
45
+ return {};
46
+ const out = {};
47
+ for (const line of readFileSync(path, 'utf8').split(/\r?\n/)) {
48
+ const trimmed = line.trim();
49
+ if (!trimmed || trimmed.startsWith('#'))
50
+ continue;
51
+ const eq = trimmed.indexOf('=');
52
+ if (eq < 0)
53
+ continue;
54
+ const key = trimmed.slice(0, eq).trim();
55
+ let val = trimmed.slice(eq + 1).trim();
56
+ if ((val.startsWith('"') && val.endsWith('"')) ||
57
+ (val.startsWith("'") && val.endsWith("'"))) {
58
+ val = val.slice(1, -1);
59
+ }
60
+ out[key] = val;
61
+ }
62
+ return out;
63
+ }
64
+ function mergeDeep(base, override) {
65
+ if (override == null)
66
+ return base;
67
+ if (typeof base !== 'object' || typeof override !== 'object') {
68
+ return override ?? base;
69
+ }
70
+ const out = { ...base };
71
+ for (const [key, value] of Object.entries(override)) {
72
+ if (value == null)
73
+ continue;
74
+ const baseVal = base[key];
75
+ if (typeof baseVal === 'object' &&
76
+ baseVal !== null &&
77
+ !Array.isArray(baseVal) &&
78
+ typeof value === 'object' &&
79
+ !Array.isArray(value)) {
80
+ out[key] = mergeDeep(baseVal, value);
81
+ }
82
+ else {
83
+ out[key] = value;
84
+ }
85
+ }
86
+ return out;
87
+ }
88
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export declare function userSystemdDir(): string;
2
+ export declare function unitName(instance: string): string;
3
+ export declare function unitPath(): string;
4
+ export declare function renderUnit(prismBin: string): string;
5
+ export declare function installUnit(prismBin: string): string;
6
+ export declare function uninstallUnit(): void;
7
+ export declare function ensureInstancePaths(instance: string): void;
8
+ export declare function systemctl(args: string[], opts?: {
9
+ check?: boolean;
10
+ }): {
11
+ status: number;
12
+ stdout: string;
13
+ stderr: string;
14
+ };
15
+ export declare function detectPrismBin(): string;
16
+ export declare function claudeAvailable(bin?: string): boolean;
package/dist/daemon.js ADDED
@@ -0,0 +1,72 @@
1
+ import { execFileSync, spawnSync } from 'node:child_process';
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { dirname, join, resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { instanceRoot } from './config.js';
7
+ import { instancesRoot } from './instances.js';
8
+ const here = dirname(fileURLToPath(import.meta.url));
9
+ // dist/daemon.js -> ../assets/systemd/prism@.service relative to package root
10
+ const TEMPLATE_PATH = resolve(here, '..', 'assets', 'systemd', 'prism@.service');
11
+ export function userSystemdDir() {
12
+ return join(homedir(), '.config', 'systemd', 'user');
13
+ }
14
+ export function unitName(instance) {
15
+ return `prism@${instance}.service`;
16
+ }
17
+ export function unitPath() {
18
+ return join(userSystemdDir(), 'prism@.service');
19
+ }
20
+ export function renderUnit(prismBin) {
21
+ const tmpl = readFileSync(TEMPLATE_PATH, 'utf8');
22
+ return tmpl
23
+ .replaceAll('__PRISM_BIN__', prismBin)
24
+ .replaceAll('__HOME__', homedir())
25
+ .replaceAll('__INSTANCE_DIR__', instancesRoot());
26
+ }
27
+ export function installUnit(prismBin) {
28
+ const dir = userSystemdDir();
29
+ mkdirSync(dir, { recursive: true });
30
+ const path = unitPath();
31
+ writeFileSync(path, renderUnit(prismBin), 'utf8');
32
+ systemctl(['daemon-reload']);
33
+ return path;
34
+ }
35
+ export function uninstallUnit() {
36
+ const path = unitPath();
37
+ if (existsSync(path))
38
+ unlinkSync(path);
39
+ systemctl(['daemon-reload']);
40
+ }
41
+ export function ensureInstancePaths(instance) {
42
+ const root = instanceRoot(instance);
43
+ if (!existsSync(root)) {
44
+ throw new Error(`instance ${instance} not found at ${root} — run 'prism onboard' first`);
45
+ }
46
+ mkdirSync(join(root, 'logs'), { recursive: true });
47
+ mkdirSync(join(root, 'artifacts'), { recursive: true });
48
+ }
49
+ export function systemctl(args, opts = {}) {
50
+ const r = spawnSync('systemctl', ['--user', ...args], { encoding: 'utf8' });
51
+ if (opts.check && r.status !== 0) {
52
+ throw new Error(`systemctl --user ${args.join(' ')} failed: ${r.stderr || r.stdout}`);
53
+ }
54
+ return { status: r.status ?? -1, stdout: r.stdout ?? '', stderr: r.stderr ?? '' };
55
+ }
56
+ export function detectPrismBin() {
57
+ const which = spawnSync(process.platform === 'win32' ? 'where' : 'which', ['prism'], { encoding: 'utf8' });
58
+ if (which.status === 0 && which.stdout.trim()) {
59
+ return which.stdout.trim().split(/\r?\n/)[0];
60
+ }
61
+ return 'prism';
62
+ }
63
+ export function claudeAvailable(bin = 'claude') {
64
+ try {
65
+ execFileSync(bin, ['--version'], { stdio: 'ignore' });
66
+ return true;
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ }
72
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,8EAA8E;AAC9E,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;AAEjF,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,QAAgB;IACvC,OAAO,SAAS,QAAQ,UAAU,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,IAAI,GAAG,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,IAAI;SACR,UAAU,CAAC,eAAe,EAAE,QAAQ,CAAC;SACrC,UAAU,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;SACjC,UAAU,CAAC,kBAAkB,EAAE,aAAa,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;IAC7B,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;IAClD,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,IAAI,UAAU,CAAC,IAAI,CAAC;QAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACvC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,YAAY,QAAQ,iBAAiB,IAAI,8BAA8B,CAAC,CAAC;IAC3F,CAAC;IACD,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAc,EAAE,OAA4B,EAAE;IACtE,MAAM,CAAC,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5E,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3G,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,CAAC;IAChD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAG,GAAG,QAAQ;IAC5C,IAAI,CAAC;QACH,YAAY,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { generate } from './runner.js';
2
+ export type { RunOptions, RunResult } from './runner.js';
3
+ export { loadConfig, defaultConfig } from './config.js';
4
+ export type { PrismConfig } from './config.js';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { generate } from './runner.js';
2
+ export { loadConfig, defaultConfig } from './config.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function instancesRoot(): string;
2
+ export declare function listInstances(): string[];
@@ -0,0 +1,16 @@
1
+ import { existsSync, readdirSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ export function instancesRoot() {
5
+ return join(homedir(), '.prism', 'instances');
6
+ }
7
+ export function listInstances() {
8
+ const root = instancesRoot();
9
+ if (!existsSync(root))
10
+ return [];
11
+ return readdirSync(root, { withFileTypes: true })
12
+ .filter((d) => d.isDirectory())
13
+ .map((d) => d.name)
14
+ .sort();
15
+ }
16
+ //# sourceMappingURL=instances.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instances.js","sourceRoot":"","sources":["../src/instances.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,OAAO,WAAW,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SAC9C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,IAAI,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,9 @@
1
+ type Level = 'debug' | 'info' | 'warn' | 'error';
2
+ export interface Logger {
3
+ debug: (msg: string, extra?: Record<string, unknown>) => void;
4
+ info: (msg: string, extra?: Record<string, unknown>) => void;
5
+ warn: (msg: string, extra?: Record<string, unknown>) => void;
6
+ error: (msg: string, extra?: Record<string, unknown>) => void;
7
+ }
8
+ export declare function createLogger(level?: Level): Logger;
9
+ export {};
package/dist/logger.js ADDED
@@ -0,0 +1,23 @@
1
+ const LEVELS = { debug: 10, info: 20, warn: 30, error: 40 };
2
+ export function createLogger(level = 'info') {
3
+ const threshold = LEVELS[level] ?? LEVELS.info;
4
+ function emit(at, msg, extra) {
5
+ if (LEVELS[at] < threshold)
6
+ return;
7
+ const line = {
8
+ ts: new Date().toISOString(),
9
+ level: at,
10
+ msg,
11
+ ...(extra ?? {}),
12
+ };
13
+ const stream = at === 'error' || at === 'warn' ? process.stderr : process.stdout;
14
+ stream.write(JSON.stringify(line) + '\n');
15
+ }
16
+ return {
17
+ debug: (msg, extra) => emit('debug', msg, extra),
18
+ info: (msg, extra) => emit('info', msg, extra),
19
+ warn: (msg, extra) => emit('warn', msg, extra),
20
+ error: (msg, extra) => emit('error', msg, extra),
21
+ };
22
+ }
23
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAA0B,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AASnF,MAAM,UAAU,YAAY,CAAC,QAAe,MAAM;IAChD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC;IAC/C,SAAS,IAAI,CAAC,EAAS,EAAE,GAAW,EAAE,KAA+B;QACnE,IAAI,MAAM,CAAC,EAAE,CAAC,GAAG,SAAS;YAAE,OAAO;QACnC,MAAM,IAAI,GAAG;YACX,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,KAAK,EAAE,EAAE;YACT,GAAG;YACH,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;SACjB,CAAC;QACF,MAAM,MAAM,GAAG,EAAE,KAAK,OAAO,IAAI,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QACjF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC;QAChD,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC;QAC9C,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC;QAC9C,KAAK,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC;KACjD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ export interface RunOptions {
2
+ brief: string;
3
+ workdir?: string;
4
+ timeout_ms?: number;
5
+ claude_bin?: string;
6
+ env?: NodeJS.ProcessEnv;
7
+ on_stdout?: (chunk: string) => void;
8
+ on_stderr?: (chunk: string) => void;
9
+ }
10
+ export interface RunResult {
11
+ text: string;
12
+ files: string[];
13
+ stderr: string;
14
+ exit_code: number;
15
+ workdir: string;
16
+ duration_ms: number;
17
+ timed_out: boolean;
18
+ }
19
+ export declare function generate(opts: RunOptions): Promise<RunResult>;
package/dist/runner.js ADDED
@@ -0,0 +1,89 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { mkdtempSync, readdirSync, statSync, existsSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
6
+ export async function generate(opts) {
7
+ const workdir = opts.workdir ?? mkdtempSync(join(tmpdir(), 'prism-'));
8
+ const before = snapshotMtimes(workdir);
9
+ const claude_bin = opts.claude_bin ?? process.env.CLAUDE_BIN ?? 'claude';
10
+ const timeout_ms = opts.timeout_ms ?? DEFAULT_TIMEOUT_MS;
11
+ const start = Date.now();
12
+ return new Promise((resolve, reject) => {
13
+ const child = spawn(claude_bin, ['-p', opts.brief, '--dangerously-skip-permissions'], {
14
+ cwd: workdir,
15
+ stdio: ['ignore', 'pipe', 'pipe'],
16
+ env: { ...process.env, ...opts.env },
17
+ });
18
+ let stdout = '';
19
+ let stderr = '';
20
+ let timed_out = false;
21
+ child.stdout.on('data', (chunk) => {
22
+ const text = chunk.toString('utf8');
23
+ stdout += text;
24
+ opts.on_stdout?.(text);
25
+ });
26
+ child.stderr.on('data', (chunk) => {
27
+ const text = chunk.toString('utf8');
28
+ stderr += text;
29
+ opts.on_stderr?.(text);
30
+ });
31
+ const timer = setTimeout(() => {
32
+ timed_out = true;
33
+ child.kill('SIGTERM');
34
+ setTimeout(() => {
35
+ if (!child.killed)
36
+ child.kill('SIGKILL');
37
+ }, 5_000);
38
+ }, timeout_ms);
39
+ child.on('error', (err) => {
40
+ clearTimeout(timer);
41
+ reject(err);
42
+ });
43
+ child.on('exit', (code) => {
44
+ clearTimeout(timer);
45
+ const after = snapshotMtimes(workdir);
46
+ const files = [];
47
+ for (const [path, mtime] of after) {
48
+ const prev = before.get(path);
49
+ if (prev == null || mtime > prev)
50
+ files.push(path);
51
+ }
52
+ files.sort();
53
+ resolve({
54
+ text: stdout.trim(),
55
+ files,
56
+ stderr,
57
+ exit_code: code ?? -1,
58
+ workdir,
59
+ duration_ms: Date.now() - start,
60
+ timed_out,
61
+ });
62
+ });
63
+ });
64
+ }
65
+ function snapshotMtimes(dir) {
66
+ const map = new Map();
67
+ if (!existsSync(dir))
68
+ return map;
69
+ let entries;
70
+ try {
71
+ entries = readdirSync(dir, { recursive: true });
72
+ }
73
+ catch {
74
+ return map;
75
+ }
76
+ for (const name of entries) {
77
+ const full = join(dir, name);
78
+ try {
79
+ const st = statSync(full);
80
+ if (st.isFile())
81
+ map.set(full, st.mtimeMs);
82
+ }
83
+ catch {
84
+ // unreadable entry — skip
85
+ }
86
+ }
87
+ return map;
88
+ }
89
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type FastifyInstance } from 'fastify';
2
+ import type { PrismConfig } from '../config.js';
3
+ import type { Logger } from '../logger.js';
4
+ export interface HttpServerOptions {
5
+ config: PrismConfig;
6
+ env: Record<string, string>;
7
+ logger: Logger;
8
+ api_key?: string;
9
+ public_base_url?: string;
10
+ }
11
+ export declare function createHttpServer(opts: HttpServerOptions): Promise<FastifyInstance>;
12
+ export declare function startHttpServer(opts: HttpServerOptions): Promise<FastifyInstance>;