@cortexkit/aft-opencode 0.35.4 → 0.36.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.
@@ -41,3 +41,65 @@ export function rpcPortFileDir(storageDir: string, directory: string): string {
41
41
  const hash = projectHash(directory);
42
42
  return join(storageDir, "rpc", hash, "ports");
43
43
  }
44
+
45
+ /**
46
+ * Contents of a per-instance RPC port file. `pid` + `started_at` let the client
47
+ * skip files whose owning process is dead (no health-check round-trip) and pick
48
+ * the freshest live server, instead of wading through every crash/restart
49
+ * leftover. Older files carry only `{ port, token }` (no pid); those are treated
50
+ * as "can't prove dead" and fall back to the health-check path.
51
+ */
52
+ export interface RpcPortRecord {
53
+ port: number;
54
+ token: string | null;
55
+ /** PID of the plugin process that owns this server, if recorded. */
56
+ pid?: number;
57
+ /** `Date.now()` when this server started, for newest-first ordering. */
58
+ started_at?: number;
59
+ }
60
+
61
+ /** True if `pid` names a live process. `process.kill(pid, 0)` sends no signal. */
62
+ export function isPidAlive(pid: number | undefined): boolean {
63
+ if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0) return false;
64
+ try {
65
+ process.kill(pid, 0);
66
+ return true;
67
+ } catch (err) {
68
+ // EPERM = process exists but we can't signal it (still alive).
69
+ return (err as NodeJS.ErrnoException).code === "EPERM";
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Parse a port file's contents into a record. Accepts the current JSON shape
75
+ * (`{ port, token, pid?, started_at? }`) and the legacy bare-integer format
76
+ * (unauthenticated, pre-v0.28.2). Returns `null` for unusable contents.
77
+ */
78
+ export function parseRpcPortRecord(content: string): RpcPortRecord | null {
79
+ const trimmed = content.trim();
80
+ if (trimmed.length === 0) return null;
81
+ if (trimmed.startsWith("{")) {
82
+ try {
83
+ const parsed = JSON.parse(trimmed) as {
84
+ port?: unknown;
85
+ token?: unknown;
86
+ pid?: unknown;
87
+ started_at?: unknown;
88
+ };
89
+ const port = typeof parsed.port === "number" ? parsed.port : Number.NaN;
90
+ if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
91
+ return {
92
+ port,
93
+ token: typeof parsed.token === "string" ? parsed.token : null,
94
+ pid:
95
+ typeof parsed.pid === "number" && Number.isInteger(parsed.pid) ? parsed.pid : undefined,
96
+ started_at: typeof parsed.started_at === "number" ? parsed.started_at : undefined,
97
+ };
98
+ } catch {
99
+ return null;
100
+ }
101
+ }
102
+ const port = Number.parseInt(trimmed, 10);
103
+ if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
104
+ return { port, token: null };
105
+ }
@@ -1,29 +0,0 @@
1
- /**
2
- * Pending tool metadata store.
3
- *
4
- * OpenCode's `fromPlugin()` wrapper always replaces plugin metadata with
5
- * `{ truncated, outputPath }`, discarding title and custom metadata.
6
- *
7
- * This store captures metadata during execute(), then the `tool.execute.after`
8
- * hook consumes it and merges it back before the final part is written.
9
- *
10
- * Flow:
11
- * execute() → storeToolMetadata(sessionID, callID, data)
12
- * fromPlugin() → overwrites metadata with { truncated }
13
- * tool.execute.after → consumeToolMetadata(sessionID, callID) → merges back
14
- */
15
- export interface PendingToolMetadata {
16
- title?: string;
17
- metadata?: Record<string, unknown>;
18
- }
19
- /**
20
- * Store metadata to be restored after fromPlugin() overwrites it.
21
- * Called from tool execute() functions.
22
- */
23
- export declare function storeToolMetadata(sessionID: string, callID: string, data: PendingToolMetadata): void;
24
- /**
25
- * Consume stored metadata (one-time read, removes from store).
26
- * Called from tool.execute.after hook.
27
- */
28
- export declare function consumeToolMetadata(sessionID: string, callID: string): PendingToolMetadata | undefined;
29
- //# sourceMappingURL=metadata-store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"metadata-store.d.ts","sourceRoot":"","sources":["../src/metadata-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAmBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,mBAAmB,GACxB,IAAI,CAMN;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,mBAAmB,GAAG,SAAS,CASjC"}