@bbigbang/runtime-acp 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.
- package/dist/acp/client.d.ts +101 -0
- package/dist/acp/client.js +747 -0
- package/dist/acp/jsonrpc.d.ts +31 -0
- package/dist/acp/jsonrpc.js +18 -0
- package/dist/acp/stdio.d.ts +15 -0
- package/dist/acp/stdio.js +201 -0
- package/dist/acp/types.d.ts +171 -0
- package/dist/acp/types.js +1 -0
- package/dist/db/db.d.ts +3 -0
- package/dist/db/db.js +10 -0
- package/dist/db/deliveryCheckpointStore.d.ts +21 -0
- package/dist/db/deliveryCheckpointStore.js +28 -0
- package/dist/db/migrations.d.ts +2 -0
- package/dist/db/migrations.js +6196 -0
- package/dist/db/uiPrefStore.d.ts +4 -0
- package/dist/db/uiPrefStore.js +18 -0
- package/dist/gateway/bindingRuntime.d.ts +113 -0
- package/dist/gateway/bindingRuntime.js +1267 -0
- package/dist/gateway/history.d.ts +7 -0
- package/dist/gateway/history.js +146 -0
- package/dist/gateway/sessionStore.d.ts +79 -0
- package/dist/gateway/sessionStore.js +126 -0
- package/dist/gateway/toolAuth.d.ts +36 -0
- package/dist/gateway/toolAuth.js +372 -0
- package/dist/gateway/types.d.ts +79 -0
- package/dist/gateway/types.js +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +19 -0
- package/dist/logging.d.ts +7 -0
- package/dist/logging.js +28 -0
- package/dist/runtime/lock.d.ts +5 -0
- package/dist/runtime/lock.js +87 -0
- package/dist/runtime/workspaceLockManager.d.ts +23 -0
- package/dist/runtime/workspaceLockManager.js +141 -0
- package/dist/tools/workspace.d.ts +1 -0
- package/dist/tools/workspace.js +13 -0
- package/package.json +38 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
export class WorkspaceLockManager {
|
|
3
|
+
locks = new Map();
|
|
4
|
+
normalizeKey(workspaceRoot) {
|
|
5
|
+
return path.resolve(workspaceRoot);
|
|
6
|
+
}
|
|
7
|
+
async acquire(workspaceRoot, hooks) {
|
|
8
|
+
const key = this.normalizeKey(workspaceRoot);
|
|
9
|
+
const state = this.getState(key);
|
|
10
|
+
throwIfAborted(hooks?.signal);
|
|
11
|
+
let waited = false;
|
|
12
|
+
if (state.locked || state.waiters.length > 0) {
|
|
13
|
+
waited = true;
|
|
14
|
+
hooks?.onWaitStart?.();
|
|
15
|
+
await new Promise((resolve, reject) => {
|
|
16
|
+
let onAbort = () => { };
|
|
17
|
+
const cleanup = () => {
|
|
18
|
+
hooks?.signal?.removeEventListener('abort', onAbort);
|
|
19
|
+
};
|
|
20
|
+
const waiter = {
|
|
21
|
+
granted: false,
|
|
22
|
+
settled: false,
|
|
23
|
+
resolve: () => {
|
|
24
|
+
if (waiter.settled)
|
|
25
|
+
return;
|
|
26
|
+
waiter.settled = true;
|
|
27
|
+
cleanup();
|
|
28
|
+
resolve();
|
|
29
|
+
},
|
|
30
|
+
reject: (error) => {
|
|
31
|
+
if (waiter.settled)
|
|
32
|
+
return;
|
|
33
|
+
waiter.settled = true;
|
|
34
|
+
cleanup();
|
|
35
|
+
reject(error);
|
|
36
|
+
},
|
|
37
|
+
signal: hooks?.signal,
|
|
38
|
+
};
|
|
39
|
+
onAbort = () => {
|
|
40
|
+
const index = state.waiters.indexOf(waiter);
|
|
41
|
+
if (index >= 0) {
|
|
42
|
+
state.waiters.splice(index, 1);
|
|
43
|
+
}
|
|
44
|
+
if (waiter.granted) {
|
|
45
|
+
this.release(key);
|
|
46
|
+
}
|
|
47
|
+
waiter.reject(createWorkspaceLockAbortError());
|
|
48
|
+
};
|
|
49
|
+
hooks?.signal?.addEventListener('abort', onAbort, { once: true });
|
|
50
|
+
state.waiters.push(waiter);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (hooks?.signal?.aborted) {
|
|
54
|
+
if (waited) {
|
|
55
|
+
this.release(key);
|
|
56
|
+
}
|
|
57
|
+
throw createWorkspaceLockAbortError();
|
|
58
|
+
}
|
|
59
|
+
state.locked = true;
|
|
60
|
+
hooks?.onAcquired?.({ waited });
|
|
61
|
+
let released = false;
|
|
62
|
+
return {
|
|
63
|
+
key,
|
|
64
|
+
waited,
|
|
65
|
+
release: () => {
|
|
66
|
+
if (released)
|
|
67
|
+
return;
|
|
68
|
+
released = true;
|
|
69
|
+
this.release(key);
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async runExclusive(workspaceRoot, action, hooks) {
|
|
74
|
+
const lease = await this.acquire(workspaceRoot, hooks);
|
|
75
|
+
try {
|
|
76
|
+
return await action();
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
lease.release();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async runAfterPendingWrites(workspaceRoot, action, hooks) {
|
|
83
|
+
const key = this.normalizeKey(workspaceRoot);
|
|
84
|
+
const state = this.locks.get(key);
|
|
85
|
+
if (!state || (!state.locked && state.waiters.length === 0)) {
|
|
86
|
+
throwIfAborted(hooks?.signal);
|
|
87
|
+
return await action();
|
|
88
|
+
}
|
|
89
|
+
const lease = await this.acquire(workspaceRoot, hooks);
|
|
90
|
+
try {
|
|
91
|
+
return await action();
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
lease.release();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async waitForPendingWrites(workspaceRoot, hooks) {
|
|
98
|
+
await this.runAfterPendingWrites(workspaceRoot, () => { }, hooks);
|
|
99
|
+
}
|
|
100
|
+
getState(key) {
|
|
101
|
+
let state = this.locks.get(key);
|
|
102
|
+
if (!state) {
|
|
103
|
+
state = { locked: false, waiters: [] };
|
|
104
|
+
this.locks.set(key, state);
|
|
105
|
+
}
|
|
106
|
+
return state;
|
|
107
|
+
}
|
|
108
|
+
release(key) {
|
|
109
|
+
const state = this.locks.get(key);
|
|
110
|
+
if (!state)
|
|
111
|
+
return;
|
|
112
|
+
while (state.waiters.length > 0) {
|
|
113
|
+
const next = state.waiters.shift();
|
|
114
|
+
if (next.signal?.aborted || next.settled) {
|
|
115
|
+
next.reject(createWorkspaceLockAbortError());
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
next.granted = true;
|
|
119
|
+
state.locked = true;
|
|
120
|
+
queueMicrotask(() => {
|
|
121
|
+
if (next.signal?.aborted || next.settled) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
next.resolve();
|
|
125
|
+
});
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
state.locked = false;
|
|
129
|
+
this.locks.delete(key);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function throwIfAborted(signal) {
|
|
133
|
+
if (!signal?.aborted)
|
|
134
|
+
return;
|
|
135
|
+
throw createWorkspaceLockAbortError();
|
|
136
|
+
}
|
|
137
|
+
function createWorkspaceLockAbortError() {
|
|
138
|
+
const error = new Error('Workspace lock acquisition cancelled.');
|
|
139
|
+
error.name = 'AbortError';
|
|
140
|
+
return error;
|
|
141
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolveWorkspacePath(workspaceRoot: string, requestedPath: string): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
export function resolveWorkspacePath(workspaceRoot, requestedPath) {
|
|
3
|
+
if (!path.isAbsolute(requestedPath)) {
|
|
4
|
+
throw new Error(`ACP path must be absolute: ${requestedPath}`);
|
|
5
|
+
}
|
|
6
|
+
const resolved = path.resolve(requestedPath);
|
|
7
|
+
const root = path.resolve(workspaceRoot);
|
|
8
|
+
if (resolved === root)
|
|
9
|
+
return resolved;
|
|
10
|
+
if (resolved.startsWith(root + path.sep))
|
|
11
|
+
return resolved;
|
|
12
|
+
throw new Error(`Path escapes WORKSPACE_ROOT: ${requestedPath}`);
|
|
13
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bbigbang/runtime-acp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "ACP execution engine — shared runtime for core and agent-node",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"!dist/**/__tests__/**",
|
|
11
|
+
"!dist/**/*.test.*",
|
|
12
|
+
"!dist/**/*.map",
|
|
13
|
+
"package.json"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"better-sqlite3": "^12.6.2"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
26
|
+
"@types/node": "^25.3.3",
|
|
27
|
+
"typescript": "^5.9.3",
|
|
28
|
+
"vitest": "^3.2.1"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc -p tsconfig.json",
|
|
32
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
33
|
+
"lint": "echo 'No lint configured'",
|
|
34
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:watch": "vitest"
|
|
37
|
+
}
|
|
38
|
+
}
|