@some-useful-agents/core 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 (69) hide show
  1. package/dist/agent-executor.d.ts +12 -0
  2. package/dist/agent-executor.d.ts.map +1 -0
  3. package/dist/agent-executor.js +121 -0
  4. package/dist/agent-executor.js.map +1 -0
  5. package/dist/agent-loader.d.ts +19 -0
  6. package/dist/agent-loader.d.ts.map +1 -0
  7. package/dist/agent-loader.js +76 -0
  8. package/dist/agent-loader.js.map +1 -0
  9. package/dist/agent-loader.test.d.ts +2 -0
  10. package/dist/agent-loader.test.d.ts.map +1 -0
  11. package/dist/agent-loader.test.js +82 -0
  12. package/dist/agent-loader.test.js.map +1 -0
  13. package/dist/chain-executor.d.ts +16 -0
  14. package/dist/chain-executor.d.ts.map +1 -0
  15. package/dist/chain-executor.js +54 -0
  16. package/dist/chain-executor.js.map +1 -0
  17. package/dist/chain-resolver.d.ts +27 -0
  18. package/dist/chain-resolver.d.ts.map +1 -0
  19. package/dist/chain-resolver.js +82 -0
  20. package/dist/chain-resolver.js.map +1 -0
  21. package/dist/chain-resolver.test.d.ts +2 -0
  22. package/dist/chain-resolver.test.d.ts.map +1 -0
  23. package/dist/chain-resolver.test.js +86 -0
  24. package/dist/chain-resolver.test.js.map +1 -0
  25. package/dist/env-builder.d.ts +16 -0
  26. package/dist/env-builder.d.ts.map +1 -0
  27. package/dist/env-builder.js +59 -0
  28. package/dist/env-builder.js.map +1 -0
  29. package/dist/env-builder.test.d.ts +2 -0
  30. package/dist/env-builder.test.d.ts.map +1 -0
  31. package/dist/env-builder.test.js +167 -0
  32. package/dist/env-builder.test.js.map +1 -0
  33. package/dist/index.d.ts +11 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +11 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/local-provider.d.ts +24 -0
  38. package/dist/local-provider.d.ts.map +1 -0
  39. package/dist/local-provider.js +101 -0
  40. package/dist/local-provider.js.map +1 -0
  41. package/dist/run-store.d.ts +16 -0
  42. package/dist/run-store.d.ts.map +1 -0
  43. package/dist/run-store.js +115 -0
  44. package/dist/run-store.js.map +1 -0
  45. package/dist/run-store.test.d.ts +2 -0
  46. package/dist/run-store.test.d.ts.map +1 -0
  47. package/dist/run-store.test.js +83 -0
  48. package/dist/run-store.test.js.map +1 -0
  49. package/dist/schema.d.ts +104 -0
  50. package/dist/schema.d.ts.map +1 -0
  51. package/dist/schema.js +35 -0
  52. package/dist/schema.js.map +1 -0
  53. package/dist/schema.test.d.ts +2 -0
  54. package/dist/schema.test.d.ts.map +1 -0
  55. package/dist/schema.test.js +108 -0
  56. package/dist/schema.test.js.map +1 -0
  57. package/dist/secrets-store.d.ts +34 -0
  58. package/dist/secrets-store.d.ts.map +1 -0
  59. package/dist/secrets-store.js +116 -0
  60. package/dist/secrets-store.js.map +1 -0
  61. package/dist/secrets-store.test.d.ts +2 -0
  62. package/dist/secrets-store.test.d.ts.map +1 -0
  63. package/dist/secrets-store.test.js +99 -0
  64. package/dist/secrets-store.test.js.map +1 -0
  65. package/dist/types.d.ts +52 -0
  66. package/dist/types.d.ts.map +1 -0
  67. package/dist/types.js +2 -0
  68. package/dist/types.js.map +1 -0
  69. package/package.json +30 -0
@@ -0,0 +1,115 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import { mkdirSync, existsSync } from 'node:fs';
3
+ import { dirname } from 'node:path';
4
+ export class RunStore {
5
+ db;
6
+ constructor(dbPath) {
7
+ const dir = dirname(dbPath);
8
+ if (!existsSync(dir)) {
9
+ mkdirSync(dir, { recursive: true });
10
+ }
11
+ this.db = new DatabaseSync(dbPath);
12
+ this.db.exec('PRAGMA journal_mode = WAL');
13
+ this.db.exec(`
14
+ CREATE TABLE IF NOT EXISTS runs (
15
+ id TEXT PRIMARY KEY,
16
+ agentName TEXT NOT NULL,
17
+ status TEXT NOT NULL,
18
+ startedAt TEXT NOT NULL,
19
+ completedAt TEXT,
20
+ result TEXT,
21
+ exitCode INTEGER,
22
+ error TEXT,
23
+ triggeredBy TEXT NOT NULL
24
+ )
25
+ `);
26
+ this.db.exec(`
27
+ CREATE INDEX IF NOT EXISTS idx_runs_agent ON runs(agentName);
28
+ CREATE INDEX IF NOT EXISTS idx_runs_status ON runs(status);
29
+ `);
30
+ }
31
+ createRun(run) {
32
+ const stmt = this.db.prepare(`
33
+ INSERT INTO runs (id, agentName, status, startedAt, completedAt, result, exitCode, error, triggeredBy)
34
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
35
+ `);
36
+ stmt.run(run.id, run.agentName, run.status, run.startedAt, run.completedAt ?? null, run.result ?? null, run.exitCode ?? null, run.error ?? null, run.triggeredBy);
37
+ }
38
+ getRun(id) {
39
+ const stmt = this.db.prepare('SELECT * FROM runs WHERE id = ?');
40
+ const row = stmt.get(id);
41
+ if (!row)
42
+ return null;
43
+ return this.rowToRun(row);
44
+ }
45
+ updateRun(id, updates) {
46
+ const fields = [];
47
+ const values = [];
48
+ if (updates.status !== undefined) {
49
+ fields.push('status = ?');
50
+ values.push(updates.status);
51
+ }
52
+ if (updates.completedAt !== undefined) {
53
+ fields.push('completedAt = ?');
54
+ values.push(updates.completedAt);
55
+ }
56
+ if (updates.result !== undefined) {
57
+ fields.push('result = ?');
58
+ values.push(updates.result);
59
+ }
60
+ if (updates.exitCode !== undefined) {
61
+ fields.push('exitCode = ?');
62
+ values.push(updates.exitCode);
63
+ }
64
+ if (updates.error !== undefined) {
65
+ fields.push('error = ?');
66
+ values.push(updates.error);
67
+ }
68
+ if (fields.length === 0)
69
+ return;
70
+ values.push(id);
71
+ const stmt = this.db.prepare(`UPDATE runs SET ${fields.join(', ')} WHERE id = ?`);
72
+ stmt.run(...values);
73
+ }
74
+ listRuns(filter) {
75
+ let sql = 'SELECT * FROM runs';
76
+ const conditions = [];
77
+ const values = [];
78
+ if (filter?.agentName) {
79
+ conditions.push('agentName = ?');
80
+ values.push(filter.agentName);
81
+ }
82
+ if (filter?.status) {
83
+ conditions.push('status = ?');
84
+ values.push(filter.status);
85
+ }
86
+ if (conditions.length > 0) {
87
+ sql += ' WHERE ' + conditions.join(' AND ');
88
+ }
89
+ sql += ' ORDER BY startedAt DESC';
90
+ if (filter?.limit) {
91
+ sql += ' LIMIT ?';
92
+ values.push(filter.limit);
93
+ }
94
+ const stmt = this.db.prepare(sql);
95
+ const rows = stmt.all(...values);
96
+ return rows.map(row => this.rowToRun(row));
97
+ }
98
+ close() {
99
+ this.db.close();
100
+ }
101
+ rowToRun(row) {
102
+ return {
103
+ id: row.id,
104
+ agentName: row.agentName,
105
+ status: row.status,
106
+ startedAt: row.startedAt,
107
+ completedAt: row.completedAt,
108
+ result: row.result,
109
+ exitCode: row.exitCode,
110
+ error: row.error,
111
+ triggeredBy: row.triggeredBy,
112
+ };
113
+ }
114
+ }
115
+ //# sourceMappingURL=run-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-store.js","sourceRoot":"","sources":["../src/run-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=run-store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-store.test.d.ts","sourceRoot":"","sources":["../src/run-store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,83 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { rmSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { RunStore } from './run-store.js';
5
+ const TEST_DB = join(import.meta.dirname, '__test-data__', 'test-runs.db');
6
+ function makeRun(overrides) {
7
+ return {
8
+ id: `test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
9
+ agentName: 'test-agent',
10
+ status: 'completed',
11
+ startedAt: new Date().toISOString(),
12
+ triggeredBy: 'cli',
13
+ ...overrides,
14
+ };
15
+ }
16
+ let store;
17
+ beforeEach(() => {
18
+ store = new RunStore(TEST_DB);
19
+ });
20
+ afterEach(() => {
21
+ store.close();
22
+ rmSync(join(import.meta.dirname, '__test-data__'), { recursive: true, force: true });
23
+ });
24
+ describe('RunStore', () => {
25
+ it('creates and retrieves a run', () => {
26
+ const run = makeRun({ id: 'run-1' });
27
+ store.createRun(run);
28
+ const retrieved = store.getRun('run-1');
29
+ expect(retrieved).not.toBeNull();
30
+ expect(retrieved.agentName).toBe('test-agent');
31
+ });
32
+ it('returns null for non-existent run', () => {
33
+ expect(store.getRun('nonexistent')).toBeNull();
34
+ });
35
+ it('updates run status', () => {
36
+ const run = makeRun({ id: 'run-2', status: 'running' });
37
+ store.createRun(run);
38
+ store.updateRun('run-2', { status: 'completed', completedAt: new Date().toISOString() });
39
+ const updated = store.getRun('run-2');
40
+ expect(updated.status).toBe('completed');
41
+ expect(updated.completedAt).toBeTruthy();
42
+ });
43
+ it('lists runs filtered by agent name', () => {
44
+ store.createRun(makeRun({ id: 'r1', agentName: 'agent-a' }));
45
+ store.createRun(makeRun({ id: 'r2', agentName: 'agent-b' }));
46
+ store.createRun(makeRun({ id: 'r3', agentName: 'agent-a' }));
47
+ const runs = store.listRuns({ agentName: 'agent-a' });
48
+ expect(runs.length).toBe(2);
49
+ expect(runs.every(r => r.agentName === 'agent-a')).toBe(true);
50
+ });
51
+ it('lists runs filtered by status', () => {
52
+ store.createRun(makeRun({ id: 'r1', status: 'completed' }));
53
+ store.createRun(makeRun({ id: 'r2', status: 'failed' }));
54
+ const runs = store.listRuns({ status: 'failed' });
55
+ expect(runs.length).toBe(1);
56
+ expect(runs[0].status).toBe('failed');
57
+ });
58
+ it('lists runs with limit', () => {
59
+ for (let i = 0; i < 5; i++) {
60
+ store.createRun(makeRun({ id: `r${i}` }));
61
+ }
62
+ const runs = store.listRuns({ limit: 3 });
63
+ expect(runs.length).toBe(3);
64
+ });
65
+ it('auto-creates data directory', () => {
66
+ // The constructor already creates the directory, this test verifies
67
+ // no error is thrown when the directory doesn't exist
68
+ const deepPath = join(import.meta.dirname, '__test-data__', 'deep', 'nested', 'test.db');
69
+ const deepStore = new RunStore(deepPath);
70
+ const run = makeRun({ id: 'deep-1' });
71
+ deepStore.createRun(run);
72
+ expect(deepStore.getRun('deep-1')).not.toBeNull();
73
+ deepStore.close();
74
+ });
75
+ it('stores and retrieves result and error fields', () => {
76
+ const run = makeRun({ id: 'r-fields', result: 'hello output', exitCode: 0 });
77
+ store.createRun(run);
78
+ const retrieved = store.getRun('r-fields');
79
+ expect(retrieved.result).toBe('hello output');
80
+ expect(retrieved.exitCode).toBe(0);
81
+ });
82
+ });
83
+ //# sourceMappingURL=run-store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-store.test.js","sourceRoot":"","sources":["../src/run-store.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ import { z } from 'zod';
2
+ export declare const agentDefinitionSchema: z.ZodEffects<z.ZodObject<{
3
+ name: z.ZodString;
4
+ description: z.ZodOptional<z.ZodString>;
5
+ type: z.ZodEnum<["claude-code", "shell"]>;
6
+ command: z.ZodOptional<z.ZodString>;
7
+ prompt: z.ZodOptional<z.ZodString>;
8
+ model: z.ZodOptional<z.ZodString>;
9
+ maxTurns: z.ZodOptional<z.ZodNumber>;
10
+ allowedTools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
11
+ timeout: z.ZodDefault<z.ZodNumber>;
12
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
13
+ schedule: z.ZodOptional<z.ZodString>;
14
+ workingDirectory: z.ZodOptional<z.ZodString>;
15
+ dependsOn: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
16
+ input: z.ZodOptional<z.ZodString>;
17
+ secrets: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
18
+ envAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
19
+ author: z.ZodOptional<z.ZodString>;
20
+ version: z.ZodOptional<z.ZodString>;
21
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
22
+ }, "strip", z.ZodTypeAny, {
23
+ name: string;
24
+ type: "claude-code" | "shell";
25
+ timeout: number;
26
+ schedule?: string | undefined;
27
+ env?: Record<string, string> | undefined;
28
+ description?: string | undefined;
29
+ command?: string | undefined;
30
+ prompt?: string | undefined;
31
+ model?: string | undefined;
32
+ maxTurns?: number | undefined;
33
+ allowedTools?: string[] | undefined;
34
+ workingDirectory?: string | undefined;
35
+ dependsOn?: string[] | undefined;
36
+ input?: string | undefined;
37
+ secrets?: string[] | undefined;
38
+ envAllowlist?: string[] | undefined;
39
+ author?: string | undefined;
40
+ version?: string | undefined;
41
+ tags?: string[] | undefined;
42
+ }, {
43
+ name: string;
44
+ type: "claude-code" | "shell";
45
+ schedule?: string | undefined;
46
+ env?: Record<string, string> | undefined;
47
+ description?: string | undefined;
48
+ command?: string | undefined;
49
+ prompt?: string | undefined;
50
+ model?: string | undefined;
51
+ maxTurns?: number | undefined;
52
+ allowedTools?: string[] | undefined;
53
+ timeout?: number | undefined;
54
+ workingDirectory?: string | undefined;
55
+ dependsOn?: string[] | undefined;
56
+ input?: string | undefined;
57
+ secrets?: string[] | undefined;
58
+ envAllowlist?: string[] | undefined;
59
+ author?: string | undefined;
60
+ version?: string | undefined;
61
+ tags?: string[] | undefined;
62
+ }>, {
63
+ name: string;
64
+ type: "claude-code" | "shell";
65
+ timeout: number;
66
+ schedule?: string | undefined;
67
+ env?: Record<string, string> | undefined;
68
+ description?: string | undefined;
69
+ command?: string | undefined;
70
+ prompt?: string | undefined;
71
+ model?: string | undefined;
72
+ maxTurns?: number | undefined;
73
+ allowedTools?: string[] | undefined;
74
+ workingDirectory?: string | undefined;
75
+ dependsOn?: string[] | undefined;
76
+ input?: string | undefined;
77
+ secrets?: string[] | undefined;
78
+ envAllowlist?: string[] | undefined;
79
+ author?: string | undefined;
80
+ version?: string | undefined;
81
+ tags?: string[] | undefined;
82
+ }, {
83
+ name: string;
84
+ type: "claude-code" | "shell";
85
+ schedule?: string | undefined;
86
+ env?: Record<string, string> | undefined;
87
+ description?: string | undefined;
88
+ command?: string | undefined;
89
+ prompt?: string | undefined;
90
+ model?: string | undefined;
91
+ maxTurns?: number | undefined;
92
+ allowedTools?: string[] | undefined;
93
+ timeout?: number | undefined;
94
+ workingDirectory?: string | undefined;
95
+ dependsOn?: string[] | undefined;
96
+ input?: string | undefined;
97
+ secrets?: string[] | undefined;
98
+ envAllowlist?: string[] | undefined;
99
+ author?: string | undefined;
100
+ version?: string | undefined;
101
+ tags?: string[] | undefined;
102
+ }>;
103
+ export type AgentDefinitionInput = z.input<typeof agentDefinitionSchema>;
104
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuCjC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
package/dist/schema.js ADDED
@@ -0,0 +1,35 @@
1
+ import { z } from 'zod';
2
+ export const agentDefinitionSchema = z.object({
3
+ name: z.string().min(1).regex(/^[a-z0-9-]+$/, 'Must be lowercase with hyphens only'),
4
+ description: z.string().optional(),
5
+ type: z.enum(['claude-code', 'shell']),
6
+ // Shell agents
7
+ command: z.string().optional(),
8
+ // Claude-code agents
9
+ prompt: z.string().optional(),
10
+ model: z.string().optional(),
11
+ maxTurns: z.number().int().positive().optional(),
12
+ allowedTools: z.array(z.string()).optional(),
13
+ // Common
14
+ timeout: z.number().positive().default(300),
15
+ env: z.record(z.string()).optional(),
16
+ schedule: z.string().optional(),
17
+ workingDirectory: z.string().optional(),
18
+ // Chaining
19
+ dependsOn: z.array(z.string()).optional(),
20
+ input: z.string().optional(),
21
+ // Secrets and env control
22
+ secrets: z.array(z.string().regex(/^[A-Z_][A-Z0-9_]*$/, 'Must be a valid env var name (e.g. MY_API_KEY)')).optional(),
23
+ envAllowlist: z.array(z.string()).optional(),
24
+ // Metadata
25
+ author: z.string().optional(),
26
+ version: z.string().optional(),
27
+ tags: z.array(z.string()).optional(),
28
+ }).refine((data) => {
29
+ if (data.type === 'shell')
30
+ return !!data.command;
31
+ if (data.type === 'claude-code')
32
+ return !!data.prompt;
33
+ return false;
34
+ }, { message: 'Shell agents require "command", claude-code agents require "prompt"' });
35
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,EAAE,qCAAqC,CAAC;IACpF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAEtC,eAAe;IACf,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAE9B,qBAAqB;IACrB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAChD,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAE5C,SAAS;IACT,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IAC3C,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAEvC,WAAW;IACX,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACzC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAE5B,0BAA0B;IAC1B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,EAAE,gDAAgD,CAAC,CAAC,CAAC,QAAQ,EAAE;IACrH,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAE5C,WAAW;IACX,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC,MAAM,CACP,CAAC,IAAI,EAAE,EAAE;IACP,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IACjD,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa;QAAE,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IACtD,OAAO,KAAK,CAAC;AACf,CAAC,EACD,EAAE,OAAO,EAAE,qEAAqE,EAAE,CACnF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.test.d.ts","sourceRoot":"","sources":["../src/schema.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,108 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { agentDefinitionSchema } from './schema.js';
3
+ describe('agentDefinitionSchema', () => {
4
+ it('validates a valid shell agent', () => {
5
+ const result = agentDefinitionSchema.safeParse({
6
+ name: 'hello-shell',
7
+ type: 'shell',
8
+ command: 'echo hello',
9
+ });
10
+ expect(result.success).toBe(true);
11
+ });
12
+ it('validates a valid claude-code agent', () => {
13
+ const result = agentDefinitionSchema.safeParse({
14
+ name: 'hello-claude',
15
+ type: 'claude-code',
16
+ prompt: 'Say hello',
17
+ model: 'claude-sonnet-4-20250514',
18
+ });
19
+ expect(result.success).toBe(true);
20
+ });
21
+ it('rejects missing name', () => {
22
+ const result = agentDefinitionSchema.safeParse({
23
+ type: 'shell',
24
+ command: 'echo hello',
25
+ });
26
+ expect(result.success).toBe(false);
27
+ });
28
+ it('rejects missing type', () => {
29
+ const result = agentDefinitionSchema.safeParse({
30
+ name: 'test',
31
+ command: 'echo hello',
32
+ });
33
+ expect(result.success).toBe(false);
34
+ });
35
+ it('rejects invalid type value', () => {
36
+ const result = agentDefinitionSchema.safeParse({
37
+ name: 'test',
38
+ type: 'python',
39
+ command: 'echo hello',
40
+ });
41
+ expect(result.success).toBe(false);
42
+ });
43
+ it('rejects shell agent without command', () => {
44
+ const result = agentDefinitionSchema.safeParse({
45
+ name: 'test',
46
+ type: 'shell',
47
+ });
48
+ expect(result.success).toBe(false);
49
+ });
50
+ it('rejects claude-code agent without prompt', () => {
51
+ const result = agentDefinitionSchema.safeParse({
52
+ name: 'test',
53
+ type: 'claude-code',
54
+ });
55
+ expect(result.success).toBe(false);
56
+ });
57
+ it('rejects name with uppercase letters', () => {
58
+ const result = agentDefinitionSchema.safeParse({
59
+ name: 'Hello-Shell',
60
+ type: 'shell',
61
+ command: 'echo hello',
62
+ });
63
+ expect(result.success).toBe(false);
64
+ });
65
+ it('rejects name with spaces', () => {
66
+ const result = agentDefinitionSchema.safeParse({
67
+ name: 'hello shell',
68
+ type: 'shell',
69
+ command: 'echo hello',
70
+ });
71
+ expect(result.success).toBe(false);
72
+ });
73
+ it('passes through extra fields (zod strips them)', () => {
74
+ const result = agentDefinitionSchema.safeParse({
75
+ name: 'test',
76
+ type: 'shell',
77
+ command: 'echo hello',
78
+ unknownField: 'value',
79
+ });
80
+ expect(result.success).toBe(true);
81
+ });
82
+ it('applies default timeout of 300', () => {
83
+ const result = agentDefinitionSchema.parse({
84
+ name: 'test',
85
+ type: 'shell',
86
+ command: 'echo hello',
87
+ });
88
+ expect(result.timeout).toBe(300);
89
+ });
90
+ it('validates all optional metadata fields', () => {
91
+ const result = agentDefinitionSchema.safeParse({
92
+ name: 'test',
93
+ type: 'shell',
94
+ command: 'echo hello',
95
+ author: 'gregmeyer',
96
+ version: '1.0.0',
97
+ tags: ['test', 'example'],
98
+ description: 'A test agent',
99
+ env: { FOO: 'bar' },
100
+ schedule: '0 9 * * *',
101
+ workingDirectory: '/tmp',
102
+ dependsOn: ['other-agent'],
103
+ input: '{{outputs.other-agent.result}}',
104
+ });
105
+ expect(result.success).toBe(true);
106
+ });
107
+ });
108
+ //# sourceMappingURL=schema.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.test.js","sourceRoot":"","sources":["../src/schema.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,YAAY;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,0BAA0B;SAClC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,YAAY;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,YAAY;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,YAAY;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,aAAa;SACpB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,YAAY;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,YAAY;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,YAAY;YACrB,YAAY,EAAE,OAAO;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC;YACzC,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,YAAY;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,YAAY;YACrB,MAAM,EAAE,WAAW;YACnB,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;YACzB,WAAW,EAAE,cAAc;YAC3B,GAAG,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;YACnB,QAAQ,EAAE,WAAW;YACrB,gBAAgB,EAAE,MAAM;YACxB,SAAS,EAAE,CAAC,aAAa,CAAC;YAC1B,KAAK,EAAE,gCAAgC;SACxC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,34 @@
1
+ export interface SecretsStore {
2
+ get(name: string): Promise<string | undefined>;
3
+ set(name: string, value: string): Promise<void>;
4
+ delete(name: string): Promise<void>;
5
+ list(): Promise<string[]>;
6
+ has(name: string): Promise<boolean>;
7
+ getAll(): Promise<Record<string, string>>;
8
+ }
9
+ export declare class EncryptedFileStore implements SecretsStore {
10
+ private readonly path;
11
+ private readonly key;
12
+ constructor(filePath: string);
13
+ get(name: string): Promise<string | undefined>;
14
+ set(name: string, value: string): Promise<void>;
15
+ delete(name: string): Promise<void>;
16
+ list(): Promise<string[]>;
17
+ has(name: string): Promise<boolean>;
18
+ getAll(): Promise<Record<string, string>>;
19
+ private read;
20
+ private write;
21
+ }
22
+ /**
23
+ * In-memory secrets store for tests and CI environments.
24
+ */
25
+ export declare class MemorySecretsStore implements SecretsStore {
26
+ private readonly data;
27
+ get(name: string): Promise<string | undefined>;
28
+ set(name: string, value: string): Promise<void>;
29
+ delete(name: string): Promise<void>;
30
+ list(): Promise<string[]>;
31
+ has(name: string): Promise<boolean>;
32
+ getAll(): Promise<Record<string, string>>;
33
+ }
34
+ //# sourceMappingURL=secrets-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets-store.d.ts","sourceRoot":"","sources":["../src/secrets-store.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC3C;AAmBD,qBAAa,kBAAmB,YAAW,YAAY;IACrD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;gBAEjB,QAAQ,EAAE,MAAM;IAUtB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAK9C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnC,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAIzB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKnC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAI/C,OAAO,CAAC,IAAI;IA4BZ,OAAO,CAAC,KAAK;CAsBd;AAOD;;GAEG;AACH,qBAAa,kBAAmB,YAAW,YAAY;IACrD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAE5C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAI9C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInC,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAIzB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAInC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAGhD"}
@@ -0,0 +1,116 @@
1
+ import { randomBytes, scryptSync, createCipheriv, createDecipheriv } from 'node:crypto';
2
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync } from 'node:fs';
3
+ import { dirname } from 'node:path';
4
+ import { hostname, userInfo } from 'node:os';
5
+ const ALGORITHM = 'aes-256-gcm';
6
+ const KEY_LENGTH = 32;
7
+ const IV_LENGTH = 12;
8
+ const TAG_LENGTH = 16;
9
+ const SALT = 'sua-secrets-v1';
10
+ export class EncryptedFileStore {
11
+ path;
12
+ key;
13
+ constructor(filePath) {
14
+ this.path = filePath;
15
+ this.key = deriveKey();
16
+ const dir = dirname(filePath);
17
+ if (!existsSync(dir)) {
18
+ mkdirSync(dir, { recursive: true });
19
+ }
20
+ }
21
+ async get(name) {
22
+ const data = this.read();
23
+ return data[name];
24
+ }
25
+ async set(name, value) {
26
+ const data = this.read();
27
+ data[name] = value;
28
+ this.write(data);
29
+ }
30
+ async delete(name) {
31
+ const data = this.read();
32
+ delete data[name];
33
+ this.write(data);
34
+ }
35
+ async list() {
36
+ return Object.keys(this.read()).sort();
37
+ }
38
+ async has(name) {
39
+ const data = this.read();
40
+ return name in data;
41
+ }
42
+ async getAll() {
43
+ return { ...this.read() };
44
+ }
45
+ read() {
46
+ if (!existsSync(this.path))
47
+ return {};
48
+ try {
49
+ const raw = readFileSync(this.path, 'utf-8');
50
+ const payload = JSON.parse(raw);
51
+ if (payload.version !== 1) {
52
+ throw new Error(`Unsupported secrets version: ${payload.version}`);
53
+ }
54
+ const iv = Buffer.from(payload.iv, 'base64');
55
+ const tag = Buffer.from(payload.tag, 'base64');
56
+ const encrypted = Buffer.from(payload.data, 'base64');
57
+ const decipher = createDecipheriv(ALGORITHM, this.key, iv);
58
+ decipher.setAuthTag(tag);
59
+ const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
60
+ return JSON.parse(decrypted.toString('utf-8'));
61
+ }
62
+ catch (err) {
63
+ throw new Error(`Failed to read secrets store at ${this.path}: ${err.message}. ` +
64
+ `The file may be corrupted or encrypted with a different key (different user/hostname).`);
65
+ }
66
+ }
67
+ write(data) {
68
+ const plaintext = Buffer.from(JSON.stringify(data), 'utf-8');
69
+ const iv = randomBytes(IV_LENGTH);
70
+ const cipher = createCipheriv(ALGORITHM, this.key, iv);
71
+ const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
72
+ const tag = cipher.getAuthTag();
73
+ const payload = {
74
+ version: 1,
75
+ iv: iv.toString('base64'),
76
+ tag: tag.toString('base64'),
77
+ data: encrypted.toString('base64'),
78
+ };
79
+ writeFileSync(this.path, JSON.stringify(payload, null, 2), 'utf-8');
80
+ try {
81
+ chmodSync(this.path, 0o600);
82
+ }
83
+ catch {
84
+ // Best effort: chmod may fail on Windows or network mounts
85
+ }
86
+ }
87
+ }
88
+ function deriveKey() {
89
+ const seed = `${hostname()}:${userInfo().username}`;
90
+ return scryptSync(seed, SALT, KEY_LENGTH);
91
+ }
92
+ /**
93
+ * In-memory secrets store for tests and CI environments.
94
+ */
95
+ export class MemorySecretsStore {
96
+ data = new Map();
97
+ async get(name) {
98
+ return this.data.get(name);
99
+ }
100
+ async set(name, value) {
101
+ this.data.set(name, value);
102
+ }
103
+ async delete(name) {
104
+ this.data.delete(name);
105
+ }
106
+ async list() {
107
+ return Array.from(this.data.keys()).sort();
108
+ }
109
+ async has(name) {
110
+ return this.data.has(name);
111
+ }
112
+ async getAll() {
113
+ return Object.fromEntries(this.data);
114
+ }
115
+ }
116
+ //# sourceMappingURL=secrets-store.js.map