@staix/agent-hub 0.34.1 → 0.35.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 (159) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +35 -6
  3. package/docs/adding-an-ai-tool.md +2 -2
  4. package/docs/addons/claude-mem.md +4 -4
  5. package/docs/addons/open-code-review.md +1 -1
  6. package/docs/agent-notes/README.md +6 -0
  7. package/docs/agent-notes/adapters.md +9 -5
  8. package/docs/agent-notes/budget.md +1 -1
  9. package/docs/agent-notes/bus.md +1 -1
  10. package/docs/agent-notes/daemon.md +4 -3
  11. package/docs/agent-notes/local-worker.md +1 -1
  12. package/docs/agent-notes/models.md +2 -0
  13. package/docs/agent-notes/tasks.md +1 -1
  14. package/docs/agent-notes/tests.md +5 -0
  15. package/docs/design/adapters.md +110 -2
  16. package/docs/design/agent-hub-architecture.md +63 -1
  17. package/docs/design/agent-hub.md +6 -0
  18. package/docs/design/bus.md +18 -0
  19. package/docs/design/execution-reference.md +146 -0
  20. package/docs/design/task-board.md +10 -0
  21. package/docs/dogfood.md +33 -12
  22. package/docs/events.md +38 -20
  23. package/docs/memory.md +21 -7
  24. package/docs/operations.md +539 -24
  25. package/docs/quickstart.md +12 -4
  26. package/docs/research.md +71 -13
  27. package/docs/roles.md +1 -1
  28. package/docs/sdlc.md +9 -7
  29. package/docs/security.md +87 -11
  30. package/docs/smoke.md +14 -0
  31. package/docs/specs/2026-09-19-agent-hub-design.md +8 -3
  32. package/docs/verification/2026-11-07-compat-python-startup-1248.md +51 -0
  33. package/docs/verification/2026-11-07-compat-receipt-harness-1248.md +105 -0
  34. package/docs/verification/2026-11-07-compat-receipt-producers-1248.md +96 -0
  35. package/docs/verification/2026-11-07-compat-workflow-1248.md +94 -0
  36. package/docs/verification/2026-11-07-daemon-startup-1232.md +169 -0
  37. package/docs/verification/2026-11-07-jcode-receipt-reconstruction-1248.md +118 -0
  38. package/docs/verification/2026-11-07-kimi-delayed-usage.md +34 -0
  39. package/docs/verification/2026-11-07-kimi-review-watch-1284.md +115 -0
  40. package/docs/verification/2026-11-08-agy-1.5.3.md +96 -0
  41. package/docs/verification/2026-11-08-agy-acp-t0.md +56 -0
  42. package/docs/verification/2026-11-08-hub-visual-1058.md +161 -0
  43. package/docs/verification/2026-11-08-jcode-0991-model-setter-1317.md +143 -0
  44. package/docs/verification/2026-11-08-kimi-252-model-setter-1317.md +137 -0
  45. package/docs/verification/2026-11-08-kimi-tui-completion-1282.md +45 -0
  46. package/docs/verification/2026-11-08-kimi-wire-yield-1283.md +31 -0
  47. package/docs/verification/2026-11-08-live-model-override-1317.md +250 -0
  48. package/docs/verification/2026-11-08-qwen-0269-acp.md +138 -0
  49. package/docs/verification/2026-11-08-qwen-0269-model-setter-1317.md +91 -0
  50. package/docs/verification/2026-11-09-0.35.0.md +129 -0
  51. package/docs/verification/2026-11-09-headless-records-1320.md +157 -0
  52. package/docs/verification/claude-permission-transport-native.py +10 -3
  53. package/docs/verification/claude-shell-wrapper-native.py +8 -8
  54. package/docs/verified.json +245 -15
  55. package/package.json +3 -3
  56. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  57. package/plugins/agent-hub/kimi-hook.js +20397 -0
  58. package/plugins/agent-hub/kimi-review-policy-worker.js +217 -0
  59. package/plugins/agent-hub/server.js +2701 -664
  60. package/scripts/check-docs.mjs +12 -1
  61. package/src/adapters/acp-model-policy.ts +56 -0
  62. package/src/adapters/acp.ts +175 -5
  63. package/src/adapters/agy/entry.ts +8 -5
  64. package/src/adapters/agy/hooks.ts +65 -15
  65. package/src/adapters/channel-peer.ts +33 -1
  66. package/src/adapters/claude-implementer.ts +16 -3
  67. package/src/adapters/codex-appserver.ts +118 -8
  68. package/src/adapters/codex-review-isolation.ts +3 -1
  69. package/src/adapters/compat.ts +11 -6
  70. package/src/adapters/definitions/builtin-metadata.ts +8 -1
  71. package/src/adapters/definitions/native-cli-entry-kimi.ts +76 -7
  72. package/src/adapters/definitions/native-cli-preview-common.ts +2 -2
  73. package/src/adapters/definitions/native-cli-preview-kimi.ts +9 -2
  74. package/src/adapters/definitions/reviewer-variants.ts +3 -1
  75. package/src/adapters/kimi-review-policy-worker.js +2 -0
  76. package/src/adapters/kimi-review-policy-worker.ts +85 -0
  77. package/src/adapters/kimi-review-policy.ts +68 -0
  78. package/src/adapters/kimi-review.ts +41 -41
  79. package/src/adapters/kimi-tui-facts.ts +153 -0
  80. package/src/adapters/kimi-wire-usage.ts +33 -8
  81. package/src/adapters/local-worker.ts +59 -20
  82. package/src/adapters/model-token.ts +3 -0
  83. package/src/adapters/pi.ts +27 -5
  84. package/src/adapters/registry-types.ts +34 -3
  85. package/src/adapters/registry.ts +1 -0
  86. package/src/adapters/reviewer-policy-watch.ts +86 -0
  87. package/src/adapters/reviewer-print.ts +80 -18
  88. package/src/cli/agents.ts +1 -1
  89. package/src/cli/facts-hook.ts +4 -2
  90. package/src/cli/help.ts +3 -2
  91. package/src/cli/identity.ts +3 -0
  92. package/src/cli/kimi-facts-hook.ts +11 -0
  93. package/src/cli/kimi-plugin.ts +157 -0
  94. package/src/cli/main.ts +48 -9
  95. package/src/cli/model.ts +52 -0
  96. package/src/cli/output.ts +23 -1
  97. package/src/cli/reset.ts +1 -1
  98. package/src/cli/status-lines.ts +8 -4
  99. package/src/hub/budget.ts +1 -1
  100. package/src/hub/bus.ts +40 -2
  101. package/src/hub/code-facts.ts +10 -3
  102. package/src/hub/completions.ts +3 -1
  103. package/src/hub/config-apply.ts +2 -1
  104. package/src/hub/control-client.ts +1 -1
  105. package/src/hub/daemon.ts +1050 -106
  106. package/src/hub/deliverable-files.ts +38 -5
  107. package/src/hub/dogfood-profile.ts +1 -1
  108. package/src/hub/envelope.ts +1 -1
  109. package/src/hub/events.ts +28 -18
  110. package/src/hub/execution-lineage.ts +120 -0
  111. package/src/hub/execution-reference.ts +36 -0
  112. package/src/hub/hub-tools.ts +21 -2
  113. package/src/hub/instances.ts +4 -3
  114. package/src/hub/kimi-events.ts +46 -0
  115. package/src/hub/kimi-usage.ts +132 -29
  116. package/src/hub/lifecycle.ts +31 -15
  117. package/src/hub/limits.ts +13 -4
  118. package/src/hub/manager.ts +15 -2
  119. package/src/hub/memory-policy.ts +2 -1
  120. package/src/hub/memory-sync-attestation.ts +54 -0
  121. package/src/hub/memory-sync-state.ts +20 -5
  122. package/src/hub/model-overrides.ts +115 -0
  123. package/src/hub/native-hook-launch.ts +12 -3
  124. package/src/hub/operational-view.ts +2 -2
  125. package/src/hub/peers.ts +27 -0
  126. package/src/hub/permission-mode.ts +1 -1
  127. package/src/hub/person-figures.ts +88 -0
  128. package/src/hub/report.ts +38 -4
  129. package/src/hub/research-dataset.ts +158 -0
  130. package/src/hub/research-memory.ts +68 -0
  131. package/src/hub/research-quality.ts +118 -0
  132. package/src/hub/research-record.ts +279 -0
  133. package/src/hub/research.ts +126 -27
  134. package/src/hub/restart.ts +14 -0
  135. package/src/hub/settings.ts +3 -0
  136. package/src/hub/startup-event-seeds.ts +51 -0
  137. package/src/hub/startup-readiness.ts +65 -0
  138. package/src/hub/startup-timing.ts +38 -0
  139. package/src/hub/tasks.ts +29 -9
  140. package/src/hub/ui.ts +9 -5
  141. package/src/hub/visual-assets.ts +50 -0
  142. package/src/hub/visual.ts +257 -0
  143. package/src/memory/brief.ts +169 -14
  144. package/src/memory/capture.ts +2 -1
  145. package/src/memory/recall.ts +46 -5
  146. package/src/memory/record-provenance.ts +82 -0
  147. package/src/memory/records.ts +116 -0
  148. package/src/models/route/adec.ts +190 -0
  149. package/src/models/route/config.ts +37 -3
  150. package/src/models/route/decision-evidence.ts +83 -0
  151. package/src/models/route/decision.ts +143 -0
  152. package/src/models/route/runtime.ts +13 -6
  153. package/src/ui/index.html +134 -6
  154. package/src/ui/plugin.ts +65 -4
  155. package/templates/AGENTS.block.md +1 -1
  156. package/templates/config.json +1 -1
  157. package/templates/profiles/general.json +1 -1
  158. package/templates/profiles/research.json +1 -1
  159. package/templates/profiles/writing.json +1 -1
@@ -0,0 +1,217 @@
1
+ // @bun
2
+ // src/adapters/kimi-review-policy-worker.ts
3
+ import { isMainThread, parentPort, workerData, Worker } from "worker_threads";
4
+
5
+ // src/adapters/kimi-review-policy.ts
6
+ import { createHash } from "crypto";
7
+ import { lstatSync, readFileSync } from "fs";
8
+ import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
9
+
10
+ // node_modules/@staix/agent-mem/src/memory/platform.ts
11
+ import { realpathSync } from "fs";
12
+ import { basename, dirname, join, resolve, sep } from "path";
13
+ import { createRequire } from "module";
14
+ var require2 = createRequire(import.meta.url);
15
+ var processes;
16
+ var childProcess = () => processes ??= require2("node:child_process");
17
+ function realPath(path) {
18
+ try {
19
+ return realpathSync(path);
20
+ } catch (error) {
21
+ if (!resolve(path).includes("\\"))
22
+ throw error;
23
+ const argv = process.platform === "darwin" ? ["/bin/realpath", "--", path] : ["realpath", "-e", "--", path];
24
+ const r = childProcess().spawnSync(argv[0], argv.slice(1), { encoding: "utf8" });
25
+ if (r.status !== 0 || !r.stdout.endsWith(`
26
+ `))
27
+ throw error;
28
+ return r.stdout.slice(0, -1);
29
+ }
30
+ }
31
+ var DENY_NAMES = ["^\\.env", "\\.pem$", "\\.key$", "^id_rsa", "^id_ed25519", "^credentials(\\.|$)", "^auth\\.json$", "^\\.netrc$", "^\\.npmrc$", "^\\.pypirc$"];
32
+ var denyNamePatterns = new Map(DENY_NAMES.map((source) => [source, new RegExp(source)]));
33
+ var CREDENTIAL_KEYS = new Set(["credential.helper=", "core.askpass="]);
34
+ // src/adapters/kimi-review-policy.ts
35
+ var kimiReviewFingerprint = (text) => createHash("sha256").update(text).digest("hex");
36
+ function readKimiReviewFile(file, limit = 262144) {
37
+ const stat = lstatSync(file);
38
+ if (!stat.isFile() || stat.size > limit)
39
+ throw new Error("unsupported reviewer file");
40
+ return readFileSync(file, "utf8");
41
+ }
42
+ function assertCleanCwdAncestors(...candidates) {
43
+ const seen = new Set;
44
+ for (const candidate of candidates) {
45
+ let ancestor = resolve2(candidate);
46
+ for (;; ) {
47
+ if (!seen.has(ancestor)) {
48
+ seen.add(ancestor);
49
+ for (const marker of [".git", ".kimi-code", "AGENTS.md"]) {
50
+ if (lstatSync(join2(ancestor, marker), { throwIfNoEntry: false }) !== undefined) {
51
+ throw new Error("private cwd ancestor contains ambient configuration");
52
+ }
53
+ }
54
+ }
55
+ const parent = dirname2(ancestor);
56
+ if (parent === ancestor)
57
+ break;
58
+ ancestor = parent;
59
+ }
60
+ }
61
+ }
62
+ function projectKimiReviewPolicyBinding(binding) {
63
+ return Object.freeze({
64
+ lexicalCwd: binding.lexicalCwd,
65
+ physicalCwd: binding.physicalCwd,
66
+ sourcePath: binding.sourcePath,
67
+ source: binding.source,
68
+ sourceConfig: binding.sourceConfig,
69
+ sourceConfigHash: binding.sourceConfigHash,
70
+ executable: binding.executable,
71
+ executableStat: Object.freeze({
72
+ dev: binding.executableStat.dev,
73
+ ino: binding.executableStat.ino,
74
+ size: binding.executableStat.size,
75
+ mtimeMs: binding.executableStat.mtimeMs,
76
+ ctimeMs: binding.executableStat.ctimeMs
77
+ }),
78
+ privateFiles: Object.freeze(binding.privateFiles.map((file) => Object.freeze({ path: file.path, hash: file.hash }))),
79
+ tool: binding.tool,
80
+ authTargets: Object.freeze(binding.authTargets.map((target) => target))
81
+ });
82
+ }
83
+ function checkKimiReviewPolicy(binding) {
84
+ try {
85
+ assertCleanCwdAncestors(binding.lexicalCwd, binding.physicalCwd);
86
+ const now = lstatSync(binding.executable), expected = binding.executableStat;
87
+ return realPath(binding.sourcePath) === binding.source && now.dev === expected.dev && now.ino === expected.ino && now.size === expected.size && now.mtimeMs === expected.mtimeMs && now.ctimeMs === expected.ctimeMs && kimiReviewFingerprint(readKimiReviewFile(binding.sourceConfig)) === binding.sourceConfigHash && binding.privateFiles.length === 3 && binding.privateFiles.every((file) => kimiReviewFingerprint(readKimiReviewFile(file.path, 2097152)) === file.hash) && binding.authTargets.length === 3 && ["credentials", "oauth", "device_id"].every((name, index) => realPath(join2(binding.source, name)) === binding.authTargets[index] && realPath(join2(binding.tool, name)) === binding.authTargets[index]);
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+
93
+ // src/adapters/kimi-review-policy-worker.ts
94
+ function startKimiReviewPolicyWatch(binding, options = {}) {
95
+ const projected = projectKimiReviewPolicyBinding(binding);
96
+ if (options.gate && options.gate.byteLength !== 8)
97
+ throw new Error("review policy fixture gate is invalid");
98
+ let worker;
99
+ try {
100
+ worker = new Worker(new URL("./kimi-review-policy-worker.js", import.meta.url), {
101
+ env: {},
102
+ execArgv: [],
103
+ stdout: true,
104
+ stderr: true,
105
+ workerData: { binding: projected, ...options.gate ? { gate: options.gate } : {} }
106
+ });
107
+ } catch {
108
+ throw new Error("review policy worker could not start; retry the review");
109
+ }
110
+ let failed = false, stopping = false, exited = false, sequence = 0;
111
+ let pending;
112
+ let stopWork;
113
+ let resolveExit, resolveFailure;
114
+ const exit = new Promise((resolve) => {
115
+ resolveExit = resolve;
116
+ });
117
+ const failure = new Promise((resolve) => {
118
+ resolveFailure = resolve;
119
+ });
120
+ const settle = (current) => {
121
+ const request = pending;
122
+ pending = undefined;
123
+ request?.resolve(current);
124
+ };
125
+ const fail = () => {
126
+ failed = true;
127
+ resolveFailure();
128
+ settle(false);
129
+ };
130
+ worker.on("error", fail);
131
+ worker.on("exit", () => {
132
+ exited = true;
133
+ fail();
134
+ resolveExit();
135
+ });
136
+ try {
137
+ worker.stdout?.on("data", fail);
138
+ worker.stderr?.on("data", fail);
139
+ worker.on("message", (message) => {
140
+ if (stopping || failed)
141
+ return;
142
+ if (!message || typeof message !== "object" || Array.isArray(message))
143
+ return fail();
144
+ const reply = message;
145
+ if (Object.keys(reply).sort().join() !== "current,id" || !pending || reply.id !== pending.id || typeof reply.current !== "boolean")
146
+ return fail();
147
+ if (!reply.current)
148
+ return fail();
149
+ settle(true);
150
+ });
151
+ } catch {
152
+ fail();
153
+ }
154
+ return {
155
+ failure,
156
+ check() {
157
+ if (failed || stopping || exited)
158
+ return Promise.resolve(false);
159
+ if (pending || sequence >= Number.MAX_SAFE_INTEGER) {
160
+ fail();
161
+ return Promise.resolve(false);
162
+ }
163
+ return new Promise((resolve) => {
164
+ pending = { id: ++sequence, resolve };
165
+ try {
166
+ worker.postMessage({ id: sequence });
167
+ } catch {
168
+ fail();
169
+ }
170
+ });
171
+ },
172
+ stop() {
173
+ if (stopWork)
174
+ return stopWork;
175
+ stopping = true;
176
+ fail();
177
+ stopWork = (async () => {
178
+ if (!exited)
179
+ await worker.terminate();
180
+ await exit;
181
+ })().catch(() => {
182
+ stopWork = undefined;
183
+ throw new Error("review policy worker stop is unconfirmed; retry stopping the review");
184
+ });
185
+ return stopWork;
186
+ }
187
+ };
188
+ }
189
+ if (!isMainThread) {
190
+ const port = parentPort;
191
+ if (!port || Object.keys(process.env).length !== 0 || process.execArgv.length !== 0)
192
+ throw new Error("review policy worker environment is invalid");
193
+ const data = workerData;
194
+ const binding = projectKimiReviewPolicyBinding(data.binding);
195
+ const gate = data.gate ? new Int32Array(data.gate) : undefined;
196
+ if (gate && gate.length !== 2)
197
+ throw new Error("review policy fixture gate is invalid");
198
+ let last = 0;
199
+ port.on("message", (message) => {
200
+ if (!message || typeof message !== "object" || Array.isArray(message))
201
+ throw new Error("review policy request is invalid");
202
+ const request = message;
203
+ if (Object.keys(request).join() !== "id" || request.id !== last + 1)
204
+ throw new Error("review policy request is invalid");
205
+ last++;
206
+ if (gate) {
207
+ Atomics.add(gate, 0, 1);
208
+ Atomics.notify(gate, 0);
209
+ while (Atomics.load(gate, 1) === 0)
210
+ Atomics.wait(gate, 1, 0);
211
+ }
212
+ port.postMessage({ id: last, current: checkKimiReviewPolicy(binding) });
213
+ });
214
+ }
215
+ export {
216
+ startKimiReviewPolicyWatch
217
+ };