agentworkshop 0.7.47 → 0.7.49

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 (42) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/builds/latest.json +1 -1
  3. package/.output/public/_nuxt/builds/meta/0530cee1-fff5-4025-a6f4-5708b6534608.json +1 -0
  4. package/.output/server/chunks/_/nitro.mjs +871 -857
  5. package/.output/server/package.json +1 -1
  6. package/README-zh.md +813 -806
  7. package/README.md +823 -816
  8. package/config.yml +176 -176
  9. package/docs/aml.md +1 -0
  10. package/docs/cli.en.md +445 -445
  11. package/docs/cli.md +410 -410
  12. package/docs/full-test-plan.md +191 -191
  13. package/docs/plugins.en.md +567 -567
  14. package/docs/plugins.md +560 -560
  15. package/docs/sdk.en.md +922 -922
  16. package/docs/sdk.md +861 -861
  17. package/package.json +172 -172
  18. package/scripts/_aw0746-stage12.mjs +4 -4
  19. package/scripts/_aw0746-stage34.mjs +6 -4
  20. package/scripts/_aw0746-stage5.mjs +159 -106
  21. package/scripts/_aw0746-stage6-aml.mjs +3 -3
  22. package/scripts/_aw0746-stage6b-train-sweep.mjs +6 -3
  23. package/scripts/_aw0746-stage6c-jobsmoke.mjs +69 -0
  24. package/scripts/_aw0746-stage7-twin.mjs +301 -259
  25. package/scripts/_aw0747-readme-rows.mjs +32 -0
  26. package/scripts/_aw0748-failclosed-probe.mjs +117 -0
  27. package/scripts/_aw0748-fresh-channel.mjs +21 -0
  28. package/scripts/_aw0748-mock-closedloop.mjs +89 -0
  29. package/scripts/_aw0748-wake-channel.mjs +46 -0
  30. package/scripts/_aw0749-readme-rows.mjs +23 -0
  31. package/scripts/_probe-lease.cjs +13 -0
  32. package/scripts/_probe-task-queue.cjs +9 -0
  33. package/server/services/workshop/aml/twin/physics-runtime.ts +16 -1
  34. package/server/services/workshop/aml/twin/provider-contracts.ts +34 -0
  35. package/server/services/workshop/aml/twin/provider-health.ts +8 -0
  36. package/server/services/workshop/aml/twin/provider-loader.ts +67 -0
  37. package/server/services/workshop/aml/twin/provider-registry.ts +50 -0
  38. package/server/services/workshop/runtime/manager/state.ts +21 -4
  39. package/.output/public/_nuxt/builds/meta/1b18aaf2-ccbc-45e0-b9c3-107655b226f9.json +0 -1
  40. package/scripts/_probe-density.cjs +0 -15
  41. package/scripts/_probe-gate-model.mjs +0 -34
  42. package/scripts/_probe-model-eligibility.cjs +0 -13
@@ -221,12 +221,18 @@ export abstract class ManagerState extends ManagerContracts {
221
221
  }
222
222
  }
223
223
 
224
+ /**
225
+ * 按需装配频道(lead 运行时 + SchedulerLoop,幂等)。实现位于装配层
226
+ * `ManagerRuntimeWiring.ensureChannelActive`;基类只声明,调用点在任务事件钩子里。
227
+ */
228
+ protected abstract ensureChannelActive(channelId: string): void
229
+
224
230
  protected getTaskEngine(): TaskEngine {
225
231
  if (!this.taskEngine) {
226
232
  const factory = this.deps.taskEngineFactory ?? (r => new TaskEngineImpl(r, {
227
233
  onTaskChange: (e) => {
228
- // 全字段转发(含 progress):TaskEngine 内部进度变化(applyEvent 分块折算 /
229
- // complete 置 100)须经总线 → WS task.progress 实时同步,否则前端实体进度滞后
234
+ // 全字段转发(含 progress):TaskEngine 内部进度变化(applyEvent 分块折算 /
235
+ // complete 置 100)须经总线 → WS task.progress 实时同步,否则前端实体进度滞后
230
236
  this.buses.get(e.channelId)?.notifyTask({
231
237
  taskId: e.taskId,
232
238
  state: e.state,
@@ -237,8 +243,19 @@ export abstract class ManagerState extends ManagerContracts {
237
243
  reassignFrom: e.reassignFrom,
238
244
  reason: e.reason,
239
245
  })
240
- // 事件驱动调度:任务状态变化即唤醒该频道调度循环(空闲退避即刻恢复快节奏)
241
- this.channels.get(e.channelId)?.scheduler?.wake()
246
+ // 事件驱动调度:任务状态变化即唤醒该频道调度循环(空闲退避即刻恢复快节奏)。
247
+ //
248
+ // ⚠️ 只 wake 不够:lead 运行时因空闲被清扫卸载后 `cr.scheduler` 会被置空
249
+ // (见 runtime-wiring.attachScheduler 注释),此后新建的根任务只落库,
250
+ // `scheduler?.wake()` 变成空操作 —— 任务永久停在 SUBMITTED,直到
251
+ // ROOT_TIMEOUT(~18 分钟)被判 FAILED(实测复现:mock Channel 第一条根任务
252
+ // COMPLETED,后续两条一直 SUBMITTED;omp Channel 同样如此)。
253
+ // `reviveScheduler` 只在"lead 正在被装配"的窗口里被调用,没有别的事件会重建
254
+ // 调度循环,所以这里补上**重新挂载**的分支:没有 scheduler 就按需装配 lead +
255
+ // 调度循环(ensureChannelActive 幂等;频道停用/无 lead 时内部直接返回)。
256
+ const cr = this.channels.get(e.channelId)
257
+ if (cr?.scheduler) cr.scheduler.wake()
258
+ else if (e.state === 'SUBMITTED' || e.state === 'ASSIGNED') ((this as unknown) as { ensureChannelActive: (channelId: string) => void }).ensureChannelActive(e.channelId)
242
259
  },
243
260
  }))
244
261
  this.taskEngine = factory({ tasks: this.deps.repos.tasks, messages: this.deps.repos.messages })
@@ -1 +0,0 @@
1
- {"id":"1b18aaf2-ccbc-45e0-b9c3-107655b226f9","timestamp":1790321904277,"prerendered":[]}
@@ -1,15 +0,0 @@
1
- /** 临时:探测 daq_samples 采样密度(评估 AML beatMs 可下调空间) */
2
- const { Client } = require('pg')
3
- ;(async () => {
4
- const c = new Client({ host: '127.0.0.1', port: 5432, user: 'postgres', password: 'awshop', database: 'awshop' })
5
- await c.connect()
6
- const q = (sql) => c.query(sql).then(r => r.rows)
7
- const rows = await q(`select node_id, count(*)::int n, min(ts) a, max(ts) b,
8
- round(extract(epoch from (max(ts)-min(ts)))/greatest(count(*)-1,1),2) avg_gap_s
9
- from daq_samples where ts > now() - interval '45 minutes'
10
- group by node_id order by n desc limit 12`)
11
- console.table(rows)
12
- const t = await q(`select count(*)::int total, count(distinct node_id)::int nodes from daq_samples where ts > now() - interval '45 minutes'`)
13
- console.log('total', t)
14
- await c.end()
15
- })().catch(e => { console.error(e.message); process.exit(1) })
@@ -1,34 +0,0 @@
1
- /** 临时:看 twin_gate_evaluate 的 modelUpdate 尾部 + 最近作业来源 */
2
- import { DatabaseSync } from 'node:sqlite'
3
- const BASE = 'http://127.0.0.1:3001'
4
- const ADMIN = { email: 'admin@awshop.local', password: 'Awshop@123!' }
5
-
6
- const j = async (method, path, body, token) => {
7
- const r = await fetch(BASE + path, { method, headers: { 'content-type': 'application/json', ...(token ? { authorization: `Bearer ${token}` } : {}) }, body: body === undefined ? undefined : JSON.stringify(body) })
8
- return { status: r.status, ...(await r.json().catch(() => ({}))) }
9
- }
10
- const token = (await j('POST', '/api/users/login', ADMIN)).data?.token
11
- const chans = (await j('GET', '/api/workshop/channels', undefined, token)).data ?? []
12
- const twin = chans.find(c => /闭环优化-hybridtwin/.test(c.name))
13
- const members = (await j('GET', `/api/workshop/channels/${twin.id}/agents`, undefined, token)).data ?? []
14
- const lead = members.find(m => m.role === 'lead')
15
- const models = ((await j('GET', '/api/workshop/aml/models', undefined, token)).data?.models ?? [])
16
- const prod = models.find(m => m.stage === 'production')
17
- console.log('production model =', prod?.id, 'ds =', prod?.datasetId)
18
-
19
- const res = await j('POST', '/api/workshop/agent-tools/invoke', {
20
- agentId: lead.id,
21
- tool: 'twin_gate_evaluate',
22
- args: { rows: 1724, runs: 10, one_step_nrmse: 0.0763, rollout_nrmse: 0.0964, val_test_gap: 0.1072, calibration_rows: 1724, coverage: 1, candidate_trials: [], physics_failure_rate: 0, model_id: prod?.id ?? '' },
23
- }, token)
24
- const text = String(res.data?.result?.text ?? '')
25
- const tail = text.slice(-700)
26
- console.log('--- gate tail ---')
27
- console.log(tail)
28
- console.log('--- parsed keys ---', Object.keys(JSON.parse(text)).join(','))
29
-
30
- const db = new DatabaseSync('D:/codes/ABO/AgentWorkShop/.aw0746-home/data/workshop.sqlite', { readOnly: true })
31
- const cols = db.prepare('pragma table_info(aml_jobs)').all().map(c => c.name)
32
- console.log('\naml_jobs columns:', cols.join(','))
33
- const pick = ['id', 'status', 'kind', 'created_by', 'change_note', 'created_at'].filter(c => cols.includes(c))
34
- for (const r of db.prepare(`select ${pick.join(',')} from aml_jobs order by created_at desc limit 6`).all()) console.log(' ', JSON.stringify(r).slice(0, 220))
@@ -1,13 +0,0 @@
1
- /** 临时:检查 AML 模型 metrics_json 里的 twinEligibility 是否回写 */
2
- const { DatabaseSync } = require('node:sqlite')
3
- const db = new DatabaseSync('D:/codes/ABO/AgentWorkShop/.aw0746-home/data/workshop.sqlite', { readOnly: true })
4
- const rows = db.prepare('select id, stage, dataset_id, experiment_id, metrics_json from aml_models order by created_at desc limit 4').all()
5
- for (const r of rows) {
6
- let m = {}
7
- try { m = JSON.parse(r.metrics_json || '{}') } catch { m = { parse: 'fail' } }
8
- console.log(`${r.id} stage=${r.stage} ds=${r.dataset_id} exp=${r.experiment_id}`)
9
- console.log(` twinEligibility=${JSON.stringify(m.twinEligibility ?? null)} oneStep=${m.oneStepTest?.nrmse}`)
10
- }
11
- const jobs = db.prepare('select id, status, created_by_kind, created_by, substr(change_note,1,60) note, created_at from aml_jobs order by created_at desc limit 6').all()
12
- console.log('\njobs:')
13
- for (const j of jobs) console.log(` ${j.id} ${j.status} by=${j.created_by_kind}/${j.created_by} ${j.created_at} ${j.note}`)