@omnicrawl/cli-linux-x64 0.4.2 → 0.4.3

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/bin/omnicrawl CHANGED
Binary file
package/host/omnicrawl CHANGED
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -51,7 +51,7 @@
51
51
  - 方案结构和各阶段之间的数据流;
52
52
  - 文件/模块职责与必要的接口、类型、配置或数据变更;
53
53
  - 输入校验、权限、敏感信息、错误、超时、取消和重试处理;
54
- - 与现有行为、历史数据、客户端、Provider、插件或外部依赖的兼容性;
54
+ - 与现有行为、历史数据、客户端、Provider 或外部依赖的兼容性;
55
55
  - 最小而有针对性的测试案例、验收条件和失败后的诊断路径;
56
56
  - 发布、迁移、部署、监控与回滚影响(确有影响时才展开)。
57
57
 
@@ -2,7 +2,11 @@
2
2
  name: explore
3
3
  description: 快速只读探索代码、网页和外部能力,返回文件路径、行号与可复核证据
4
4
  disallowedTools:
5
- - subagent
5
+ - subagent_run
6
+ - subagent_list
7
+ - subagent_cancel
8
+ - subagent_apply_worktree
9
+ - subagent_discard_worktree
6
10
  - Edit_file
7
11
  - write_file
8
12
  - memory_write
@@ -15,7 +15,11 @@ tools:
15
15
  - bash
16
16
  - powershell
17
17
  disallowedTools:
18
- - subagent
18
+ - subagent_run
19
+ - subagent_list
20
+ - subagent_cancel
21
+ - subagent_apply_worktree
22
+ - subagent_discard_worktree
19
23
  - switch_model
20
24
  - switch_skill
21
25
  - load_skill
@@ -36,7 +40,7 @@ background: false
36
40
  5. 完成后用简洁中文总结:改了什么、为什么、如何验证、残留风险。
37
41
 
38
42
  约束:
39
- - 禁止调用 subagent、switch_model、switch_skill、load_skill、search_skills。
43
+ - 禁止调用 subagent_run、subagent_list、subagent_cancel、subagent_apply_worktree、subagent_discard_worktree、switch_model、switch_skill、load_skill、search_skills。
40
44
  - 不要提交 git commit、push 或改远程。
41
45
  - 不要删除用户未明确要求删除的文件。
42
46
  - isolation=worktree 时,结果会以分支/diff 形式返回父 Agent,由父决定是否应用。
@@ -2,7 +2,11 @@
2
2
  name: plan
3
3
  description: 结合项目与外部证据制定只读的软件架构、实施步骤、风险与验证计划
4
4
  disallowedTools:
5
- - subagent
5
+ - subagent_run
6
+ - subagent_list
7
+ - subagent_cancel
8
+ - subagent_apply_worktree
9
+ - subagent_discard_worktree
6
10
  - Edit_file
7
11
  - write_file
8
12
  - memory_write
@@ -9,7 +9,11 @@ tools:
9
9
  - grep
10
10
  - git
11
11
  disallowedTools:
12
- - subagent
12
+ - subagent_run
13
+ - subagent_list
14
+ - subagent_cancel
15
+ - subagent_apply_worktree
16
+ - subagent_discard_worktree
13
17
  - Edit_file
14
18
  - write_file
15
19
  - memory_write
@@ -12,7 +12,11 @@ tools:
12
12
  - memory_expand_related
13
13
  - verify_command
14
14
  disallowedTools:
15
- - subagent
15
+ - subagent_run
16
+ - subagent_list
17
+ - subagent_cancel
18
+ - subagent_apply_worktree
19
+ - subagent_discard_worktree
16
20
  - Edit_file
17
21
  - write_file
18
22
  - bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnicrawl/cli-linux-x64",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "OmniCrawl 平台包(Linux x64:内核 + 完整宿主)",
5
5
  "repository": {
6
6
  "type": "git",
package/version.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@omnicrawl/cli-linux-x64",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "os": "linux",
5
5
  "cpu": "x64",
6
- "kernelVersion": "0.4.2",
7
- "hostVersion": "0.4.2",
6
+ "kernelVersion": "0.4.3",
7
+ "hostVersion": "0.4.3",
8
8
  "hostPlatform": "linux-x64",
9
- "builtAt": "2026-10-29T17:05:22.894Z"
9
+ "builtAt": "2026-10-30T18:31:27.735Z"
10
10
  }
@@ -1,402 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * OmniCrawl 单插件 Node runner。
4
- *
5
- * Host 固定调用:
6
- * node node_runner.mjs --plugin-root <canonical-path>
7
- *
8
- * 协议:stdin/stdout NDJSON JSON-RPC 2.0。
9
- * 插件日志经 SDK logger 走 stderr 结构化行;普通 console 也被重定向到 stderr。
10
- */
11
-
12
- import { createRequire } from "node:module";
13
- import path from "node:path";
14
- import process from "node:process";
15
- import { pathToFileURL } from "node:url";
16
- import readline from "node:readline";
17
- import fs from "node:fs";
18
-
19
- const require = createRequire(import.meta.url);
20
-
21
- function parseArgs(argv) {
22
- const args = { pluginRoot: "" };
23
- for (let i = 0; i < argv.length; i += 1) {
24
- const item = argv[i];
25
- if (item === "--plugin-root") {
26
- args.pluginRoot = argv[i + 1] || "";
27
- i += 1;
28
- }
29
- }
30
- return args;
31
- }
32
-
33
- function writeStdout(message) {
34
- process.stdout.write(`${JSON.stringify(message)}\n`);
35
- }
36
-
37
- function writeStderrLine(level, message, fields = {}) {
38
- const payload = {
39
- level,
40
- message: String(message),
41
- fields,
42
- ts: new Date().toISOString(),
43
- };
44
- process.stderr.write(`${JSON.stringify(payload)}\n`);
45
- }
46
-
47
- // 强制把 console 导向 stderr,避免污染协议 stdout。
48
- const originalConsole = { ...console };
49
- for (const level of ["log", "info", "warn", "error", "debug"]) {
50
- console[level] = (...parts) => {
51
- writeStderrLine(level === "log" ? "info" : level, parts.map(String).join(" "));
52
- };
53
- }
54
-
55
- function createLogger() {
56
- return {
57
- debug(message, fields) {
58
- writeStderrLine("debug", message, fields || {});
59
- },
60
- info(message, fields) {
61
- writeStderrLine("info", message, fields || {});
62
- },
63
- warn(message, fields) {
64
- writeStderrLine("warn", message, fields || {});
65
- },
66
- error(message, fields) {
67
- writeStderrLine("error", message, fields || {});
68
- },
69
- };
70
- }
71
-
72
- function definePlugin(plugin) {
73
- return plugin;
74
- }
75
-
76
- function loadPackageJson(pluginRoot) {
77
- const packagePath = path.join(pluginRoot, "package.json");
78
- const raw = fs.readFileSync(packagePath, "utf8");
79
- return JSON.parse(raw);
80
- }
81
-
82
- async function importPlugin(entryPath) {
83
- const url = pathToFileURL(entryPath).href;
84
- const mod = await import(url);
85
- return mod.default || mod.plugin || mod;
86
- }
87
-
88
- class PluginRuntime {
89
- constructor(pluginRoot) {
90
- this.pluginRoot = path.resolve(pluginRoot);
91
- this.packageJson = loadPackageJson(this.pluginRoot);
92
- this.manifest = this.packageJson.omnicrawl || {};
93
- this.handlers = new Map();
94
- this.plugin = null;
95
- this.initialized = false;
96
- this.activeCancellations = new Set();
97
- this.logger = createLogger();
98
- this._hostRequestId = 1;
99
- this._pendingHostRequests = new Map();
100
- }
101
-
102
- /** Host 对 Worker 请求的响应入口(custom.emit 等)。 */
103
- resolveHostResponse(message) {
104
- if (!message || message.id == null) return false;
105
- const pending = this._pendingHostRequests.get(message.id);
106
- if (!pending) return false;
107
- this._pendingHostRequests.delete(message.id);
108
- if (message.error) {
109
- pending.reject(new Error(message.error.message || String(message.error)));
110
- } else {
111
- pending.resolve(message.result || { ok: true });
112
- }
113
- return true;
114
- }
115
-
116
- _requestHost(method, params = {}) {
117
- const id = this._hostRequestId;
118
- this._hostRequestId += 1;
119
- return new Promise((resolve, reject) => {
120
- this._pendingHostRequests.set(id, { resolve, reject });
121
- writeStdout({
122
- jsonrpc: "2.0",
123
- id,
124
- method,
125
- params,
126
- });
127
- // Host 超时由 Python 侧控制;Worker 侧给一个安全兜底。
128
- setTimeout(() => {
129
- if (this._pendingHostRequests.has(id)) {
130
- this._pendingHostRequests.delete(id);
131
- reject(new Error(`Host 请求超时:${method}`));
132
- }
133
- }, 10000);
134
- });
135
- }
136
-
137
- async initialize(params = {}) {
138
- if (this.initialized) {
139
- return this._registrationSnapshot();
140
- }
141
- const entryRel = this.manifest.entry || this.packageJson.main;
142
- if (!entryRel) {
143
- throw new Error("package.json 缺少 omnicrawl.entry / main");
144
- }
145
- const entryPath = path.resolve(this.pluginRoot, entryRel);
146
- const rootResolved = path.resolve(this.pluginRoot);
147
- if (!entryPath.startsWith(rootResolved + path.sep) && entryPath !== rootResolved) {
148
- throw new Error(`entry 逃逸包根目录:${entryRel}`);
149
- }
150
-
151
- const imported = await importPlugin(entryPath);
152
- const definition = typeof imported === "function" ? imported({ definePlugin }) : imported;
153
- if (!definition || typeof definition.activate !== "function") {
154
- throw new Error("插件必须导出 activate(context) 的 PluginDefinition");
155
- }
156
- this.plugin = definition;
157
-
158
- const declared = Array.isArray(this.manifest.hooks) ? this.manifest.hooks : [];
159
- const declaredIds = new Set(declared.map((item) => item.id));
160
-
161
- const context = {
162
- plugin: {
163
- name: this.packageJson.name,
164
- version: this.packageJson.version,
165
- apiVersion: String(this.manifest.apiVersion || "1"),
166
- },
167
- runtime: {
168
- omnicrawlVersion: params.omnicrawlVersion || process.env.OMNICRAWL_VERSION || "0.1.5",
169
- nodeVersion: process.version,
170
- },
171
- hooks: {
172
- on: (registration) => {
173
- if (!registration || typeof registration !== "object") {
174
- throw new Error("hooks.on(registration) 需要对象");
175
- }
176
- const id = String(registration.id || "");
177
- const hook = String(registration.hook || "");
178
- const mode = String(registration.mode || "observe");
179
- const handler = registration.handler;
180
- if (!declaredIds.has(id)) {
181
- throw new Error(`运行期不能注册 manifest 未声明的 Handler:${id}`);
182
- }
183
- if (typeof handler !== "function") {
184
- throw new Error(`Handler ${id} 缺少 handler 函数`);
185
- }
186
- this.handlers.set(id, { id, hook, mode, handler });
187
- return () => {
188
- this.handlers.delete(id);
189
- };
190
- },
191
- emitCustom: async (event, payload = {}, options = {}) => {
192
- if (!this.initialized) {
193
- throw new Error("initialize 完成前不能 emitCustom");
194
- }
195
- const permissions = Array.isArray(this.manifest.permissions)
196
- ? this.manifest.permissions
197
- : [];
198
- if (!permissions.includes("hook:custom-emit")) {
199
- throw new Error("缺少 hook:custom-emit 权限");
200
- }
201
- const version =
202
- options.version != null
203
- ? Number(options.version)
204
- : Number(
205
- (Array.isArray(this.manifest.customEvents)
206
- ? this.manifest.customEvents.find((item) => item.name === event)
207
- : null)?.version || 1
208
- );
209
-
210
- // 同插件订阅必须本地投递:Host 若在 hook.invoke 中再回调本 Worker
211
- // 会与“等待 custom.emit 响应”形成死锁。
212
- let localDelivered = 0;
213
- const localEvent = {
214
- apiVersion: String(this.manifest.apiVersion || "1"),
215
- hook: event,
216
- payload: payload || {},
217
- timestamp: new Date().toISOString(),
218
- };
219
- for (const binding of this.handlers.values()) {
220
- if (binding.hook !== event) continue;
221
- await binding.handler(localEvent);
222
- localDelivered += 1;
223
- }
224
-
225
- const result = await this._requestHost("custom.emit", {
226
- event,
227
- version,
228
- payload: payload || {},
229
- localDelivered,
230
- });
231
- return {
232
- ...(result || { ok: true }),
233
- localDelivered,
234
- delivered: Number(result?.delivered || 0) + localDelivered,
235
- };
236
- },
237
- },
238
- logger: this.logger,
239
- };
240
-
241
- await definition.activate(context);
242
-
243
- // 若插件未在 activate 中显式 on(),但 manifest 声明了 hooks,则保持空绑定;
244
- // Host 会在二次校验时发现实际注册子集。
245
- this.initialized = true;
246
- return this._registrationSnapshot();
247
- }
248
-
249
- _registrationSnapshot() {
250
- const registrations = [];
251
- for (const item of this.handlers.values()) {
252
- registrations.push({
253
- id: item.id,
254
- hook: item.hook,
255
- mode: item.mode,
256
- });
257
- }
258
- // 若 activate 没手动 on,回落为 manifest 声明(开发期便利);
259
- // Host 仍要求它们是 manifest 子集。
260
- if (registrations.length === 0 && Array.isArray(this.manifest.hooks)) {
261
- for (const item of this.manifest.hooks) {
262
- registrations.push({
263
- id: item.id,
264
- hook: item.hook,
265
- mode: item.mode,
266
- });
267
- }
268
- }
269
- return {
270
- plugin: {
271
- name: this.packageJson.name,
272
- version: this.packageJson.version,
273
- apiVersion: String(this.manifest.apiVersion || "1"),
274
- },
275
- handlers: registrations,
276
- capabilities: {
277
- customEmit: Boolean(
278
- Array.isArray(this.manifest.permissions) &&
279
- this.manifest.permissions.includes("hook:custom-emit")
280
- ),
281
- },
282
- };
283
- }
284
-
285
- async invoke(handlerId, event) {
286
- const binding = this.handlers.get(handlerId);
287
- if (!binding) {
288
- // 允许仅声明未绑定:默认 continue,便于 observe 空实现。
289
- return { action: "continue" };
290
- }
291
- const result = await binding.handler(event);
292
- if (result == null) {
293
- return { action: "continue" };
294
- }
295
- if (typeof result !== "object") {
296
- throw new Error(`Handler ${handlerId} 必须返回对象`);
297
- }
298
- return result;
299
- }
300
-
301
- async shutdown() {
302
- if (this.plugin && typeof this.plugin.deactivate === "function") {
303
- await this.plugin.deactivate();
304
- }
305
- this.handlers.clear();
306
- this.initialized = false;
307
- }
308
- }
309
-
310
- async function main() {
311
- const args = parseArgs(process.argv.slice(2));
312
- if (!args.pluginRoot) {
313
- writeStderrLine("error", "missing --plugin-root");
314
- process.exit(2);
315
- }
316
- const runtime = new PluginRuntime(args.pluginRoot);
317
- const rl = readline.createInterface({ input: process.stdin, crlfDelay: Infinity });
318
-
319
- const sendResult = (id, result) => {
320
- writeStdout({ jsonrpc: "2.0", id, result });
321
- };
322
- const sendError = (id, code, message) => {
323
- writeStdout({ jsonrpc: "2.0", id, error: { code, message } });
324
- };
325
-
326
- // 必须用事件驱动读取 stdin:handler 内 await custom.emit 时 Host 响应
327
- // 也要从同一 stdin 进来。若 for-await 串行阻塞,会形成死锁超时。
328
- let shuttingDown = false;
329
- const inflight = new Set();
330
-
331
- const handleMessage = async (message) => {
332
- // Host 对 Worker 请求的响应:无 method,带 id+result/error。
333
- if (
334
- message.id != null &&
335
- (Object.prototype.hasOwnProperty.call(message, "result") ||
336
- Object.prototype.hasOwnProperty.call(message, "error")) &&
337
- !message.method
338
- ) {
339
- runtime.resolveHostResponse(message);
340
- return;
341
- }
342
-
343
- const { id, method, params } = message;
344
- try {
345
- if (method === "initialize") {
346
- const result = await runtime.initialize(params || {});
347
- if (id !== undefined) sendResult(id, result);
348
- } else if (method === "hook.invoke") {
349
- const handlerId = params?.handlerId;
350
- const event = params?.event || {};
351
- const result = await runtime.invoke(handlerId, event);
352
- if (id !== undefined) sendResult(id, result);
353
- } else if (method === "hook.cancel") {
354
- const requestId = params?.requestId;
355
- if (requestId != null) runtime.activeCancellations.add(requestId);
356
- if (id !== undefined) sendResult(id, { ok: true });
357
- } else if (method === "ping") {
358
- if (id !== undefined) sendResult(id, { ok: true, ts: Date.now() });
359
- } else if (method === "shutdown") {
360
- shuttingDown = true;
361
- await runtime.shutdown();
362
- if (id !== undefined) sendResult(id, { ok: true });
363
- process.exit(0);
364
- } else if (method) {
365
- if (id !== undefined) sendError(id, -32601, `Method not found: ${method}`);
366
- }
367
- } catch (error) {
368
- const text = error instanceof Error ? error.message : String(error);
369
- writeStderrLine("error", text);
370
- if (id !== undefined) sendError(id, -32000, text);
371
- }
372
- };
373
-
374
- rl.on("line", (line) => {
375
- if (shuttingDown) return;
376
- const trimmed = String(line || "").trim();
377
- if (!trimmed) return;
378
- let message;
379
- try {
380
- message = JSON.parse(trimmed);
381
- } catch (error) {
382
- writeStderrLine("error", "invalid json from host", { error: String(error) });
383
- return;
384
- }
385
- if (!message || typeof message !== "object") return;
386
- const task = handleMessage(message);
387
- inflight.add(task);
388
- task.finally(() => inflight.delete(task));
389
- });
390
-
391
- await new Promise((resolve) => {
392
- rl.on("close", resolve);
393
- });
394
- await Promise.allSettled([...inflight]);
395
- }
396
-
397
- main().catch((error) => {
398
- writeStderrLine("error", error instanceof Error ? error.message : String(error));
399
- process.exit(1);
400
- });
401
-
402
- export { definePlugin };