@scotthuang/agent-knock-knock-pi 0.1.0-poc.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/README.md +396 -0
- package/lib/callback-helper.d.ts +14 -0
- package/lib/callback-helper.js +133 -0
- package/lib/callback-helper.js.map +1 -0
- package/lib/callback-inbox.d.ts +40 -0
- package/lib/callback-inbox.js +281 -0
- package/lib/callback-inbox.js.map +1 -0
- package/lib/constants.d.ts +14 -0
- package/lib/constants.js +15 -0
- package/lib/constants.js.map +1 -0
- package/lib/index.d.ts +20 -0
- package/lib/index.js +418 -0
- package/lib/index.js.map +1 -0
- package/lib/ipc.d.ts +30 -0
- package/lib/ipc.js +255 -0
- package/lib/ipc.js.map +1 -0
- package/lib/profile.d.ts +14 -0
- package/lib/profile.js +160 -0
- package/lib/profile.js.map +1 -0
- package/lib/routes.d.ts +71 -0
- package/lib/routes.js +255 -0
- package/lib/routes.js.map +1 -0
- package/lib/schema-adapter.d.ts +7 -0
- package/lib/schema-adapter.js +85 -0
- package/lib/schema-adapter.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const INBOX_SCHEMA = "agent-knock-knock/pi-callback-inbox";
|
|
5
|
+
const INBOX_VERSION = 1;
|
|
6
|
+
const DEFAULT_MAX_ENTRIES = 256;
|
|
7
|
+
const DEFAULT_MAX_FILE_BYTES = 64 * 1024 * 1024;
|
|
8
|
+
/**
|
|
9
|
+
* A small, process-owned durable inbox for the last callback hop into Pi.
|
|
10
|
+
*
|
|
11
|
+
* `admit()` returns only after an atomic, fsync-backed file replacement. This
|
|
12
|
+
* lets the callback helper acknowledge connector admission even though Pi's
|
|
13
|
+
* `sendMessage()` API itself does not return an admission receipt.
|
|
14
|
+
*/
|
|
15
|
+
export class CallbackInbox {
|
|
16
|
+
entries;
|
|
17
|
+
transactionTail = Promise.resolve();
|
|
18
|
+
active = true;
|
|
19
|
+
filePath;
|
|
20
|
+
maxEntries;
|
|
21
|
+
maxFileBytes;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
if (!path.isAbsolute(options.filePath)) {
|
|
24
|
+
throw new Error("Pi callback inbox path must be absolute");
|
|
25
|
+
}
|
|
26
|
+
this.filePath = options.filePath;
|
|
27
|
+
this.maxEntries = positiveInteger(options.maxEntries ?? DEFAULT_MAX_ENTRIES, "maxEntries");
|
|
28
|
+
this.maxFileBytes = positiveInteger(options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, "maxFileBytes");
|
|
29
|
+
this.entries = loadInbox(this.filePath, this.maxEntries, this.maxFileBytes);
|
|
30
|
+
}
|
|
31
|
+
admit(request) {
|
|
32
|
+
return this.withTransaction(async () => {
|
|
33
|
+
const key = callbackKey(request.controllerId, request.idempotencyKey);
|
|
34
|
+
const fingerprint = requestFingerprint(request);
|
|
35
|
+
const previous = this.entries.get(key);
|
|
36
|
+
if (previous) {
|
|
37
|
+
if (previous.fingerprint !== fingerprint) {
|
|
38
|
+
return { disposition: "collision" };
|
|
39
|
+
}
|
|
40
|
+
return { disposition: "duplicate", entry: previous };
|
|
41
|
+
}
|
|
42
|
+
const entry = Object.freeze({
|
|
43
|
+
...request,
|
|
44
|
+
fingerprint,
|
|
45
|
+
acceptanceId: `akk-pi-callback:${randomBytes(18).toString("base64url")}`,
|
|
46
|
+
state: "pending",
|
|
47
|
+
acceptedAt: new Date().toISOString(),
|
|
48
|
+
});
|
|
49
|
+
const next = new Map(this.entries);
|
|
50
|
+
pruneDeliveredEntries(next, this.maxEntries - 1);
|
|
51
|
+
if (next.size >= this.maxEntries) {
|
|
52
|
+
throw new Error("Pi callback inbox is full");
|
|
53
|
+
}
|
|
54
|
+
next.set(key, entry);
|
|
55
|
+
await persistInbox(this.filePath, next.values(), this.maxFileBytes);
|
|
56
|
+
this.entries = next;
|
|
57
|
+
return { disposition: "admitted", entry };
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
markDelivered(entry) {
|
|
61
|
+
return this.withTransaction(async () => {
|
|
62
|
+
const key = callbackKey(entry.controllerId, entry.idempotencyKey);
|
|
63
|
+
const current = this.entries.get(key);
|
|
64
|
+
if (!current || current.fingerprint !== entry.fingerprint) {
|
|
65
|
+
throw new Error("Pi callback inbox entry is no longer current");
|
|
66
|
+
}
|
|
67
|
+
if (current.state === "delivered")
|
|
68
|
+
return current;
|
|
69
|
+
const delivered = Object.freeze({
|
|
70
|
+
...current,
|
|
71
|
+
state: "delivered",
|
|
72
|
+
deliveredAt: new Date().toISOString(),
|
|
73
|
+
});
|
|
74
|
+
const next = new Map(this.entries);
|
|
75
|
+
next.set(key, delivered);
|
|
76
|
+
await persistInbox(this.filePath, next.values(), this.maxFileBytes);
|
|
77
|
+
this.entries = next;
|
|
78
|
+
return delivered;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
listPending(controllerId) {
|
|
82
|
+
return this.withTransaction(() => Promise.resolve([...this.entries.values()].filter((entry) => entry.state === "pending" &&
|
|
83
|
+
(controllerId === undefined || entry.controllerId === controllerId))));
|
|
84
|
+
}
|
|
85
|
+
async close() {
|
|
86
|
+
await this.transactionTail;
|
|
87
|
+
this.active = false;
|
|
88
|
+
}
|
|
89
|
+
withTransaction(operation) {
|
|
90
|
+
const run = this.transactionTail.then(() => {
|
|
91
|
+
if (!this.active)
|
|
92
|
+
throw new Error("Pi callback inbox is closed");
|
|
93
|
+
return operation();
|
|
94
|
+
});
|
|
95
|
+
this.transactionTail = run.then(() => undefined, () => undefined);
|
|
96
|
+
return run;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function loadInbox(filePath, maxEntries, maxFileBytes) {
|
|
100
|
+
const directory = path.dirname(filePath);
|
|
101
|
+
fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
102
|
+
let stat;
|
|
103
|
+
try {
|
|
104
|
+
stat = fs.lstatSync(filePath);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
108
|
+
return new Map();
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
112
|
+
throw new Error("Pi callback inbox must be a regular file");
|
|
113
|
+
}
|
|
114
|
+
if (stat.size > maxFileBytes) {
|
|
115
|
+
throw new Error("Pi callback inbox exceeded its size limit");
|
|
116
|
+
}
|
|
117
|
+
let parsed;
|
|
118
|
+
try {
|
|
119
|
+
parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
throw new Error("Pi callback inbox is invalid");
|
|
123
|
+
}
|
|
124
|
+
if (!isInboxDocument(parsed)) {
|
|
125
|
+
throw new Error("Pi callback inbox is invalid");
|
|
126
|
+
}
|
|
127
|
+
if (parsed.entries.length > maxEntries) {
|
|
128
|
+
throw new Error("Pi callback inbox contains too many entries");
|
|
129
|
+
}
|
|
130
|
+
const entries = new Map();
|
|
131
|
+
for (const candidate of parsed.entries) {
|
|
132
|
+
const entry = validateInboxEntry(candidate);
|
|
133
|
+
const key = callbackKey(entry.controllerId, entry.idempotencyKey);
|
|
134
|
+
if (entries.has(key))
|
|
135
|
+
throw new Error("Pi callback inbox contains duplicate entries");
|
|
136
|
+
entries.set(key, Object.freeze(entry));
|
|
137
|
+
}
|
|
138
|
+
return entries;
|
|
139
|
+
}
|
|
140
|
+
async function persistInbox(filePath, entries, maxFileBytes) {
|
|
141
|
+
const document = {
|
|
142
|
+
schema: INBOX_SCHEMA,
|
|
143
|
+
version: INBOX_VERSION,
|
|
144
|
+
entries: [...entries],
|
|
145
|
+
};
|
|
146
|
+
const body = `${JSON.stringify(document)}\n`;
|
|
147
|
+
if (Buffer.byteLength(body, "utf8") > maxFileBytes) {
|
|
148
|
+
throw new Error("Pi callback inbox exceeded its size limit");
|
|
149
|
+
}
|
|
150
|
+
const directory = path.dirname(filePath);
|
|
151
|
+
const temporaryPath = path.join(directory, `.${path.basename(filePath)}.${process.pid}.${randomBytes(8).toString("hex")}.tmp`);
|
|
152
|
+
let handle;
|
|
153
|
+
try {
|
|
154
|
+
handle = await fs.promises.open(temporaryPath, "wx", 0o600);
|
|
155
|
+
await handle.writeFile(body, "utf8");
|
|
156
|
+
await handle.sync();
|
|
157
|
+
await handle.close();
|
|
158
|
+
handle = undefined;
|
|
159
|
+
await fs.promises.rename(temporaryPath, filePath);
|
|
160
|
+
await fs.promises.chmod(filePath, 0o600);
|
|
161
|
+
await syncDirectory(directory);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
await handle?.close().catch(() => undefined);
|
|
165
|
+
await fs.promises.rm(temporaryPath, { force: true }).catch(() => undefined);
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function syncDirectory(directory) {
|
|
170
|
+
let handle;
|
|
171
|
+
try {
|
|
172
|
+
handle = await fs.promises.open(directory, "r");
|
|
173
|
+
await handle.sync();
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
if (!isNodeError(error) ||
|
|
177
|
+
!["EINVAL", "ENOTSUP", "EISDIR"].includes(error.code ?? "")) {
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
await handle?.close().catch(() => undefined);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function pruneDeliveredEntries(entries, targetSize) {
|
|
186
|
+
if (entries.size <= targetSize)
|
|
187
|
+
return;
|
|
188
|
+
const delivered = [...entries.entries()]
|
|
189
|
+
.filter(([, entry]) => entry.state === "delivered")
|
|
190
|
+
.sort((left, right) => left[1].acceptedAt.localeCompare(right[1].acceptedAt));
|
|
191
|
+
for (const [key] of delivered) {
|
|
192
|
+
if (entries.size <= targetSize)
|
|
193
|
+
return;
|
|
194
|
+
entries.delete(key);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function requestFingerprint(request) {
|
|
198
|
+
return createHash("sha256")
|
|
199
|
+
.update(JSON.stringify([
|
|
200
|
+
request.controllerId,
|
|
201
|
+
request.deliveryId,
|
|
202
|
+
request.messageId,
|
|
203
|
+
request.idempotencyKey,
|
|
204
|
+
request.body,
|
|
205
|
+
]))
|
|
206
|
+
.digest("hex");
|
|
207
|
+
}
|
|
208
|
+
function callbackKey(controllerId, idempotencyKey) {
|
|
209
|
+
return `${controllerId}\u0000${idempotencyKey}`;
|
|
210
|
+
}
|
|
211
|
+
function isInboxDocument(value) {
|
|
212
|
+
if (!isRecord(value))
|
|
213
|
+
return false;
|
|
214
|
+
return value.schema === INBOX_SCHEMA &&
|
|
215
|
+
value.version === INBOX_VERSION &&
|
|
216
|
+
Array.isArray(value.entries) &&
|
|
217
|
+
Object.keys(value).every((key) => ["schema", "version", "entries"].includes(key));
|
|
218
|
+
}
|
|
219
|
+
function validateInboxEntry(value) {
|
|
220
|
+
if (!isRecord(value))
|
|
221
|
+
throw new Error("Pi callback inbox entry is invalid");
|
|
222
|
+
const requiredStrings = [
|
|
223
|
+
"controllerId",
|
|
224
|
+
"deliveryId",
|
|
225
|
+
"messageId",
|
|
226
|
+
"idempotencyKey",
|
|
227
|
+
"body",
|
|
228
|
+
"fingerprint",
|
|
229
|
+
"acceptanceId",
|
|
230
|
+
"acceptedAt",
|
|
231
|
+
];
|
|
232
|
+
if (requiredStrings.some((key) => typeof value[key] !== "string")) {
|
|
233
|
+
throw new Error("Pi callback inbox entry is invalid");
|
|
234
|
+
}
|
|
235
|
+
if (value.state !== "pending" && value.state !== "delivered") {
|
|
236
|
+
throw new Error("Pi callback inbox entry is invalid");
|
|
237
|
+
}
|
|
238
|
+
if (value.deliveredAt !== undefined && typeof value.deliveredAt !== "string") {
|
|
239
|
+
throw new Error("Pi callback inbox entry is invalid");
|
|
240
|
+
}
|
|
241
|
+
const allowedKeys = new Set([...requiredStrings, "state", "deliveredAt"]);
|
|
242
|
+
if (Object.keys(value).some((key) => !allowedKeys.has(key))) {
|
|
243
|
+
throw new Error("Pi callback inbox entry is invalid");
|
|
244
|
+
}
|
|
245
|
+
const entry = value;
|
|
246
|
+
if (!validIdentity(entry.controllerId) ||
|
|
247
|
+
!validIdentity(entry.deliveryId) ||
|
|
248
|
+
!validIdentity(entry.messageId) ||
|
|
249
|
+
!validIdentity(entry.idempotencyKey) ||
|
|
250
|
+
!/^[a-f0-9]{64}$/u.test(entry.fingerprint) ||
|
|
251
|
+
!validIdentity(entry.acceptanceId) ||
|
|
252
|
+
!validDate(entry.acceptedAt) ||
|
|
253
|
+
(entry.state === "delivered" && !entry.deliveredAt) ||
|
|
254
|
+
(entry.deliveredAt !== undefined && !validDate(entry.deliveredAt)) ||
|
|
255
|
+
requestFingerprint(entry) !== entry.fingerprint) {
|
|
256
|
+
throw new Error("Pi callback inbox entry is invalid");
|
|
257
|
+
}
|
|
258
|
+
return entry;
|
|
259
|
+
}
|
|
260
|
+
function validIdentity(value) {
|
|
261
|
+
return value.length > 0 &&
|
|
262
|
+
value.length <= 4096 &&
|
|
263
|
+
value.trim() === value &&
|
|
264
|
+
!/[\u0000-\u001f\u007f]/u.test(value);
|
|
265
|
+
}
|
|
266
|
+
function validDate(value) {
|
|
267
|
+
return Number.isFinite(Date.parse(value));
|
|
268
|
+
}
|
|
269
|
+
function positiveInteger(value, name) {
|
|
270
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
271
|
+
throw new Error(`Pi callback inbox ${name} must be a positive integer`);
|
|
272
|
+
}
|
|
273
|
+
return value;
|
|
274
|
+
}
|
|
275
|
+
function isRecord(value) {
|
|
276
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
277
|
+
}
|
|
278
|
+
function isNodeError(error) {
|
|
279
|
+
return error instanceof Error && "code" in error;
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=callback-inbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback-inbox.js","sourceRoot":"","sources":["../src/callback-inbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const CONNECTOR_NAME = "agent-knock-knock-pi";
|
|
2
|
+
export declare const CONNECTOR_PACKAGE = "@scotthuang/agent-knock-knock-pi";
|
|
3
|
+
export declare const CONNECTOR_VERSION = "0.1.0-poc.1";
|
|
4
|
+
export declare const PI_HOST_ID = "pi-coding-agent";
|
|
5
|
+
export declare const SUPPORTED_PI_VERSION = "0.84.4";
|
|
6
|
+
export declare const CONTROLLER_ID_ENV = "AKK_PI_CONTROLLER_ID";
|
|
7
|
+
export declare const CALLBACK_SOCKET_ENV = "AKK_PI_CALLBACK_SOCKET";
|
|
8
|
+
export declare const CALLBACK_TOKEN_ENV = "AKK_PI_CALLBACK_TOKEN";
|
|
9
|
+
export declare const CONNECTOR_STATE_DIR_ENV = "AKK_PI_STATE_DIR";
|
|
10
|
+
export declare const CONNECTOR_STORE_DIR_ENV = "AKK_PI_STORE_DIR";
|
|
11
|
+
export declare const CALLBACK_MAX_REQUEST_BYTES: number;
|
|
12
|
+
export declare const CALLBACK_MAX_RESPONSE_BYTES: number;
|
|
13
|
+
export declare const CALLBACK_TIMEOUT_MS = 8000;
|
|
14
|
+
export declare const LIFECYCLE_INTERVAL_MS = 5000;
|
package/lib/constants.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const CONNECTOR_NAME = "agent-knock-knock-pi";
|
|
2
|
+
export const CONNECTOR_PACKAGE = "@scotthuang/agent-knock-knock-pi";
|
|
3
|
+
export const CONNECTOR_VERSION = "0.1.0-poc.1";
|
|
4
|
+
export const PI_HOST_ID = "pi-coding-agent";
|
|
5
|
+
export const SUPPORTED_PI_VERSION = "0.84.4";
|
|
6
|
+
export const CONTROLLER_ID_ENV = "AKK_PI_CONTROLLER_ID";
|
|
7
|
+
export const CALLBACK_SOCKET_ENV = "AKK_PI_CALLBACK_SOCKET";
|
|
8
|
+
export const CALLBACK_TOKEN_ENV = "AKK_PI_CALLBACK_TOKEN";
|
|
9
|
+
export const CONNECTOR_STATE_DIR_ENV = "AKK_PI_STATE_DIR";
|
|
10
|
+
export const CONNECTOR_STORE_DIR_ENV = "AKK_PI_STORE_DIR";
|
|
11
|
+
export const CALLBACK_MAX_REQUEST_BYTES = 2 * 1024 * 1024;
|
|
12
|
+
export const CALLBACK_MAX_RESPONSE_BYTES = 64 * 1024;
|
|
13
|
+
export const CALLBACK_TIMEOUT_MS = 8_000;
|
|
14
|
+
export const LIFECYCLE_INTERVAL_MS = 5_000;
|
|
15
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,sBAAsB,CAAC;AACrD,MAAM,CAAC,MAAM,iBAAiB,GAAG,kCAAkC,CAAC;AACpE,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAE/C,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAC5C,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC;AAE7C,MAAM,CAAC,MAAM,iBAAiB,GAAG,sBAAsB,CAAC;AACxD,MAAM,CAAC,MAAM,mBAAmB,GAAG,wBAAwB,CAAC;AAC5D,MAAM,CAAC,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AAC1D,MAAM,CAAC,MAAM,uBAAuB,GAAG,kBAAkB,CAAC;AAC1D,MAAM,CAAC,MAAM,uBAAuB,GAAG,kBAAkB,CAAC;AAE1D,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAC1D,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,GAAG,IAAI,CAAC;AACrD,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AACzC,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Pi-as-orchestrator POC: Pi controls Codex and Claude Code through AKK. */
|
|
2
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import { type CreateHostAdapterOptions, type HostAdapter } from "@scotthuang/agent-knock-knock/host-adapter";
|
|
4
|
+
import { CallbackInbox } from "./callback-inbox.js";
|
|
5
|
+
import { createCallbackIpcServer } from "./ipc.js";
|
|
6
|
+
import { createConnectorProfileResources } from "./profile.js";
|
|
7
|
+
import { PiRouteTable } from "./routes.js";
|
|
8
|
+
/** @internal Replaceable seams for native wiring and lifecycle tests. */
|
|
9
|
+
export interface ConnectorDependencies {
|
|
10
|
+
readonly piVersion: string;
|
|
11
|
+
readonly createConnectorProfileResources: typeof createConnectorProfileResources;
|
|
12
|
+
readonly createCallbackInbox: (options: ConstructorParameters<typeof CallbackInbox>[0]) => CallbackInbox;
|
|
13
|
+
readonly createRouteTable: (inbox: CallbackInbox, instanceNonce: string) => PiRouteTable;
|
|
14
|
+
readonly createCallbackIpcServer: typeof createCallbackIpcServer;
|
|
15
|
+
readonly createHostAdapter: (options: CreateHostAdapterOptions) => HostAdapter;
|
|
16
|
+
}
|
|
17
|
+
/** Mount one Host-owned AKK runtime for the current Pi session incarnation. */
|
|
18
|
+
export default function agentKnockKnockPi(pi: ExtensionAPI): void;
|
|
19
|
+
/** @internal Mount with deterministic process, IPC, and HostAdapter seams. */
|
|
20
|
+
export declare function applyWithDependencies(pi: ExtensionAPI, dependencies?: Partial<ConnectorDependencies>): void;
|