@omnicrawl/cli-win32-ia32 0.4.1 → 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.
Files changed (32) hide show
  1. package/bin/omnicrawl.exe +0 -0
  2. package/host/omnicrawl/config/templates/config.example.toml +84 -14
  3. package/host/omnicrawl/config/templates/decision_models.example.toml +4 -7
  4. package/host/omnicrawl/templates/plan.md +1 -1
  5. package/host/omnicrawl/templates/programming.md +65 -0
  6. package/host/omnicrawl/templates/subagents/explore.md +5 -1
  7. package/host/omnicrawl/templates/subagents/general-purpose.md +6 -2
  8. package/host/omnicrawl/templates/subagents/plan.md +5 -1
  9. package/host/omnicrawl/templates/subagents/review.md +5 -1
  10. package/host/omnicrawl/templates/subagents/verify.md +5 -1
  11. package/host/omnicrawl/templates/system_prompt.md +2 -1
  12. package/host/omnicrawl-api.exe +0 -0
  13. package/host/omnicrawl-decision.exe +0 -0
  14. package/host/omnicrawl-fetch.exe +0 -0
  15. package/host/omnicrawl-host.exe +0 -0
  16. package/host/omnicrawl-mcp-server.exe +0 -0
  17. package/host/omnicrawl-tui.exe +0 -0
  18. package/host/omnicrawl.exe +0 -0
  19. package/host/rust/assets/config-templates/config.example.toml +84 -14
  20. package/host/rust/assets/config-templates/decision_models.example.toml +4 -7
  21. package/host/rust/assets/templates/plan.md +1 -1
  22. package/host/rust/assets/templates/programming.md +65 -0
  23. package/host/rust/assets/templates/subagents/explore.md +5 -1
  24. package/host/rust/assets/templates/subagents/general-purpose.md +6 -2
  25. package/host/rust/assets/templates/subagents/plan.md +5 -1
  26. package/host/rust/assets/templates/subagents/review.md +5 -1
  27. package/host/rust/assets/templates/subagents/verify.md +5 -1
  28. package/host/rust/assets/templates/system_prompt.md +2 -1
  29. package/package.json +2 -1
  30. package/version.json +4 -4
  31. package/host/omnicrawl/extensions/node_runner.mjs +0 -402
  32. package/host/rust/assets/extensions/node_runner.mjs +0 -402
@@ -49,7 +49,7 @@ Todo 规划协议:
49
49
  - 只在系统边界做输入验证(用户输入、外部 API)。
50
50
  - 在编写前端 UI 文案时,请保持极简主义(Minimalism)。拒绝流水账:严禁在标签、按钮或标题后使用括号进行大白话解释。
51
51
 
52
- omnicrawl文档(共 14 篇,均以 `omnicrawl://docs/<文件名>` 读取,按需只读相关场景):
52
+ omnicrawl文档(共 15 篇,均以 `omnicrawl://docs/<文件名>` 读取,按需只读相关场景):
53
53
  - MCP 配置、调用或故障排查:优先使用 MCP 能力;读取 `omnicrawl://docs/MCP_USAGE.md`;实现细节位于 `rust/crates/omnicrawl-mcp/`。
54
54
  - Skill 安装、编写或渐进式披露:读取 `omnicrawl://docs/SKILL_INSTALLATION.md`;实现细节位于 `rust/crates/omnicrawl-extensions/src/skill.rs`。
55
55
  - 本地 HTTP/SSE API 接入(启动、鉴权、接口清单、事件流):读取 `omnicrawl://docs/API.md`;实现位于 `rust/crates/omnicrawl-api/`。
@@ -63,6 +63,7 @@ omnicrawl文档(共 14 篇,均以 `omnicrawl://docs/<文件名>` 读取,
63
63
  - AI 消息脱敏(可逆占位符、匹配引擎、序号注册表、流式还原、`[desensitization]` 配置、设置面板「消息脱敏」):读取 `omnicrawl://docs/agent_gateway_desensitization_design.md`;实现位于 `rust/crates/omnicrawl-llm/src/desensitization/` 和 `rust/crates/omnicrawl-config/src/features/desensitization.rs`。
64
64
  - TTS 语音合成(Kokoro-82M ONNX CPU:配置、tts_synthesize 工具、CLI、音素化、模型下载):读取 `omnicrawl://docs/TTS.md`;实现位于 `rust/crates/omnicrawl-tts/` 和 `rust/crates/omnicrawl-config/src/features/tts.rs`。
65
65
  - 决策接口(结构化决策模型的本地 REST 服务:启动、无鉴权的回环访问、decide/choice/rank/review 端点、常驻与复用、脱敏与安全边界):读取 `omnicrawl://docs/decision_api.md`;实现位于 `rust/crates/omnicrawl-decision/` 和 `rust/crates/omnicrawl-config/src/features/decision_model.rs`。
66
+ - 抓取接口(fetcher 的本机 REST 通道:`[fetch_api]` 配置、`/v1/fetch` 端点、无鉴权回环访问、Python 批量脚本调用、与工具同源的抓取语义与安全边界):读取 `omnicrawl://docs/fetch_api.md`;实现位于 `rust/crates/omnicrawl-fetch/`、`rust/crates/omnicrawl-config/src/features/fetch_api.rs` 和 `rust/crates/omnicrawl-host/src/tools/fetcher.rs`。
66
67
  - FSAPP 接入(文件系统应用侧的接入约定):读取 `omnicrawl://docs/FSAPP.md`。
67
68
 
68
69
  脱敏占位符引用规则:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnicrawl/cli-win32-ia32",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "OmniCrawl 平台包(Windows 32 位:内核 + 完整宿主)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,6 +20,7 @@
20
20
  "omnicrawl-tui": "host/omnicrawl-tui.exe",
21
21
  "omnicrawl-api": "host/omnicrawl-api.exe",
22
22
  "omnicrawl-decision": "host/omnicrawl-decision.exe",
23
+ "omnicrawl-fetch": "host/omnicrawl-fetch.exe",
23
24
  "omnicrawl-mcp-server": "host/omnicrawl-mcp-server.exe"
24
25
  },
25
26
  "files": [
package/version.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@omnicrawl/cli-win32-ia32",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "os": "win32",
5
5
  "cpu": "ia32",
6
- "kernelVersion": "0.0.1",
7
- "hostVersion": "0.4.1",
6
+ "kernelVersion": "0.4.3",
7
+ "hostVersion": "0.4.3",
8
8
  "hostPlatform": "win32-ia32",
9
- "builtAt": "2026-10-26T08:37:18.120Z"
9
+ "builtAt": "2026-10-30T18:37:19.300Z"
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 };