@grackle-ai/powerline 0.170.0 → 0.171.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 (39) hide show
  1. package/dist/ahp-handlers.d.ts +7 -44
  2. package/dist/ahp-handlers.d.ts.map +1 -1
  3. package/dist/ahp-handlers.js +21 -1024
  4. package/dist/ahp-handlers.js.map +1 -1
  5. package/dist/ahp-types.d.ts +92 -0
  6. package/dist/ahp-types.d.ts.map +1 -0
  7. package/dist/ahp-types.js +19 -0
  8. package/dist/ahp-types.js.map +1 -0
  9. package/dist/channel-codec.d.ts +31 -0
  10. package/dist/channel-codec.d.ts.map +1 -0
  11. package/dist/channel-codec.js +38 -0
  12. package/dist/channel-codec.js.map +1 -0
  13. package/dist/forwarder.d.ts +26 -0
  14. package/dist/forwarder.d.ts.map +1 -0
  15. package/dist/forwarder.js +223 -0
  16. package/dist/forwarder.js.map +1 -0
  17. package/dist/handlers/action-handlers.d.ts +12 -0
  18. package/dist/handlers/action-handlers.d.ts.map +1 -0
  19. package/dist/handlers/action-handlers.js +49 -0
  20. package/dist/handlers/action-handlers.js.map +1 -0
  21. package/dist/handlers/session-handlers.d.ts +16 -0
  22. package/dist/handlers/session-handlers.d.ts.map +1 -0
  23. package/dist/handlers/session-handlers.js +262 -0
  24. package/dist/handlers/session-handlers.js.map +1 -0
  25. package/dist/handlers/subscribe-handlers.d.ts +10 -0
  26. package/dist/handlers/subscribe-handlers.d.ts.map +1 -0
  27. package/dist/handlers/subscribe-handlers.js +82 -0
  28. package/dist/handlers/subscribe-handlers.js.map +1 -0
  29. package/dist/index.js +11 -25
  30. package/dist/index.js.map +1 -1
  31. package/dist/resource-watch.d.ts +30 -0
  32. package/dist/resource-watch.d.ts.map +1 -0
  33. package/dist/resource-watch.js +169 -0
  34. package/dist/resource-watch.js.map +1 -0
  35. package/dist/runtime-loader.d.ts +9 -0
  36. package/dist/runtime-loader.d.ts.map +1 -0
  37. package/dist/runtime-loader.js +69 -0
  38. package/dist/runtime-loader.js.map +1 -0
  39. package/package.json +10 -10
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Filesystem resource watch lifecycle: create, start, stop, flush.
3
+ * @module resource-watch
4
+ */
5
+ import { ActionType, AhpErrorCodes, JsonRpcErrorCodes, ResourceChangeType } from "@grackle-ai/ahp";
6
+ import { watch as chokidarWatch } from "chokidar";
7
+ import { existsSync } from "node:fs";
8
+ import { randomUUID } from "node:crypto";
9
+ import { join as joinPath, relative as relativePath, sep as pathSep } from "node:path";
10
+ import { pathToFileURL } from "node:url";
11
+ import picomatch from "picomatch";
12
+ import { MAX_RESOURCE_WATCHES_PER_CONNECTION, RESOURCE_WATCH_CHANNEL_PREFIX, WATCH_COALESCE_MS, } from "./channel-codec.js";
13
+ import { logger } from "./logger.js";
14
+ import { assertWithinRoots, ResourceError, resourceUriToPath } from "./resource-fs.js";
15
+ import { COALESCE_DROP, coalesceChangeType } from "./resource-watch-coalesce.js";
16
+ /**
17
+ * Validate an optional AHP `GlobSet` (excludes/includes) from untrusted client
18
+ * params: it must be `undefined` or an object with an `items` array of strings.
19
+ *
20
+ * @throws ResourceError with `InvalidParams` for any other shape.
21
+ */
22
+ function assertGlobSet(value, field) {
23
+ if (value === undefined) {
24
+ return;
25
+ }
26
+ const items = typeof value === "object" && value !== null ? value.items : undefined;
27
+ if (!Array.isArray(items) || !items.every((g) => typeof g === "string")) {
28
+ throw new ResourceError(JsonRpcErrorCodes.InvalidParams, `createResourceWatch: ${field} must be { items: string[] }`);
29
+ }
30
+ }
31
+ /**
32
+ * Allocate a resource-watch channel for a sandbox-validated URI. The watcher
33
+ * itself is started lazily when the client subscribes to the returned channel
34
+ * ({@link startResourceWatch}).
35
+ *
36
+ * @throws ResourceError — `InvalidParams`/`PermissionDenied` (sandbox) or
37
+ * `NotFound` if the watch target does not exist.
38
+ */
39
+ export async function createResourceWatchEntry(params, cState) {
40
+ if (cState.watches.size >= MAX_RESOURCE_WATCHES_PER_CONNECTION) {
41
+ throw new ResourceError(JsonRpcErrorCodes.InvalidParams, `Too many active resource watches (max ${MAX_RESOURCE_WATCHES_PER_CONNECTION})`);
42
+ }
43
+ assertGlobSet(params.excludes, "excludes");
44
+ assertGlobSet(params.includes, "includes");
45
+ const rootPath = await assertWithinRoots(resourceUriToPath(params.uri), cState.allowedRoots);
46
+ if (!existsSync(rootPath)) {
47
+ throw new ResourceError(AhpErrorCodes.NotFound, `Watch target does not exist: ${params.uri}`);
48
+ }
49
+ const channel = `${RESOURCE_WATCH_CHANNEL_PREFIX}${randomUUID()}`;
50
+ const descriptor = {
51
+ root: params.uri,
52
+ recursive: params.recursive ?? false,
53
+ ...(params.excludes !== undefined ? { excludes: params.excludes } : {}),
54
+ ...(params.includes !== undefined ? { includes: params.includes } : {}),
55
+ };
56
+ cState.watches.set(channel, { rootPath, descriptor, serverSeq: 0, pending: new Map() });
57
+ return { channel };
58
+ }
59
+ /**
60
+ * Flush the coalesced change batch for a watch as a single
61
+ * `resourceWatch/changed` action. Never dispatches an empty batch (per spec).
62
+ */
63
+ export function flushResourceWatch(conn, channel, entry) {
64
+ entry.flushTimer = undefined;
65
+ if (entry.stopped === true || entry.pending.size === 0) {
66
+ return;
67
+ }
68
+ const items = [...entry.pending.values()];
69
+ entry.pending.clear();
70
+ const action = {
71
+ type: ActionType.ResourceWatchChanged,
72
+ changes: { items },
73
+ };
74
+ conn.session.notify("action", {
75
+ channel,
76
+ serverSeq: entry.serverSeq++,
77
+ action,
78
+ origin: undefined,
79
+ });
80
+ }
81
+ /**
82
+ * Start the chokidar watcher for a previously-created watch entry and wire its
83
+ * events into coalesced `resourceWatch/changed` notifications. Idempotent: a
84
+ * second subscribe to the same channel is a no-op.
85
+ */
86
+ export function startResourceWatch(conn, channel, entry) {
87
+ if (entry.watcher !== undefined) {
88
+ return;
89
+ }
90
+ entry.stopped = false;
91
+ const { rootPath, descriptor } = entry;
92
+ const excludeMatchers = (descriptor.excludes?.items ?? []).map((g) => picomatch(g));
93
+ const includeMatchers = (descriptor.includes?.items ?? []).map((g) => picomatch(g));
94
+ const relForMatch = (p) => relativePath(rootPath, p).split(pathSep).join("/");
95
+ const lexicalRoot = resourceUriToPath(descriptor.root);
96
+ const emitUriFor = (changedPath) => {
97
+ const rel = relativePath(rootPath, changedPath);
98
+ const lexicalPath = rel === "" ? lexicalRoot : joinPath(lexicalRoot, rel);
99
+ return pathToFileURL(lexicalPath).href;
100
+ };
101
+ const watcher = chokidarWatch(rootPath, {
102
+ ignoreInitial: true,
103
+ awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 },
104
+ followSymlinks: false,
105
+ ignored: (p) => {
106
+ if (p.split(pathSep).includes(".git")) {
107
+ return true;
108
+ }
109
+ if (excludeMatchers.length === 0) {
110
+ return false;
111
+ }
112
+ const rel = relForMatch(p);
113
+ return rel !== "" && excludeMatchers.some((m) => m(rel));
114
+ },
115
+ depth: descriptor.recursive ? undefined : 0,
116
+ });
117
+ entry.watcher = watcher;
118
+ const record = (type) => (changedPath) => {
119
+ if (entry.stopped === true) {
120
+ return;
121
+ }
122
+ if (includeMatchers.length > 0) {
123
+ const rel = relForMatch(changedPath);
124
+ if (rel !== "" && !includeMatchers.some((m) => m(rel))) {
125
+ return;
126
+ }
127
+ }
128
+ const uri = emitUriFor(changedPath);
129
+ const next = coalesceChangeType(entry.pending.get(uri)?.type, type);
130
+ if (next === COALESCE_DROP) {
131
+ entry.pending.delete(uri);
132
+ }
133
+ else {
134
+ entry.pending.set(uri, { uri, type: next });
135
+ }
136
+ if (entry.pending.size > 0 && entry.flushTimer === undefined) {
137
+ entry.flushTimer = setTimeout(() => {
138
+ flushResourceWatch(conn, channel, entry);
139
+ }, WATCH_COALESCE_MS);
140
+ }
141
+ };
142
+ watcher.on("add", record(ResourceChangeType.Added));
143
+ watcher.on("addDir", record(ResourceChangeType.Added));
144
+ watcher.on("change", record(ResourceChangeType.Updated));
145
+ watcher.on("unlink", record(ResourceChangeType.Deleted));
146
+ watcher.on("unlinkDir", record(ResourceChangeType.Deleted));
147
+ watcher.on("error", (err) => {
148
+ logger.error({ err, channel }, "Resource watch error; tearing down watch");
149
+ stopResourceWatch(entry);
150
+ });
151
+ }
152
+ /** Release a watch's filesystem resources (watcher + pending flush timer). */
153
+ export function stopResourceWatch(entry) {
154
+ entry.stopped = true;
155
+ if (entry.flushTimer !== undefined) {
156
+ clearTimeout(entry.flushTimer);
157
+ entry.flushTimer = undefined;
158
+ }
159
+ entry.pending.clear();
160
+ const w = entry.watcher;
161
+ if (w !== undefined) {
162
+ for (const ev of ["add", "addDir", "change", "unlink", "unlinkDir", "error"]) {
163
+ w.removeAllListeners(ev);
164
+ }
165
+ w.close().catch(() => undefined);
166
+ }
167
+ entry.watcher = undefined;
168
+ }
169
+ //# sourceMappingURL=resource-watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-watch.js","sourceRoot":"","sources":["../src/resource-watch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Load and register all runtimes whose catalog entry has a `factory`
3
+ * descriptor.
4
+ *
5
+ * @param filter - When provided, only runtimes whose name passes the
6
+ * predicate are loaded. Enables Code/Claw runtime-set composition.
7
+ */
8
+ export declare function loadRuntimesFromCatalog(filter?: (name: string) => boolean): Promise<void>;
9
+ //# sourceMappingURL=runtime-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-loader.d.ts","sourceRoot":"","sources":["../src/runtime-loader.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/F"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Catalog-driven runtime instantiation.
3
+ *
4
+ * Iterates {@link RUNTIME_CATALOG}, interprets each entry's factory
5
+ * descriptor, and registers the resulting {@link AgentRuntime}. This is
6
+ * the mechanism layer; the catalog is the policy layer.
7
+ */
8
+ import { RUNTIME_CATALOG } from "@grackle-ai/common";
9
+ import { registerRuntime, listRuntimes } from "./runtime-registry.js";
10
+ import { logger } from "./logger.js";
11
+ /**
12
+ * Load and register all runtimes whose catalog entry has a `factory`
13
+ * descriptor.
14
+ *
15
+ * @param filter - When provided, only runtimes whose name passes the
16
+ * predicate are loaded. Enables Code/Claw runtime-set composition.
17
+ */
18
+ export async function loadRuntimesFromCatalog(filter) {
19
+ for (const [name, entry] of Object.entries(RUNTIME_CATALOG)) {
20
+ if (entry.factory === undefined) {
21
+ continue;
22
+ }
23
+ if (filter !== undefined && !filter(name)) {
24
+ logger.debug({ runtime: name }, "Skipping runtime excluded by filter");
25
+ continue;
26
+ }
27
+ try {
28
+ const runtime = await instantiateRuntime(name, entry.factory);
29
+ registerRuntime(runtime);
30
+ logger.debug({ runtime: name }, "Registered runtime from catalog");
31
+ }
32
+ catch (err) {
33
+ logger.error({ err, runtime: name }, "Failed to load runtime %s — skipping", name);
34
+ }
35
+ }
36
+ const loaded = listRuntimes();
37
+ logger.info({ count: loaded.length, runtimes: loaded }, "Loaded %d runtimes", loaded.length);
38
+ }
39
+ async function instantiateRuntime(name, factory) {
40
+ switch (factory.type) {
41
+ case "sdk": {
42
+ const mod = (await import(factory.package));
43
+ const Constructor = mod[factory.exportName];
44
+ if (typeof Constructor !== "function") {
45
+ throw new Error(`Export "${factory.exportName}" from "${factory.package}" is not a constructor`);
46
+ }
47
+ try {
48
+ return new Constructor();
49
+ }
50
+ catch (err) {
51
+ throw new Error(`Failed to construct "${factory.exportName}" from "${factory.package}": ${err instanceof Error ? err.message : String(err)}`);
52
+ }
53
+ }
54
+ case "acp": {
55
+ const { AcpRuntime } = (await import("@grackle-ai/runtime-acp"));
56
+ return new AcpRuntime({
57
+ name,
58
+ command: factory.config.command,
59
+ args: factory.config.args,
60
+ isolateClaudeConfig: factory.config.isolateClaudeConfig,
61
+ });
62
+ }
63
+ default: {
64
+ const _exhaustive = factory;
65
+ throw new Error(`Unknown factory type: ${JSON.stringify(_exhaustive)}`);
66
+ }
67
+ }
68
+ }
69
+ //# sourceMappingURL=runtime-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-loader.js","sourceRoot":"","sources":["../src/runtime-loader.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grackle-ai/powerline",
3
- "version": "0.170.0",
3
+ "version": "0.171.0",
4
4
  "description": "gRPC PowerLine server for Grackle AI agent integration",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -37,15 +37,15 @@
37
37
  "picomatch": "4.0.4",
38
38
  "pino": "^10.3.1",
39
39
  "zod": "^4.0.0",
40
- "@grackle-ai/ahp-transport": "0.170.0",
41
- "@grackle-ai/ahp": "0.170.0",
42
- "@grackle-ai/common": "0.170.0",
43
- "@grackle-ai/runtime-claude-code": "0.170.0",
44
- "@grackle-ai/runtime-sdk": "0.170.0",
45
- "@grackle-ai/runtime-copilot": "0.170.0",
46
- "@grackle-ai/runtime-codex": "0.170.0",
47
- "@grackle-ai/runtime-genaiscript": "0.170.0",
48
- "@grackle-ai/runtime-acp": "0.170.0"
40
+ "@grackle-ai/ahp-transport": "0.171.0",
41
+ "@grackle-ai/ahp": "0.171.0",
42
+ "@grackle-ai/runtime-sdk": "0.171.0",
43
+ "@grackle-ai/runtime-claude-code": "0.171.0",
44
+ "@grackle-ai/common": "0.171.0",
45
+ "@grackle-ai/runtime-copilot": "0.171.0",
46
+ "@grackle-ai/runtime-codex": "0.171.0",
47
+ "@grackle-ai/runtime-genaiscript": "0.171.0",
48
+ "@grackle-ai/runtime-acp": "0.171.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@rushstack/heft": "1.2.7",