agentworkshop 0.7.14 → 0.7.16
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/.AgentWorkShop/prompts/host-tools.json +819 -755
- package/.output/.AgentWorkShop/prompts/host-tools.json +819 -755
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/cf0a8831-4514-493d-ad5a-4e371a089ef9.json +1 -0
- package/.output/server/chunks/_/nitro.mjs +885 -725
- package/.output/server/chunks/_/nitro.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index3.post.mjs.map +1 -1
- package/.output/server/package.json +1 -1
- package/package.json +1 -1
- package/scripts/_dbg-harness-ui-e2e.py +23 -13
- package/scripts/_dbg-opslog-agent-e2e.mjs +191 -0
- package/scripts/aw-expose.mjs +159 -0
- package/server/api/workshop/daq/index.post.ts +1 -1
- package/server/api/workshop/dcw/lines/index.post.ts +1 -1
- package/server/data/daqs.json +471 -61
- package/server/data/dcw-lines.json +49 -0
- package/server/data/dcw-products.json +49 -0
- package/server/data/dcw-recipes.json +64 -0
- package/server/data/dcw-rollback.json +239 -6
- package/server/data/dcw-runs.json +162 -142
- package/server/data/dcw-writes.json +156 -0
- package/server/data/dcws.json +363 -217
- package/server/data/line-runs.json +41 -11
- package/server/data/scene-layouts.json +11 -0
- package/server/plugins/workshop.ts +9 -0
- package/server/services/workshop/agents/agent-badge.ts +38 -0
- package/server/services/workshop/agents/host-tool-bridge.ts +622 -612
- package/server/services/workshop/agents/industrial-tools.ts +139 -4
- package/server/services/workshop/daq/drivers.ts +25 -5
- package/server/services/workshop/dcw/recipe-rollback-manager.ts +8 -6
- package/.output/public/_nuxt/builds/meta/23c30854-f9e1-4651-bc3a-b695ef5faca4.json +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nitro.mjs","sources":["../../../../node_modules/.pnpm/uncrypto@0.1.3/node_modules/uncrypto/dist/crypto.node.mjs","../../../../node_modules/.pnpm/destr@2.0.5/node_modules/destr/dist/index.mjs","../../../../node_modules/.pnpm/ufo@1.6.4/node_modules/ufo/dist/index.mjs","../../../../node_modules/.pnpm/cookie-es@1.2.3/node_modules/cookie-es/dist/index.mjs","../../../../node_modules/.pnpm/radix3@1.1.2/node_modules/radix3/dist/index.mjs","../../../../node_modules/.pnpm/defu@6.1.7/node_modules/defu/dist/defu.mjs","../../../../node_modules/.pnpm/iron-webcrypto@1.2.1/node_modules/iron-webcrypto/dist/index.js","../../../../node_modules/.pnpm/node-mock-http@1.0.5/node_modules/node-mock-http/dist/index.mjs","../../../../node_modules/.pnpm/h3@1.15.11/node_modules/h3/dist/index.mjs","../../../../node_modules/.pnpm/hookable@5.5.3/node_modules/hookable/dist/index.mjs","../../../../node_modules/.pnpm/node-fetch-native@1.6.7/node_modules/node-fetch-native/dist/native.mjs","../../../../node_modules/.pnpm/ofetch@1.5.1/node_modules/ofetch/dist/shared/ofetch.CWycOUEr.mjs","../../../../node_modules/.pnpm/ofetch@1.5.1/node_modules/ofetch/dist/node.mjs","../../../../node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/dist/shared/unstorage.zVDD2mZo.mjs","../../../../node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/dist/index.mjs","../../../../node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/drivers/utils/index.mjs","../../../../node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/drivers/utils/node-fs.mjs","../../../../node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/drivers/fs-lite.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/storage.mjs","../../../../node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/shared/ohash.D__AXeF1.mjs","../../../../node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/crypto/node/index.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/hash.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/cache.mjs","../../../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/dist/index.mjs","../../../../node_modules/.pnpm/scule@1.3.0/node_modules/scule/dist/index.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/utils.env.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/config.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/route-rules-utils.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/route-rules.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/utils.mjs","../../../../node_modules/.pnpm/@nuxt+nitro-server@4.5.2_b6375e2fc1335b7cac3be8af25556e69/node_modules/@nuxt/nitro-server/dist/runtime/utils/error.mjs","../../../../node_modules/.pnpm/@nuxt+nitro-server@4.5.2_b6375e2fc1335b7cac3be8af25556e69/node_modules/@nuxt/nitro-server/dist/runtime/handlers/error.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/error/utils.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/error/prod.mjs","../../../../node_modules/.pnpm/nuxt-auth-utils@0.5.30_magi_25cfea03c37d60c613297752f2919dae/node_modules/nuxt-auth-utils/dist/runtime/server/plugins/oauth.js","../../../../node_modules/.pnpm/hookable@6.1.1/node_modules/hookable/dist/index.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/plugin.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/renderer.mjs","../../../../node_modules/.pnpm/@nuxt+nitro-server@4.5.2_b6375e2fc1335b7cac3be8af25556e69/node_modules/@nuxt/nitro-server/dist/runtime/utils/paths.mjs","../../../../server/utils/errors.ts","../../../../sdk/hooks.mjs","../../../../sdk/api.mjs","../../../../sdk/context.mjs","../../../../server/services/workshop/plugins/host.mjs","../../../../server/services/workshop/scene-events.ts","../../../../server/services/workshop/ops/ops.ts","../../../../server/utils/approval-gate.ts","../../../../server/utils/auth.ts","../../../../server/utils/config.ts","../../../../server/utils/response.ts","../../../../server/utils/validate.ts","../../../../node_modules/.pnpm/nuxt-auth-utils@0.5.30_magi_25cfea03c37d60c613297752f2919dae/node_modules/nuxt-auth-utils/dist/runtime/server/utils/session.js","../../../../node_modules/.pnpm/nuxt-auth-utils@0.5.30_magi_25cfea03c37d60c613297752f2919dae/node_modules/nuxt-auth-utils/dist/runtime/server/plugins/ws.js","../../../../shared/local-time.mjs","../../../../server/plugins/00-local-time.ts","../../../../server/plugins/aw-plugins.ts","../../../../shared/config/home.mjs","../../../../shared/config/engine.mjs","../../../../server/services/workshop/settings.ts","../../../../server/services/workshop/db/backup-registry.ts","../../../../server/plugins/backup.ts","../../../../server/services/workshop/logger.ts","../../../../server/services/workshop/daq/infra.ts","../../../../server/services/workshop/daq/storage/sqlite.adapter.ts","../../../../server/services/workshop/daq/storage/timescale.adapter.ts","../../../../server/services/workshop/daq/storage/index.ts","../../../../server/services/workshop/daq/objectstore/disk.adapter.ts","../../../../server/services/workshop/daq/objectstore/minio.adapter.ts","../../../../server/services/workshop/daq/objectstore/index.ts","../../../../server/services/workshop/daq/bus/inproc.adapter.ts","../../../../server/services/workshop/daq/bus/mqtt.adapter.ts","../../../../server/services/workshop/daq/bus/index.ts","../../../../server/services/system-config.ts","../../../../shared/daq-protocol.ts","../../../../server/services/workshop/daq/png-enc.ts","../../../../server/services/workshop/daq/drivers.ts","../../../../server/services/workshop/json-store.mjs","../../../../server/services/workshop/daq/daq-templates.ts","../../../../server/services/workshop/daq/daq-node.ts","../../../../server/services/workshop/daq/daq-runtime.ts","../../../../server/services/workshop/daq/daq-node.repo.ts","../../../../server/services/workshop/daq/host-ports.ts","../../../../server/services/workshop/daq/frames.ts","../../../../server/services/workshop/daq/objectstore/objectstore-port.ts","../../../../server/services/workshop/daq/alarm-notify.ts","../../../../server/services/workshop/daq/plugin-bridge.ts","../../../../server/services/workshop/daq/daq-controller.ts","../../../../server/plugins/daq.ts","../../../../server/plugins/dev-stability-guard.ts","../../../../server/services/workshop/db/retention.ts","../../../../server/plugins/retention.ts","../../../../server/plugins/security.ts","../../../../server/plugins/system-config.ts","../../../../server/services/workshop/db/database.ts","../../../../server/services/workshop/db/channel.repo.ts","../../../../server/services/workshop/db/agent.repo.ts","../../../../server/services/workshop/db/channel-agent.repo.ts","../../../../server/services/workshop/db/team.repo.ts","../../../../server/services/workshop/db/team-member.repo.ts","../../../../server/services/workshop/db/channel-template.repo.ts","../../../../server/services/workshop/db/task.repo.ts","../../../../server/services/workshop/db/message.repo.ts","../../../../server/services/workshop/db/subscription.repo.ts","../../../../server/services/workshop/db/memory.repo.ts","../../../../server/services/workshop/db/user.repo.ts","../../../../server/services/workshop/db/channel-event.repo.ts","../../../../server/services/workshop/db/ops.repo.ts","../../../../server/services/workshop/agents/hitl-registry.ts","../../../../server/repositories/user.repository.ts","../../../../server/services/user.service.ts","../../../../server/services/workshop/runtime/mailbox.ts","../../../../server/services/workshop/permissions.ts","../../../../server/api/workshop/ws.ts","../../../../server/services/workshop/runtime/execution-mode.ts","../../../../server/services/workshop/agents/mock-agent.ts","../../../../server/services/workshop/agents/harness-process.ts","../../../../server/services/workshop/agents/adapters/omp-rpc-client.ts","../../../../shared/terminal-protocol.ts","../../../../server/services/workshop/agents/harness-terminal.ts","../../../../server/services/workshop/prompts/loader.ts","../../../../server/services/workshop/agents/node-bindings.repo.ts","../../../../server/services/workshop/agents/tool-approvals.ts","../../../../shared/dcw-protocol.ts","../../../../server/services/workshop/dcw/drivers.ts","../../../../server/services/workshop/dcw/dcw-templates.ts","../../../../server/services/workshop/assets/device-twin.repo.ts","../../../../server/services/workshop/dcw/dcw-node.ts","../../../../server/services/workshop/dcw/dcw-node.repo.ts","../../../../server/services/workshop/dcw/dcw-runtime.ts","../../../../server/services/workshop/dcw/dcw-product.repo.ts","../../../../server/services/workshop/dcw/dcw-recipe.repo.ts","../../../../server/services/workshop/dcw/dcw-line.repo.ts","../../../../server/services/workshop/dcw/line-run.ts","../../../../server/services/workshop/dcw/recipe-rollback.repo.ts","../../../../server/services/workshop/dcw/recipe-rollback-manager.ts","../../../../server/services/workshop/dcw/dcw-controller.ts","../../../../server/services/workshop/agents/industrial-context.ts","../../../../server/services/workshop/agents/industrial-tools.ts","../../../../server/services/workshop/agents/plugin-tools.ts","../../../../server/services/workshop/agents/host-tool-bridge.ts","../../../../server/services/workshop/agents/prompt-builder.ts","../../../../server/services/workshop/agents/omp-agent.ts","../../../../server/services/workshop/agents/claude-agent.ts","../../../../server/services/workshop/agents/adapters/line-spawn.ts","../../../../server/services/workshop/agents/harness-env.ts","../../../../server/services/workshop/agents/opencode-agent.ts","../../../../server/services/workshop/agents/adapters/stdio-jsonrpc.ts","../../../../server/services/workshop/agents/codex-agent.ts","../../../../server/services/workshop/agents/dsh-agent.ts","../../../../server/services/workshop/agents/registry.ts","../../../../server/services/workshop/agents/factory.ts","../../../../server/services/workshop/types/task.ts","../../../../server/services/workshop/runtime/agent-runtime.ts","../../../../server/services/workshop/runtime/channel-runtime.ts","../../../../server/services/workshop/runtime/scheduler-loop.ts","../../../../server/services/workshop/runtime/task-engine.ts","../../../../server/services/workshop/runtime/memory.ts","../../../../server/services/workshop/runtime/embedding-provider.ts","../../../../server/services/workshop/agents/harness-availability.ts","../../../../server/services/workshop/runtime/manager.ts","../../../../server/plugins/workshop.ts","../../../../node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/static.mjs","../../../../server/middleware/request-log.ts","../../../../node_modules/.pnpm/nuxt-auth-utils@0.5.30_magi_25cfea03c37d60c613297752f2919dae/node_modules/nuxt-auth-utils/dist/runtime/server/api/session.delete.js","../../../../node_modules/.pnpm/nuxt-auth-utils@0.5.30_magi_25cfea03c37d60c613297752f2919dae/node_modules/nuxt-auth-utils/dist/runtime/server/api/session.get.js","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/app.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/lib/http-graceful-shutdown.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/shutdown.mjs"],"names":["decode","getQuery","parse","serialize","createRouter","f","h","c","i","l","g","p","createError","process","mergeHeaders","crypto","flatHooks","createTask","serialTaskCaller","parallelTaskCaller","callEachWith","createHooks","Hookable","s","callHooks","nodeFetch","fetch","Headers","Headers$1","AbortController","AbortController$1","normalizeKey","defineDriver","DRIVER_NAME","dirname","fsPromises","resolve","fsp","_inlineAppConfig","createRadixRouter","__publicField","permissions","userRepository","log","watch","AEP_VERSION","randomUUID","cache","registry","copyFileAsync","state","_a","DB_PATH","rows","pointsFromMeta","asObject","_b","_c","_d","makeFallback","writeFile","readFile","reqNative","modbusRead","sleep","REGISTRY","bad","load","normalize","pubMs","now","allowPublish","singleton","num","attached","require","SCHEMA_SQL","COLS","randomPassword","randomBytes","hubGlobal","hub","criteria","worker","frame","save","DATA_DIR","COOLDOWN_MS","_e","fresh","partsToText","buildContextPrefix","pid","launchChildProcess","seen","modeInfo","rowToTask","TaskEngineImpl","callNodeRequestHandler","fetchNodeRequestHandler","gracefulShutdown"],"mappings":"","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,51,52,161,162,164,165,166,167,168]}
|
|
1
|
+
{"version":3,"file":"nitro.mjs","sources":["../../../../node_modules/.pnpm/uncrypto@0.1.3/node_modules/uncrypto/dist/crypto.node.mjs","../../../../node_modules/.pnpm/destr@2.0.5/node_modules/destr/dist/index.mjs","../../../../node_modules/.pnpm/ufo@1.6.4/node_modules/ufo/dist/index.mjs","../../../../node_modules/.pnpm/cookie-es@1.2.3/node_modules/cookie-es/dist/index.mjs","../../../../node_modules/.pnpm/radix3@1.1.2/node_modules/radix3/dist/index.mjs","../../../../node_modules/.pnpm/defu@6.1.7/node_modules/defu/dist/defu.mjs","../../../../node_modules/.pnpm/iron-webcrypto@1.2.1/node_modules/iron-webcrypto/dist/index.js","../../../../node_modules/.pnpm/node-mock-http@1.0.5/node_modules/node-mock-http/dist/index.mjs","../../../../node_modules/.pnpm/h3@1.15.11/node_modules/h3/dist/index.mjs","../../../../node_modules/.pnpm/hookable@5.5.3/node_modules/hookable/dist/index.mjs","../../../../node_modules/.pnpm/node-fetch-native@1.6.7/node_modules/node-fetch-native/dist/native.mjs","../../../../node_modules/.pnpm/ofetch@1.5.1/node_modules/ofetch/dist/shared/ofetch.CWycOUEr.mjs","../../../../node_modules/.pnpm/ofetch@1.5.1/node_modules/ofetch/dist/node.mjs","../../../../node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/dist/shared/unstorage.zVDD2mZo.mjs","../../../../node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/dist/index.mjs","../../../../node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/drivers/utils/index.mjs","../../../../node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/drivers/utils/node-fs.mjs","../../../../node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/drivers/fs-lite.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/storage.mjs","../../../../node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/shared/ohash.D__AXeF1.mjs","../../../../node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/crypto/node/index.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/hash.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/cache.mjs","../../../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/dist/index.mjs","../../../../node_modules/.pnpm/scule@1.3.0/node_modules/scule/dist/index.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/utils.env.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/config.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/route-rules-utils.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/route-rules.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/utils.mjs","../../../../node_modules/.pnpm/@nuxt+nitro-server@4.5.2_b6375e2fc1335b7cac3be8af25556e69/node_modules/@nuxt/nitro-server/dist/runtime/utils/error.mjs","../../../../node_modules/.pnpm/@nuxt+nitro-server@4.5.2_b6375e2fc1335b7cac3be8af25556e69/node_modules/@nuxt/nitro-server/dist/runtime/handlers/error.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/error/utils.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/error/prod.mjs","../../../../node_modules/.pnpm/nuxt-auth-utils@0.5.30_magi_25cfea03c37d60c613297752f2919dae/node_modules/nuxt-auth-utils/dist/runtime/server/plugins/oauth.js","../../../../node_modules/.pnpm/hookable@6.1.1/node_modules/hookable/dist/index.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/plugin.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/renderer.mjs","../../../../node_modules/.pnpm/@nuxt+nitro-server@4.5.2_b6375e2fc1335b7cac3be8af25556e69/node_modules/@nuxt/nitro-server/dist/runtime/utils/paths.mjs","../../../../server/utils/errors.ts","../../../../sdk/hooks.mjs","../../../../sdk/api.mjs","../../../../sdk/context.mjs","../../../../server/services/workshop/plugins/host.mjs","../../../../server/services/workshop/scene-events.ts","../../../../server/services/workshop/ops/ops.ts","../../../../server/utils/approval-gate.ts","../../../../server/utils/auth.ts","../../../../server/utils/config.ts","../../../../server/utils/response.ts","../../../../server/utils/validate.ts","../../../../node_modules/.pnpm/nuxt-auth-utils@0.5.30_magi_25cfea03c37d60c613297752f2919dae/node_modules/nuxt-auth-utils/dist/runtime/server/utils/session.js","../../../../node_modules/.pnpm/nuxt-auth-utils@0.5.30_magi_25cfea03c37d60c613297752f2919dae/node_modules/nuxt-auth-utils/dist/runtime/server/plugins/ws.js","../../../../shared/local-time.mjs","../../../../server/plugins/00-local-time.ts","../../../../server/plugins/aw-plugins.ts","../../../../shared/config/home.mjs","../../../../shared/config/engine.mjs","../../../../server/services/workshop/settings.ts","../../../../server/services/workshop/db/backup-registry.ts","../../../../server/plugins/backup.ts","../../../../server/services/workshop/logger.ts","../../../../server/services/workshop/daq/infra.ts","../../../../server/services/workshop/daq/storage/sqlite.adapter.ts","../../../../server/services/workshop/daq/storage/timescale.adapter.ts","../../../../server/services/workshop/daq/storage/index.ts","../../../../server/services/workshop/daq/objectstore/disk.adapter.ts","../../../../server/services/workshop/daq/objectstore/minio.adapter.ts","../../../../server/services/workshop/daq/objectstore/index.ts","../../../../server/services/workshop/daq/bus/inproc.adapter.ts","../../../../server/services/workshop/daq/bus/mqtt.adapter.ts","../../../../server/services/workshop/daq/bus/index.ts","../../../../server/services/system-config.ts","../../../../shared/daq-protocol.ts","../../../../server/services/workshop/daq/png-enc.ts","../../../../server/services/workshop/daq/drivers.ts","../../../../server/services/workshop/json-store.mjs","../../../../server/services/workshop/daq/daq-templates.ts","../../../../server/services/workshop/daq/daq-node.ts","../../../../server/services/workshop/daq/daq-runtime.ts","../../../../server/services/workshop/daq/daq-node.repo.ts","../../../../server/services/workshop/daq/host-ports.ts","../../../../server/services/workshop/daq/frames.ts","../../../../server/services/workshop/daq/objectstore/objectstore-port.ts","../../../../server/services/workshop/daq/alarm-notify.ts","../../../../server/services/workshop/daq/plugin-bridge.ts","../../../../server/services/workshop/daq/daq-controller.ts","../../../../server/plugins/daq.ts","../../../../server/plugins/dev-stability-guard.ts","../../../../server/services/workshop/db/retention.ts","../../../../server/plugins/retention.ts","../../../../server/plugins/security.ts","../../../../server/plugins/system-config.ts","../../../../server/services/workshop/db/database.ts","../../../../server/services/workshop/db/channel.repo.ts","../../../../server/services/workshop/db/agent.repo.ts","../../../../server/services/workshop/db/channel-agent.repo.ts","../../../../server/services/workshop/db/team.repo.ts","../../../../server/services/workshop/db/team-member.repo.ts","../../../../server/services/workshop/db/channel-template.repo.ts","../../../../server/services/workshop/db/task.repo.ts","../../../../server/services/workshop/db/message.repo.ts","../../../../server/services/workshop/db/subscription.repo.ts","../../../../server/services/workshop/db/memory.repo.ts","../../../../server/services/workshop/db/user.repo.ts","../../../../server/services/workshop/db/channel-event.repo.ts","../../../../server/services/workshop/db/ops.repo.ts","../../../../server/services/workshop/agents/hitl-registry.ts","../../../../server/services/workshop/agents/agent-badge.ts","../../../../server/repositories/user.repository.ts","../../../../server/services/user.service.ts","../../../../server/services/workshop/runtime/mailbox.ts","../../../../server/services/workshop/permissions.ts","../../../../server/api/workshop/ws.ts","../../../../server/services/workshop/runtime/execution-mode.ts","../../../../server/services/workshop/agents/mock-agent.ts","../../../../server/services/workshop/agents/harness-process.ts","../../../../server/services/workshop/agents/adapters/omp-rpc-client.ts","../../../../shared/terminal-protocol.ts","../../../../server/services/workshop/agents/harness-terminal.ts","../../../../server/services/workshop/prompts/loader.ts","../../../../server/services/workshop/agents/node-bindings.repo.ts","../../../../server/services/workshop/agents/tool-approvals.ts","../../../../shared/dcw-protocol.ts","../../../../server/services/workshop/dcw/drivers.ts","../../../../server/services/workshop/dcw/dcw-templates.ts","../../../../server/services/workshop/assets/device-twin.repo.ts","../../../../server/services/workshop/dcw/dcw-node.ts","../../../../server/services/workshop/dcw/dcw-node.repo.ts","../../../../server/services/workshop/dcw/dcw-runtime.ts","../../../../server/services/workshop/dcw/dcw-product.repo.ts","../../../../server/services/workshop/dcw/dcw-recipe.repo.ts","../../../../server/services/workshop/dcw/dcw-line.repo.ts","../../../../server/services/workshop/dcw/line-run.ts","../../../../server/services/workshop/dcw/recipe-rollback.repo.ts","../../../../server/services/workshop/dcw/recipe-rollback-manager.ts","../../../../server/services/workshop/dcw/dcw-controller.ts","../../../../server/services/workshop/agents/industrial-context.ts","../../../../server/services/workshop/agents/industrial-tools.ts","../../../../server/services/workshop/agents/plugin-tools.ts","../../../../server/services/workshop/agents/host-tool-bridge.ts","../../../../server/services/workshop/agents/prompt-builder.ts","../../../../server/services/workshop/agents/omp-agent.ts","../../../../server/services/workshop/agents/claude-agent.ts","../../../../server/services/workshop/agents/adapters/line-spawn.ts","../../../../server/services/workshop/agents/harness-env.ts","../../../../server/services/workshop/agents/opencode-agent.ts","../../../../server/services/workshop/agents/adapters/stdio-jsonrpc.ts","../../../../server/services/workshop/agents/codex-agent.ts","../../../../server/services/workshop/agents/dsh-agent.ts","../../../../server/services/workshop/agents/registry.ts","../../../../server/services/workshop/agents/factory.ts","../../../../server/services/workshop/types/task.ts","../../../../server/services/workshop/runtime/agent-runtime.ts","../../../../server/services/workshop/runtime/channel-runtime.ts","../../../../server/services/workshop/runtime/scheduler-loop.ts","../../../../server/services/workshop/runtime/task-engine.ts","../../../../server/services/workshop/runtime/memory.ts","../../../../server/services/workshop/runtime/embedding-provider.ts","../../../../server/services/workshop/agents/harness-availability.ts","../../../../server/services/workshop/runtime/manager.ts","../../../../server/plugins/workshop.ts","../../../../node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/static.mjs","../../../../server/middleware/request-log.ts","../../../../node_modules/.pnpm/nuxt-auth-utils@0.5.30_magi_25cfea03c37d60c613297752f2919dae/node_modules/nuxt-auth-utils/dist/runtime/server/api/session.delete.js","../../../../node_modules/.pnpm/nuxt-auth-utils@0.5.30_magi_25cfea03c37d60c613297752f2919dae/node_modules/nuxt-auth-utils/dist/runtime/server/api/session.get.js","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/app.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/lib/http-graceful-shutdown.mjs","../../../../node_modules/.pnpm/nitropack@2.13.4_oxc-parser_1ea3e01e591cb0fd9b154d63486cc9e1/node_modules/nitropack/dist/runtime/internal/shutdown.mjs"],"names":["decode","getQuery","parse","serialize","createRouter","f","h","c","i","l","g","p","createError","process","mergeHeaders","crypto","flatHooks","createTask","serialTaskCaller","parallelTaskCaller","callEachWith","createHooks","Hookable","s","callHooks","nodeFetch","fetch","Headers","Headers$1","AbortController","AbortController$1","normalizeKey","defineDriver","DRIVER_NAME","dirname","fsPromises","resolve","fsp","_inlineAppConfig","createRadixRouter","__publicField","permissions","userRepository","log","watch","AEP_VERSION","randomUUID","cache","registry","copyFileAsync","state","_a","DB_PATH","rows","pointsFromMeta","asObject","_b","_c","_d","makeFallback","writeFile","readFile","reqNative","modbusRead","sleep","REGISTRY","bad","load","normalize","pubMs","now","allowPublish","singleton","num","attached","require","SCHEMA_SQL","COLS","randomPassword","randomBytes","hubGlobal","hub","criteria","worker","frame","save","DATA_DIR","COOLDOWN_MS","_e","fresh","partsToText","buildContextPrefix","pid","launchChildProcess","seen","modeInfo","rowToTask","TaskEngineImpl","callNodeRequestHandler","fetchNodeRequestHandler","gracefulShutdown"],"mappings":"","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,51,52,162,163,165,166,167,168,169]}
|
|
@@ -20,7 +20,7 @@ import 'node:zlib';
|
|
|
20
20
|
|
|
21
21
|
const index_post = defineApiHandler(async (event) => {
|
|
22
22
|
var _a;
|
|
23
|
-
requireRole(event, ["admin", "editor"]);
|
|
23
|
+
const user = requireRole(event, ["admin", "editor"]);
|
|
24
24
|
bindDcwBroadcast(broadcastSceneEvent);
|
|
25
25
|
const body = (_a = await readBody(event)) != null ? _a : { name: "" };
|
|
26
26
|
const line = getDcwController().createLine(body);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.post.mjs","sources":["../../../../../../../server/api/workshop/dcw/lines/index.post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAYA,mBAAe,gBAAA,CAAiB,OAAO,KAAA,KAAU;AAZjD,EAAA,IAAA,EAAA;AAaE,EAAA,WAAA,CAAY,KAAA,EAAO,CAAC,OAAA,EAAS,QAAQ,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"index.post.mjs","sources":["../../../../../../../server/api/workshop/dcw/lines/index.post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAYA,mBAAe,gBAAA,CAAiB,OAAO,KAAA,KAAU;AAZjD,EAAA,IAAA,EAAA;AAaE,EAAA,MAAM,OAAO,WAAA,CAAY,KAAA,EAAO,CAAC,OAAA,EAAS,QAAQ,CAAC,CAAA;AACnD,EAAA,gBAAA,CAAiB,mBAAmB,CAAA;AACpC,EAAA,MAAM,IAAA,GAAA,CAAO,WAAM,QAAA,CAAoB,KAAK,MAA/B,IAAA,GAAA,EAAA,GAAoC,EAAE,MAAM,EAAA,EAAG;AAC5D,EAAA,MAAM,IAAA,GAAO,gBAAA,EAAiB,CAAE,UAAA,CAAW,IAAI,CAAA;AAC/C,EAAA,mBAAA,CAAoB,kBAAA,EAAoB,EAAE,EAAA,EAAI,SAAA,EAAW,MAAM,IAAA,EAAM,MAAA,EAAQ,IAAA,CAAK,EAAA,EAAI,CAAA;AACtF,EAAA,SAAA,CAAU;AAAA,IACR,OAAO,IAAA,CAAK,EAAA;AAAA,IACZ,WAAW,IAAA,CAAK,IAAA;AAAA,IAChB,SAAA,EAAW,MAAA;AAAA,IACX,MAAA,EAAQ,aAAA;AAAA,IACR,IAAA,EAAM,MAAA;AAAA,IACN,UAAA,EAAY,MAAA;AAAA,IACZ,UAAU,IAAA,CAAK,EAAA;AAAA,IACf,OAAA,EAAS,CAAA,8BAAA,EAAQ,IAAA,CAAK,IAAI,CAAA,MAAA,CAAA;AAAA,IAC1B,QAAQ,IAAA,CAAK;AAAA,GACd,CAAA;AACD,EAAA,OAAO,EAAE,IAAA,EAAK;AAChB,CAAC,CAAA;;;;"}
|
|
@@ -21,7 +21,7 @@ import 'node:zlib';
|
|
|
21
21
|
|
|
22
22
|
const index_post = defineApiHandler(async (event) => {
|
|
23
23
|
var _a, _b;
|
|
24
|
-
requireRole(event, ["admin", "editor"]);
|
|
24
|
+
const user = requireRole(event, ["admin", "editor"]);
|
|
25
25
|
bindDaqHost(broadcastSceneEvent);
|
|
26
26
|
const body = (_a = await readBody(event)) != null ? _a : {};
|
|
27
27
|
const node = getDaqController().create(body);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index3.post.mjs","sources":["../../../../../../server/api/workshop/daq/index.post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAcA,mBAAe,gBAAA,CAAiB,OAAO,KAAA,KAAU;AAdjD,EAAA,IAAA,EAAA,EAAA,EAAA;AAeE,EAAA,WAAA,CAAY,KAAA,EAAO,CAAC,OAAA,EAAS,QAAQ,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"index3.post.mjs","sources":["../../../../../../server/api/workshop/daq/index.post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAcA,mBAAe,gBAAA,CAAiB,OAAO,KAAA,KAAU;AAdjD,EAAA,IAAA,EAAA,EAAA,EAAA;AAeE,EAAA,MAAM,OAAO,WAAA,CAAY,KAAA,EAAO,CAAC,OAAA,EAAS,QAAQ,CAAC,CAAA;AACnD,EAAA,WAAA,CAAY,mBAAmB,CAAA;AAC/B,EAAA,MAAM,QAAO,EAAA,GAAA,MAAM,QAAA,CAAyB,KAAK,CAAA,KAApC,YAAyC,EAAC;AACvD,EAAA,MAAM,IAAA,GAAO,gBAAA,EAAiB,CAAE,MAAA,CAAO,IAAI,CAAA;AAC3C,EAAA,SAAA,CAAU;AAAA,IACR,OAAO,IAAA,CAAK,EAAA;AAAA,IACZ,WAAW,IAAA,CAAK,IAAA;AAAA,IAChB,SAAA,EAAW,MAAA;AAAA,IACX,MAAA,EAAQ,iBAAA;AAAA,IACR,IAAA,EAAM,KAAA;AAAA,IACN,UAAA,EAAY,UAAA;AAAA,IACZ,UAAU,IAAA,CAAK,EAAA;AAAA,IACf,SAAS,CAAA,0CAAA,EAAU,IAAA,CAAK,IAAI,CAAA,cAAA,EAAY,KAAK,MAAM,CAAA,CAAA,CAAA;AAAA,IACnD,MAAA,EAAA,CAAQ,EAAA,GAAA,IAAA,CAAK,MAAA,KAAL,IAAA,GAAA,EAAA,GAAe,EAAA;AAAA,IACvB,QAAQ,EAAE,MAAA,EAAQ,KAAK,MAAA,EAAQ,WAAA,EAAa,KAAK,WAAA;AAAY,GAC9D,CAAA;AACD,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,MAAA,EAAO,EAAE;AAC/B,CAAC,CAAA;;;;"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"""Harness 可用性 UI E2E:用户名登录 → 仪表盘 Harness 面板(dsh=未安装灰化) → agents 模板选择禁用 → teams 页截图。
|
|
2
|
-
dsh 未安装态由外部脚本预置;恢复也由外部执行(本脚本不发起 HTTP)。
|
|
3
|
-
|
|
2
|
+
dsh 未安装态由外部脚本预置;恢复也由外部执行(本脚本不发起 HTTP)。
|
|
3
|
+
AW_BASE 环境变量切换目标实例(默认 :3021);EXPECT_OFF=1 时断言恰好 1 条灰化。"""
|
|
4
|
+
import asyncio, os, sys
|
|
4
5
|
from playwright.async_api import async_playwright
|
|
5
6
|
|
|
6
|
-
BASE = 'http://127.0.0.1:3021'
|
|
7
|
+
BASE = os.environ.get('AW_BASE', 'http://127.0.0.1:3021')
|
|
8
|
+
EXPECT_OFF = os.environ.get('EXPECT_OFF', '1') == '1'
|
|
7
9
|
SHOT = '.e2e-shots'
|
|
8
10
|
|
|
9
11
|
async def main():
|
|
@@ -49,12 +51,17 @@ async def main():
|
|
|
49
51
|
ok(items == 6, f'仪表盘 6 引擎条目(实际 {items})')
|
|
50
52
|
off = page.locator('.harness-row .h-item.off')
|
|
51
53
|
off_n = await off.count()
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
if EXPECT_OFF:
|
|
55
|
+
ok(off_n == 1, f'未安装灰化条目=1(实际 {off_n})')
|
|
56
|
+
if off_n == 1:
|
|
57
|
+
txt = await off.first.inner_text()
|
|
58
|
+
ok('未安装' in txt and 'dsh' in txt, f'灰化条目为 dsh:{txt!r}')
|
|
59
|
+
total = await page.locator('.dp-hd:has-text("执行引擎") .fleet-total').inner_text()
|
|
60
|
+
ok('5/6' in total, f'就绪计数 5/6(实际 {total!r})')
|
|
61
|
+
else:
|
|
62
|
+
print(f' · 灰化条目={off_n}(当前环境探测结果;全部安装时为 0)', flush=True)
|
|
63
|
+
total = await page.locator('.dp-hd:has-text("执行引擎") .fleet-total').inner_text()
|
|
64
|
+
print(f' · 就绪计数={total!r}', flush=True)
|
|
58
65
|
await page.screenshot(path=f'{SHOT}/harness-1-dashboard-off.png', full_page=False)
|
|
59
66
|
|
|
60
67
|
# ---- 3. agents 模板页:选择器禁用未安装项 ----
|
|
@@ -64,12 +71,15 @@ async def main():
|
|
|
64
71
|
await page.click('.ant-modal .ant-select')
|
|
65
72
|
await page.wait_for_selector('.ant-select-dropdown .ant-select-item-option', timeout=10000)
|
|
66
73
|
opts = await page.locator('.ant-select-dropdown .ant-select-item-option').all_inner_texts()
|
|
67
|
-
ok(any('未安装' in o for o in opts), f'下拉含(未安装)标记:{[o for o in opts if "未安装" in o]!r}')
|
|
68
74
|
disabled = page.locator('.ant-select-dropdown .ant-select-item-option-disabled')
|
|
69
75
|
dis_n = await disabled.count()
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
ok(
|
|
76
|
+
if EXPECT_OFF:
|
|
77
|
+
ok(any('未安装' in o for o in opts), f'下拉含(未安装)标记:{[o for o in opts if "未安装" in o]!r}')
|
|
78
|
+
ok(dis_n == 1, f'禁用选项=1(实际 {dis_n})')
|
|
79
|
+
if dis_n == 1:
|
|
80
|
+
ok('dsh' in (await disabled.first.inner_text()), '禁用项为 dsh')
|
|
81
|
+
else:
|
|
82
|
+
print(f' · 下拉选项={len(opts)},禁用={dis_n}(全部安装时为 0)', flush=True)
|
|
73
83
|
await page.screenshot(path=f'{SHOT}/harness-2-agent-select-disabled.png', full_page=False)
|
|
74
84
|
await page.keyboard.press('Escape')
|
|
75
85
|
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpsLog Agent 归属 + ops_log/recipe_log 工具 E2E(隔离实例 :3021)
|
|
3
|
+
*
|
|
4
|
+
* 验证:
|
|
5
|
+
* 1) Agent dcw_control 下发 → audit: actorKind=agent, actorName=「Channel名/成员名」(非 UUID)
|
|
6
|
+
* 2) ops_log / recipe_log 注入全部 harness worker 的工具面(agent-tools/list)
|
|
7
|
+
* 3) REST 直调 ops_log/recipe_log:能看到 来源=Agent 条目 + 配方下发/优化开窗
|
|
8
|
+
* 4) 负向:未绑定节点查询被拒
|
|
9
|
+
* 5) 真实 LLM 任务 ×4 引擎(omp/codex/dsh/opencode):Agent 自主调用两工具并在交付中
|
|
10
|
+
* 回带 LOGCHECK-OK / RECIPECHECK-OK 标记(mock 引擎无 LLM 回合,由 2/3 覆盖)
|
|
11
|
+
* 用法:NO_PROXY='127.0.0.1,localhost' node scripts/_dbg-opslog-agent-e2e.mjs [base]
|
|
12
|
+
*/
|
|
13
|
+
const BASE = process.argv[2] ?? 'http://127.0.0.1:3021'
|
|
14
|
+
const TAG = `ol${Math.random().toString(36).slice(2, 6)}`
|
|
15
|
+
let pass = 0
|
|
16
|
+
let fail = 0
|
|
17
|
+
const ok = (cond, name, extra = '') => {
|
|
18
|
+
if (cond) { pass++; console.log(` ✓ ${name}`) }
|
|
19
|
+
else { fail++; console.log(` ✗ ${name} ${extra}`) }
|
|
20
|
+
}
|
|
21
|
+
const sleep = ms => new Promise(r => setTimeout(r, ms))
|
|
22
|
+
const api = async (method, path, { body, token } = {}) => {
|
|
23
|
+
const res = await fetch(`${BASE}${path}`, {
|
|
24
|
+
method,
|
|
25
|
+
headers: { 'content-type': 'application/json', ...(token ? { authorization: `Bearer ${token}` } : {}) },
|
|
26
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
27
|
+
signal: AbortSignal.timeout(30_000),
|
|
28
|
+
})
|
|
29
|
+
return { status: res.status, ...(await res.json().catch(() => ({}))) }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const ENGINES = [
|
|
33
|
+
{ key: 'omp', harness: 'omp', cfg: { provider: 'zhipu-coding-plan', model: 'glm-5.3-flash' } },
|
|
34
|
+
{ key: 'codex', harness: 'codex', cfg: { model: 'glm-5.3-flash', approvalPolicy: 'never' } },
|
|
35
|
+
{ key: 'dsh', harness: 'dsh', cfg: { provider: 'ustc', model: 'glm-5.3-flash' } },
|
|
36
|
+
{ key: 'opencode', harness: 'opencode', cfg: { model: 'zhipuai-coding-plan/glm-5.3-flash' } },
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
async function main() {
|
|
40
|
+
console.log(`━━━ OpsLog/Recipe 工具 E2E @ ${BASE} (tag=${TAG}) ━━━`)
|
|
41
|
+
|
|
42
|
+
// ── 0. admin 登录(用户名) ──
|
|
43
|
+
const login = await api('POST', '/api/users/login', { body: { email: 'admin', password: 'admin123' } })
|
|
44
|
+
const token = login.data?.token
|
|
45
|
+
ok(Boolean(token), 'admin 用户名登录')
|
|
46
|
+
if (!token) process.exit(1)
|
|
47
|
+
|
|
48
|
+
// ── 1. 产线 + mock 节点 + 配方(+下发) ──
|
|
49
|
+
const line = (await api('POST', '/api/workshop/dcw/lines', { body: { name: `opsline-${TAG}` }, token })).data?.line
|
|
50
|
+
ok(Boolean(line?.id), `产线创建 ${line?.id ?? ''}`)
|
|
51
|
+
const node = (await api('POST', '/api/workshop/dcw', {
|
|
52
|
+
body: { name: `opsnode-${TAG}`, templateRef: 'temp-sp', driver: 'mock', driverConfig: { key: `opsnode-${TAG}` }, min: 0, max: 100, unit: '℃', lineId: line.id },
|
|
53
|
+
token,
|
|
54
|
+
})).data?.node
|
|
55
|
+
ok(Boolean(node?.id), `mock 数控节点创建 ${node?.id ?? ''}`)
|
|
56
|
+
const product = (await api('POST', '/api/workshop/dcw/products', {
|
|
57
|
+
body: { name: `opsproduct-${TAG}`, lineId: line.id },
|
|
58
|
+
token,
|
|
59
|
+
})).data?.product
|
|
60
|
+
ok(Boolean(product?.id), `产品创建 ${product?.id ?? ''}`)
|
|
61
|
+
const recipe = (await api('POST', '/api/workshop/dcw/recipes', {
|
|
62
|
+
body: { name: `opsrecipe-${TAG}`, productId: product?.id, params: [{ nodeId: node.id, value: 42, min: 0, max: 100 }] },
|
|
63
|
+
token,
|
|
64
|
+
})).data?.recipe ?? (await api('GET', '/api/workshop/dcw/recipes', { token })).data?.recipes?.find(r => r.name === `opsrecipe-${TAG}`)
|
|
65
|
+
ok(Boolean(recipe?.id), `配方创建 ${recipe?.id ?? ''}`)
|
|
66
|
+
const applied = await api('POST', `/api/workshop/dcw/recipes/${recipe.id}/apply`, { body: {}, token })
|
|
67
|
+
ok(applied.status === 200 || applied.pending === true, `配方一键下发(status=${applied.status} ${applied.message ?? ''})`)
|
|
68
|
+
|
|
69
|
+
// ── 2. 每 harness:channel(mock lead)+ worker + 绑定 ──
|
|
70
|
+
const members = {}
|
|
71
|
+
for (const e of [...ENGINES, { key: 'mock', harness: 'mock', cfg: { delayMs: 50 } }]) {
|
|
72
|
+
const ch = (await api('POST', '/api/workshop/channels', {
|
|
73
|
+
body: { name: `opslog-${e.key}-${TAG}`, leadAgent: { name: `lead-${TAG}`, harness: 'mock', config: { delayMs: 60 } } },
|
|
74
|
+
token,
|
|
75
|
+
})).data
|
|
76
|
+
const tpl = await api('POST', '/api/workshop/agents', {
|
|
77
|
+
body: { name: `ops-${e.key}-${TAG}`, harness: e.harness, config: { ...e.cfg, systemPromptPrefix: '你是产线操作员:严格按任务执行,只做任务要求的事,完成后立即调用 complete_task。' } },
|
|
78
|
+
token,
|
|
79
|
+
})
|
|
80
|
+
const join = await api('POST', `/api/workshop/channels/${ch.channelId}/agents`, { body: { agentId: tpl.data.id, role: 'worker' }, token })
|
|
81
|
+
const instId = join.data?.id
|
|
82
|
+
const bind = await api('POST', '/api/workshop/agent-tools/bindings', { body: { agentId: instId, nodeId: node.id, kind: 'dcw', mode: 'auto' }, token })
|
|
83
|
+
members[e.key] = { channelId: ch.channelId, instId, name: `ops-${e.key}-${TAG}` }
|
|
84
|
+
ok(Boolean(instId) && bind.code === 0, `${e.harness} worker 建号+绑定(bind=${bind.code === 0 ? 'ok' : bind.message})`)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ── 3. 工具面注入断言(全 harness 一致) ──
|
|
88
|
+
for (const [k, m] of Object.entries(members)) {
|
|
89
|
+
const list = await api('GET', `/api/workshop/agent-tools/list?agentId=${m.instId}`, { token })
|
|
90
|
+
const names = ((list.data?.tools) ?? []).map(t => t.name)
|
|
91
|
+
ok(names.includes('ops_log') && names.includes('recipe_log'), `[${k}] 工具面含 ops_log+recipe_log`)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ── 4. Agent 下发(mock 直调:mock 驱动确定性 ACK,无需 PLC)→ 审计归属 ──
|
|
95
|
+
const wr = await api('POST', '/api/workshop/agent-tools/invoke', {
|
|
96
|
+
body: { agentId: members.omp.instId, tool: 'dcw_control', args: { node_id: node.id, value: 55, task_id: 'e2e-opslog' } },
|
|
97
|
+
token,
|
|
98
|
+
})
|
|
99
|
+
ok(wr.data?.result?.text?.includes('下发成功'), '[omp 直调] dcw_control 下发成功', wr.data?.result?.text?.slice(0, 80))
|
|
100
|
+
const audit = await api('GET', '/api/workshop/audit?limit=100&action=dcw.write.agent', { token })
|
|
101
|
+
const entry = ((audit.data?.entries) ?? []).find(x => x.targetId === node.id)
|
|
102
|
+
ok(Boolean(entry), 'audit 出现 dcw.write.agent 条目')
|
|
103
|
+
ok(entry?.actorKind === 'agent', `条目来源=agent(实际 ${entry?.actorKind})`)
|
|
104
|
+
ok(entry?.actorName === `opslog-omp-${TAG}/ops-omp-${TAG}`, `操作者=Channel/成员(实际 ${entry?.actorName})`)
|
|
105
|
+
|
|
106
|
+
// ── 5. 工具直调查询 ──
|
|
107
|
+
const q1 = await api('POST', '/api/workshop/agent-tools/invoke', {
|
|
108
|
+
body: { agentId: members.omp.instId, tool: 'ops_log', args: { minutes: 120 } },
|
|
109
|
+
token,
|
|
110
|
+
})
|
|
111
|
+
ok(q1.data?.result?.text?.includes('来源=Agent') && q1.data?.result?.text?.includes(`opslog-omp-${TAG}/ops-omp-${TAG}`), '[omp] ops_log 看到来源=Agent + 人话操作者', q1.data?.result?.text?.slice(0, 100))
|
|
112
|
+
const q2 = await api('POST', '/api/workshop/agent-tools/invoke', {
|
|
113
|
+
body: { agentId: members.omp.instId, tool: 'recipe_log', args: { minutes: 120 } },
|
|
114
|
+
token,
|
|
115
|
+
})
|
|
116
|
+
ok(q2.data?.result?.text?.includes('配方下发') || q2.data?.result?.text?.includes('优化开窗'), '[omp] recipe_log 看到配方下发/优化开窗', q2.data?.result?.text?.slice(0, 100))
|
|
117
|
+
const q3 = await api('POST', '/api/workshop/agent-tools/invoke', {
|
|
118
|
+
body: { agentId: members.omp.instId, tool: 'ops_log', args: { node_id: 'not-bound-node' } },
|
|
119
|
+
token,
|
|
120
|
+
})
|
|
121
|
+
ok(q3.data?.result?.isError === true, '负向:未绑定节点查询被拒')
|
|
122
|
+
|
|
123
|
+
// ── 6. 真实 LLM 任务 ×4:Agent 自主调用两工具并回带标记 ──
|
|
124
|
+
const tasks = {}
|
|
125
|
+
for (const e of ENGINES) {
|
|
126
|
+
const m = members[e.key]
|
|
127
|
+
const t = await api('POST', `/api/workshop/channels/${m.channelId}/tasks`, {
|
|
128
|
+
body: {
|
|
129
|
+
title: `opslog-check-${e.key}-${TAG}`,
|
|
130
|
+
parts: [{ text: `执行自查(严格按步骤,不要下发任何控制指令):
|
|
131
|
+
1. 调用工具 ops_log(minutes=180)查看你负责产线的运维日志;
|
|
132
|
+
2. 调用工具 recipe_log(minutes=180)查看配方下发与回退历史;
|
|
133
|
+
3. 在最终交付中原样包含两行标记(各占一行):LOGCHECK-OK 与 RECIPECHECK-OK,并各引用一条你看到的日志摘要(一句话)。
|
|
134
|
+
完成后调用 complete_task。` }],
|
|
135
|
+
assigneeId: m.instId,
|
|
136
|
+
},
|
|
137
|
+
token,
|
|
138
|
+
})
|
|
139
|
+
tasks[e.key] = t.data?.task?.id ?? t.data?.id
|
|
140
|
+
ok(Boolean(tasks[e.key]), `[${e.key}] 任务下发`)
|
|
141
|
+
}
|
|
142
|
+
const states = {}
|
|
143
|
+
const pollTask = async (id) => {
|
|
144
|
+
for (let i = 0; i < 3; i++) {
|
|
145
|
+
try {
|
|
146
|
+
const me = await api('GET', `/api/workshop/tasks/${id}`, { token })
|
|
147
|
+
return me.data?.state
|
|
148
|
+
}
|
|
149
|
+
catch { await sleep(3000) }
|
|
150
|
+
}
|
|
151
|
+
return undefined
|
|
152
|
+
}
|
|
153
|
+
const deadline = Date.now() + 20 * 60_000
|
|
154
|
+
while (Date.now() < deadline && Object.keys(states).length < ENGINES.length) {
|
|
155
|
+
for (const e of ENGINES) {
|
|
156
|
+
if (states[e.key]) continue
|
|
157
|
+
const st = await pollTask(tasks[e.key])
|
|
158
|
+
if (st && ['COMPLETED', 'FAILED', 'CANCELED'].includes(st)) states[e.key] = st
|
|
159
|
+
}
|
|
160
|
+
if (Object.keys(states).length < ENGINES.length) await sleep(6000)
|
|
161
|
+
}
|
|
162
|
+
for (const e of ENGINES) {
|
|
163
|
+
ok(states[e.key] === 'COMPLETED', `[${e.key}] 引擎任务 COMPLETED(state=${states[e.key] ?? 'RUNNING'})`)
|
|
164
|
+
// 交付标记在 任务 artifacts / channel messages / events 三处任一出现即可
|
|
165
|
+
const taskBlob = JSON.stringify((await api('GET', `/api/workshop/tasks/${tasks[e.key]}`, { token })).data ?? {})
|
|
166
|
+
const msgBlob = JSON.stringify((await api('GET', `/api/workshop/channels/${members[e.key].channelId}/messages?limit=200`, { token })).data ?? {})
|
|
167
|
+
const evBlob = JSON.stringify((await api('GET', `/api/workshop/channels/${members[e.key].channelId}/events?limit=400`, { token })).data ?? {})
|
|
168
|
+
const blob = taskBlob + msgBlob + evBlob
|
|
169
|
+
ok(blob.includes('LOGCHECK-OK'), `[${e.key}] 交付含 LOGCHECK-OK(Agent 真读到日志)`)
|
|
170
|
+
ok(blob.includes('RECIPECHECK-OK'), `[${e.key}] 交付含 RECIPECHECK-OK(Agent 真读到 Recipe 历史)`)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ── 清理 ──
|
|
174
|
+
for (const m of Object.values(members)) await api('DELETE', `/api/workshop/channels/${m.channelId}?purge=1`, { token }).catch(() => {})
|
|
175
|
+
for (const e of [...ENGINES, { key: 'mock' }]) {
|
|
176
|
+
const list = await api('GET', '/api/workshop/agents', { token })
|
|
177
|
+
const tpl = (list.data ?? []).find(x => x.name === `ops-${e.key}-${TAG}`)
|
|
178
|
+
if (tpl) await api('DELETE', `/api/workshop/agents/${tpl.id}`, { token }).catch(() => {})
|
|
179
|
+
}
|
|
180
|
+
await api('DELETE', `/api/workshop/dcw/${node.id}`, { token }).catch(() => {})
|
|
181
|
+
await api('DELETE', `/api/workshop/dcw/recipes/${recipe.id}`, { token }).catch(() => {})
|
|
182
|
+
await api('DELETE', `/api/workshop/dcw/lines/${line.id}`, { token }).catch(() => {})
|
|
183
|
+
|
|
184
|
+
console.log(`\n━━━ OpsLog E2E: ${pass} passed / ${fail} failed ━━━`)
|
|
185
|
+
process.exit(fail === 0 ? 0 : 1)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
main().catch((err) => {
|
|
189
|
+
console.error('E2E 异常:', err)
|
|
190
|
+
process.exit(1)
|
|
191
|
+
})
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* aw-expose —— 把本机 AgentWorkShop 通过 Cloudflare Tunnel 映射到公网。
|
|
4
|
+
*
|
|
5
|
+
* 用法(在本机已能访问 Web UI 的前提下):
|
|
6
|
+
* node scripts/aw-expose.mjs # 自动探测本机实例(默认端口 3001/顺延)
|
|
7
|
+
* node scripts/aw-expose.mjs --port 3002 # 指定本地端口
|
|
8
|
+
* node scripts/aw-expose.mjs --token <TUNNEL_TOKEN> # 具名隧道(绑定自己的域名;token 来自
|
|
9
|
+
* # Cloudflare Zero Trust → Networks → Tunnels → Create tunnel 的安装令牌,
|
|
10
|
+
* # 也可用环境变量 CLOUDFLARE_TUNNEL_TOKEN 传入,避免进入 shell 历史)
|
|
11
|
+
*
|
|
12
|
+
* 两种模式:
|
|
13
|
+
* - 快速隧道(默认,免账号):分配 https://<随机>.trycloudflare.com 公网地址,每次启动会变;
|
|
14
|
+
* - 具名隧道(--token):固定绑定你 Cloudflare 账号里的域名,地址长期不变,生产推荐。
|
|
15
|
+
*
|
|
16
|
+
* 行为:
|
|
17
|
+
* 1) 定位 cloudflared(PATH → Windows 默认安装位 → ~/.AgentWorkShop/bin);
|
|
18
|
+
* 2) 探活 http://127.0.0.1:<port>/api/health,实例未启动则给出 `aw start` 提示(--start 自动拉起);
|
|
19
|
+
* 3) 拉起隧道进程,从输出解析公网 URL 并打印;
|
|
20
|
+
* 4) 常驻保活(cloudflared 崩溃自动重启,10s 退避);Ctrl+C 一并收尾本地实例(--start 模式)与隧道。
|
|
21
|
+
*
|
|
22
|
+
* 安全提示:公网地址任何人可访问,登录门/权限体系是唯一边界;建议用具名隧道 +
|
|
23
|
+
* Cloudflare Access(Zero Trust)做外层鉴权后再长期公开。
|
|
24
|
+
*/
|
|
25
|
+
import { spawn } from 'node:child_process'
|
|
26
|
+
import { existsSync } from 'node:fs'
|
|
27
|
+
import { homedir, platform } from 'node:os'
|
|
28
|
+
import { join } from 'node:path'
|
|
29
|
+
|
|
30
|
+
// ---------- 参数 ----------
|
|
31
|
+
const argv = process.argv.slice(2)
|
|
32
|
+
const argOf = (name) => {
|
|
33
|
+
const i = argv.indexOf(name)
|
|
34
|
+
return i >= 0 && argv[i + 1] ? argv[i + 1] : undefined
|
|
35
|
+
}
|
|
36
|
+
const hasFlag = name => argv.includes(name)
|
|
37
|
+
const PORT = argOf('--port') ?? '3001'
|
|
38
|
+
const LOCAL = `http://127.0.0.1:${PORT}`
|
|
39
|
+
const TUNNEL_TOKEN = argOf('--token') ?? process.env.CLOUDFLARE_TUNNEL_TOKEN ?? ''
|
|
40
|
+
const WANT_START = hasFlag('--start')
|
|
41
|
+
const IS_WIN = platform() === 'win32'
|
|
42
|
+
const BIN = join(homedir(), '.AgentWorkShop', 'bin')
|
|
43
|
+
|
|
44
|
+
const say = msg => console.log(`[aw-expose] ${msg}`)
|
|
45
|
+
const die = (msg) => {
|
|
46
|
+
say(`✖ ${msg}`)
|
|
47
|
+
process.exit(1)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ---------- 定位 cloudflared ----------
|
|
51
|
+
function findCloudflared() {
|
|
52
|
+
const candidates = [
|
|
53
|
+
argOf('--cloudflared'),
|
|
54
|
+
join(BIN, IS_WIN ? 'cloudflared.exe' : 'cloudflared'),
|
|
55
|
+
...(IS_WIN ? [join(process.env['ProgramFiles(x86)'] ?? 'C:\\Program Files (x86)', 'cloudflared', 'cloudflared.exe')] : ['/usr/local/bin/cloudflared', '/usr/bin/cloudflared']),
|
|
56
|
+
]
|
|
57
|
+
for (const c of candidates) {
|
|
58
|
+
if (c && existsSync(c)) return c
|
|
59
|
+
}
|
|
60
|
+
return null // 最后交给 PATH
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function healthy() {
|
|
64
|
+
try {
|
|
65
|
+
const res = await fetch(`${LOCAL}/api/health`, { signal: AbortSignal.timeout(3000) })
|
|
66
|
+
return res.ok
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function waitForHealthy(timeoutMs) {
|
|
74
|
+
const deadline = Date.now() + timeoutMs
|
|
75
|
+
while (Date.now() < deadline) {
|
|
76
|
+
if (await healthy()) return true
|
|
77
|
+
await new Promise(r => setTimeout(r, 1500))
|
|
78
|
+
}
|
|
79
|
+
return false
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ---------- 主流程 ----------
|
|
83
|
+
const cloudflared = findCloudflared()
|
|
84
|
+
if (!cloudflared) {
|
|
85
|
+
die(`未找到 cloudflared。安装方式任选其一:
|
|
86
|
+
winget install --id Cloudflare.cloudflared
|
|
87
|
+
# 或下载到 ~/.AgentWorkShop/bin/cloudflared.exe
|
|
88
|
+
https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/`)
|
|
89
|
+
}
|
|
90
|
+
say(`cloudflared: ${cloudflared}`)
|
|
91
|
+
say(`本地实例: ${LOCAL}`)
|
|
92
|
+
|
|
93
|
+
if (!(await healthy())) {
|
|
94
|
+
if (!WANT_START) {
|
|
95
|
+
die(`本地实例未就绪。请先启动(或加 --start 由本脚本拉起):
|
|
96
|
+
aw start # 生产模式(默认端口 3001,占用时自动顺延)
|
|
97
|
+
aw start --port ${PORT}`)
|
|
98
|
+
}
|
|
99
|
+
say('本地实例未就绪,--start 模式:拉起 aw start …')
|
|
100
|
+
const appRoot = process.env.AW_PACKAGE_ROOT ?? process.cwd()
|
|
101
|
+
const awBin = join(appRoot, 'bin', 'aw.mjs')
|
|
102
|
+
if (!existsSync(awBin)) die(`未找到 ${awBin};请在项目/包目录内运行,或用 --port 指向已运行实例`)
|
|
103
|
+
const app = spawn(process.execPath, [awBin, 'start', '--port', PORT], {
|
|
104
|
+
cwd: appRoot,
|
|
105
|
+
stdio: 'ignore',
|
|
106
|
+
detached: false,
|
|
107
|
+
shell: false,
|
|
108
|
+
env: { ...process.env },
|
|
109
|
+
})
|
|
110
|
+
app.on('exit', (code) => {
|
|
111
|
+
if (code !== 0 && code !== null) say(`aw start 退出(code=${code})`)
|
|
112
|
+
})
|
|
113
|
+
say('等待本地实例就绪(最长 120s)…')
|
|
114
|
+
if (!(await waitForHealthy(120_000))) die('本地实例 120s 内未就绪,放弃(可手工 aw start 后重试)')
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ---------- 隧道进程(崩溃自动重启) ----------
|
|
118
|
+
let quitting = false
|
|
119
|
+
let child = null
|
|
120
|
+
let currentUrl = ''
|
|
121
|
+
|
|
122
|
+
function startTunnel() {
|
|
123
|
+
const args = TUNNEL_TOKEN
|
|
124
|
+
? ['tunnel', '--no-autoupdate', 'run', '--token', TUNNEL_TOKEN]
|
|
125
|
+
: ['tunnel', '--no-autoupdate', '--url', LOCAL]
|
|
126
|
+
child = spawn(cloudflared, args, { stdio: ['ignore', 'pipe', 'pipe'], shell: false })
|
|
127
|
+
const scan = (buf) => {
|
|
128
|
+
for (const line of String(buf).split(/\r?\n/)) {
|
|
129
|
+
const m = line.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/i)
|
|
130
|
+
if (m && m[0] !== currentUrl) {
|
|
131
|
+
currentUrl = m[0]
|
|
132
|
+
say('公网地址(快速隧道,重启会变):')
|
|
133
|
+
console.log(`\n ${currentUrl}\n`)
|
|
134
|
+
say('浏览器打开即为本机 AgentWorkShop;Ctrl+C 结束映射。')
|
|
135
|
+
}
|
|
136
|
+
if (/Registered tunnel connection|connect.*registered/i.test(line) && TUNNEL_TOKEN) {
|
|
137
|
+
say('具名隧道已连接(域名以 Cloudflare Tunnels 配置为准)。')
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
child.stdout.on('data', scan)
|
|
142
|
+
child.stderr.on('data', scan)
|
|
143
|
+
child.on('exit', (code) => {
|
|
144
|
+
if (quitting) return
|
|
145
|
+
say(`隧道进程退出(code=${code}),10s 后重启…`)
|
|
146
|
+
setTimeout(startTunnel, 10_000)
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
startTunnel()
|
|
151
|
+
|
|
152
|
+
const cleanup = () => {
|
|
153
|
+
quitting = true
|
|
154
|
+
say('正在结束隧道…')
|
|
155
|
+
if (child) child.kill(IS_WIN ? undefined : 'SIGTERM')
|
|
156
|
+
process.exit(0)
|
|
157
|
+
}
|
|
158
|
+
process.on('SIGINT', cleanup)
|
|
159
|
+
process.on('SIGTERM', cleanup)
|
|
@@ -13,7 +13,7 @@ import { broadcastSceneEvent } from '../../../services/workshop/scene-events'
|
|
|
13
13
|
import { recordOps } from '../../../services/workshop/ops/ops'
|
|
14
14
|
|
|
15
15
|
export default defineApiHandler(async (event) => {
|
|
16
|
-
requireRole(event, ['admin', 'editor'])
|
|
16
|
+
const user = requireRole(event, ['admin', 'editor'])
|
|
17
17
|
bindDaqHost(broadcastSceneEvent)
|
|
18
18
|
const body = await readBody<DaqCreateInput>(event) ?? {}
|
|
19
19
|
const node = getDaqController().create(body)
|
|
@@ -11,7 +11,7 @@ import { recordOps } from '@/server/services/workshop/ops/ops'
|
|
|
11
11
|
import type { LineInput } from '#shared/dcw-protocol'
|
|
12
12
|
|
|
13
13
|
export default defineApiHandler(async (event) => {
|
|
14
|
-
requireRole(event, ['admin', 'editor'])
|
|
14
|
+
const user = requireRole(event, ['admin', 'editor'])
|
|
15
15
|
bindDcwBroadcast(broadcastSceneEvent)
|
|
16
16
|
const body = await readBody<LineInput>(event) ?? { name: '' }
|
|
17
17
|
const line = getDcwController().createLine(body)
|