agentworkshop 0.2.1 → 0.3.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 (34) hide show
  1. package/app/plugins/aw-plugins.client.ts +79 -0
  2. package/cli/commands/plugin.mjs +169 -0
  3. package/cli/commands/update.mjs +12 -4
  4. package/docs/plugins.md +127 -0
  5. package/package.json +19 -2
  6. package/scripts/dev-guard.mjs +13 -0
  7. package/scripts/home-bootstrap.mjs +25 -1
  8. package/sdk/api.mjs +101 -0
  9. package/sdk/client.mjs +120 -0
  10. package/sdk/context.mjs +219 -0
  11. package/sdk/examples/sample-insight/client.mjs +23 -0
  12. package/sdk/examples/sample-insight/index.mjs +39 -0
  13. package/sdk/hooks.mjs +103 -0
  14. package/sdk/index.d.mts +135 -0
  15. package/sdk/index.mjs +41 -0
  16. package/sdk/lifecycle.mjs +25 -0
  17. package/server/api/plugins/[name]/[...path].ts +22 -0
  18. package/server/api/plugins/client/[name].get.ts +18 -0
  19. package/server/api/plugins/manifest.get.ts +10 -0
  20. package/server/api/workshop/dcw/lines/[id]/start.post.ts +2 -0
  21. package/server/api/workshop/dcw/lines/[id]/stop.post.ts +2 -0
  22. package/server/data/daqs.json +347 -61
  23. package/server/data/dcw-lines.json +91 -0
  24. package/server/data/dcw-products.json +77 -0
  25. package/server/data/dcw-recipes.json +220 -0
  26. package/server/data/dcw-rollback.json +1 -1
  27. package/server/data/dcw-runs.json +275 -198
  28. package/server/data/dcws.json +231 -0
  29. package/server/data/line-runs.json +74 -14
  30. package/server/plugins/aw-plugins.ts +24 -0
  31. package/server/services/workshop/daq/daq-controller.ts +6 -2
  32. package/server/services/workshop/dcw/dcw-controller.ts +3 -0
  33. package/server/services/workshop/plugins/host.mjs +289 -0
  34. package/server/services/workshop/scene-events.ts +3 -0
@@ -1732,5 +1732,236 @@
1732
1732
  "state": "ok",
1733
1733
  "lastError": null,
1734
1734
  "createdAt": "2026-09-01T12:27:14.362Z"
1735
+ },
1736
+ {
1737
+ "id": "dw-be292513",
1738
+ "templateRef": "temp-sp",
1739
+ "name": "温控",
1740
+ "driver": "mock",
1741
+ "enabled": true,
1742
+ "holdIntervalMs": null,
1743
+ "unit": "℃",
1744
+ "decimals": 1,
1745
+ "min": 150,
1746
+ "max": 200,
1747
+ "deviceBindingId": null,
1748
+ "driverConfig": {},
1749
+ "lineId": "ln-6e75316a",
1750
+ "value": null,
1751
+ "lastAckAt": null,
1752
+ "lastWriteAt": null,
1753
+ "state": "idle",
1754
+ "lastError": null,
1755
+ "createdAt": "2026-09-02T03:30:56.130Z"
1756
+ },
1757
+ {
1758
+ "id": "dw-488fdd91",
1759
+ "templateRef": "temp-sp",
1760
+ "name": "温控",
1761
+ "driver": "mock",
1762
+ "enabled": true,
1763
+ "holdIntervalMs": null,
1764
+ "unit": "℃",
1765
+ "decimals": 1,
1766
+ "min": 150,
1767
+ "max": 200,
1768
+ "deviceBindingId": null,
1769
+ "driverConfig": {},
1770
+ "lineId": "ln-e2d8aebc",
1771
+ "value": null,
1772
+ "lastAckAt": null,
1773
+ "lastWriteAt": null,
1774
+ "state": "idle",
1775
+ "lastError": null,
1776
+ "createdAt": "2026-09-02T03:34:13.100Z"
1777
+ },
1778
+ {
1779
+ "id": "dw-b98f94d2",
1780
+ "templateRef": "temp-sp",
1781
+ "name": "温控",
1782
+ "driver": "mock",
1783
+ "enabled": true,
1784
+ "holdIntervalMs": null,
1785
+ "unit": "℃",
1786
+ "decimals": 1,
1787
+ "min": 150,
1788
+ "max": 200,
1789
+ "deviceBindingId": null,
1790
+ "driverConfig": {},
1791
+ "lineId": "ln-4849768e",
1792
+ "value": null,
1793
+ "lastAckAt": null,
1794
+ "lastWriteAt": null,
1795
+ "state": "idle",
1796
+ "lastError": null,
1797
+ "createdAt": "2026-09-02T03:36:45.499Z"
1798
+ },
1799
+ {
1800
+ "id": "dw-093215e8",
1801
+ "templateRef": "temp-sp",
1802
+ "name": "温控",
1803
+ "driver": "mock",
1804
+ "enabled": true,
1805
+ "holdIntervalMs": null,
1806
+ "unit": "℃",
1807
+ "decimals": 1,
1808
+ "min": 150,
1809
+ "max": 200,
1810
+ "deviceBindingId": null,
1811
+ "driverConfig": {},
1812
+ "lineId": "ln-e0769d5b",
1813
+ "value": null,
1814
+ "lastAckAt": null,
1815
+ "lastWriteAt": null,
1816
+ "state": "idle",
1817
+ "lastError": null,
1818
+ "createdAt": "2026-09-02T03:39:43.737Z"
1819
+ },
1820
+ {
1821
+ "id": "dw-4b8064da",
1822
+ "templateRef": "temp-sp",
1823
+ "name": "温控",
1824
+ "driver": "mock",
1825
+ "enabled": true,
1826
+ "holdIntervalMs": null,
1827
+ "unit": "℃",
1828
+ "decimals": 1,
1829
+ "min": 150,
1830
+ "max": 200,
1831
+ "deviceBindingId": null,
1832
+ "driverConfig": {},
1833
+ "lineId": "ln-8c17f4e7",
1834
+ "value": null,
1835
+ "lastAckAt": null,
1836
+ "lastWriteAt": null,
1837
+ "state": "idle",
1838
+ "lastError": null,
1839
+ "createdAt": "2026-09-02T03:42:11.685Z"
1840
+ },
1841
+ {
1842
+ "id": "dw-3c7b50c0",
1843
+ "templateRef": "temp-sp",
1844
+ "name": "温控",
1845
+ "driver": "mock",
1846
+ "enabled": true,
1847
+ "holdIntervalMs": null,
1848
+ "unit": "℃",
1849
+ "decimals": 1,
1850
+ "min": 150,
1851
+ "max": 200,
1852
+ "deviceBindingId": null,
1853
+ "driverConfig": {},
1854
+ "lineId": "ln-0eccf6ba",
1855
+ "value": null,
1856
+ "lastAckAt": null,
1857
+ "lastWriteAt": null,
1858
+ "state": "idle",
1859
+ "lastError": null,
1860
+ "createdAt": "2026-09-02T04:09:11.392Z"
1861
+ },
1862
+ {
1863
+ "id": "dw-ce326742",
1864
+ "templateRef": "temp-sp",
1865
+ "name": "温控",
1866
+ "driver": "mock",
1867
+ "enabled": true,
1868
+ "holdIntervalMs": null,
1869
+ "unit": "℃",
1870
+ "decimals": 1,
1871
+ "min": 150,
1872
+ "max": 200,
1873
+ "deviceBindingId": null,
1874
+ "driverConfig": {},
1875
+ "lineId": "ln-e984246e",
1876
+ "value": null,
1877
+ "lastAckAt": null,
1878
+ "lastWriteAt": null,
1879
+ "state": "idle",
1880
+ "lastError": null,
1881
+ "createdAt": "2026-09-02T04:11:25.307Z"
1882
+ },
1883
+ {
1884
+ "id": "dw-9b40d8d6",
1885
+ "templateRef": "temp-sp",
1886
+ "name": "温控",
1887
+ "driver": "mock",
1888
+ "enabled": true,
1889
+ "holdIntervalMs": null,
1890
+ "unit": "℃",
1891
+ "decimals": 1,
1892
+ "min": 150,
1893
+ "max": 200,
1894
+ "deviceBindingId": null,
1895
+ "driverConfig": {},
1896
+ "lineId": "ln-1fe0b5bc",
1897
+ "value": null,
1898
+ "lastAckAt": null,
1899
+ "lastWriteAt": null,
1900
+ "state": "idle",
1901
+ "lastError": null,
1902
+ "createdAt": "2026-09-02T04:13:16.679Z"
1903
+ },
1904
+ {
1905
+ "id": "dw-1596b290",
1906
+ "templateRef": "temp-sp",
1907
+ "name": "温控",
1908
+ "driver": "mock",
1909
+ "enabled": true,
1910
+ "holdIntervalMs": null,
1911
+ "unit": "℃",
1912
+ "decimals": 1,
1913
+ "min": 150,
1914
+ "max": 200,
1915
+ "deviceBindingId": null,
1916
+ "driverConfig": {},
1917
+ "lineId": "ln-d826473e",
1918
+ "value": null,
1919
+ "lastAckAt": null,
1920
+ "lastWriteAt": null,
1921
+ "state": "idle",
1922
+ "lastError": null,
1923
+ "createdAt": "2026-09-02T04:16:58.668Z"
1924
+ },
1925
+ {
1926
+ "id": "dw-9e3a958a",
1927
+ "templateRef": "temp-sp",
1928
+ "name": "温控",
1929
+ "driver": "mock",
1930
+ "enabled": true,
1931
+ "holdIntervalMs": null,
1932
+ "unit": "℃",
1933
+ "decimals": 1,
1934
+ "min": 150,
1935
+ "max": 200,
1936
+ "deviceBindingId": null,
1937
+ "driverConfig": {},
1938
+ "lineId": "ln-156abb71",
1939
+ "value": null,
1940
+ "lastAckAt": null,
1941
+ "lastWriteAt": null,
1942
+ "state": "idle",
1943
+ "lastError": null,
1944
+ "createdAt": "2026-09-02T04:18:28.100Z"
1945
+ },
1946
+ {
1947
+ "id": "dw-a2e1ca20",
1948
+ "templateRef": "temp-sp",
1949
+ "name": "温控",
1950
+ "driver": "mock",
1951
+ "enabled": true,
1952
+ "holdIntervalMs": null,
1953
+ "unit": "℃",
1954
+ "decimals": 1,
1955
+ "min": 150,
1956
+ "max": 200,
1957
+ "deviceBindingId": null,
1958
+ "driverConfig": {},
1959
+ "lineId": "ln-bac43927",
1960
+ "value": null,
1961
+ "lastAckAt": null,
1962
+ "lastWriteAt": null,
1963
+ "state": "idle",
1964
+ "lastError": null,
1965
+ "createdAt": "2026-09-02T04:20:58.320Z"
1735
1966
  }
1736
1967
  ]
@@ -7,7 +7,7 @@
7
7
  "productId": "pd-3ad54846",
8
8
  "productName": "光学膜 BOPP",
9
9
  "startedAt": "2026-08-31T16:20:13.707Z",
10
- "taggedSamples": 28822
10
+ "taggedSamples": 29764
11
11
  },
12
12
  {
13
13
  "lineId": "ln-c377a6bf",
@@ -17,7 +17,7 @@
17
17
  "productId": "pd-7e69e0ee",
18
18
  "productName": "警告验证产品-k2xh",
19
19
  "startedAt": "2026-09-01T03:23:18.233Z",
20
- "taggedSamples": 11221
20
+ "taggedSamples": 11692
21
21
  },
22
22
  {
23
23
  "lineId": "ln-9224d3d7",
@@ -27,7 +27,7 @@
27
27
  "productId": "pd-910c0fa8",
28
28
  "productName": "新协议产品-9xhn",
29
29
  "startedAt": "2026-09-01T05:59:24.062Z",
30
- "taggedSamples": 14198
30
+ "taggedSamples": 14665
31
31
  },
32
32
  {
33
33
  "lineId": "ln-386c53ed",
@@ -37,7 +37,7 @@
37
37
  "productId": "pd-2d4f9357",
38
38
  "productName": "新协议产品-6ofk",
39
39
  "startedAt": "2026-09-01T06:05:53.063Z",
40
- "taggedSamples": 14488
40
+ "taggedSamples": 14955
41
41
  },
42
42
  {
43
43
  "lineId": "ln-5957f6db",
@@ -47,7 +47,7 @@
47
47
  "productId": "pd-a3ed5047",
48
48
  "productName": "新协议产品-x4hd",
49
49
  "startedAt": "2026-09-01T06:09:02.148Z",
50
- "taggedSamples": 14074
50
+ "taggedSamples": 14541
51
51
  },
52
52
  {
53
53
  "lineId": "ln-9ec42f08",
@@ -57,7 +57,7 @@
57
57
  "productId": "pd-5de729c0",
58
58
  "productName": "新协议产品-teti",
59
59
  "startedAt": "2026-09-01T06:13:44.315Z",
60
- "taggedSamples": 14053
60
+ "taggedSamples": 14520
61
61
  },
62
62
  {
63
63
  "lineId": "ln-69e37924",
@@ -67,7 +67,7 @@
67
67
  "productId": "pd-45eb8d43",
68
68
  "productName": "新协议产品-fg8t",
69
69
  "startedAt": "2026-09-01T06:16:47.469Z",
70
- "taggedSamples": 14086
70
+ "taggedSamples": 14553
71
71
  },
72
72
  {
73
73
  "lineId": "ln-c269e692",
@@ -77,7 +77,7 @@
77
77
  "productId": "pd-b3bd0191",
78
78
  "productName": "新协议产品-w2sp",
79
79
  "startedAt": "2026-09-01T06:56:05.893Z",
80
- "taggedSamples": 14137
80
+ "taggedSamples": 14604
81
81
  },
82
82
  {
83
83
  "lineId": "ln-229d1637",
@@ -87,7 +87,7 @@
87
87
  "productId": "pd-06b896f9",
88
88
  "productName": "新协议产品-lp4h",
89
89
  "startedAt": "2026-09-01T06:57:29.288Z",
90
- "taggedSamples": 14009
90
+ "taggedSamples": 14476
91
91
  },
92
92
  {
93
93
  "lineId": "ln-9546f91f",
@@ -97,7 +97,7 @@
97
97
  "productId": "pd-53e55078",
98
98
  "productName": "新协议产品-jri6",
99
99
  "startedAt": "2026-09-01T07:00:25.059Z",
100
- "taggedSamples": 13432
100
+ "taggedSamples": 13899
101
101
  },
102
102
  {
103
103
  "lineId": "ln-087aad5b",
@@ -107,7 +107,7 @@
107
107
  "productId": "pd-e7e969af",
108
108
  "productName": "新协议产品-4c2d",
109
109
  "startedAt": "2026-09-01T07:09:07.307Z",
110
- "taggedSamples": 12423
110
+ "taggedSamples": 12890
111
111
  },
112
112
  {
113
113
  "lineId": "ln-97d44f8a",
@@ -117,7 +117,7 @@
117
117
  "productId": "pd-28a3ab2c",
118
118
  "productName": "新协议产品-b2ni",
119
119
  "startedAt": "2026-09-01T07:13:44.912Z",
120
- "taggedSamples": 12272
120
+ "taggedSamples": 12739
121
121
  },
122
122
  {
123
123
  "lineId": "ln-a9551770",
@@ -127,7 +127,7 @@
127
127
  "productId": "pd-0c6a64c8",
128
128
  "productName": "新协议产品-uwkf",
129
129
  "startedAt": "2026-09-01T07:15:40.113Z",
130
- "taggedSamples": 11917
130
+ "taggedSamples": 12384
131
131
  },
132
132
  {
133
133
  "lineId": "ln-844ad82f",
@@ -137,7 +137,7 @@
137
137
  "productId": "pd-6932b24f",
138
138
  "productName": "新协议产品-kk6l",
139
139
  "startedAt": "2026-09-01T09:06:55.728Z",
140
- "taggedSamples": 10072
140
+ "taggedSamples": 10539
141
141
  },
142
142
  {
143
143
  "lineId": "ln-af002514",
@@ -147,6 +147,66 @@
147
147
  "productId": "pd-6348a595",
148
148
  "productName": "0.8mm 光学膜",
149
149
  "startedAt": "2026-09-01T14:06:28.766Z",
150
+ "taggedSamples": 952
151
+ },
152
+ {
153
+ "lineId": "ln-0eccf6ba",
154
+ "runId": "rr-4e0a115f",
155
+ "recipeId": "rc-8a60518e",
156
+ "recipeName": "哨兵配方-mtjku36w",
157
+ "productId": "pd-4b71be77",
158
+ "productName": "哨兵产品-mtjku36w",
159
+ "startedAt": "2026-09-02T04:09:11.482Z",
160
+ "taggedSamples": 5
161
+ },
162
+ {
163
+ "lineId": "ln-e984246e",
164
+ "runId": "rr-39b3edda",
165
+ "recipeId": "rc-70f39a03",
166
+ "recipeName": "配方C-mtjkwyhu",
167
+ "productId": "pd-bb1e0bed",
168
+ "productName": "产品C-mtjkwyhu",
169
+ "startedAt": "2026-09-02T04:11:26.583Z",
170
+ "taggedSamples": 4
171
+ },
172
+ {
173
+ "lineId": "ln-1fe0b5bc",
174
+ "runId": "rr-2baf5f34",
175
+ "recipeId": "rc-25081a45",
176
+ "recipeName": "配方D-mtjkzcfr",
177
+ "productId": "pd-9f2d9507",
178
+ "productName": "产品D-mtjkzcfr",
179
+ "startedAt": "2026-09-02T04:13:17.902Z",
180
+ "taggedSamples": 3
181
+ },
182
+ {
183
+ "lineId": "ln-d826473e",
184
+ "runId": "rr-7585cef0",
185
+ "recipeId": "rc-3ebd1a97",
186
+ "recipeName": "配方E-mtjl43pv",
187
+ "productId": "pd-d230255e",
188
+ "productName": "产品E-mtjl43pv",
189
+ "startedAt": "2026-09-02T04:16:59.891Z",
190
+ "taggedSamples": 2
191
+ },
192
+ {
193
+ "lineId": "ln-156abb71",
194
+ "runId": "rr-d8002452",
195
+ "recipeId": "rc-fce9474f",
196
+ "recipeName": "配方F-mtjl60qf",
197
+ "productId": "pd-6065b4ba",
198
+ "productName": "产品F-mtjl60qf",
199
+ "startedAt": "2026-09-02T04:18:29.340Z",
200
+ "taggedSamples": 1
201
+ },
202
+ {
203
+ "lineId": "ln-bac43927",
204
+ "runId": "rr-7f4a6ac0",
205
+ "recipeId": "rc-e27a0673",
206
+ "recipeName": "配方G-mtjl98nl",
207
+ "productId": "pd-52f54e33",
208
+ "productName": "产品G-mtjl98nl",
209
+ "startedAt": "2026-09-02T04:20:59.682Z",
150
210
  "taggedSamples": 0
151
211
  }
152
212
  ]
@@ -0,0 +1,24 @@
1
+ /**
2
+ * 插件宿主 nitro 装配点 —— 启动期装载 ~/.AgentWorkShop/plugins 与
3
+ * <repo>/.AgentWorkShop/plugins 下的用户插件;服务关闭时发出 server:close。
4
+ * 装载细节见 server/services/workshop/plugins/host.mjs(错误隔离:单插件失败不拖垮主服务)。
5
+ */
6
+ import { initPluginHost, shutdownPluginHost } from '@/server/services/workshop/plugins/host.mjs'
7
+ import { fileURLToPath } from 'node:url'
8
+ import { dirname, resolve } from 'node:path'
9
+
10
+ // packageRoot = 本包根(nitro 打包后由运行 cwd 提供事实源,此处兜底)
11
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..')
12
+
13
+ export default defineNitroPlugin((nitroApp) => {
14
+ void initPluginHost({ cwd: process.cwd(), packageRoot }).then((host) => {
15
+ // 实际监听端口回填(nitro listen 后 ctx.api 自环 origin 才准确)
16
+ nitroApp.hooks.hookOnce('listen', (listener: { port?: number }) => {
17
+ if (listener?.port)
18
+ host.setSelfOrigin(listener.port)
19
+ })
20
+ })
21
+ nitroApp.hooks.hookOnce('close', () => {
22
+ void shutdownPluginHost()
23
+ })
24
+ })
@@ -33,6 +33,7 @@ import { getDaqNodeRepo } from './daq-node.repo'
33
33
  import { getTsdb, tsdbReady } from './storage'
34
34
  import { getDaqQueue } from './bus'
35
35
  import { getDaqHostPorts } from './host-ports'
36
+ import { emitDaqSample } from '@/server/services/workshop/plugins/host.mjs'
36
37
  import { getOps, recordOps } from '../ops/ops'
37
38
  import { notifyAlarm, newAlarmId, startAlarmEscalator } from './alarm-notify'
38
39
  import type { DaqSampleEnvelope } from './bus/queue-port'
@@ -193,13 +194,16 @@ class DaqController {
193
194
  // 配方级数采监控窗口的越限判定已前移到运行时 onSample(与量程告警共用边沿语义,
194
195
  // 越窗即 raise 落库 + 广播);此处 state 已含窗口结论,仅负责管线汇聚。
195
196
  if (allowPublish) {
196
- this.broadcast?.('daq.reading', {
197
+ const reading = {
197
198
  nodeId: node.id,
198
199
  templateRef: node.templateRef,
199
200
  value: node.value ?? env.value,
200
201
  state: node.state,
201
202
  at: env.at,
202
- } satisfies AepDaqReading)
203
+ } satisfies AepDaqReading
204
+ this.broadcast?.('daq.reading', reading)
205
+ // 插件钩子:下发级采样观察(与 WS daq.reading 同点同节拍;宿主未装载时零开销 no-op)
206
+ emitDaqSample(reading)
203
207
  }
204
208
  this.writeBackTelemetry(node)
205
209
 
@@ -22,6 +22,7 @@ import { DcwNodeRuntime } from './dcw-runtime'
22
22
  import { getDcwRecipeRepo, type DcwWriteHistoryEntry } from './dcw-recipe.repo'
23
23
  import { getDcwProductRepo } from './dcw-product.repo'
24
24
  import { getDcwLineRepo } from './dcw-line.repo'
25
+ import { emitDcwWrite } from '@/server/services/workshop/plugins/host.mjs'
25
26
  import { clearActiveLineRun, getActiveLineRun, getAllActiveLineRuns, setActiveLineRun } from './line-run'
26
27
  import { getRecipeRollBackManager } from './recipe-rollback-manager'
27
28
  import { recordOps } from '../ops/ops'
@@ -463,6 +464,8 @@ class DcwController {
463
464
  recipeId: runNow?.recipeId ?? recipeRunId ?? '',
464
465
  detail: { eng, prevValue, ok: outcome.ok, message: outcome.message, taskId: meta?.taskId ?? null },
465
466
  })
467
+ // 插件钩子:写控 ACK 观察(与运维入册同点同去重节流)
468
+ emitDcwWrite({ nodeId: id, name: node.name, eng, prevValue, ok: outcome.ok, source: src, lineId: node.lineId ?? '', at: new Date().toISOString() })
466
469
  }
467
470
  }
468
471
  catch {