@ash-ai/server 0.0.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/LICENSE +21 -0
- package/dist/__tests__/auth.test.d.ts +2 -0
- package/dist/__tests__/auth.test.d.ts.map +1 -0
- package/dist/__tests__/auth.test.js +111 -0
- package/dist/__tests__/auth.test.js.map +1 -0
- package/dist/__tests__/backpressure.test.d.ts +2 -0
- package/dist/__tests__/backpressure.test.d.ts.map +1 -0
- package/dist/__tests__/backpressure.test.js +81 -0
- package/dist/__tests__/backpressure.test.js.map +1 -0
- package/dist/__tests__/db.test.d.ts +2 -0
- package/dist/__tests__/db.test.d.ts.map +1 -0
- package/dist/__tests__/db.test.js +111 -0
- package/dist/__tests__/db.test.js.map +1 -0
- package/dist/__tests__/files.test.d.ts +2 -0
- package/dist/__tests__/files.test.d.ts.map +1 -0
- package/dist/__tests__/files.test.js +171 -0
- package/dist/__tests__/files.test.js.map +1 -0
- package/dist/__tests__/openapi.test.d.ts +2 -0
- package/dist/__tests__/openapi.test.d.ts.map +1 -0
- package/dist/__tests__/openapi.test.js +88 -0
- package/dist/__tests__/openapi.test.js.map +1 -0
- package/dist/__tests__/pool.test.d.ts +2 -0
- package/dist/__tests__/pool.test.d.ts.map +1 -0
- package/dist/__tests__/pool.test.js +352 -0
- package/dist/__tests__/pool.test.js.map +1 -0
- package/dist/__tests__/resource-limits.test.d.ts +2 -0
- package/dist/__tests__/resource-limits.test.d.ts.map +1 -0
- package/dist/__tests__/resource-limits.test.js +119 -0
- package/dist/__tests__/resource-limits.test.js.map +1 -0
- package/dist/__tests__/sandbox-env.test.d.ts +2 -0
- package/dist/__tests__/sandbox-env.test.d.ts.map +1 -0
- package/dist/__tests__/sandbox-env.test.js +40 -0
- package/dist/__tests__/sandbox-env.test.js.map +1 -0
- package/dist/__tests__/snapshot-store.test.d.ts +2 -0
- package/dist/__tests__/snapshot-store.test.d.ts.map +1 -0
- package/dist/__tests__/snapshot-store.test.js +101 -0
- package/dist/__tests__/snapshot-store.test.js.map +1 -0
- package/dist/__tests__/state-persistence.test.d.ts +2 -0
- package/dist/__tests__/state-persistence.test.d.ts.map +1 -0
- package/dist/__tests__/state-persistence.test.js +116 -0
- package/dist/__tests__/state-persistence.test.js.map +1 -0
- package/dist/auth.d.ts +10 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +30 -0
- package/dist/auth.js.map +1 -0
- package/dist/db/index.d.ts +54 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +91 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/pg.d.ts +31 -0
- package/dist/db/pg.d.ts.map +1 -0
- package/dist/db/pg.js +214 -0
- package/dist/db/pg.js.map +1 -0
- package/dist/db/sqlite.d.ts +30 -0
- package/dist/db/sqlite.d.ts.map +1 -0
- package/dist/db/sqlite.js +195 -0
- package/dist/db/sqlite.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +122 -0
- package/dist/index.js.map +1 -0
- package/dist/routes/agents.d.ts +3 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +103 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/routes/files.d.ts +4 -0
- package/dist/routes/files.d.ts.map +1 -0
- package/dist/routes/files.js +189 -0
- package/dist/routes/files.js.map +1 -0
- package/dist/routes/health.d.ts +5 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +72 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/runners.d.ts +8 -0
- package/dist/routes/runners.d.ts.map +1 -0
- package/dist/routes/runners.js +33 -0
- package/dist/routes/runners.js.map +1 -0
- package/dist/routes/sessions.d.ts +10 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +392 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/runner/coordinator.d.ts +52 -0
- package/dist/runner/coordinator.d.ts.map +1 -0
- package/dist/runner/coordinator.js +157 -0
- package/dist/runner/coordinator.js.map +1 -0
- package/dist/runner/local-backend.d.ts +26 -0
- package/dist/runner/local-backend.d.ts.map +1 -0
- package/dist/runner/local-backend.js +79 -0
- package/dist/runner/local-backend.js.map +1 -0
- package/dist/runner/remote-backend.d.ts +32 -0
- package/dist/runner/remote-backend.d.ts.map +1 -0
- package/dist/runner/remote-backend.js +81 -0
- package/dist/runner/remote-backend.js.map +1 -0
- package/dist/runner/runner-client.d.ts +53 -0
- package/dist/runner/runner-client.d.ts.map +1 -0
- package/dist/runner/runner-client.js +157 -0
- package/dist/runner/runner-client.js.map +1 -0
- package/dist/runner/types.d.ts +37 -0
- package/dist/runner/types.d.ts.map +1 -0
- package/dist/runner/types.js +2 -0
- package/dist/runner/types.js.map +1 -0
- package/dist/schemas.d.ts +3 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +73 -0
- package/dist/schemas.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { SANDBOX_ENV_ALLOWLIST } from '@ash-ai/shared';
|
|
3
|
+
/**
|
|
4
|
+
* Security invariant: sandbox processes must NOT receive host secrets.
|
|
5
|
+
* The allowlist is the enforcement mechanism — test that it doesn't
|
|
6
|
+
* contain dangerous keys, and that the manager respects it.
|
|
7
|
+
*/
|
|
8
|
+
describe('sandbox environment isolation', () => {
|
|
9
|
+
const DANGEROUS_KEYS = [
|
|
10
|
+
'AWS_SECRET_ACCESS_KEY',
|
|
11
|
+
'AWS_ACCESS_KEY_ID',
|
|
12
|
+
'AWS_SESSION_TOKEN',
|
|
13
|
+
'SSH_AUTH_SOCK',
|
|
14
|
+
'GITHUB_TOKEN',
|
|
15
|
+
'GH_TOKEN',
|
|
16
|
+
'NPM_TOKEN',
|
|
17
|
+
'DATABASE_URL',
|
|
18
|
+
'PGPASSWORD',
|
|
19
|
+
'REDIS_URL',
|
|
20
|
+
'OPENAI_API_KEY',
|
|
21
|
+
'STRIPE_SECRET_KEY',
|
|
22
|
+
'DOCKER_HOST',
|
|
23
|
+
];
|
|
24
|
+
it('allowlist does not contain any dangerous keys', () => {
|
|
25
|
+
for (const key of DANGEROUS_KEYS) {
|
|
26
|
+
expect(SANDBOX_ENV_ALLOWLIST, `SANDBOX_ENV_ALLOWLIST must not contain ${key}`).not.toContain(key);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
it('allowlist contains only expected keys', () => {
|
|
30
|
+
// If someone adds a key, this test forces them to think about it
|
|
31
|
+
const expected = new Set(['PATH', 'NODE_PATH', 'HOME', 'LANG', 'TERM', 'ANTHROPIC_API_KEY', 'ASH_DEBUG_TIMING', 'ASH_REAL_SDK', 'CLAUDE_CODE_EXECUTABLE']);
|
|
32
|
+
const actual = new Set(SANDBOX_ENV_ALLOWLIST);
|
|
33
|
+
expect(actual).toEqual(expected);
|
|
34
|
+
});
|
|
35
|
+
it('ANTHROPIC_API_KEY is the only secret in the allowlist', () => {
|
|
36
|
+
const secrets = SANDBOX_ENV_ALLOWLIST.filter((k) => k.includes('KEY') || k.includes('TOKEN') || k.includes('SECRET') || k.includes('PASSWORD'));
|
|
37
|
+
expect(secrets).toEqual(['ANTHROPIC_API_KEY']);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=sandbox-env.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-env.test.js","sourceRoot":"","sources":["../../src/__tests__/sandbox-env.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;;GAIG;AACH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,MAAM,cAAc,GAAG;QACrB,uBAAuB;QACvB,mBAAmB;QACnB,mBAAmB;QACnB,eAAe;QACf,cAAc;QACd,UAAU;QACV,WAAW;QACX,cAAc;QACd,YAAY;QACZ,WAAW;QACX,gBAAgB;QAChB,mBAAmB;QACnB,aAAa;KACd,CAAC;IAEF,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;YACjC,MAAM,CACJ,qBAAqB,EACrB,0CAA0C,GAAG,EAAE,CAChD,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,iEAAiE;QACjE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,cAAc,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAC3J,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,OAAO,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACjD,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC3F,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-store.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/snapshot-store.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { createSnapshotStore, getSnapshotStore, resetSnapshotStore, } from '@ash-ai/sandbox';
|
|
6
|
+
import { syncStateToCloud, restoreStateFromCloud, deleteCloudState, } from '@ash-ai/sandbox';
|
|
7
|
+
describe('snapshot-store', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
resetSnapshotStore();
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
resetSnapshotStore();
|
|
13
|
+
delete process.env.ASH_SNAPSHOT_URL;
|
|
14
|
+
});
|
|
15
|
+
describe('createSnapshotStore', () => {
|
|
16
|
+
it('throws on unrecognized scheme', async () => {
|
|
17
|
+
await expect(createSnapshotStore('ftp://bucket/prefix/')).rejects.toThrow('Unsupported snapshot URL scheme');
|
|
18
|
+
});
|
|
19
|
+
it('throws on empty bucket for s3', async () => {
|
|
20
|
+
await expect(createSnapshotStore('s3://')).rejects.toThrow('Invalid S3 URL: missing bucket name');
|
|
21
|
+
});
|
|
22
|
+
it('throws on empty bucket for gs', async () => {
|
|
23
|
+
await expect(createSnapshotStore('gs://')).rejects.toThrow('Invalid GCS URL: missing bucket name');
|
|
24
|
+
});
|
|
25
|
+
it('parses s3 URL with bucket only', async () => {
|
|
26
|
+
// This will fail to import @aws-sdk/client-s3 in test env (not installed)
|
|
27
|
+
// but we verify parsing by checking the error message
|
|
28
|
+
try {
|
|
29
|
+
await createSnapshotStore('s3://my-bucket');
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
// Either "Install @aws-sdk/client-s3" or the actual import succeeds
|
|
33
|
+
// Both are valid outcomes depending on test environment
|
|
34
|
+
expect(err).toBeDefined();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
it('parses gs URL with bucket and prefix', async () => {
|
|
38
|
+
try {
|
|
39
|
+
await createSnapshotStore('gs://my-bucket/some/prefix/');
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
expect(err).toBeDefined();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe('getSnapshotStore', () => {
|
|
47
|
+
it('returns null when ASH_SNAPSHOT_URL is not set', async () => {
|
|
48
|
+
delete process.env.ASH_SNAPSHOT_URL;
|
|
49
|
+
const store = await getSnapshotStore();
|
|
50
|
+
expect(store).toBeNull();
|
|
51
|
+
});
|
|
52
|
+
it('caches the null result', async () => {
|
|
53
|
+
delete process.env.ASH_SNAPSHOT_URL;
|
|
54
|
+
const store1 = await getSnapshotStore();
|
|
55
|
+
const store2 = await getSnapshotStore();
|
|
56
|
+
expect(store1).toBeNull();
|
|
57
|
+
expect(store2).toBeNull();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('syncStateToCloud', () => {
|
|
61
|
+
let dataDir;
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
dataDir = mkdtempSync(join(tmpdir(), 'ash-test-cloud-'));
|
|
64
|
+
});
|
|
65
|
+
afterEach(() => {
|
|
66
|
+
rmSync(dataDir, { recursive: true, force: true });
|
|
67
|
+
});
|
|
68
|
+
it('returns false when no store configured', async () => {
|
|
69
|
+
delete process.env.ASH_SNAPSHOT_URL;
|
|
70
|
+
const result = await syncStateToCloud(dataDir, 'sess-1');
|
|
71
|
+
expect(result).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
it('returns false when no persisted workspace exists', async () => {
|
|
74
|
+
delete process.env.ASH_SNAPSHOT_URL;
|
|
75
|
+
const result = await syncStateToCloud(dataDir, 'nonexistent');
|
|
76
|
+
expect(result).toBe(false);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe('restoreStateFromCloud', () => {
|
|
80
|
+
let dataDir;
|
|
81
|
+
beforeEach(() => {
|
|
82
|
+
dataDir = mkdtempSync(join(tmpdir(), 'ash-test-cloud-'));
|
|
83
|
+
});
|
|
84
|
+
afterEach(() => {
|
|
85
|
+
rmSync(dataDir, { recursive: true, force: true });
|
|
86
|
+
});
|
|
87
|
+
it('returns false when no store configured', async () => {
|
|
88
|
+
delete process.env.ASH_SNAPSHOT_URL;
|
|
89
|
+
const result = await restoreStateFromCloud(dataDir, 'sess-1');
|
|
90
|
+
expect(result).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
describe('deleteCloudState', () => {
|
|
94
|
+
it('is a no-op when no store configured', async () => {
|
|
95
|
+
delete process.env.ASH_SNAPSHOT_URL;
|
|
96
|
+
// Should not throw
|
|
97
|
+
await deleteCloudState('sess-1');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
//# sourceMappingURL=snapshot-store.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-store.test.js","sourceRoot":"","sources":["../../src/__tests__/snapshot-store.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAM,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,WAAW,EAAsD,MAAM,EAAE,MAAM,SAAS,CAAC;AAClG,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,GAEjB,MAAM,iBAAiB,CAAC;AAEzB,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,UAAU,CAAC,GAAG,EAAE;QACd,kBAAkB,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,kBAAkB,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,MAAM,MAAM,CAAC,mBAAmB,CAAC,sBAAsB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACvE,iCAAiC,CAClC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,MAAM,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACxD,qCAAqC,CACtC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,MAAM,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACxD,sCAAsC,CACvC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC9C,0EAA0E;YAC1E,sDAAsD;YACtD,IAAI,CAAC;gBACH,MAAM,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;YAC9C,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,oEAAoE;gBACpE,wDAAwD;gBACxD,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YAC5B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YACpD,IAAI,CAAC;gBACH,MAAM,mBAAmB,CAAC,6BAA6B,CAAC,CAAC;YAC3D,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YAC5B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACpC,MAAM,KAAK,GAAG,MAAM,gBAAgB,EAAE,CAAC;YACvC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;YACtC,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,gBAAgB,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,MAAM,gBAAgB,EAAE,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC1B,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,IAAI,OAAe,CAAC;QAEpB,UAAU,CAAC,GAAG,EAAE;YACd,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YACzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YAC9D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,IAAI,OAAe,CAAC;QAEpB,UAAU,CAAC,GAAG,EAAE;YACd,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC9D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACpC,mBAAmB;YACnB,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-persistence.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/state-persistence.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdtempSync, mkdirSync, writeFileSync, existsSync, readFileSync, rmSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { persistSessionState, restoreSessionState, hasPersistedState, deleteSessionState, getStateMetadata, } from '@ash-ai/sandbox';
|
|
6
|
+
describe('state-persistence', () => {
|
|
7
|
+
let dataDir;
|
|
8
|
+
let workspaceDir;
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
dataDir = mkdtempSync(join(tmpdir(), 'ash-test-state-'));
|
|
11
|
+
workspaceDir = mkdtempSync(join(tmpdir(), 'ash-test-workspace-'));
|
|
12
|
+
});
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
rmSync(dataDir, { recursive: true, force: true });
|
|
15
|
+
rmSync(workspaceDir, { recursive: true, force: true });
|
|
16
|
+
});
|
|
17
|
+
function populateWorkspace(dir) {
|
|
18
|
+
// .claude session state
|
|
19
|
+
mkdirSync(join(dir, '.claude', 'projects', 'abc123'), { recursive: true });
|
|
20
|
+
writeFileSync(join(dir, '.claude', 'projects', 'abc123', 'session.jsonl'), 'session-data');
|
|
21
|
+
// Agent files
|
|
22
|
+
writeFileSync(join(dir, 'CLAUDE.md'), '# My Agent');
|
|
23
|
+
// Files created by the agent during session
|
|
24
|
+
mkdirSync(join(dir, 'output'), { recursive: true });
|
|
25
|
+
writeFileSync(join(dir, 'output', 'result.json'), '{"answer": 42}');
|
|
26
|
+
}
|
|
27
|
+
it('persists and restores entire workspace roundtrip', () => {
|
|
28
|
+
populateWorkspace(workspaceDir);
|
|
29
|
+
const persisted = persistSessionState(dataDir, 'sess-1', workspaceDir, 'my-agent');
|
|
30
|
+
expect(persisted).toBe(true);
|
|
31
|
+
expect(hasPersistedState(dataDir, 'sess-1')).toBe(true);
|
|
32
|
+
// Wipe workspace entirely and restore
|
|
33
|
+
rmSync(workspaceDir, { recursive: true });
|
|
34
|
+
expect(existsSync(workspaceDir)).toBe(false);
|
|
35
|
+
const restored = restoreSessionState(dataDir, 'sess-1', workspaceDir);
|
|
36
|
+
expect(restored).toBe(true);
|
|
37
|
+
// Verify all files restored
|
|
38
|
+
expect(readFileSync(join(workspaceDir, '.claude', 'projects', 'abc123', 'session.jsonl'), 'utf-8')).toBe('session-data');
|
|
39
|
+
expect(readFileSync(join(workspaceDir, 'CLAUDE.md'), 'utf-8')).toBe('# My Agent');
|
|
40
|
+
expect(readFileSync(join(workspaceDir, 'output', 'result.json'), 'utf-8')).toBe('{"answer": 42}');
|
|
41
|
+
});
|
|
42
|
+
it('returns false when no persisted state exists', () => {
|
|
43
|
+
expect(hasPersistedState(dataDir, 'nonexistent')).toBe(false);
|
|
44
|
+
expect(restoreSessionState(dataDir, 'nonexistent', workspaceDir)).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
it('returns false when workspace does not exist', () => {
|
|
47
|
+
rmSync(workspaceDir, { recursive: true });
|
|
48
|
+
const result = persistSessionState(dataDir, 'sess-1', workspaceDir, 'my-agent');
|
|
49
|
+
expect(result).toBe(false);
|
|
50
|
+
expect(hasPersistedState(dataDir, 'sess-1')).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
it('overwrites previous state on re-persist', () => {
|
|
53
|
+
populateWorkspace(workspaceDir);
|
|
54
|
+
persistSessionState(dataDir, 'sess-1', workspaceDir, 'my-agent');
|
|
55
|
+
// Update a file and add a new one, then re-persist
|
|
56
|
+
writeFileSync(join(workspaceDir, 'output', 'result.json'), '{"answer": 99}');
|
|
57
|
+
writeFileSync(join(workspaceDir, 'new-file.txt'), 'hello');
|
|
58
|
+
persistSessionState(dataDir, 'sess-1', workspaceDir, 'my-agent');
|
|
59
|
+
// Restore and verify updated content
|
|
60
|
+
rmSync(workspaceDir, { recursive: true });
|
|
61
|
+
restoreSessionState(dataDir, 'sess-1', workspaceDir);
|
|
62
|
+
expect(readFileSync(join(workspaceDir, 'output', 'result.json'), 'utf-8')).toBe('{"answer": 99}');
|
|
63
|
+
expect(readFileSync(join(workspaceDir, 'new-file.txt'), 'utf-8')).toBe('hello');
|
|
64
|
+
});
|
|
65
|
+
it('deletes persisted state', () => {
|
|
66
|
+
populateWorkspace(workspaceDir);
|
|
67
|
+
persistSessionState(dataDir, 'sess-1', workspaceDir, 'my-agent');
|
|
68
|
+
expect(hasPersistedState(dataDir, 'sess-1')).toBe(true);
|
|
69
|
+
deleteSessionState(dataDir, 'sess-1');
|
|
70
|
+
expect(hasPersistedState(dataDir, 'sess-1')).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
it('writes and reads metadata', () => {
|
|
73
|
+
populateWorkspace(workspaceDir);
|
|
74
|
+
persistSessionState(dataDir, 'sess-1', workspaceDir, 'my-agent');
|
|
75
|
+
const meta = getStateMetadata(dataDir, 'sess-1');
|
|
76
|
+
expect(meta).not.toBeNull();
|
|
77
|
+
expect(meta.sessionId).toBe('sess-1');
|
|
78
|
+
expect(meta.agentName).toBe('my-agent');
|
|
79
|
+
expect(meta.persistedAt).toBeTruthy();
|
|
80
|
+
});
|
|
81
|
+
it('returns null metadata for nonexistent session', () => {
|
|
82
|
+
expect(getStateMetadata(dataDir, 'ghost')).toBeNull();
|
|
83
|
+
});
|
|
84
|
+
it('delete is idempotent for nonexistent state', () => {
|
|
85
|
+
// Should not throw
|
|
86
|
+
deleteSessionState(dataDir, 'nonexistent');
|
|
87
|
+
});
|
|
88
|
+
it('skips node_modules, .git, and other filtered dirs during persist', () => {
|
|
89
|
+
populateWorkspace(workspaceDir);
|
|
90
|
+
// Add dirs/files that should be filtered out
|
|
91
|
+
mkdirSync(join(workspaceDir, 'node_modules', 'some-pkg'), { recursive: true });
|
|
92
|
+
writeFileSync(join(workspaceDir, 'node_modules', 'some-pkg', 'index.js'), 'module.exports = {}');
|
|
93
|
+
mkdirSync(join(workspaceDir, '.git', 'objects'), { recursive: true });
|
|
94
|
+
writeFileSync(join(workspaceDir, '.git', 'HEAD'), 'ref: refs/heads/main');
|
|
95
|
+
mkdirSync(join(workspaceDir, '__pycache__'), { recursive: true });
|
|
96
|
+
writeFileSync(join(workspaceDir, '__pycache__', 'mod.pyc'), 'bytecode');
|
|
97
|
+
writeFileSync(join(workspaceDir, 'bridge.sock'), 'socket');
|
|
98
|
+
writeFileSync(join(workspaceDir, 'app.pid'), '12345');
|
|
99
|
+
persistSessionState(dataDir, 'sess-1', workspaceDir, 'my-agent');
|
|
100
|
+
// Restore into a fresh dir
|
|
101
|
+
const restoreDir = mkdtempSync(join(tmpdir(), 'ash-test-restore-'));
|
|
102
|
+
restoreSessionState(dataDir, 'sess-1', restoreDir);
|
|
103
|
+
// Agent files and .claude state should be there
|
|
104
|
+
expect(existsSync(join(restoreDir, 'CLAUDE.md'))).toBe(true);
|
|
105
|
+
expect(existsSync(join(restoreDir, '.claude'))).toBe(true);
|
|
106
|
+
expect(existsSync(join(restoreDir, 'output', 'result.json'))).toBe(true);
|
|
107
|
+
// Filtered dirs/files should NOT be there
|
|
108
|
+
expect(existsSync(join(restoreDir, 'node_modules'))).toBe(false);
|
|
109
|
+
expect(existsSync(join(restoreDir, '.git'))).toBe(false);
|
|
110
|
+
expect(existsSync(join(restoreDir, '__pycache__'))).toBe(false);
|
|
111
|
+
expect(existsSync(join(restoreDir, 'bridge.sock'))).toBe(false);
|
|
112
|
+
expect(existsSync(join(restoreDir, 'app.pid'))).toBe(false);
|
|
113
|
+
rmSync(restoreDir, { recursive: true, force: true });
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=state-persistence.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-persistence.test.js","sourceRoot":"","sources":["../../src/__tests__/state-persistence.test.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FastifyInstance } from 'fastify';
|
|
2
|
+
/**
|
|
3
|
+
* API key authentication hook.
|
|
4
|
+
*
|
|
5
|
+
* If ASH_API_KEY is set, all requests (except /health and /docs) must include
|
|
6
|
+
* a matching `Authorization: Bearer <key>` header. If ASH_API_KEY is not set,
|
|
7
|
+
* auth is disabled (local dev mode).
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerAuth(app: FastifyInstance, apiKey: string | undefined): void;
|
|
10
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAyBnF"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API key authentication hook.
|
|
3
|
+
*
|
|
4
|
+
* If ASH_API_KEY is set, all requests (except /health and /docs) must include
|
|
5
|
+
* a matching `Authorization: Bearer <key>` header. If ASH_API_KEY is not set,
|
|
6
|
+
* auth is disabled (local dev mode).
|
|
7
|
+
*/
|
|
8
|
+
export function registerAuth(app, apiKey) {
|
|
9
|
+
if (!apiKey) {
|
|
10
|
+
app.log.info('ASH_API_KEY not set — auth disabled (local dev mode)');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
app.addHook('onRequest', async (request, reply) => {
|
|
14
|
+
// Health and docs endpoints are always public
|
|
15
|
+
if (request.url === '/health' || request.url.startsWith('/docs')) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const header = request.headers.authorization;
|
|
19
|
+
if (!header) {
|
|
20
|
+
return reply.status(401).send({ error: 'Missing Authorization header', statusCode: 401 });
|
|
21
|
+
}
|
|
22
|
+
// Expect "Bearer <key>"
|
|
23
|
+
const parts = header.split(' ');
|
|
24
|
+
if (parts.length !== 2 || parts[0] !== 'Bearer' || parts[1] !== apiKey) {
|
|
25
|
+
return reply.status(401).send({ error: 'Invalid API key', statusCode: 401 });
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
app.log.info('API key authentication enabled');
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAoB,EAAE,MAA0B;IAC3E,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;QACrE,OAAO;IACT,CAAC;IAED,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAChD,8CAA8C;QAC9C,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACjE,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,8BAA8B,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5F,CAAC;QAED,wBAAwB;QACxB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;YACvE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Agent, Session, SessionStatus, SandboxRecord, SandboxState } from '@ash-ai/shared';
|
|
2
|
+
export interface Db {
|
|
3
|
+
upsertAgent(name: string, path: string): Promise<Agent>;
|
|
4
|
+
getAgent(name: string): Promise<Agent | null>;
|
|
5
|
+
listAgents(): Promise<Agent[]>;
|
|
6
|
+
deleteAgent(name: string): Promise<boolean>;
|
|
7
|
+
insertSession(id: string, agentName: string, sandboxId: string): Promise<Session>;
|
|
8
|
+
updateSessionStatus(id: string, status: SessionStatus): Promise<void>;
|
|
9
|
+
updateSessionSandbox(id: string, sandboxId: string): Promise<void>;
|
|
10
|
+
updateSessionRunner(id: string, runnerId: string | null): Promise<void>;
|
|
11
|
+
getSession(id: string): Promise<Session | null>;
|
|
12
|
+
listSessions(agent?: string): Promise<Session[]>;
|
|
13
|
+
listSessionsByRunner(runnerId: string): Promise<Session[]>;
|
|
14
|
+
touchSession(id: string): Promise<void>;
|
|
15
|
+
insertSandbox(id: string, agentName: string, workspaceDir: string, sessionId?: string): Promise<void>;
|
|
16
|
+
updateSandboxState(id: string, state: SandboxState): Promise<void>;
|
|
17
|
+
updateSandboxSession(id: string, sessionId: string | null): Promise<void>;
|
|
18
|
+
touchSandbox(id: string): Promise<void>;
|
|
19
|
+
getSandbox(id: string): Promise<SandboxRecord | null>;
|
|
20
|
+
countSandboxes(): Promise<number>;
|
|
21
|
+
getBestEvictionCandidate(): Promise<SandboxRecord | null>;
|
|
22
|
+
getIdleSandboxes(olderThan: string): Promise<SandboxRecord[]>;
|
|
23
|
+
deleteSandbox(id: string): Promise<void>;
|
|
24
|
+
markAllSandboxesCold(): Promise<number>;
|
|
25
|
+
close(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export declare function initDb(opts: {
|
|
28
|
+
dataDir: string;
|
|
29
|
+
databaseUrl?: string;
|
|
30
|
+
}): Promise<Db>;
|
|
31
|
+
export declare function upsertAgent(name: string, path: string): Promise<Agent>;
|
|
32
|
+
export declare function getAgent(name: string): Promise<Agent | null>;
|
|
33
|
+
export declare function listAgents(): Promise<Agent[]>;
|
|
34
|
+
export declare function deleteAgent(name: string): Promise<boolean>;
|
|
35
|
+
export declare function insertSession(id: string, agentName: string, sandboxId: string): Promise<Session>;
|
|
36
|
+
export declare function updateSessionStatus(id: string, status: SessionStatus): Promise<void>;
|
|
37
|
+
export declare function updateSessionSandbox(id: string, sandboxId: string): Promise<void>;
|
|
38
|
+
export declare function updateSessionRunner(id: string, runnerId: string | null): Promise<void>;
|
|
39
|
+
export declare function getSession(id: string): Promise<Session | null>;
|
|
40
|
+
export declare function listSessions(agent?: string): Promise<Session[]>;
|
|
41
|
+
export declare function listSessionsByRunner(runnerId: string): Promise<Session[]>;
|
|
42
|
+
export declare function touchSession(id: string): Promise<void>;
|
|
43
|
+
export declare function insertSandbox(id: string, agentName: string, workspaceDir: string, sessionId?: string): Promise<void>;
|
|
44
|
+
export declare function updateSandboxState(id: string, state: SandboxState): Promise<void>;
|
|
45
|
+
export declare function updateSandboxSession(id: string, sessionId: string | null): Promise<void>;
|
|
46
|
+
export declare function touchSandbox(id: string): Promise<void>;
|
|
47
|
+
export declare function getSandbox(id: string): Promise<SandboxRecord | null>;
|
|
48
|
+
export declare function countSandboxes(): Promise<number>;
|
|
49
|
+
export declare function getBestEvictionCandidate(): Promise<SandboxRecord | null>;
|
|
50
|
+
export declare function getIdleSandboxes(olderThan: string): Promise<SandboxRecord[]>;
|
|
51
|
+
export declare function deleteSandbox(id: string): Promise<void>;
|
|
52
|
+
export declare function markAllSandboxesCold(): Promise<number>;
|
|
53
|
+
export declare function closeDb(): Promise<void>;
|
|
54
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"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"}
|
package/dist/db/index.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
let db;
|
|
2
|
+
function getDb() {
|
|
3
|
+
if (!db)
|
|
4
|
+
throw new Error('Database not initialized — call initDb first');
|
|
5
|
+
return db;
|
|
6
|
+
}
|
|
7
|
+
export async function initDb(opts) {
|
|
8
|
+
if (opts.databaseUrl && /^postgres(ql)?:\/\//.test(opts.databaseUrl)) {
|
|
9
|
+
const { PgDb } = await import('./pg.js');
|
|
10
|
+
const pgDb = new PgDb(opts.databaseUrl);
|
|
11
|
+
await pgDb.init();
|
|
12
|
+
db = pgDb;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
const { SqliteDb } = await import('./sqlite.js');
|
|
16
|
+
db = new SqliteDb(opts.dataDir);
|
|
17
|
+
}
|
|
18
|
+
return db;
|
|
19
|
+
}
|
|
20
|
+
// -- Async re-exports (preserve call-site compatibility) ----------------------
|
|
21
|
+
export async function upsertAgent(name, path) {
|
|
22
|
+
return getDb().upsertAgent(name, path);
|
|
23
|
+
}
|
|
24
|
+
export async function getAgent(name) {
|
|
25
|
+
return getDb().getAgent(name);
|
|
26
|
+
}
|
|
27
|
+
export async function listAgents() {
|
|
28
|
+
return getDb().listAgents();
|
|
29
|
+
}
|
|
30
|
+
export async function deleteAgent(name) {
|
|
31
|
+
return getDb().deleteAgent(name);
|
|
32
|
+
}
|
|
33
|
+
export async function insertSession(id, agentName, sandboxId) {
|
|
34
|
+
return getDb().insertSession(id, agentName, sandboxId);
|
|
35
|
+
}
|
|
36
|
+
export async function updateSessionStatus(id, status) {
|
|
37
|
+
return getDb().updateSessionStatus(id, status);
|
|
38
|
+
}
|
|
39
|
+
export async function updateSessionSandbox(id, sandboxId) {
|
|
40
|
+
return getDb().updateSessionSandbox(id, sandboxId);
|
|
41
|
+
}
|
|
42
|
+
export async function updateSessionRunner(id, runnerId) {
|
|
43
|
+
return getDb().updateSessionRunner(id, runnerId);
|
|
44
|
+
}
|
|
45
|
+
export async function getSession(id) {
|
|
46
|
+
return getDb().getSession(id);
|
|
47
|
+
}
|
|
48
|
+
export async function listSessions(agent) {
|
|
49
|
+
return getDb().listSessions(agent);
|
|
50
|
+
}
|
|
51
|
+
export async function listSessionsByRunner(runnerId) {
|
|
52
|
+
return getDb().listSessionsByRunner(runnerId);
|
|
53
|
+
}
|
|
54
|
+
export async function touchSession(id) {
|
|
55
|
+
return getDb().touchSession(id);
|
|
56
|
+
}
|
|
57
|
+
// -- Sandboxes ----------------------------------------------------------------
|
|
58
|
+
export async function insertSandbox(id, agentName, workspaceDir, sessionId) {
|
|
59
|
+
return getDb().insertSandbox(id, agentName, workspaceDir, sessionId);
|
|
60
|
+
}
|
|
61
|
+
export async function updateSandboxState(id, state) {
|
|
62
|
+
return getDb().updateSandboxState(id, state);
|
|
63
|
+
}
|
|
64
|
+
export async function updateSandboxSession(id, sessionId) {
|
|
65
|
+
return getDb().updateSandboxSession(id, sessionId);
|
|
66
|
+
}
|
|
67
|
+
export async function touchSandbox(id) {
|
|
68
|
+
return getDb().touchSandbox(id);
|
|
69
|
+
}
|
|
70
|
+
export async function getSandbox(id) {
|
|
71
|
+
return getDb().getSandbox(id);
|
|
72
|
+
}
|
|
73
|
+
export async function countSandboxes() {
|
|
74
|
+
return getDb().countSandboxes();
|
|
75
|
+
}
|
|
76
|
+
export async function getBestEvictionCandidate() {
|
|
77
|
+
return getDb().getBestEvictionCandidate();
|
|
78
|
+
}
|
|
79
|
+
export async function getIdleSandboxes(olderThan) {
|
|
80
|
+
return getDb().getIdleSandboxes(olderThan);
|
|
81
|
+
}
|
|
82
|
+
export async function deleteSandbox(id) {
|
|
83
|
+
return getDb().deleteSandbox(id);
|
|
84
|
+
}
|
|
85
|
+
export async function markAllSandboxesCold() {
|
|
86
|
+
return getDb().markAllSandboxesCold();
|
|
87
|
+
}
|
|
88
|
+
export async function closeDb() {
|
|
89
|
+
return getDb().close();
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"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"}
|
package/dist/db/pg.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Agent, Session, SessionStatus, SandboxRecord, SandboxState } from '@ash-ai/shared';
|
|
2
|
+
import type { Db } from './index.js';
|
|
3
|
+
export declare class PgDb implements Db {
|
|
4
|
+
private pool;
|
|
5
|
+
constructor(databaseUrl: string);
|
|
6
|
+
init(): Promise<void>;
|
|
7
|
+
upsertAgent(name: string, path: string): Promise<Agent>;
|
|
8
|
+
getAgent(name: string): Promise<Agent | null>;
|
|
9
|
+
listAgents(): Promise<Agent[]>;
|
|
10
|
+
deleteAgent(name: string): Promise<boolean>;
|
|
11
|
+
insertSession(id: string, agentName: string, sandboxId: string): Promise<Session>;
|
|
12
|
+
updateSessionStatus(id: string, status: SessionStatus): Promise<void>;
|
|
13
|
+
updateSessionSandbox(id: string, sandboxId: string): Promise<void>;
|
|
14
|
+
updateSessionRunner(id: string, runnerId: string | null): Promise<void>;
|
|
15
|
+
getSession(id: string): Promise<Session | null>;
|
|
16
|
+
listSessions(agent?: string): Promise<Session[]>;
|
|
17
|
+
listSessionsByRunner(runnerId: string): Promise<Session[]>;
|
|
18
|
+
touchSession(id: string): Promise<void>;
|
|
19
|
+
insertSandbox(id: string, agentName: string, workspaceDir: string, sessionId?: string): Promise<void>;
|
|
20
|
+
updateSandboxState(id: string, state: SandboxState): Promise<void>;
|
|
21
|
+
updateSandboxSession(id: string, sessionId: string | null): Promise<void>;
|
|
22
|
+
touchSandbox(id: string): Promise<void>;
|
|
23
|
+
getSandbox(id: string): Promise<SandboxRecord | null>;
|
|
24
|
+
countSandboxes(): Promise<number>;
|
|
25
|
+
getBestEvictionCandidate(): Promise<SandboxRecord | null>;
|
|
26
|
+
getIdleSandboxes(olderThan: string): Promise<SandboxRecord[]>;
|
|
27
|
+
deleteSandbox(id: string): Promise<void>;
|
|
28
|
+
markAllSandboxesCold(): Promise<number>;
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=pg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg.d.ts","sourceRoot":"","sources":["../../src/db/pg.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACjG,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAErC,qBAAa,IAAK,YAAW,EAAE;IAC7B,OAAO,CAAC,IAAI,CAAU;gBAEV,WAAW,EAAE,MAAM;IAIzB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4DrB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAcvD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAO7C,UAAU,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAK9B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ3C,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUjF,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrE,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlE,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAO/C,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAOhD,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAK1D,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvC,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrG,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlE,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzE,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAerD,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAKjC,wBAAwB,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAsBzD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAgB7D,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;IASvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|