@jack200714/mafw 4.5.2 → 4.10.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.
Files changed (37) hide show
  1. package/README.md +27 -3
  2. package/gateway/dist/core/manager/goal-snapshot.js +2 -2
  3. package/gateway/dist/core/manager/manager-session-runtime.js +59 -0
  4. package/gateway/dist/core/manager/milestone-push.js +25 -10
  5. package/gateway/dist/index.js +315 -139
  6. package/gateway/dist/media/media-plugin-loader.js +25 -13
  7. package/gateway/dist/media/resolve-prompt.js +20 -0
  8. package/gateway/dist/memory/gateway-db.js +23 -0
  9. package/gateway/dist/opencode-adapter.js +34 -0
  10. package/gateway/dist/plugins/hub.js +153 -19
  11. package/gateway/dist/plugins/package-context.js +24 -0
  12. package/gateway/dist/plugins/package-host.js +331 -0
  13. package/gateway/dist/plugins/package-types.js +2 -0
  14. package/gateway/dist/recall/gateway-db-migrate.js +5 -2
  15. package/gateway/dist/recall/redact.js +53 -0
  16. package/gateway/dist/recall/turn-pipeline.js +2 -0
  17. package/gateway/dist/routes/event-publish.js +44 -0
  18. package/gateway/dist/routes/plugins.js +19 -6
  19. package/gateway/dist/routes/waitwhat-command.js +43 -0
  20. package/gateway/dist/runtime/contract.js +4 -1
  21. package/gateway/dist/runtime/event-broadcast.js +41 -0
  22. package/gateway/dist/runtime/loader.js +45 -14
  23. package/gateway/dist/runtime/normalize.js +13 -0
  24. package/gateway/dist/runtime/pi/pi-approval-bridge.js +12 -2
  25. package/gateway/dist/runtime/pi/pi-approval-extension.js +11 -3
  26. package/gateway/dist/runtime/pi/pi-session.js +21 -3
  27. package/gateway/dist/runtime/plugins/pi-runtime.js +6 -3
  28. package/gateway/dist/runtime/serve-sidecar.js +4 -1
  29. package/gateway/dist/runtime/serve-supervisor.js +12 -0
  30. package/gateway/dist/runtime/validate.js +39 -0
  31. package/gateway/dist/skills/manager-identity.js +6 -1
  32. package/gateway/dist/usage/builtin-plugins/gateway.js +103 -26
  33. package/gateway/dist/usage/plugin-context.js +42 -2
  34. package/gateway/dist/usage/plugin-loader.js +32 -13
  35. package/gateway/package.json +2 -2
  36. package/package.json +3 -1
  37. package/packages/tui/dist/cli.js +28 -5
@@ -74,6 +74,7 @@ class PluginLoader {
74
74
  builtinNames;
75
75
  usageStats;
76
76
  resolveInlineApiKey;
77
+ packageEntries = [];
77
78
  constructor(pluginsDir, builtinNames, opts) {
78
79
  this.pluginsDir = pluginsDir;
79
80
  this.builtinNames = new Set(builtinNames);
@@ -91,7 +92,6 @@ class PluginLoader {
91
92
  if (!fs.existsSync(this.pluginsDir)) {
92
93
  fs.mkdirSync(this.pluginsDir, { recursive: true });
93
94
  fs.writeFileSync(path.join(this.pluginsDir, 'README.md'), README_CONTENT);
94
- fs.writeFileSync(path.join(this.pluginsDir, 'example.js.disabled'), EXAMPLE_CONTENT);
95
95
  logger_1.log.info(`[PluginLoader] Created ${this.pluginsDir}`);
96
96
  }
97
97
  }
@@ -174,18 +174,47 @@ class PluginLoader {
174
174
  this.builtinNames = builtinNameSet;
175
175
  }
176
176
  getAdapters() {
177
+ const packageNames = new Set(this.packageEntries.map((e) => e.mod.name));
177
178
  const adapters = [];
178
179
  for (const s of this.state.values()) {
179
- if (s.status === 'ok' && s.adapter && !s.disabled)
180
+ if (s.status === 'ok' && s.adapter && !s.disabled && !packageNames.has(s.name))
180
181
  adapters.push(s.adapter);
181
182
  }
183
+ for (const e of this.packageEntries) {
184
+ if (this.disabledPlugins.has(e.mod.name))
185
+ continue;
186
+ adapters.push((0, plugin_context_1.makeAdapter)(e.mod, e.source, this.usageStats, this.resolveInlineApiKey));
187
+ }
182
188
  return adapters;
183
189
  }
184
190
  isBuiltinName(name) {
185
191
  return this.builtinNames.has(name);
186
192
  }
187
193
  getState() {
188
- return [...this.state.values()];
194
+ const out = [...this.state.values()].map((s) => ({ ...s }));
195
+ const packageNames = new Set(this.packageEntries.map((e) => e.mod.name));
196
+ for (const s of out) {
197
+ if (s.name && packageNames.has(s.name))
198
+ s.overridden = true;
199
+ }
200
+ for (const e of this.packageEntries) {
201
+ out.push({
202
+ file: e.source,
203
+ name: e.mod.name,
204
+ status: 'ok',
205
+ overridden: false,
206
+ builtin: false,
207
+ adapter: undefined,
208
+ configSchema: validateConfigSchema(e.mod.configSchema),
209
+ disabled: this.disabledPlugins.has(e.mod.name),
210
+ pluginType: typeof e.mod.type === 'string' ? e.mod.type : undefined,
211
+ });
212
+ }
213
+ return out;
214
+ }
215
+ /** PluginHost 推送的包贡献。同名包覆盖 legacy 文件与内置;disabledPlugins 同样生效。 */
216
+ setPackageEntries(entries) {
217
+ this.packageEntries = entries ?? [];
189
218
  }
190
219
  async reload() {
191
220
  await this.scan();
@@ -268,13 +297,3 @@ Return \`null\` to hide provider. Builtin plugins live in the package
268
297
  \`dist/usage/builtin-plugins/\`; drop a file with the same \`name\` here to override,
269
298
  or add the name to \`usage.disabledPlugins\` in config to disable.
270
299
  `;
271
- const EXAMPLE_CONTENT = `// Rename to example.js to activate
272
- module.exports = {
273
- name: "example",
274
- type: "api",
275
- plan: "Example Plan",
276
- async fetch(ctx) {
277
- return null; // Hide provider
278
- },
279
- };
280
- `;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mafw-gateway",
3
- "version": "5.0.0",
4
- "description": "MAFW Gateway v5.0 — SSE Event-Driven Scheduler",
3
+ "version": "4.10.0",
4
+ "description": "MAFW Gateway v5.0 —SSE Event-Driven Scheduler",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
7
7
  "build": "tsc && node -e \"const fs=require('fs'),p=require('path');const cp=(s,d)=>{if(fs.existsSync(s)){fs.cpSync(s,d,{recursive:true});console.log('[copy] '+d)}else{console.log('[skip] '+s)};};cp(p.join(__dirname,'src','dashboard','public'),p.join(__dirname,'dist','dashboard','public'));cp(p.join(__dirname,'src','tray','tray.ps1'),p.join(__dirname,'dist','tray','tray.ps1'));cp(p.join(__dirname,'src','usage','builtin-plugins'),p.join(__dirname,'dist','usage','builtin-plugins'));\"",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jack200714/mafw",
3
- "version": "4.5.2",
3
+ "version": "4.10.1",
4
4
  "description": "MAFW Loop Agent Plugin for OpenCode - Phase Relay + TMEM + Dynamic Compression",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,6 +14,8 @@
14
14
  "postinstall": "node -e \"var p=require('path'),f=require('fs'),d=p.join(__dirname,'gateway'),ts=p.join(d,'node_modules','typescript','bin','tsc');if(f.existsSync(d)){if(f.existsSync(ts)){console.log('[mafw] gateway dev deps present, skip prod install')}else{require('child_process').execSync('npm install --omit=dev --no-audit --no-fund --loglevel=error',{cwd:d,stdio:'inherit'})}}\"",
15
15
  "prepare": "node -e \"var p=require('path'),f=require('fs'),ts=p.join(__dirname,'gateway','node_modules','typescript','bin','tsc');if(!f.existsSync(ts)){console.log('[mafw] gateway dev deps missing, skip prepare build (fresh CI install)');process.exit(0)}require('child_process').execSync('npm run build',{cwd:__dirname,stdio:'inherit'})\"",
16
16
  "pack:install": "npm run build && npm pack && npm install -g jack200714-mafw-*.tgz && mafw version",
17
+ "version:set": "node scripts/bump-version.mjs",
18
+ "version:check": "node scripts/bump-version.mjs --check",
17
19
  "test": "npm test --prefix gateway",
18
20
  "test:unit": "npm test --prefix gateway",
19
21
  "test:tui": "node --test packages/tui/tests/*.test.ts"
@@ -380,7 +380,7 @@ var require_client = __commonJS({
380
380
  return { id: data.projectDir || ".", worktree: data.projectDir || "." };
381
381
  },
382
382
  setCurrent: async (path) => {
383
- await this.request("/api/projects/register", {
383
+ await this.request("/register", {
384
384
  method: "POST",
385
385
  body: JSON.stringify({ projectDir: path, mafwDir: path + "/.mafw" })
386
386
  });
@@ -413,7 +413,14 @@ var require_client = __commonJS({
413
413
  };
414
414
  },
415
415
  /** SSE 连接状态(onopen/onerror 维护;供监督器健康轮询)。 */
416
- connected: () => this._sse.connected
416
+ connected: () => this._sse.connected,
417
+ /** 发布自定义事件到全部 UI 通道(SSE/WS/推送)。type 建议命名空间
418
+ * 'plugin:<name>:<event>';消费方对未知 type 忽略(SSE 通知语义,无注册制)。 */
419
+ publish: async (event) => this.request("/api/events", {
420
+ method: "POST",
421
+ headers: { "Content-Type": "application/json" },
422
+ body: JSON.stringify(event)
423
+ })
417
424
  };
418
425
  // ── Runtime ──
419
426
  runtime = {
@@ -455,10 +462,15 @@ var require_client = __commonJS({
455
462
  plugins = {
456
463
  list: async () => this.request("/api/plugins"),
457
464
  install: async (input) => {
458
- const res = await this.fetchImpl(`${this.baseUrl}/api/plugins/install`, {
465
+ const params = new URLSearchParams({ filename: input.filename });
466
+ if (input.type)
467
+ params.set("type", input.type);
468
+ if (input.overwrite)
469
+ params.set("overwrite", "1");
470
+ const res = await this.fetchImpl(`${this.baseUrl}/api/plugins/install?${params.toString()}`, {
459
471
  method: "POST",
460
- headers: { "Content-Type": "application/json" },
461
- body: JSON.stringify({ ...input, overwrite: !!input.overwrite })
472
+ headers: { "Content-Type": "application/octet-stream" },
473
+ body: input.bytes
462
474
  });
463
475
  if (!res.ok) {
464
476
  const body = await res.json().catch(() => ({}));
@@ -1826,6 +1838,7 @@ var init_command_registry = __esm({
1826
1838
  { name: "status", description: "\u4F1A\u8BDD\u72B6\u6001\u56DE\u987E\uFF08\u672C\u5730\u8BA1\u7B97\uFF09", category: "\u4F1A\u8BDD", immediate: true },
1827
1839
  { name: "queue", description: "\u6392\u961F\u6D88\u606F\u7BA1\u7406\uFF08\u6536\u56DE/\u4E22\u5F03\uFF09", category: "\u4F1A\u8BDD", aliases: ["q"], immediate: true },
1828
1840
  { name: "btw", description: "\u652F\u7EBF\u95EE\u7B54\uFF1A/btw <\u95EE\u9898>", category: "\u4F1A\u8BDD" },
1841
+ { name: "waitwhat", description: "\u6CA1\u542C\u61C2\uFF1A\u7528\u7B80\u660E\u8BED\u8A00+\u9879\u76EE\u672F\u8BED\u91CD\u8FF0\u4E0A\u4E00\u6761\u56DE\u590D", category: "\u4F1A\u8BDD", immediate: true },
1829
1842
  { name: "compact", description: "\u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u4E0A\u4E0B\u6587", category: "\u4E0A\u4E0B\u6587", destructive: true, immediate: true },
1830
1843
  { name: "undo", description: "\u56DE\u9000\u6700\u540E\u4E00\u8F6E\u5BF9\u8BDD", category: "\u4E0A\u4E0B\u6587", destructive: true },
1831
1844
  { name: "redo", description: "\u6062\u590D\u4E0A\u4E00\u6B21\u56DE\u9000", category: "\u4E0A\u4E0B\u6587", destructive: true },
@@ -2160,6 +2173,8 @@ function createSlashHandler(deps) {
2160
2173
  case "status":
2161
2174
  deps.showStatusRecap();
2162
2175
  return null;
2176
+ case "waitwhat":
2177
+ return deps.waitwhat();
2163
2178
  case "queue":
2164
2179
  await deps.showQueueManager();
2165
2180
  return null;
@@ -3916,6 +3931,14 @@ async function runApp(opts) {
3916
3931
  if ("error" in r) return `btw \u5931\u8D25: ${r.error}`;
3917
3932
  return null;
3918
3933
  },
3934
+ waitwhat: async () => {
3935
+ const sid = chatStore.sessionID;
3936
+ if (!sid) return "\u5F53\u524D\u65E0\u4F1A\u8BDD";
3937
+ const r = await client.mafwCommands.run({ command: "waitwhat", sessionID: sid }).catch((e) => ({ error: e.message }));
3938
+ if ("error" in r) return `waitwhat \u5931\u8D25: ${r.error}`;
3939
+ if (r.ok === false) return `waitwhat: ${r.error ?? "\u6CA1\u6709\u53EF\u91CD\u8FF0\u7684\u56DE\u590D"}`;
3940
+ return null;
3941
+ },
3919
3942
  showSessionPicker,
3920
3943
  showQueueManager,
3921
3944
  showModelPicker,