@probelabs/visor 0.1.183-ee → 0.1.184-ee
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/dist/agent-protocol/task-live-update-slack.d.ts +24 -0
- package/dist/agent-protocol/task-live-update-slack.d.ts.map +1 -0
- package/dist/agent-protocol/task-live-update-teams.d.ts +25 -0
- package/dist/agent-protocol/task-live-update-teams.d.ts.map +1 -0
- package/dist/agent-protocol/task-live-update-telegram.d.ts +25 -0
- package/dist/agent-protocol/task-live-update-telegram.d.ts.map +1 -0
- package/dist/agent-protocol/task-live-updates.d.ts +102 -0
- package/dist/agent-protocol/task-live-updates.d.ts.map +1 -0
- package/dist/agent-protocol/task-progress-tool.d.ts.map +1 -1
- package/dist/agent-protocol/task-trace-resolution.d.ts +11 -0
- package/dist/agent-protocol/task-trace-resolution.d.ts.map +1 -0
- package/dist/agent-protocol/trace-serializer.d.ts.map +1 -1
- package/dist/agent-protocol/track-execution.d.ts +8 -0
- package/dist/agent-protocol/track-execution.d.ts.map +1 -1
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/frontends/slack-frontend.d.ts +2 -0
- package/dist/frontends/slack-frontend.d.ts.map +1 -1
- package/dist/frontends/teams-frontend.d.ts.map +1 -1
- package/dist/frontends/telegram-frontend.d.ts.map +1 -1
- package/dist/generated/config-schema.d.ts +110 -6
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/index.js +2239 -261
- package/dist/logger.d.ts +4 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/mcp-job-manager.d.ts +70 -0
- package/dist/mcp-job-manager.d.ts.map +1 -0
- package/dist/mcp-server.d.ts +6 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/runners/mcp-server-runner.d.ts +4 -0
- package/dist/runners/mcp-server-runner.d.ts.map +1 -1
- package/dist/runners/runner-factory.d.ts.map +1 -1
- package/dist/sdk/{a2a-frontend-5YDHFQXD.mjs → a2a-frontend-OI4OVSKC.mjs} +4 -4
- package/dist/sdk/check-provider-registry-RITJW67U.mjs +32 -0
- package/dist/sdk/check-provider-registry-ZZ6N4GDP.mjs +32 -0
- package/dist/sdk/{chunk-4BN2XI4X.mjs → chunk-4HIWZA6M.mjs} +2 -2
- package/dist/sdk/{chunk-RI4ONH5X.mjs → chunk-4MHHELVZ.mjs} +2 -2
- package/dist/sdk/{chunk-J27D43HS.mjs → chunk-4ZLYHSN4.mjs} +2 -2
- package/dist/sdk/{chunk-ZPYODGYA.mjs → chunk-6E625R3C.mjs} +19 -4
- package/dist/sdk/chunk-6E625R3C.mjs.map +1 -0
- package/dist/sdk/{chunk-GA2TYKSR.mjs → chunk-7XKHFRPN.mjs} +4 -4
- package/dist/sdk/{chunk-6C3R6E42.mjs → chunk-IY5PQ5EN.mjs} +30 -6
- package/dist/sdk/chunk-IY5PQ5EN.mjs.map +1 -0
- package/dist/sdk/{chunk-MFXPJUUE.mjs → chunk-PUHU6UY6.mjs} +4 -3
- package/dist/sdk/chunk-PUHU6UY6.mjs.map +1 -0
- package/dist/sdk/{chunk-XOAEKFKB.mjs → chunk-QLT42TX7.mjs} +2 -2
- package/dist/sdk/chunk-SRU5TFNY.mjs +620 -0
- package/dist/sdk/chunk-SRU5TFNY.mjs.map +1 -0
- package/dist/sdk/{chunk-P2K4VOMU.mjs → chunk-TSX3YS3F.mjs} +3 -3
- package/dist/sdk/{chunk-WKLJ57WF.mjs → chunk-UM7LGO2P.mjs} +6 -6
- package/dist/sdk/{chunk-7VTZDC2X.mjs → chunk-VPPBOKBQ.mjs} +2 -2
- package/dist/sdk/chunk-WZQMTD7W.mjs +33 -0
- package/dist/sdk/chunk-WZQMTD7W.mjs.map +1 -0
- package/dist/sdk/{chunk-ZOF5QT6U.mjs → chunk-YBXNG75V.mjs} +118 -10
- package/dist/sdk/chunk-YBXNG75V.mjs.map +1 -0
- package/dist/sdk/{chunk-UXB4XWEE.mjs → chunk-YYFSAAD6.mjs} +53 -51
- package/dist/sdk/chunk-YYFSAAD6.mjs.map +1 -0
- package/dist/sdk/{chunk-RHKPFJLG.mjs → chunk-ZNKL6ESZ.mjs} +2 -2
- package/dist/sdk/{chunk-IDL3AA3G.mjs → chunk-ZYDRR6PZ.mjs} +1150 -403
- package/dist/sdk/chunk-ZYDRR6PZ.mjs.map +1 -0
- package/dist/sdk/{command-executor-YNJOS77A.mjs → command-executor-LHUW77GR.mjs} +3 -3
- package/dist/sdk/{config-PCP6O6Y6.mjs → config-TVU5RWR5.mjs} +3 -3
- package/dist/sdk/{dist-3UGGEZB3.mjs → dist-PN5UHL6A.mjs} +429 -429
- package/dist/sdk/dist-PN5UHL6A.mjs.map +1 -0
- package/dist/sdk/{email-frontend-WSNADJPI.mjs → email-frontend-ECHQCFTR.mjs} +2 -2
- package/dist/sdk/{failure-condition-evaluator-IRFKTYZD.mjs → failure-condition-evaluator-USY3ISVA.mjs} +6 -6
- package/dist/sdk/{github-auth-BJQBLK2V.mjs → github-auth-UO4DMNCC.mjs} +2 -2
- package/dist/sdk/{github-frontend-DECYOBRN.mjs → github-frontend-2T5PWYD5.mjs} +6 -6
- package/dist/sdk/{host-CFM2ASDI.mjs → host-OJSMCLKK.mjs} +6 -6
- package/dist/sdk/{host-T4LNVU2H.mjs → host-RM6UJEPP.mjs} +7 -7
- package/dist/sdk/{knex-store-OEWSZEBY.mjs → knex-store-KCMFAMH5.mjs} +2 -2
- package/dist/sdk/{liquid-extensions-E3AKRX7P.mjs → liquid-extensions-KZIRR4OY.mjs} +4 -4
- package/dist/sdk/{loader-WRGI244P.mjs → loader-35YWX5UQ.mjs} +4 -4
- package/dist/sdk/{memory-store-OHUIXCWJ.mjs → memory-store-3JONK7AF.mjs} +3 -3
- package/dist/sdk/{opa-policy-engine-IVMCGVNA.mjs → opa-policy-engine-FY5D45YS.mjs} +2 -2
- package/dist/sdk/{prompt-state-LN57DQF3.mjs → prompt-state-VVJMONT3.mjs} +3 -3
- package/dist/sdk/{renderer-schema-BT2IXMLW.mjs → renderer-schema-JZRRU5CW.mjs} +2 -2
- package/dist/sdk/{routing-H2PQ57OA.mjs → routing-NNQQSLWA.mjs} +8 -8
- package/dist/sdk/{schedule-tool-2DPNSU63.mjs → schedule-tool-ADZ2ON4I.mjs} +15 -14
- package/dist/sdk/schedule-tool-EMNF3FPQ.mjs +38 -0
- package/dist/sdk/{schedule-tool-handler-NBEO46RV.mjs → schedule-tool-handler-3R3IC6VA.mjs} +15 -14
- package/dist/sdk/{schedule-tool-handler-KLHE2SOW.mjs → schedule-tool-handler-F76ZD2WU.mjs} +17 -16
- package/dist/sdk/sdk.d.mts +40 -0
- package/dist/sdk/sdk.d.ts +40 -0
- package/dist/sdk/sdk.js +1154 -176
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +14 -13
- package/dist/sdk/sdk.mjs.map +1 -1
- package/dist/sdk/{slack-frontend-DF5VL4OF.mjs → slack-frontend-K3TPGERM.mjs} +65 -9
- package/dist/sdk/slack-frontend-K3TPGERM.mjs.map +1 -0
- package/dist/sdk/{task-evaluator-OVMG7S56.mjs → task-evaluator-H3BXC7SE.mjs} +3 -3
- package/dist/sdk/{teams-frontend-DNW5GZP3.mjs → teams-frontend-6RRW533K.mjs} +54 -1
- package/dist/sdk/teams-frontend-6RRW533K.mjs.map +1 -0
- package/dist/sdk/{telegram-frontend-GA7OLADB.mjs → telegram-frontend-5UA77YAT.mjs} +48 -1
- package/dist/sdk/telegram-frontend-5UA77YAT.mjs.map +1 -0
- package/dist/sdk/{trace-helpers-26ZCAE2V.mjs → trace-helpers-OMF4C24T.mjs} +3 -3
- package/dist/sdk/{trace-serializer-KKBJHM7J.mjs → trace-serializer-EBHTHZYT.mjs} +3 -3
- package/dist/sdk/track-execution-3CHMGEPH.mjs +249 -0
- package/dist/sdk/track-execution-3CHMGEPH.mjs.map +1 -0
- package/dist/sdk/{utcp-check-provider-WI3QZ3W6.mjs → utcp-check-provider-Q4PD5EP2.mjs} +5 -5
- package/dist/sdk/workflow-check-provider-TC2G33WF.mjs +32 -0
- package/dist/sdk/workflow-check-provider-U4UXZ5YS.mjs +32 -0
- package/dist/sdk/{workflow-registry-YCZ3FCJC.mjs → workflow-registry-K56UTX36.mjs} +3 -3
- package/dist/slack/client.d.ts +14 -0
- package/dist/slack/client.d.ts.map +1 -1
- package/dist/slack/socket-runner.d.ts.map +1 -1
- package/dist/teams/client.d.ts +16 -0
- package/dist/teams/client.d.ts.map +1 -1
- package/dist/teams/webhook-runner.d.ts.map +1 -1
- package/dist/telegram/client.d.ts +17 -0
- package/dist/telegram/client.d.ts.map +1 -1
- package/dist/telegram/polling-runner.d.ts.map +1 -1
- package/dist/types/cli.d.ts +2 -0
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts +40 -0
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +4 -3
- package/dist/generated/config-schema.json +0 -4027
- package/dist/sdk/a2a-frontend-6LWBIPMS.mjs +0 -1734
- package/dist/sdk/a2a-frontend-6LWBIPMS.mjs.map +0 -1
- package/dist/sdk/check-provider-registry-WSEVHJEV.mjs +0 -31
- package/dist/sdk/check-provider-registry-YRADEEQY.mjs +0 -31
- package/dist/sdk/chunk-34QX63WK.mjs +0 -244
- package/dist/sdk/chunk-34QX63WK.mjs.map +0 -1
- package/dist/sdk/chunk-54KOAC4W.mjs +0 -665
- package/dist/sdk/chunk-6C3R6E42.mjs.map +0 -1
- package/dist/sdk/chunk-7W5QCO4Y.mjs +0 -5943
- package/dist/sdk/chunk-7W5QCO4Y.mjs.map +0 -1
- package/dist/sdk/chunk-7XRSCOKE.mjs +0 -825
- package/dist/sdk/chunk-FT3I25QV.mjs +0 -251
- package/dist/sdk/chunk-FT3I25QV.mjs.map +0 -1
- package/dist/sdk/chunk-G7GSN3SK.mjs +0 -390
- package/dist/sdk/chunk-G7GSN3SK.mjs.map +0 -1
- package/dist/sdk/chunk-IDL3AA3G.mjs.map +0 -1
- package/dist/sdk/chunk-J27D43HS.mjs.map +0 -1
- package/dist/sdk/chunk-MEB2TTIE.mjs +0 -157
- package/dist/sdk/chunk-MEB2TTIE.mjs.map +0 -1
- package/dist/sdk/chunk-MFXPJUUE.mjs.map +0 -1
- package/dist/sdk/chunk-NPSLGKXB.mjs +0 -1502
- package/dist/sdk/chunk-P2K4VOMU.mjs.map +0 -1
- package/dist/sdk/chunk-PQWZ6NFL.mjs +0 -459
- package/dist/sdk/chunk-PQWZ6NFL.mjs.map +0 -1
- package/dist/sdk/chunk-S5FSRHMY.mjs +0 -139
- package/dist/sdk/chunk-S5FSRHMY.mjs.map +0 -1
- package/dist/sdk/chunk-TFUQ2D5L.mjs +0 -307
- package/dist/sdk/chunk-TFUQ2D5L.mjs.map +0 -1
- package/dist/sdk/chunk-UCMJJ3IM.mjs +0 -227
- package/dist/sdk/chunk-UCMJJ3IM.mjs.map +0 -1
- package/dist/sdk/chunk-UFHOIB3R.mjs +0 -482
- package/dist/sdk/chunk-UFHOIB3R.mjs.map +0 -1
- package/dist/sdk/chunk-UXB4XWEE.mjs.map +0 -1
- package/dist/sdk/chunk-V45TITKX.mjs +0 -739
- package/dist/sdk/chunk-V45TITKX.mjs.map +0 -1
- package/dist/sdk/chunk-WKLJ57WF.mjs.map +0 -1
- package/dist/sdk/chunk-ZOF5QT6U.mjs.map +0 -1
- package/dist/sdk/chunk-ZPYODGYA.mjs.map +0 -1
- package/dist/sdk/command-executor-3AHGIYQG.mjs +0 -14
- package/dist/sdk/config-JE4HKTWW.mjs +0 -16
- package/dist/sdk/dist-3UGGEZB3.mjs.map +0 -1
- package/dist/sdk/failure-condition-evaluator-H3PBFBYT.mjs +0 -18
- package/dist/sdk/github-auth-27SZGPEC.mjs +0 -196
- package/dist/sdk/github-auth-BJQBLK2V.mjs.map +0 -1
- package/dist/sdk/github-frontend-TZRBOQCN.mjs +0 -1394
- package/dist/sdk/github-frontend-TZRBOQCN.mjs.map +0 -1
- package/dist/sdk/lazy-otel-5NH4ZJJM.mjs +0 -24
- package/dist/sdk/liquid-extensions-P6KDYILF.mjs +0 -25
- package/dist/sdk/memory-store-K5N7MC7U.mjs +0 -12
- package/dist/sdk/metrics-JTOG2HNO.mjs +0 -41
- package/dist/sdk/prompt-state-YPICX7PI.mjs +0 -16
- package/dist/sdk/renderer-schema-KOIH75RZ.mjs +0 -51
- package/dist/sdk/renderer-schema-KOIH75RZ.mjs.map +0 -1
- package/dist/sdk/routing-JMZ7HDCC.mjs +0 -26
- package/dist/sdk/schedule-tool-4M45RK3E.mjs +0 -37
- package/dist/sdk/schedule-tool-4M45RK3E.mjs.map +0 -1
- package/dist/sdk/schedule-tool-handler-KLHE2SOW.mjs.map +0 -1
- package/dist/sdk/schedule-tool-handler-NBEO46RV.mjs.map +0 -1
- package/dist/sdk/slack-frontend-BPWXNIHE.mjs +0 -929
- package/dist/sdk/slack-frontend-BPWXNIHE.mjs.map +0 -1
- package/dist/sdk/slack-frontend-DF5VL4OF.mjs.map +0 -1
- package/dist/sdk/task-evaluator-GQYDOSGT.mjs +0 -1392
- package/dist/sdk/task-evaluator-GQYDOSGT.mjs.map +0 -1
- package/dist/sdk/teams-frontend-DNW5GZP3.mjs.map +0 -1
- package/dist/sdk/telegram-frontend-GA7OLADB.mjs.map +0 -1
- package/dist/sdk/trace-helpers-26ZCAE2V.mjs.map +0 -1
- package/dist/sdk/trace-helpers-XV5GAX5L.mjs +0 -29
- package/dist/sdk/trace-helpers-XV5GAX5L.mjs.map +0 -1
- package/dist/sdk/trace-serializer-KKBJHM7J.mjs.map +0 -1
- package/dist/sdk/track-execution-3EC24C2X.mjs +0 -163
- package/dist/sdk/track-execution-3EC24C2X.mjs.map +0 -1
- package/dist/sdk/track-execution-66RLL6QT.mjs +0 -143
- package/dist/sdk/track-execution-66RLL6QT.mjs.map +0 -1
- package/dist/sdk/utcp-check-provider-JLIYF5HH.mjs +0 -16
- package/dist/sdk/utcp-check-provider-JLIYF5HH.mjs.map +0 -1
- package/dist/sdk/utcp-check-provider-WI3QZ3W6.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-X2UREEH7.mjs +0 -31
- package/dist/sdk/workflow-check-provider-X2UREEH7.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-YXALZNAQ.mjs +0 -31
- package/dist/sdk/workflow-check-provider-YXALZNAQ.mjs.map +0 -1
- package/dist/sdk/workflow-registry-X2IPY35M.mjs +0 -12
- package/dist/sdk/workflow-registry-X2IPY35M.mjs.map +0 -1
- package/dist/sdk/workflow-registry-YCZ3FCJC.mjs.map +0 -1
- /package/dist/sdk/{a2a-frontend-5YDHFQXD.mjs.map → a2a-frontend-OI4OVSKC.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-WSEVHJEV.mjs.map → check-provider-registry-RITJW67U.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-YRADEEQY.mjs.map → check-provider-registry-ZZ6N4GDP.mjs.map} +0 -0
- /package/dist/sdk/{chunk-4BN2XI4X.mjs.map → chunk-4HIWZA6M.mjs.map} +0 -0
- /package/dist/sdk/{chunk-RI4ONH5X.mjs.map → chunk-4MHHELVZ.mjs.map} +0 -0
- /package/dist/sdk/{chunk-54KOAC4W.mjs.map → chunk-4ZLYHSN4.mjs.map} +0 -0
- /package/dist/sdk/{chunk-GA2TYKSR.mjs.map → chunk-7XKHFRPN.mjs.map} +0 -0
- /package/dist/sdk/{chunk-XOAEKFKB.mjs.map → chunk-QLT42TX7.mjs.map} +0 -0
- /package/dist/sdk/{chunk-7XRSCOKE.mjs.map → chunk-TSX3YS3F.mjs.map} +0 -0
- /package/dist/sdk/{chunk-NPSLGKXB.mjs.map → chunk-UM7LGO2P.mjs.map} +0 -0
- /package/dist/sdk/{chunk-7VTZDC2X.mjs.map → chunk-VPPBOKBQ.mjs.map} +0 -0
- /package/dist/sdk/{chunk-RHKPFJLG.mjs.map → chunk-ZNKL6ESZ.mjs.map} +0 -0
- /package/dist/sdk/{command-executor-3AHGIYQG.mjs.map → command-executor-LHUW77GR.mjs.map} +0 -0
- /package/dist/sdk/{command-executor-YNJOS77A.mjs.map → config-TVU5RWR5.mjs.map} +0 -0
- /package/dist/sdk/{email-frontend-WSNADJPI.mjs.map → email-frontend-ECHQCFTR.mjs.map} +0 -0
- /package/dist/sdk/{config-JE4HKTWW.mjs.map → failure-condition-evaluator-USY3ISVA.mjs.map} +0 -0
- /package/dist/sdk/{github-auth-27SZGPEC.mjs.map → github-auth-UO4DMNCC.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-DECYOBRN.mjs.map → github-frontend-2T5PWYD5.mjs.map} +0 -0
- /package/dist/sdk/{host-CFM2ASDI.mjs.map → host-OJSMCLKK.mjs.map} +0 -0
- /package/dist/sdk/{host-T4LNVU2H.mjs.map → host-RM6UJEPP.mjs.map} +0 -0
- /package/dist/sdk/{knex-store-OEWSZEBY.mjs.map → knex-store-KCMFAMH5.mjs.map} +0 -0
- /package/dist/sdk/{config-PCP6O6Y6.mjs.map → liquid-extensions-KZIRR4OY.mjs.map} +0 -0
- /package/dist/sdk/{loader-WRGI244P.mjs.map → loader-35YWX5UQ.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-H3PBFBYT.mjs.map → memory-store-3JONK7AF.mjs.map} +0 -0
- /package/dist/sdk/{opa-policy-engine-IVMCGVNA.mjs.map → opa-policy-engine-FY5D45YS.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-IRFKTYZD.mjs.map → prompt-state-VVJMONT3.mjs.map} +0 -0
- /package/dist/sdk/{renderer-schema-BT2IXMLW.mjs.map → renderer-schema-JZRRU5CW.mjs.map} +0 -0
- /package/dist/sdk/{lazy-otel-5NH4ZJJM.mjs.map → routing-NNQQSLWA.mjs.map} +0 -0
- /package/dist/sdk/{liquid-extensions-E3AKRX7P.mjs.map → schedule-tool-ADZ2ON4I.mjs.map} +0 -0
- /package/dist/sdk/{liquid-extensions-P6KDYILF.mjs.map → schedule-tool-EMNF3FPQ.mjs.map} +0 -0
- /package/dist/sdk/{memory-store-K5N7MC7U.mjs.map → schedule-tool-handler-3R3IC6VA.mjs.map} +0 -0
- /package/dist/sdk/{memory-store-OHUIXCWJ.mjs.map → schedule-tool-handler-F76ZD2WU.mjs.map} +0 -0
- /package/dist/sdk/{task-evaluator-OVMG7S56.mjs.map → task-evaluator-H3BXC7SE.mjs.map} +0 -0
- /package/dist/sdk/{metrics-JTOG2HNO.mjs.map → trace-helpers-OMF4C24T.mjs.map} +0 -0
- /package/dist/sdk/{prompt-state-LN57DQF3.mjs.map → trace-serializer-EBHTHZYT.mjs.map} +0 -0
- /package/dist/sdk/{prompt-state-YPICX7PI.mjs.map → utcp-check-provider-Q4PD5EP2.mjs.map} +0 -0
- /package/dist/sdk/{routing-H2PQ57OA.mjs.map → workflow-check-provider-TC2G33WF.mjs.map} +0 -0
- /package/dist/sdk/{routing-JMZ7HDCC.mjs.map → workflow-check-provider-U4UXZ5YS.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-2DPNSU63.mjs.map → workflow-registry-K56UTX36.mjs.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
process.env.VISOR_VERSION = '0.1.
|
|
3
|
-
process.env.PROBE_VERSION = '0.6.0-
|
|
4
|
-
process.env.VISOR_COMMIT_SHA = '
|
|
5
|
-
process.env.VISOR_COMMIT_SHORT = '
|
|
2
|
+
process.env.VISOR_VERSION = '0.1.184';
|
|
3
|
+
process.env.PROBE_VERSION = '0.6.0-rc311';
|
|
4
|
+
process.env.VISOR_COMMIT_SHA = 'fa523b7486d2550f30d84ebab4c46da43fafecaf';
|
|
5
|
+
process.env.VISOR_COMMIT_SHORT = 'fa523b7';
|
|
6
6
|
/******/ (() => { // webpackBootstrap
|
|
7
7
|
/******/ var __webpack_modules__ = ({
|
|
8
8
|
|
|
@@ -293448,6 +293448,868 @@ async function evaluateAndStore(taskId, store, config) {
|
|
|
293448
293448
|
}
|
|
293449
293449
|
|
|
293450
293450
|
|
|
293451
|
+
/***/ }),
|
|
293452
|
+
|
|
293453
|
+
/***/ 90535:
|
|
293454
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
293455
|
+
|
|
293456
|
+
"use strict";
|
|
293457
|
+
|
|
293458
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
293459
|
+
exports.SlackTaskLiveUpdateSink = void 0;
|
|
293460
|
+
const markdown_1 = __nccwpck_require__(34907);
|
|
293461
|
+
const logger_1 = __nccwpck_require__(86999);
|
|
293462
|
+
class SlackTaskLiveUpdateSink {
|
|
293463
|
+
slack;
|
|
293464
|
+
channel;
|
|
293465
|
+
threadTs;
|
|
293466
|
+
kind = 'slack';
|
|
293467
|
+
messageTs;
|
|
293468
|
+
constructor(slack, channel, threadTs, initialMessageTs) {
|
|
293469
|
+
this.slack = slack;
|
|
293470
|
+
this.channel = channel;
|
|
293471
|
+
this.threadTs = threadTs;
|
|
293472
|
+
this.messageTs = initialMessageTs;
|
|
293473
|
+
}
|
|
293474
|
+
async start() {
|
|
293475
|
+
logger_1.logger.debug(`[TaskLiveUpdates][Slack] Initialized live update sink for channel=${this.channel} thread=${this.threadTs}`);
|
|
293476
|
+
return null;
|
|
293477
|
+
}
|
|
293478
|
+
async update(text) {
|
|
293479
|
+
return this.publish(text, 'progress');
|
|
293480
|
+
}
|
|
293481
|
+
async complete(text) {
|
|
293482
|
+
return this.publish(text, 'final');
|
|
293483
|
+
}
|
|
293484
|
+
async fail(text) {
|
|
293485
|
+
return this.publish(text, 'final');
|
|
293486
|
+
}
|
|
293487
|
+
async publish(text, mode) {
|
|
293488
|
+
if (this.messageTs) {
|
|
293489
|
+
logger_1.logger.debug(`[TaskLiveUpdates][Slack] Updating existing message ts=${this.messageTs} in channel=${this.channel}`);
|
|
293490
|
+
const updated = await this.slack.chat.update({
|
|
293491
|
+
channel: this.channel,
|
|
293492
|
+
ts: this.messageTs,
|
|
293493
|
+
text: (0, markdown_1.formatSlackText)(text),
|
|
293494
|
+
});
|
|
293495
|
+
if (updated?.ok)
|
|
293496
|
+
return null;
|
|
293497
|
+
logger_1.logger.warn(`[TaskLiveUpdates][Slack] chat.update failed for ts=${this.messageTs} error=${updated?.error || 'unknown_error'}; falling back to chat.postMessage`);
|
|
293498
|
+
}
|
|
293499
|
+
logger_1.logger.info(`[TaskLiveUpdates][Slack] Posting live update message in channel=${this.channel} thread=${this.threadTs}`);
|
|
293500
|
+
const posted = await this.slack.chat.postMessage({
|
|
293501
|
+
channel: this.channel,
|
|
293502
|
+
thread_ts: this.threadTs,
|
|
293503
|
+
text: (0, markdown_1.formatSlackText)(text),
|
|
293504
|
+
});
|
|
293505
|
+
if (posted?.ok && posted.ts) {
|
|
293506
|
+
const previousTs = this.messageTs;
|
|
293507
|
+
this.messageTs = posted.ts;
|
|
293508
|
+
if (mode === 'final' && previousTs && previousTs !== posted.ts) {
|
|
293509
|
+
const deleted = await this.slack.chat.delete({
|
|
293510
|
+
channel: this.channel,
|
|
293511
|
+
ts: previousTs,
|
|
293512
|
+
});
|
|
293513
|
+
if (!deleted?.ok) {
|
|
293514
|
+
logger_1.logger.warn(`[TaskLiveUpdates][Slack] chat.delete failed for stale live update ts=${previousTs} error=${deleted?.error || 'unknown_error'}`);
|
|
293515
|
+
}
|
|
293516
|
+
else {
|
|
293517
|
+
logger_1.logger.info(`[TaskLiveUpdates][Slack] Removed stale live update message ts=${previousTs} after final fallback post`);
|
|
293518
|
+
}
|
|
293519
|
+
}
|
|
293520
|
+
return {
|
|
293521
|
+
ref: {
|
|
293522
|
+
slack_live_update_channel: this.channel,
|
|
293523
|
+
slack_live_update_ts: posted.ts,
|
|
293524
|
+
slack_live_update_thread_ts: this.threadTs,
|
|
293525
|
+
},
|
|
293526
|
+
};
|
|
293527
|
+
}
|
|
293528
|
+
return null;
|
|
293529
|
+
}
|
|
293530
|
+
}
|
|
293531
|
+
exports.SlackTaskLiveUpdateSink = SlackTaskLiveUpdateSink;
|
|
293532
|
+
|
|
293533
|
+
|
|
293534
|
+
/***/ }),
|
|
293535
|
+
|
|
293536
|
+
/***/ 82309:
|
|
293537
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
293538
|
+
|
|
293539
|
+
"use strict";
|
|
293540
|
+
|
|
293541
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
293542
|
+
exports.TeamsTaskLiveUpdateSink = void 0;
|
|
293543
|
+
const markdown_1 = __nccwpck_require__(37349);
|
|
293544
|
+
const logger_1 = __nccwpck_require__(86999);
|
|
293545
|
+
class TeamsTaskLiveUpdateSink {
|
|
293546
|
+
teams;
|
|
293547
|
+
conversationReference;
|
|
293548
|
+
replyToActivityId;
|
|
293549
|
+
kind = 'teams';
|
|
293550
|
+
activityId;
|
|
293551
|
+
constructor(teams, conversationReference, replyToActivityId, initialActivityId) {
|
|
293552
|
+
this.teams = teams;
|
|
293553
|
+
this.conversationReference = conversationReference;
|
|
293554
|
+
this.replyToActivityId = replyToActivityId;
|
|
293555
|
+
this.activityId = initialActivityId;
|
|
293556
|
+
}
|
|
293557
|
+
async start() {
|
|
293558
|
+
logger_1.logger.debug('[TaskLiveUpdates][Teams] Initialized live update sink');
|
|
293559
|
+
return null;
|
|
293560
|
+
}
|
|
293561
|
+
async update(text) {
|
|
293562
|
+
return this.publish(text, 'progress');
|
|
293563
|
+
}
|
|
293564
|
+
async complete(text) {
|
|
293565
|
+
return this.publish(text, 'final');
|
|
293566
|
+
}
|
|
293567
|
+
async fail(text) {
|
|
293568
|
+
return this.publish(text, 'final');
|
|
293569
|
+
}
|
|
293570
|
+
async publish(text, mode) {
|
|
293571
|
+
const formatted = (0, markdown_1.formatTeamsText)(text);
|
|
293572
|
+
if (this.activityId) {
|
|
293573
|
+
logger_1.logger.debug(`[TaskLiveUpdates][Teams] Updating existing activityId=${this.activityId}`);
|
|
293574
|
+
const updated = await this.teams.updateMessage({
|
|
293575
|
+
conversationReference: this.conversationReference,
|
|
293576
|
+
activityId: this.activityId,
|
|
293577
|
+
text: formatted,
|
|
293578
|
+
});
|
|
293579
|
+
if (updated?.ok)
|
|
293580
|
+
return null;
|
|
293581
|
+
logger_1.logger.warn(`[TaskLiveUpdates][Teams] updateMessage failed for activityId=${this.activityId} error=${updated?.error || 'unknown_error'}; falling back to sendMessage`);
|
|
293582
|
+
}
|
|
293583
|
+
logger_1.logger.info('[TaskLiveUpdates][Teams] Posting live update message');
|
|
293584
|
+
const posted = await this.teams.sendMessage({
|
|
293585
|
+
conversationReference: this.conversationReference,
|
|
293586
|
+
text: formatted,
|
|
293587
|
+
...(this.replyToActivityId ? { replyToActivityId: this.replyToActivityId } : {}),
|
|
293588
|
+
});
|
|
293589
|
+
if (posted?.ok && posted.activityId) {
|
|
293590
|
+
const previousActivityId = this.activityId;
|
|
293591
|
+
this.activityId = posted.activityId;
|
|
293592
|
+
if (mode === 'final' && previousActivityId && previousActivityId !== posted.activityId) {
|
|
293593
|
+
const deleted = await this.teams.deleteMessage({
|
|
293594
|
+
conversationReference: this.conversationReference,
|
|
293595
|
+
activityId: previousActivityId,
|
|
293596
|
+
});
|
|
293597
|
+
if (!deleted) {
|
|
293598
|
+
logger_1.logger.warn(`[TaskLiveUpdates][Teams] deleteMessage failed for stale live update activityId=${previousActivityId}`);
|
|
293599
|
+
}
|
|
293600
|
+
else {
|
|
293601
|
+
logger_1.logger.info(`[TaskLiveUpdates][Teams] Removed stale live update activityId=${previousActivityId} after final fallback post`);
|
|
293602
|
+
}
|
|
293603
|
+
}
|
|
293604
|
+
return {
|
|
293605
|
+
ref: {
|
|
293606
|
+
teams_live_update_activity_id: posted.activityId,
|
|
293607
|
+
},
|
|
293608
|
+
};
|
|
293609
|
+
}
|
|
293610
|
+
return null;
|
|
293611
|
+
}
|
|
293612
|
+
}
|
|
293613
|
+
exports.TeamsTaskLiveUpdateSink = TeamsTaskLiveUpdateSink;
|
|
293614
|
+
|
|
293615
|
+
|
|
293616
|
+
/***/ }),
|
|
293617
|
+
|
|
293618
|
+
/***/ 71872:
|
|
293619
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
293620
|
+
|
|
293621
|
+
"use strict";
|
|
293622
|
+
|
|
293623
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
293624
|
+
exports.TelegramTaskLiveUpdateSink = void 0;
|
|
293625
|
+
const markdown_1 = __nccwpck_require__(21506);
|
|
293626
|
+
const logger_1 = __nccwpck_require__(86999);
|
|
293627
|
+
class TelegramTaskLiveUpdateSink {
|
|
293628
|
+
telegram;
|
|
293629
|
+
chatId;
|
|
293630
|
+
replyToMessageId;
|
|
293631
|
+
messageThreadId;
|
|
293632
|
+
kind = 'telegram';
|
|
293633
|
+
messageId;
|
|
293634
|
+
constructor(telegram, chatId, replyToMessageId, messageThreadId, initialMessageId) {
|
|
293635
|
+
this.telegram = telegram;
|
|
293636
|
+
this.chatId = chatId;
|
|
293637
|
+
this.replyToMessageId = replyToMessageId;
|
|
293638
|
+
this.messageThreadId = messageThreadId;
|
|
293639
|
+
this.messageId = initialMessageId;
|
|
293640
|
+
}
|
|
293641
|
+
async start() {
|
|
293642
|
+
logger_1.logger.debug(`[TaskLiveUpdates][Telegram] Initialized live update sink for chat=${this.chatId} reply_to=${this.replyToMessageId}`);
|
|
293643
|
+
return null;
|
|
293644
|
+
}
|
|
293645
|
+
async update(text) {
|
|
293646
|
+
return this.publish(text, 'progress');
|
|
293647
|
+
}
|
|
293648
|
+
async complete(text) {
|
|
293649
|
+
return this.publish(text, 'final');
|
|
293650
|
+
}
|
|
293651
|
+
async fail(text) {
|
|
293652
|
+
return this.publish(text, 'final');
|
|
293653
|
+
}
|
|
293654
|
+
async publish(text, mode) {
|
|
293655
|
+
const formatted = (0, markdown_1.formatTelegramText)(text);
|
|
293656
|
+
if (this.messageId) {
|
|
293657
|
+
logger_1.logger.debug(`[TaskLiveUpdates][Telegram] Updating existing message id=${this.messageId} in chat=${this.chatId}`);
|
|
293658
|
+
const updated = await this.telegram.editMessageText({
|
|
293659
|
+
chat_id: this.chatId,
|
|
293660
|
+
message_id: this.messageId,
|
|
293661
|
+
text: formatted,
|
|
293662
|
+
parse_mode: 'HTML',
|
|
293663
|
+
});
|
|
293664
|
+
if (updated?.ok)
|
|
293665
|
+
return null;
|
|
293666
|
+
logger_1.logger.warn(`[TaskLiveUpdates][Telegram] editMessageText failed for message_id=${this.messageId} error=${updated?.error || 'unknown_error'}; falling back to sendMessage`);
|
|
293667
|
+
}
|
|
293668
|
+
logger_1.logger.info(`[TaskLiveUpdates][Telegram] Posting live update message in chat=${this.chatId} reply_to=${this.replyToMessageId}`);
|
|
293669
|
+
const posted = await this.telegram.sendMessage({
|
|
293670
|
+
chat_id: this.chatId,
|
|
293671
|
+
text: formatted,
|
|
293672
|
+
parse_mode: 'HTML',
|
|
293673
|
+
reply_to_message_id: this.replyToMessageId,
|
|
293674
|
+
...(this.messageThreadId ? { message_thread_id: this.messageThreadId } : {}),
|
|
293675
|
+
});
|
|
293676
|
+
if (posted?.ok && posted.message_id) {
|
|
293677
|
+
const previousMessageId = this.messageId;
|
|
293678
|
+
this.messageId = posted.message_id;
|
|
293679
|
+
if (mode === 'final' && previousMessageId && previousMessageId !== posted.message_id) {
|
|
293680
|
+
const deleted = await this.telegram.deleteMessage({
|
|
293681
|
+
chat_id: this.chatId,
|
|
293682
|
+
message_id: previousMessageId,
|
|
293683
|
+
});
|
|
293684
|
+
if (!deleted) {
|
|
293685
|
+
logger_1.logger.warn(`[TaskLiveUpdates][Telegram] deleteMessage failed for stale live update message_id=${previousMessageId}`);
|
|
293686
|
+
}
|
|
293687
|
+
else {
|
|
293688
|
+
logger_1.logger.info(`[TaskLiveUpdates][Telegram] Removed stale live update message id=${previousMessageId} after final fallback post`);
|
|
293689
|
+
}
|
|
293690
|
+
}
|
|
293691
|
+
return {
|
|
293692
|
+
ref: {
|
|
293693
|
+
telegram_live_update_chat_id: String(this.chatId),
|
|
293694
|
+
telegram_live_update_message_id: posted.message_id,
|
|
293695
|
+
...(this.messageThreadId ? { telegram_live_update_thread_id: this.messageThreadId } : {}),
|
|
293696
|
+
},
|
|
293697
|
+
};
|
|
293698
|
+
}
|
|
293699
|
+
return null;
|
|
293700
|
+
}
|
|
293701
|
+
}
|
|
293702
|
+
exports.TelegramTaskLiveUpdateSink = TelegramTaskLiveUpdateSink;
|
|
293703
|
+
|
|
293704
|
+
|
|
293705
|
+
/***/ }),
|
|
293706
|
+
|
|
293707
|
+
/***/ 5893:
|
|
293708
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
293709
|
+
|
|
293710
|
+
"use strict";
|
|
293711
|
+
|
|
293712
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
293713
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
293714
|
+
};
|
|
293715
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
293716
|
+
exports.TaskLiveUpdateManager = exports.DEFAULT_TASK_LIVE_UPDATE_PROMPT = exports.DEFAULT_TASK_LIVE_UPDATE_MODEL = exports.DEFAULT_TASK_LIVE_UPDATE_STALL_FALLBACK_SECONDS = exports.DEFAULT_TASK_LIVE_UPDATE_METADATA_REFRESH_SECONDS = exports.DEFAULT_TASK_LIVE_UPDATE_FIRST_UPDATE_DELAY_SECONDS = exports.DEFAULT_TASK_LIVE_UPDATE_MAX_TRACE_CHARS = exports.DEFAULT_TASK_LIVE_UPDATE_INTERVAL_SECONDS = void 0;
|
|
293717
|
+
exports.resolveTaskLiveUpdatesConfig = resolveTaskLiveUpdatesConfig;
|
|
293718
|
+
exports.isFrontendLiveUpdatesEnabled = isFrontendLiveUpdatesEnabled;
|
|
293719
|
+
exports.summarizeTaskProgress = summarizeTaskProgress;
|
|
293720
|
+
const crypto_1 = __importDefault(__nccwpck_require__(76982));
|
|
293721
|
+
const logger_1 = __nccwpck_require__(86999);
|
|
293722
|
+
const trace_serializer_1 = __nccwpck_require__(48666);
|
|
293723
|
+
exports.DEFAULT_TASK_LIVE_UPDATE_INTERVAL_SECONDS = 10;
|
|
293724
|
+
exports.DEFAULT_TASK_LIVE_UPDATE_MAX_TRACE_CHARS = 12_000;
|
|
293725
|
+
exports.DEFAULT_TASK_LIVE_UPDATE_FIRST_UPDATE_DELAY_SECONDS = 10;
|
|
293726
|
+
exports.DEFAULT_TASK_LIVE_UPDATE_METADATA_REFRESH_SECONDS = 5;
|
|
293727
|
+
exports.DEFAULT_TASK_LIVE_UPDATE_STALL_FALLBACK_SECONDS = 60;
|
|
293728
|
+
exports.DEFAULT_TASK_LIVE_UPDATE_MODEL = 'gemini-3.1-flash-lite-preview';
|
|
293729
|
+
const DEFAULT_TASK_LIVE_UPDATE_STALL_NOTICE = '_No new meaningful progress is visible yet. Some steps can stay quiet for up to 5 minutes before there is new news._';
|
|
293730
|
+
exports.DEFAULT_TASK_LIVE_UPDATE_PROMPT = `You are generating a short live progress update for a user while an AI task is still running.
|
|
293731
|
+
|
|
293732
|
+
This is NOT the final answer.
|
|
293733
|
+
Do NOT answer the user's original request.
|
|
293734
|
+
Do NOT write the final solution.
|
|
293735
|
+
Do NOT explain the topic in full.
|
|
293736
|
+
Do NOT provide a root cause, recommendation, summary of findings, or conclusion.
|
|
293737
|
+
Even if you think you already know the answer, do NOT give it here.
|
|
293738
|
+
|
|
293739
|
+
You will receive:
|
|
293740
|
+
- the user's original request
|
|
293741
|
+
- the previous progress update, if any
|
|
293742
|
+
- timing metadata for this run
|
|
293743
|
+
- the latest execution trace snapshot
|
|
293744
|
+
|
|
293745
|
+
Your job is to produce a concise status update that tells the user only:
|
|
293746
|
+
- the overall progress so far
|
|
293747
|
+
- the last meaningful action that finished
|
|
293748
|
+
- what the agent is doing right now
|
|
293749
|
+
- what it is likely waiting on, if anything
|
|
293750
|
+
|
|
293751
|
+
Rules:
|
|
293752
|
+
- This is a STATUS UPDATE, not the final answer
|
|
293753
|
+
- Never answer the user's request directly
|
|
293754
|
+
- Never switch into explanation mode
|
|
293755
|
+
- Never write a complete answer, even partially
|
|
293756
|
+
- Keep it short: exactly 4 short bullet points
|
|
293757
|
+
- Use the exact bullet labels below
|
|
293758
|
+
- Do NOT generate timing metadata lines
|
|
293759
|
+
- Do NOT generate task_id lines
|
|
293760
|
+
- Timing metadata is provided only so you understand task pace and recency
|
|
293761
|
+
- The system will append timing and task metadata separately
|
|
293762
|
+
- Prefer concrete progress over generic wording
|
|
293763
|
+
- Mention the most recent completed action before the current action
|
|
293764
|
+
- Do not claim completion unless the task is actually done
|
|
293765
|
+
- Do not mention internal implementation details unless they help explain the current work
|
|
293766
|
+
- Avoid repeating the previous update verbatim
|
|
293767
|
+
- Do not use code fences
|
|
293768
|
+
- Plain markdown text only
|
|
293769
|
+
|
|
293770
|
+
Required output format:
|
|
293771
|
+
- Progress: <very short overall progress statement, not a final answer>
|
|
293772
|
+
- Last done: <most recent completed action>
|
|
293773
|
+
- Now: <current action in progress>
|
|
293774
|
+
- Waiting on: <tool, search, model, user input, or "nothing blocking right now">
|
|
293775
|
+
|
|
293776
|
+
Trace interpretation rules:
|
|
293777
|
+
- Translate internal trace phases into user-meaningful progress, do not just repeat raw span names
|
|
293778
|
+
- If the trace shows routing or classify work, describe that as understanding the request and choosing the right path
|
|
293779
|
+
- If the trace shows setup-projects, build-config, or loading context, describe that as preparing the workspace or gathering context
|
|
293780
|
+
- If the trace shows search, extract, code-explorer, or file inspection, describe that as investigating the codebase
|
|
293781
|
+
- If the trace shows engineer work, edits, tests, PR creation, or command execution, describe that as implementing or verifying changes
|
|
293782
|
+
- If the trace shows completion prompts, final answer generation, summarization, final validation, or output rendering, describe that as validating findings and preparing the final response
|
|
293783
|
+
- If the trace shows waiting on a long AI request, delegate, tool call, or sandboxed child task, describe that as waiting for analysis or validation to finish
|
|
293784
|
+
|
|
293785
|
+
If you are tempted to answer the user's question, stop and convert that into:
|
|
293786
|
+
- what was learned so far
|
|
293787
|
+
- what was just completed
|
|
293788
|
+
- what is still being checked
|
|
293789
|
+
|
|
293790
|
+
Bad update example:
|
|
293791
|
+
- "API rate limiting works by..."
|
|
293792
|
+
|
|
293793
|
+
Good update example:
|
|
293794
|
+
- "Progress: identified the gateway components involved in rate limiting"
|
|
293795
|
+
- "Last done: found the middleware files and session manager entry points"
|
|
293796
|
+
- "Now: tracing the enforcement path through the gateway"
|
|
293797
|
+
- "Waiting on: search results for the limiter implementation details"`;
|
|
293798
|
+
function resolveTaskLiveUpdatesConfig(config) {
|
|
293799
|
+
if (!config)
|
|
293800
|
+
return null;
|
|
293801
|
+
if (config === true) {
|
|
293802
|
+
return {
|
|
293803
|
+
enabled: true,
|
|
293804
|
+
intervalSeconds: exports.DEFAULT_TASK_LIVE_UPDATE_INTERVAL_SECONDS,
|
|
293805
|
+
model: exports.DEFAULT_TASK_LIVE_UPDATE_MODEL,
|
|
293806
|
+
prompt: exports.DEFAULT_TASK_LIVE_UPDATE_PROMPT,
|
|
293807
|
+
initialMessage: '',
|
|
293808
|
+
maxTraceChars: exports.DEFAULT_TASK_LIVE_UPDATE_MAX_TRACE_CHARS,
|
|
293809
|
+
};
|
|
293810
|
+
}
|
|
293811
|
+
if (config.enabled === false)
|
|
293812
|
+
return null;
|
|
293813
|
+
return {
|
|
293814
|
+
enabled: true,
|
|
293815
|
+
intervalSeconds: Math.max(1, Math.floor(config.interval_seconds || exports.DEFAULT_TASK_LIVE_UPDATE_INTERVAL_SECONDS)),
|
|
293816
|
+
model: config.model || exports.DEFAULT_TASK_LIVE_UPDATE_MODEL,
|
|
293817
|
+
provider: config.provider,
|
|
293818
|
+
prompt: config.prompt || exports.DEFAULT_TASK_LIVE_UPDATE_PROMPT,
|
|
293819
|
+
initialMessage: config.initial_message || '',
|
|
293820
|
+
maxTraceChars: Math.max(1000, Math.floor(config.max_trace_chars || exports.DEFAULT_TASK_LIVE_UPDATE_MAX_TRACE_CHARS)),
|
|
293821
|
+
};
|
|
293822
|
+
}
|
|
293823
|
+
function isFrontendLiveUpdatesEnabled(config, frontend) {
|
|
293824
|
+
if (!config)
|
|
293825
|
+
return false;
|
|
293826
|
+
if (config === true)
|
|
293827
|
+
return true;
|
|
293828
|
+
if (config.enabled === false)
|
|
293829
|
+
return false;
|
|
293830
|
+
const frontendCfg = config.frontends?.[frontend];
|
|
293831
|
+
if (frontendCfg?.enabled === false)
|
|
293832
|
+
return false;
|
|
293833
|
+
return true;
|
|
293834
|
+
}
|
|
293835
|
+
class TaskLiveUpdateManager {
|
|
293836
|
+
ctx;
|
|
293837
|
+
deps;
|
|
293838
|
+
timer;
|
|
293839
|
+
firstTickTimer;
|
|
293840
|
+
metadataRefreshTimer;
|
|
293841
|
+
running = false;
|
|
293842
|
+
started = false;
|
|
293843
|
+
completed = false;
|
|
293844
|
+
startedAt = new Date();
|
|
293845
|
+
lastUpdateText;
|
|
293846
|
+
lastUpdateAt;
|
|
293847
|
+
lastTraceSnapshot;
|
|
293848
|
+
lastPostedMessage;
|
|
293849
|
+
lastStallFallbackAt;
|
|
293850
|
+
lastUpdateKind = 'semantic';
|
|
293851
|
+
lastSkillMetadata;
|
|
293852
|
+
constructor(ctx, deps) {
|
|
293853
|
+
this.ctx = ctx;
|
|
293854
|
+
this.deps = {
|
|
293855
|
+
summarizeProgress: deps?.summarizeProgress || summarizeTaskProgress,
|
|
293856
|
+
serializeTrace: deps?.serializeTrace || defaultSerializeTrace,
|
|
293857
|
+
extractSkillMetadata: deps?.extractSkillMetadata || extractTraceSkillMetadata,
|
|
293858
|
+
};
|
|
293859
|
+
}
|
|
293860
|
+
async start() {
|
|
293861
|
+
if (this.started)
|
|
293862
|
+
return;
|
|
293863
|
+
this.started = true;
|
|
293864
|
+
try {
|
|
293865
|
+
const started = await this.ctx.sink.start();
|
|
293866
|
+
this.recordSinkRef(started);
|
|
293867
|
+
logger_1.logger.info(`[TaskLiveUpdates] Started for task ${this.ctx.taskId}; first update in ${exports.DEFAULT_TASK_LIVE_UPDATE_FIRST_UPDATE_DELAY_SECONDS}s, interval=${this.ctx.config.intervalSeconds}s, provider=${this.ctx.config.provider || 'default'}, model=${this.ctx.config.model}`);
|
|
293868
|
+
}
|
|
293869
|
+
catch (err) {
|
|
293870
|
+
logger_1.logger.warn(`[TaskLiveUpdates] Failed to initialize live updates for task ${this.ctx.taskId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
293871
|
+
}
|
|
293872
|
+
this.firstTickTimer = setTimeout(() => {
|
|
293873
|
+
void this.runFirstTick();
|
|
293874
|
+
}, exports.DEFAULT_TASK_LIVE_UPDATE_FIRST_UPDATE_DELAY_SECONDS * 1000);
|
|
293875
|
+
if (typeof this.firstTickTimer?.unref === 'function') {
|
|
293876
|
+
this.firstTickTimer.unref();
|
|
293877
|
+
}
|
|
293878
|
+
}
|
|
293879
|
+
async complete(finalText) {
|
|
293880
|
+
if (this.completed)
|
|
293881
|
+
return;
|
|
293882
|
+
this.completed = true;
|
|
293883
|
+
this.stop();
|
|
293884
|
+
try {
|
|
293885
|
+
logger_1.logger.info(`[TaskLiveUpdates] Publishing final success update for task ${this.ctx.taskId}`);
|
|
293886
|
+
const result = await this.ctx.sink.complete(this.decorateText(finalText));
|
|
293887
|
+
this.recordSinkRef(result);
|
|
293888
|
+
this.ctx.appendHistory?.(finalText, 'completed');
|
|
293889
|
+
}
|
|
293890
|
+
catch (err) {
|
|
293891
|
+
logger_1.logger.warn(`[TaskLiveUpdates] Failed to publish final update for task ${this.ctx.taskId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
293892
|
+
}
|
|
293893
|
+
}
|
|
293894
|
+
async fail(finalText) {
|
|
293895
|
+
if (this.completed)
|
|
293896
|
+
return;
|
|
293897
|
+
this.completed = true;
|
|
293898
|
+
this.stop();
|
|
293899
|
+
try {
|
|
293900
|
+
logger_1.logger.info(`[TaskLiveUpdates] Publishing final failure update for task ${this.ctx.taskId}`);
|
|
293901
|
+
const result = await this.ctx.sink.fail(this.decorateText(finalText));
|
|
293902
|
+
this.recordSinkRef(result);
|
|
293903
|
+
this.ctx.appendHistory?.(finalText, 'failed');
|
|
293904
|
+
}
|
|
293905
|
+
catch (err) {
|
|
293906
|
+
logger_1.logger.warn(`[TaskLiveUpdates] Failed to publish failure update for task ${this.ctx.taskId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
293907
|
+
}
|
|
293908
|
+
}
|
|
293909
|
+
stop() {
|
|
293910
|
+
if (this.firstTickTimer) {
|
|
293911
|
+
clearTimeout(this.firstTickTimer);
|
|
293912
|
+
this.firstTickTimer = undefined;
|
|
293913
|
+
}
|
|
293914
|
+
if (this.timer) {
|
|
293915
|
+
clearInterval(this.timer);
|
|
293916
|
+
this.timer = undefined;
|
|
293917
|
+
}
|
|
293918
|
+
if (this.metadataRefreshTimer) {
|
|
293919
|
+
clearInterval(this.metadataRefreshTimer);
|
|
293920
|
+
this.metadataRefreshTimer = undefined;
|
|
293921
|
+
}
|
|
293922
|
+
}
|
|
293923
|
+
async tick() {
|
|
293924
|
+
if (this.completed || this.running)
|
|
293925
|
+
return;
|
|
293926
|
+
const traceState = this.getTraceState();
|
|
293927
|
+
if (!traceState.traceRef && !traceState.traceId) {
|
|
293928
|
+
logger_1.logger.debug(`[TaskLiveUpdates] Skipping tick for task ${this.ctx.taskId}: no trace reference available yet`);
|
|
293929
|
+
return;
|
|
293930
|
+
}
|
|
293931
|
+
this.running = true;
|
|
293932
|
+
try {
|
|
293933
|
+
const traceRef = traceState.traceRef || traceState.traceId;
|
|
293934
|
+
const traceSnapshot = await this.deps.serializeTrace(traceRef, this.ctx.config.maxTraceChars, traceState.traceId);
|
|
293935
|
+
if (this.completed) {
|
|
293936
|
+
logger_1.logger.debug(`[TaskLiveUpdates] Aborting in-flight tick for task ${this.ctx.taskId}: task already completed`);
|
|
293937
|
+
return;
|
|
293938
|
+
}
|
|
293939
|
+
if (!traceSnapshot || traceSnapshot === '(no trace data available)') {
|
|
293940
|
+
logger_1.logger.debug(`[TaskLiveUpdates] Skipping tick for task ${this.ctx.taskId}: no trace data available yet (traceRef=${traceRef})`);
|
|
293941
|
+
return;
|
|
293942
|
+
}
|
|
293943
|
+
if (traceSnapshot === this.lastTraceSnapshot) {
|
|
293944
|
+
await this.maybePublishStallFallback(traceSnapshot, traceState.traceId);
|
|
293945
|
+
logger_1.logger.debug(`[TaskLiveUpdates] Skipping tick for task ${this.ctx.taskId}: trace snapshot unchanged`);
|
|
293946
|
+
return;
|
|
293947
|
+
}
|
|
293948
|
+
const summary = await this.deps.summarizeProgress({
|
|
293949
|
+
requestText: this.ctx.requestText,
|
|
293950
|
+
previousUpdate: this.lastUpdateText,
|
|
293951
|
+
traceSnapshot,
|
|
293952
|
+
config: this.ctx.config,
|
|
293953
|
+
startedAt: this.startedAt,
|
|
293954
|
+
now: new Date(),
|
|
293955
|
+
elapsedSeconds: Math.max(0, Math.floor((Date.now() - this.startedAt.getTime()) / 1000)),
|
|
293956
|
+
previousUpdateAt: this.lastUpdateAt,
|
|
293957
|
+
secondsSincePreviousUpdate: this.lastUpdateAt
|
|
293958
|
+
? Math.max(0, Math.floor((Date.now() - this.lastUpdateAt.getTime()) / 1000))
|
|
293959
|
+
: undefined,
|
|
293960
|
+
});
|
|
293961
|
+
if (this.completed) {
|
|
293962
|
+
logger_1.logger.debug(`[TaskLiveUpdates] Aborting in-flight tick for task ${this.ctx.taskId}: task already completed after summarization`);
|
|
293963
|
+
return;
|
|
293964
|
+
}
|
|
293965
|
+
const cleaned = summary?.trim();
|
|
293966
|
+
if (!cleaned || cleaned === this.lastUpdateText) {
|
|
293967
|
+
await this.maybePublishStallFallback(traceSnapshot, traceState.traceId);
|
|
293968
|
+
logger_1.logger.debug(`[TaskLiveUpdates] Skipping tick for task ${this.ctx.taskId}: summary empty or unchanged`);
|
|
293969
|
+
this.lastTraceSnapshot = traceSnapshot;
|
|
293970
|
+
return;
|
|
293971
|
+
}
|
|
293972
|
+
logger_1.logger.info(`[TaskLiveUpdates] Publishing progress update for task ${this.ctx.taskId}: ${cleaned.slice(0, 160)}`);
|
|
293973
|
+
this.lastSkillMetadata = await this.deps.extractSkillMetadata(traceRef, traceState.traceId);
|
|
293974
|
+
this.lastUpdateKind = 'semantic';
|
|
293975
|
+
const message = this.decorateProgressText(cleaned, {
|
|
293976
|
+
elapsedSeconds: Math.max(0, Math.floor((Date.now() - this.startedAt.getTime()) / 1000)),
|
|
293977
|
+
previousUpdateAt: this.lastUpdateAt,
|
|
293978
|
+
secondsSincePreviousUpdate: this.lastUpdateAt
|
|
293979
|
+
? Math.max(0, Math.floor((Date.now() - this.lastUpdateAt.getTime()) / 1000))
|
|
293980
|
+
: undefined,
|
|
293981
|
+
activatedSkills: this.lastSkillMetadata?.activatedSkills,
|
|
293982
|
+
}, traceState.traceId);
|
|
293983
|
+
const result = await this.ctx.sink.update(message);
|
|
293984
|
+
this.recordSinkRef(result);
|
|
293985
|
+
this.ctx.appendHistory?.(cleaned, 'progress');
|
|
293986
|
+
this.lastUpdateText = cleaned;
|
|
293987
|
+
this.lastUpdateAt = new Date();
|
|
293988
|
+
this.lastTraceSnapshot = traceSnapshot;
|
|
293989
|
+
this.lastPostedMessage = message;
|
|
293990
|
+
this.lastStallFallbackAt = undefined;
|
|
293991
|
+
}
|
|
293992
|
+
catch (err) {
|
|
293993
|
+
logger_1.logger.warn(`[TaskLiveUpdates] Progress update failed for task ${this.ctx.taskId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
293994
|
+
}
|
|
293995
|
+
finally {
|
|
293996
|
+
this.running = false;
|
|
293997
|
+
}
|
|
293998
|
+
}
|
|
293999
|
+
async runFirstTick() {
|
|
294000
|
+
if (this.completed)
|
|
294001
|
+
return;
|
|
294002
|
+
logger_1.logger.debug(`[TaskLiveUpdates] Running first scheduled tick for task ${this.ctx.taskId}`);
|
|
294003
|
+
await this.tick();
|
|
294004
|
+
if (this.completed)
|
|
294005
|
+
return;
|
|
294006
|
+
this.timer = setInterval(() => {
|
|
294007
|
+
void this.tick();
|
|
294008
|
+
}, this.ctx.config.intervalSeconds * 1000);
|
|
294009
|
+
if (typeof this.timer?.unref === 'function') {
|
|
294010
|
+
this.timer.unref();
|
|
294011
|
+
}
|
|
294012
|
+
this.metadataRefreshTimer = setInterval(() => {
|
|
294013
|
+
void this.refreshProgressMetadata();
|
|
294014
|
+
}, exports.DEFAULT_TASK_LIVE_UPDATE_METADATA_REFRESH_SECONDS * 1000);
|
|
294015
|
+
if (typeof this.metadataRefreshTimer?.unref === 'function') {
|
|
294016
|
+
this.metadataRefreshTimer.unref();
|
|
294017
|
+
}
|
|
294018
|
+
}
|
|
294019
|
+
recordSinkRef(result) {
|
|
294020
|
+
if (result?.ref)
|
|
294021
|
+
this.ctx.onPostedRef?.(result.ref);
|
|
294022
|
+
}
|
|
294023
|
+
getTraceState() {
|
|
294024
|
+
const resolved = this.ctx.resolveTraceState?.();
|
|
294025
|
+
return {
|
|
294026
|
+
traceRef: resolved?.traceRef || this.ctx.traceRef,
|
|
294027
|
+
traceId: resolved?.traceId || this.ctx.traceId,
|
|
294028
|
+
};
|
|
294029
|
+
}
|
|
294030
|
+
decorateText(text, _traceId) {
|
|
294031
|
+
if (!this.ctx.includeTraceId)
|
|
294032
|
+
return text;
|
|
294033
|
+
if (text.includes(`task_id: ${this.ctx.taskId}`))
|
|
294034
|
+
return text;
|
|
294035
|
+
return `${text}\n\n\`task_id: ${this.ctx.taskId}\``;
|
|
294036
|
+
}
|
|
294037
|
+
decorateProgressText(text, timing, traceId) {
|
|
294038
|
+
const normalized = normalizeProgressSummary(text);
|
|
294039
|
+
const blocks = [
|
|
294040
|
+
'*Live Update*',
|
|
294041
|
+
'_Current task is still running. This message updates in place until the final answer is ready._',
|
|
294042
|
+
this.lastUpdateKind === 'stall' ? DEFAULT_TASK_LIVE_UPDATE_STALL_NOTICE : '',
|
|
294043
|
+
normalized,
|
|
294044
|
+
formatProgressMetadata(timing),
|
|
294045
|
+
].filter(Boolean);
|
|
294046
|
+
return this.decorateText(blocks.join('\n\n'), traceId);
|
|
294047
|
+
}
|
|
294048
|
+
async refreshProgressMetadata() {
|
|
294049
|
+
if (this.completed || this.running || !this.lastUpdateText)
|
|
294050
|
+
return;
|
|
294051
|
+
const traceState = this.getTraceState();
|
|
294052
|
+
const message = this.decorateProgressText(this.lastUpdateText, {
|
|
294053
|
+
elapsedSeconds: Math.max(0, Math.floor((Date.now() - this.startedAt.getTime()) / 1000)),
|
|
294054
|
+
previousUpdateAt: this.lastUpdateAt,
|
|
294055
|
+
secondsSincePreviousUpdate: this.lastUpdateAt
|
|
294056
|
+
? Math.max(0, Math.floor((Date.now() - this.lastUpdateAt.getTime()) / 1000))
|
|
294057
|
+
: undefined,
|
|
294058
|
+
activatedSkills: this.lastSkillMetadata?.activatedSkills,
|
|
294059
|
+
}, traceState.traceId);
|
|
294060
|
+
if (!message || message === this.lastPostedMessage)
|
|
294061
|
+
return;
|
|
294062
|
+
if (this.completed)
|
|
294063
|
+
return;
|
|
294064
|
+
try {
|
|
294065
|
+
logger_1.logger.debug(`[TaskLiveUpdates] Refreshing metadata-only live update for task ${this.ctx.taskId}`);
|
|
294066
|
+
const result = await this.ctx.sink.update(message);
|
|
294067
|
+
this.recordSinkRef(result);
|
|
294068
|
+
this.lastPostedMessage = message;
|
|
294069
|
+
}
|
|
294070
|
+
catch (err) {
|
|
294071
|
+
logger_1.logger.warn(`[TaskLiveUpdates] Metadata refresh failed for task ${this.ctx.taskId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
294072
|
+
}
|
|
294073
|
+
}
|
|
294074
|
+
async maybePublishStallFallback(traceSnapshot, traceId) {
|
|
294075
|
+
if (this.completed)
|
|
294076
|
+
return;
|
|
294077
|
+
const now = new Date();
|
|
294078
|
+
if (this.lastStallFallbackAt &&
|
|
294079
|
+
now.getTime() - this.lastStallFallbackAt.getTime() <
|
|
294080
|
+
exports.DEFAULT_TASK_LIVE_UPDATE_STALL_FALLBACK_SECONDS * 1000) {
|
|
294081
|
+
return;
|
|
294082
|
+
}
|
|
294083
|
+
if (this.lastUpdateAt &&
|
|
294084
|
+
now.getTime() - this.lastUpdateAt.getTime() <
|
|
294085
|
+
exports.DEFAULT_TASK_LIVE_UPDATE_STALL_FALLBACK_SECONDS * 1000) {
|
|
294086
|
+
return;
|
|
294087
|
+
}
|
|
294088
|
+
this.lastSkillMetadata = await this.deps.extractSkillMetadata(this.getTraceState().traceRef || traceId || '', traceId);
|
|
294089
|
+
const fallback = buildStallFallbackSummary(traceSnapshot, this.lastUpdateText);
|
|
294090
|
+
const baseText = this.lastUpdateText || fallback;
|
|
294091
|
+
if (!baseText)
|
|
294092
|
+
return;
|
|
294093
|
+
logger_1.logger.info(`[TaskLiveUpdates] Publishing stall notice for task ${this.ctx.taskId}: ${baseText.slice(0, 160)}`);
|
|
294094
|
+
this.lastUpdateKind = 'stall';
|
|
294095
|
+
if (this.completed)
|
|
294096
|
+
return;
|
|
294097
|
+
const message = this.decorateProgressText(baseText, {
|
|
294098
|
+
elapsedSeconds: Math.max(0, Math.floor((Date.now() - this.startedAt.getTime()) / 1000)),
|
|
294099
|
+
previousUpdateAt: this.lastUpdateAt,
|
|
294100
|
+
secondsSincePreviousUpdate: this.lastUpdateAt
|
|
294101
|
+
? Math.max(0, Math.floor((Date.now() - this.lastUpdateAt.getTime()) / 1000))
|
|
294102
|
+
: undefined,
|
|
294103
|
+
activatedSkills: this.lastSkillMetadata?.activatedSkills,
|
|
294104
|
+
}, traceId);
|
|
294105
|
+
if (message === this.lastPostedMessage) {
|
|
294106
|
+
this.lastStallFallbackAt = now;
|
|
294107
|
+
return;
|
|
294108
|
+
}
|
|
294109
|
+
const result = await this.ctx.sink.update(message);
|
|
294110
|
+
this.recordSinkRef(result);
|
|
294111
|
+
if (!this.lastUpdateText) {
|
|
294112
|
+
this.ctx.appendHistory?.(baseText, 'progress');
|
|
294113
|
+
this.lastUpdateText = baseText;
|
|
294114
|
+
this.lastUpdateAt = now;
|
|
294115
|
+
}
|
|
294116
|
+
this.lastPostedMessage = message;
|
|
294117
|
+
this.lastStallFallbackAt = now;
|
|
294118
|
+
}
|
|
294119
|
+
}
|
|
294120
|
+
exports.TaskLiveUpdateManager = TaskLiveUpdateManager;
|
|
294121
|
+
async function defaultSerializeTrace(traceRef, maxChars, traceId) {
|
|
294122
|
+
logger_1.logger.debug(`[TaskLiveUpdates] Serializing trace for progress update (traceRef=${traceRef}, traceId=${traceId || '-'}, sink=${process.env.VISOR_TELEMETRY_SINK || 'auto'})`);
|
|
294123
|
+
return (0, trace_serializer_1.serializeTraceForPrompt)(traceRef, maxChars, undefined, undefined, traceId);
|
|
294124
|
+
}
|
|
294125
|
+
async function summarizeTaskProgress(input) {
|
|
294126
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
294127
|
+
const { ProbeAgent } = __nccwpck_require__(83841);
|
|
294128
|
+
const agentOptions = {
|
|
294129
|
+
sessionId: `visor-task-progress-${Date.now()}-${crypto_1.default.randomUUID().slice(0, 8)}`,
|
|
294130
|
+
systemPrompt: input.config.prompt,
|
|
294131
|
+
maxIterations: 1,
|
|
294132
|
+
disableTools: true,
|
|
294133
|
+
};
|
|
294134
|
+
if (input.config.model)
|
|
294135
|
+
agentOptions.model = input.config.model;
|
|
294136
|
+
if (input.config.provider)
|
|
294137
|
+
agentOptions.provider = input.config.provider;
|
|
294138
|
+
const agent = new ProbeAgent(agentOptions);
|
|
294139
|
+
if (typeof agent.initialize === 'function') {
|
|
294140
|
+
await agent.initialize();
|
|
294141
|
+
}
|
|
294142
|
+
const userPrompt = [
|
|
294143
|
+
`<user_request>\n${input.requestText}\n</user_request>`,
|
|
294144
|
+
input.previousUpdate
|
|
294145
|
+
? `<previous_update>\n${input.previousUpdate}\n</previous_update>`
|
|
294146
|
+
: '<previous_update>(none)</previous_update>',
|
|
294147
|
+
`<timing>\nstarted_at: ${input.startedAt.toISOString()}\nnow: ${input.now.toISOString()}\nelapsed: ${formatDuration(input.elapsedSeconds)}\nlast_update_at: ${input.previousUpdateAt ? input.previousUpdateAt.toISOString() : '(none)'}\ntime_since_last_update: ${input.previousUpdateAt ? formatDuration(input.secondsSincePreviousUpdate || 0) : '(none)'}\n</timing>`,
|
|
294148
|
+
`<execution_trace>\n${input.traceSnapshot}\n</execution_trace>`,
|
|
294149
|
+
].join('\n\n');
|
|
294150
|
+
const response = await agent.answer(userPrompt);
|
|
294151
|
+
const cleaned = response
|
|
294152
|
+
.replace(/^```(?:markdown|md|text)?\s*\n?/i, '')
|
|
294153
|
+
.replace(/\n?```\s*$/m, '')
|
|
294154
|
+
.trim();
|
|
294155
|
+
return cleaned || null;
|
|
294156
|
+
}
|
|
294157
|
+
function formatDuration(totalSeconds) {
|
|
294158
|
+
const seconds = Math.max(0, Math.floor(totalSeconds));
|
|
294159
|
+
const hours = Math.floor(seconds / 3600);
|
|
294160
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
294161
|
+
const remainingSeconds = seconds % 60;
|
|
294162
|
+
const parts = [];
|
|
294163
|
+
if (hours > 0)
|
|
294164
|
+
parts.push(`${hours}h`);
|
|
294165
|
+
if (minutes > 0)
|
|
294166
|
+
parts.push(`${minutes}m`);
|
|
294167
|
+
if (remainingSeconds > 0 || parts.length === 0)
|
|
294168
|
+
parts.push(`${remainingSeconds}s`);
|
|
294169
|
+
return parts.join(' ');
|
|
294170
|
+
}
|
|
294171
|
+
function normalizeProgressSummary(text) {
|
|
294172
|
+
const wantedLabels = ['Progress', 'Last done', 'Now', 'Waiting on'];
|
|
294173
|
+
const lines = text
|
|
294174
|
+
.split(/\r?\n/)
|
|
294175
|
+
.map(line => line.trim())
|
|
294176
|
+
.filter(Boolean);
|
|
294177
|
+
const matched = new Map();
|
|
294178
|
+
for (const line of lines) {
|
|
294179
|
+
const match = line.match(/^-?\s*(Progress|Last done|Now|Waiting on|Timing)\s*:\s*(.+)$/i);
|
|
294180
|
+
if (!match)
|
|
294181
|
+
continue;
|
|
294182
|
+
const label = match[1].toLowerCase();
|
|
294183
|
+
if (label === 'timing')
|
|
294184
|
+
continue;
|
|
294185
|
+
const canonical = wantedLabels.find(item => item.toLowerCase() === label);
|
|
294186
|
+
if (canonical && !matched.has(canonical)) {
|
|
294187
|
+
matched.set(canonical, match[2].trim());
|
|
294188
|
+
}
|
|
294189
|
+
}
|
|
294190
|
+
if (matched.size === wantedLabels.length) {
|
|
294191
|
+
return wantedLabels.map(label => `- ${label}: ${matched.get(label)}`).join('\n');
|
|
294192
|
+
}
|
|
294193
|
+
const withoutTiming = lines.filter(line => !/^-?\s*(Timing|Metadata|Trace)\s*:/i.test(line));
|
|
294194
|
+
return withoutTiming.join('\n');
|
|
294195
|
+
}
|
|
294196
|
+
function formatProgressMetadata(timing) {
|
|
294197
|
+
const parts = [`elapsed ${formatDuration(timing.elapsedSeconds)}`];
|
|
294198
|
+
if (timing.previousUpdateAt) {
|
|
294199
|
+
parts.push(`previous update ${formatDuration(timing.secondsSincePreviousUpdate || 0)} ago`);
|
|
294200
|
+
parts.push(`at ${timing.previousUpdateAt.toISOString()}`);
|
|
294201
|
+
}
|
|
294202
|
+
else {
|
|
294203
|
+
parts.push('first live update');
|
|
294204
|
+
}
|
|
294205
|
+
if (timing.activatedSkills && timing.activatedSkills.length > 0) {
|
|
294206
|
+
parts.push(`activated skills ${formatSkillList(timing.activatedSkills)}`);
|
|
294207
|
+
}
|
|
294208
|
+
return `_Metadata: ${parts.join(' | ')}_`;
|
|
294209
|
+
}
|
|
294210
|
+
function formatSkillList(skills) {
|
|
294211
|
+
const normalized = dedupeStrings(skills);
|
|
294212
|
+
if (normalized.length <= 4)
|
|
294213
|
+
return normalized.join(', ');
|
|
294214
|
+
return `${normalized.slice(0, 4).join(', ')} +${normalized.length - 4} more`;
|
|
294215
|
+
}
|
|
294216
|
+
function dedupeStrings(values) {
|
|
294217
|
+
if (!Array.isArray(values))
|
|
294218
|
+
return [];
|
|
294219
|
+
return [...new Set(values.map(value => String(value || '').trim()).filter(Boolean))];
|
|
294220
|
+
}
|
|
294221
|
+
async function extractTraceSkillMetadata(traceRef, traceId) {
|
|
294222
|
+
if (!traceRef && !traceId)
|
|
294223
|
+
return undefined;
|
|
294224
|
+
try {
|
|
294225
|
+
const spans = await (0, trace_serializer_1.fetchTraceSpans)(traceId || traceRef);
|
|
294226
|
+
if (!spans.length)
|
|
294227
|
+
return undefined;
|
|
294228
|
+
const routeIntentSpan = spans.find(span => span.attributes['visor.check.id'] === 'route-intent');
|
|
294229
|
+
const buildConfigSpan = spans.find(span => span.attributes['visor.check.id'] === 'build-config');
|
|
294230
|
+
const classifySpan = spans.find(span => span.attributes['visor.check.id'] === 'classify');
|
|
294231
|
+
const routeIntentOutput = parseJsonAttribute(routeIntentSpan?.attributes['visor.check.output']);
|
|
294232
|
+
const classifyOutput = parseJsonAttribute(classifySpan?.attributes['visor.check.output']);
|
|
294233
|
+
const buildConfigOutput = parseJsonAttribute(buildConfigSpan?.attributes['visor.check.output']);
|
|
294234
|
+
const activatedSkills = dedupeStrings(Array.isArray(buildConfigOutput?.activated_skills)
|
|
294235
|
+
? buildConfigOutput.activated_skills
|
|
294236
|
+
: undefined);
|
|
294237
|
+
const fallbackActivatedSkills = dedupeStrings((Array.isArray(routeIntentOutput?.skills) ? routeIntentOutput.skills : undefined) ||
|
|
294238
|
+
(Array.isArray(classifyOutput?.skills) ? classifyOutput.skills : undefined));
|
|
294239
|
+
const finalActivatedSkills = activatedSkills.length > 0 ? activatedSkills : fallbackActivatedSkills;
|
|
294240
|
+
if (!finalActivatedSkills.length)
|
|
294241
|
+
return undefined;
|
|
294242
|
+
return { activatedSkills: finalActivatedSkills };
|
|
294243
|
+
}
|
|
294244
|
+
catch (err) {
|
|
294245
|
+
logger_1.logger.debug(`[TaskLiveUpdates] Failed to extract skill metadata from trace: ${err instanceof Error ? err.message : String(err)}`);
|
|
294246
|
+
return undefined;
|
|
294247
|
+
}
|
|
294248
|
+
}
|
|
294249
|
+
function parseJsonAttribute(value) {
|
|
294250
|
+
if (typeof value !== 'string' || !value.trim())
|
|
294251
|
+
return undefined;
|
|
294252
|
+
try {
|
|
294253
|
+
const parsed = JSON.parse(value);
|
|
294254
|
+
return parsed && typeof parsed === 'object' ? parsed : undefined;
|
|
294255
|
+
}
|
|
294256
|
+
catch {
|
|
294257
|
+
return undefined;
|
|
294258
|
+
}
|
|
294259
|
+
}
|
|
294260
|
+
function buildStallFallbackSummary(traceSnapshot, previousUpdate) {
|
|
294261
|
+
const lastDone = extractProgressField(previousUpdate, 'Last done') ||
|
|
294262
|
+
'continuing from the last completed analysis step';
|
|
294263
|
+
const lower = traceSnapshot.toLowerCase();
|
|
294264
|
+
let now = 'waiting for the current analysis step to finish';
|
|
294265
|
+
let waitingOn = 'the current analysis step to complete';
|
|
294266
|
+
if (lower.includes('search.delegate') ||
|
|
294267
|
+
lower.includes('tool: search') ||
|
|
294268
|
+
lower.includes('search(')) {
|
|
294269
|
+
now = 'running or waiting on the current code search step';
|
|
294270
|
+
waitingOn = 'search results and downstream analysis to finish';
|
|
294271
|
+
}
|
|
294272
|
+
else if (lower.includes('extract(') || lower.includes('tool: extract')) {
|
|
294273
|
+
now = 'extracting the relevant code or documentation context';
|
|
294274
|
+
waitingOn = 'the extract step to finish and be interpreted';
|
|
294275
|
+
}
|
|
294276
|
+
else if (lower.includes('engineer-task') || lower.includes('engineer')) {
|
|
294277
|
+
now = 'waiting on the current implementation or validation step';
|
|
294278
|
+
waitingOn = 'the engineer workflow to finish the current step';
|
|
294279
|
+
}
|
|
294280
|
+
else if (lower.includes('ai.request') ||
|
|
294281
|
+
lower.includes('gemini') ||
|
|
294282
|
+
lower.includes('claude') ||
|
|
294283
|
+
lower.includes('openai')) {
|
|
294284
|
+
now = 'waiting on the current model analysis step';
|
|
294285
|
+
waitingOn = 'the active model response to finish';
|
|
294286
|
+
}
|
|
294287
|
+
else if (lower.includes('bash(') || lower.includes('go test') || lower.includes('npm test')) {
|
|
294288
|
+
now = 'running or waiting on command-based validation';
|
|
294289
|
+
waitingOn = 'the current command or test run to finish';
|
|
294290
|
+
}
|
|
294291
|
+
else if (lower.includes('setup-projects') || lower.includes('build-config')) {
|
|
294292
|
+
now = 'preparing the workspace and loading the required context';
|
|
294293
|
+
waitingOn = 'workspace setup and context loading to finish';
|
|
294294
|
+
}
|
|
294295
|
+
return [
|
|
294296
|
+
'- Progress: still working through the same step; no new completed action yet',
|
|
294297
|
+
`- Last done: ${lastDone}`,
|
|
294298
|
+
`- Now: ${now}`,
|
|
294299
|
+
`- Waiting on: ${waitingOn}`,
|
|
294300
|
+
].join('\n');
|
|
294301
|
+
}
|
|
294302
|
+
function extractProgressField(text, label) {
|
|
294303
|
+
if (!text)
|
|
294304
|
+
return undefined;
|
|
294305
|
+
const match = text.match(new RegExp(`(?:^|\\n)-?\\s*${escapeRegExp(label)}\\s*:\\s*(.+)$`, 'im'));
|
|
294306
|
+
return match?.[1]?.trim() || undefined;
|
|
294307
|
+
}
|
|
294308
|
+
function escapeRegExp(value) {
|
|
294309
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
294310
|
+
}
|
|
294311
|
+
|
|
294312
|
+
|
|
293451
294313
|
/***/ }),
|
|
293452
294314
|
|
|
293453
294315
|
/***/ 38570:
|
|
@@ -293503,6 +294365,7 @@ exports.getTaskProgressToolDefinition = getTaskProgressToolDefinition;
|
|
|
293503
294365
|
exports.isTaskProgressTool = isTaskProgressTool;
|
|
293504
294366
|
exports.handleTaskProgressAction = handleTaskProgressAction;
|
|
293505
294367
|
const logger_1 = __nccwpck_require__(86999);
|
|
294368
|
+
const task_trace_resolution_1 = __nccwpck_require__(4018);
|
|
293506
294369
|
// ---------------------------------------------------------------------------
|
|
293507
294370
|
// Tool definition
|
|
293508
294371
|
// ---------------------------------------------------------------------------
|
|
@@ -293627,8 +294490,9 @@ async function handleTrace(taskId, taskStore) {
|
|
|
293627
294490
|
if (!task) {
|
|
293628
294491
|
return { success: false, error: `Task not found: ${taskId}` };
|
|
293629
294492
|
}
|
|
293630
|
-
const
|
|
293631
|
-
const
|
|
294493
|
+
const resolvedTrace = await (0, task_trace_resolution_1.resolveTaskTraceReference)(task.metadata);
|
|
294494
|
+
const traceId = resolvedTrace.traceId;
|
|
294495
|
+
const traceFile = resolvedTrace.traceFile;
|
|
293632
294496
|
if (!traceId && !traceFile) {
|
|
293633
294497
|
// No trace available — return basic status info
|
|
293634
294498
|
const trigger = task.metadata?.slack_trigger_text || '';
|
|
@@ -293648,17 +294512,12 @@ async function handleTrace(taskId, taskStore) {
|
|
|
293648
294512
|
};
|
|
293649
294513
|
}
|
|
293650
294514
|
// Lazy-import the trace serializer to avoid circular dependencies
|
|
293651
|
-
const { serializeTraceForPrompt
|
|
293652
|
-
// Get trace ID from file if needed
|
|
293653
|
-
let resolvedTraceId = traceId;
|
|
293654
|
-
if (!resolvedTraceId && traceFile) {
|
|
293655
|
-
resolvedTraceId = await readTraceIdFromFile(traceFile);
|
|
293656
|
-
}
|
|
294515
|
+
const { serializeTraceForPrompt } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(48666)));
|
|
293657
294516
|
// Get the task response for full output context
|
|
293658
294517
|
const taskResponse = task.status?.message?.parts?.[0]?.text;
|
|
293659
294518
|
// Serialize the trace — use generous char limit for AI consumption
|
|
293660
|
-
const traceTree = await serializeTraceForPrompt(
|
|
293661
|
-
undefined, taskResponse,
|
|
294519
|
+
const traceTree = await serializeTraceForPrompt(resolvedTrace.primaryRef || '', 8000, // generous limit so AI gets good context
|
|
294520
|
+
undefined, taskResponse, traceId || undefined);
|
|
293662
294521
|
const trigger = task.metadata?.slack_trigger_text || '';
|
|
293663
294522
|
const elapsed = timeSince(task.created_at);
|
|
293664
294523
|
const lines = [
|
|
@@ -294429,6 +295288,68 @@ class TaskStreamManager {
|
|
|
294429
295288
|
exports.TaskStreamManager = TaskStreamManager;
|
|
294430
295289
|
|
|
294431
295290
|
|
|
295291
|
+
/***/ }),
|
|
295292
|
+
|
|
295293
|
+
/***/ 4018:
|
|
295294
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
295295
|
+
|
|
295296
|
+
"use strict";
|
|
295297
|
+
|
|
295298
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
295299
|
+
if (k2 === undefined) k2 = k;
|
|
295300
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
295301
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
295302
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
295303
|
+
}
|
|
295304
|
+
Object.defineProperty(o, k2, desc);
|
|
295305
|
+
}) : (function(o, m, k, k2) {
|
|
295306
|
+
if (k2 === undefined) k2 = k;
|
|
295307
|
+
o[k2] = m[k];
|
|
295308
|
+
}));
|
|
295309
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
295310
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
295311
|
+
}) : function(o, v) {
|
|
295312
|
+
o["default"] = v;
|
|
295313
|
+
});
|
|
295314
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
295315
|
+
var ownKeys = function(o) {
|
|
295316
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
295317
|
+
var ar = [];
|
|
295318
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
295319
|
+
return ar;
|
|
295320
|
+
};
|
|
295321
|
+
return ownKeys(o);
|
|
295322
|
+
};
|
|
295323
|
+
return function (mod) {
|
|
295324
|
+
if (mod && mod.__esModule) return mod;
|
|
295325
|
+
var result = {};
|
|
295326
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
295327
|
+
__setModuleDefault(result, mod);
|
|
295328
|
+
return result;
|
|
295329
|
+
};
|
|
295330
|
+
})();
|
|
295331
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
295332
|
+
exports.resolveTaskTraceReference = resolveTaskTraceReference;
|
|
295333
|
+
async function resolveTaskTraceReference(metadata) {
|
|
295334
|
+
const traceFile = metadata?.trace_file;
|
|
295335
|
+
let traceId = metadata?.trace_id;
|
|
295336
|
+
if (!traceId && traceFile) {
|
|
295337
|
+
try {
|
|
295338
|
+
const { readTraceIdFromFile } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(48666)));
|
|
295339
|
+
traceId = (await readTraceIdFromFile(traceFile)) || undefined;
|
|
295340
|
+
}
|
|
295341
|
+
catch {
|
|
295342
|
+
traceId = undefined;
|
|
295343
|
+
}
|
|
295344
|
+
}
|
|
295345
|
+
return {
|
|
295346
|
+
traceId,
|
|
295347
|
+
traceFile,
|
|
295348
|
+
primaryRef: traceId || traceFile || undefined,
|
|
295349
|
+
};
|
|
295350
|
+
}
|
|
295351
|
+
|
|
295352
|
+
|
|
294432
295353
|
/***/ }),
|
|
294433
295354
|
|
|
294434
295355
|
/***/ 5932:
|
|
@@ -296786,13 +297707,17 @@ fallbackTraceId) {
|
|
|
296786
297707
|
const remoteTraceId = fallbackTraceId ||
|
|
296787
297708
|
(!isFilePath ? traceIdOrPath : (await readTraceIdFromFile(traceIdOrPath)) || undefined);
|
|
296788
297709
|
const preferLocalFirst = backendOrder[0] === 'file';
|
|
297710
|
+
logger_1.logger.debug(`[TraceSerializer] serializeTraceForPrompt ref=${traceIdOrPath} remoteTraceId=${remoteTraceId || '-'} backendOrder=${backendOrder.join('>')}`);
|
|
296789
297711
|
if (preferLocalFirst && localTracePath) {
|
|
297712
|
+
logger_1.logger.debug(`[TraceSerializer] Trying local trace file first: ${localTracePath}`);
|
|
296790
297713
|
spans = await fetchTraceSpans(localTracePath, { ...cfg, type: 'file' });
|
|
296791
297714
|
}
|
|
296792
297715
|
if (spans.length === 0 && remoteTraceId) {
|
|
297716
|
+
logger_1.logger.debug(`[TraceSerializer] Trying remote trace backends for trace_id=${remoteTraceId}`);
|
|
296793
297717
|
spans = await fetchTraceSpans(remoteTraceId, cfg);
|
|
296794
297718
|
}
|
|
296795
297719
|
if (spans.length === 0 && localTracePath) {
|
|
297720
|
+
logger_1.logger.debug(`[TraceSerializer] Falling back to local trace file: ${localTracePath}`);
|
|
296796
297721
|
spans = await fetchTraceSpans(localTracePath, { ...cfg, type: 'file' });
|
|
296797
297722
|
}
|
|
296798
297723
|
if (spans.length === 0) {
|
|
@@ -296889,6 +297814,9 @@ function renderSpanYaml(tree, allSpans, opts) {
|
|
|
296889
297814
|
}
|
|
296890
297815
|
function renderYamlNode(node, indent, lines, dedup, renderContext, fallbackIntent, fullOutput, maxLen, parentSpan) {
|
|
296891
297816
|
if (shouldSkipLifecycleSpan(node.span, renderContext)) {
|
|
297817
|
+
for (const child of node.children) {
|
|
297818
|
+
renderYamlNode(child, indent, lines, dedup, renderContext, fallbackIntent, fullOutput, maxLen, parentSpan);
|
|
297819
|
+
}
|
|
296892
297820
|
return;
|
|
296893
297821
|
}
|
|
296894
297822
|
const pad = ' '.repeat(indent);
|
|
@@ -297151,7 +298079,10 @@ function renderYamlOutput(rawOutput, pad, label, spanName, dedup, lines, fullOut
|
|
|
297151
298079
|
// and {text: "..."} → render text inline
|
|
297152
298080
|
if (typeof obj === 'object' && !Array.isArray(obj)) {
|
|
297153
298081
|
const keys = Object.keys(obj);
|
|
297154
|
-
if (keys.length === 1 &&
|
|
298082
|
+
if (keys.length === 1 &&
|
|
298083
|
+
typeof obj[keys[0]] === 'object' &&
|
|
298084
|
+
obj[keys[0]] !== null &&
|
|
298085
|
+
!Array.isArray(obj[keys[0]])) {
|
|
297155
298086
|
obj = obj[keys[0]]; // unwrap {answer: {...}} → {...}
|
|
297156
298087
|
}
|
|
297157
298088
|
// If single text key, render inline
|
|
@@ -297844,7 +298775,7 @@ function formatJsonPreview(obj, maxLen) {
|
|
|
297844
298775
|
let len = 2; // for { }
|
|
297845
298776
|
for (const [key, val] of Object.entries(obj)) {
|
|
297846
298777
|
// Skip internal/verbose keys
|
|
297847
|
-
if (key === 'raw' || key === '
|
|
298778
|
+
if (key === 'raw' || key === 'tags')
|
|
297848
298779
|
continue;
|
|
297849
298780
|
let valStr;
|
|
297850
298781
|
if (val === null || val === undefined)
|
|
@@ -297865,8 +298796,15 @@ function formatJsonPreview(obj, maxLen) {
|
|
|
297865
298796
|
.trim();
|
|
297866
298797
|
valStr = `"${truncate(clean.split('\n')[0], Math.min(80, maxLen / 3))}"`;
|
|
297867
298798
|
}
|
|
297868
|
-
else if (Array.isArray(val))
|
|
297869
|
-
|
|
298799
|
+
else if (Array.isArray(val)) {
|
|
298800
|
+
if (val.every(item => typeof item === 'string') &&
|
|
298801
|
+
val.join(', ').length < Math.min(120, maxLen / 2)) {
|
|
298802
|
+
valStr = `[${val.join(', ')}]`;
|
|
298803
|
+
}
|
|
298804
|
+
else {
|
|
298805
|
+
valStr = `[${val.length}]`;
|
|
298806
|
+
}
|
|
298807
|
+
}
|
|
297870
298808
|
else if (typeof val === 'object')
|
|
297871
298809
|
valStr = `{${Object.keys(val).length} keys}`;
|
|
297872
298810
|
else
|
|
@@ -298217,6 +299155,8 @@ const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
|
298217
299155
|
const logger_1 = __nccwpck_require__(86999);
|
|
298218
299156
|
const lazy_otel_1 = __nccwpck_require__(21084);
|
|
298219
299157
|
const instance_id_1 = __nccwpck_require__(89942);
|
|
299158
|
+
const task_live_updates_1 = __nccwpck_require__(5893);
|
|
299159
|
+
const task_trace_resolution_1 = __nccwpck_require__(4018);
|
|
298220
299160
|
function getPackageVersion() {
|
|
298221
299161
|
try {
|
|
298222
299162
|
return (__nccwpck_require__(8330).version) || 'dev';
|
|
@@ -298269,106 +299209,189 @@ async function trackExecution(opts, executor) {
|
|
|
298269
299209
|
},
|
|
298270
299210
|
});
|
|
298271
299211
|
const instanceId = (0, instance_id_1.getInstanceId)();
|
|
298272
|
-
|
|
298273
|
-
|
|
298274
|
-
|
|
298275
|
-
|
|
298276
|
-
|
|
298277
|
-
|
|
298278
|
-
|
|
298279
|
-
|
|
298280
|
-
|
|
298281
|
-
|
|
298282
|
-
catch {
|
|
298283
|
-
// best-effort — don't crash the task over a heartbeat failure
|
|
298284
|
-
}
|
|
298285
|
-
}, HEARTBEAT_INTERVAL);
|
|
298286
|
-
try {
|
|
298287
|
-
const result = await executor();
|
|
298288
|
-
// Now that execution is done, capture the trace ID from the active span.
|
|
298289
|
-
// At task creation time the span may not have been active yet, so we
|
|
298290
|
-
// update metadata post-execution to ensure trace_id is stored.
|
|
298291
|
-
try {
|
|
298292
|
-
const activeTraceId = lazy_otel_1.trace.getActiveSpan()?.spanContext().traceId;
|
|
298293
|
-
const persistedTraceId = (activeTraceId && activeTraceId !== '' ? activeTraceId : undefined) ||
|
|
298294
|
-
(await readTraceIdFromFallbackFile(traceFile));
|
|
298295
|
-
if (persistedTraceId && !task.metadata?.trace_id) {
|
|
298296
|
-
taskStore.updateMetadata(task.id, { trace_id: persistedTraceId });
|
|
299212
|
+
return await logger_1.logger.withTaskContext(task.id, async () => {
|
|
299213
|
+
taskStore.updateTaskState(task.id, 'working');
|
|
299214
|
+
taskStore.claimTask(task.id, instanceId);
|
|
299215
|
+
logger_1.logger.info(`[TaskTracking] Task ${task.id} started (source=${source}, workflow=${workflowId || '-'}, instance=${instanceId})`);
|
|
299216
|
+
const liveUpdateConfig = (0, task_live_updates_1.resolveTaskLiveUpdatesConfig)(opts.liveUpdates?.config);
|
|
299217
|
+
const initialTraceId = lazy_otel_1.trace.getActiveSpan()?.spanContext().traceId ||
|
|
299218
|
+
task.metadata?.trace_id;
|
|
299219
|
+
if (initialTraceId && !task.metadata?.trace_id) {
|
|
299220
|
+
try {
|
|
299221
|
+
taskStore.updateMetadata(task.id, { trace_id: initialTraceId });
|
|
298297
299222
|
}
|
|
299223
|
+
catch {
|
|
299224
|
+
// best-effort only
|
|
299225
|
+
}
|
|
299226
|
+
}
|
|
299227
|
+
const initialResolvedTrace = await (0, task_trace_resolution_1.resolveTaskTraceReference)({
|
|
299228
|
+
trace_id: initialTraceId || task.metadata?.trace_id,
|
|
299229
|
+
trace_file: task.metadata?.trace_file,
|
|
299230
|
+
});
|
|
299231
|
+
const liveUpdateManager = liveUpdateConfig && opts.liveUpdates?.sink
|
|
299232
|
+
? new task_live_updates_1.TaskLiveUpdateManager({
|
|
299233
|
+
taskId: task.id,
|
|
299234
|
+
requestText: messageText,
|
|
299235
|
+
traceRef: initialResolvedTrace.primaryRef,
|
|
299236
|
+
traceId: initialResolvedTrace.traceId,
|
|
299237
|
+
includeTraceId: opts.liveUpdates?.includeTraceId === true,
|
|
299238
|
+
sink: opts.liveUpdates.sink,
|
|
299239
|
+
config: liveUpdateConfig,
|
|
299240
|
+
resolveTraceState: () => {
|
|
299241
|
+
let current;
|
|
299242
|
+
try {
|
|
299243
|
+
current = taskStore.getTask(task.id);
|
|
299244
|
+
}
|
|
299245
|
+
catch {
|
|
299246
|
+
return {
|
|
299247
|
+
traceRef: initialResolvedTrace.primaryRef,
|
|
299248
|
+
traceId: initialResolvedTrace.traceId,
|
|
299249
|
+
};
|
|
299250
|
+
}
|
|
299251
|
+
return {
|
|
299252
|
+
traceRef: current?.metadata?.trace_id ||
|
|
299253
|
+
current?.metadata?.trace_file ||
|
|
299254
|
+
initialResolvedTrace.primaryRef,
|
|
299255
|
+
traceId: current?.metadata?.trace_id,
|
|
299256
|
+
};
|
|
299257
|
+
},
|
|
299258
|
+
onPostedRef: ref => {
|
|
299259
|
+
try {
|
|
299260
|
+
taskStore.updateMetadata(task.id, ref);
|
|
299261
|
+
}
|
|
299262
|
+
catch {
|
|
299263
|
+
// best-effort only
|
|
299264
|
+
}
|
|
299265
|
+
},
|
|
299266
|
+
appendHistory: (text, stage) => {
|
|
299267
|
+
try {
|
|
299268
|
+
taskStore.appendHistory(task.id, {
|
|
299269
|
+
message_id: crypto_1.default.randomUUID(),
|
|
299270
|
+
role: 'agent',
|
|
299271
|
+
parts: [{ text }],
|
|
299272
|
+
metadata: { kind: 'task_live_update', stage, source },
|
|
299273
|
+
});
|
|
299274
|
+
}
|
|
299275
|
+
catch {
|
|
299276
|
+
// best-effort only
|
|
299277
|
+
}
|
|
299278
|
+
},
|
|
299279
|
+
})
|
|
299280
|
+
: null;
|
|
299281
|
+
if (liveUpdateConfig && !opts.liveUpdates?.sink) {
|
|
299282
|
+
logger_1.logger.debug(`[TaskTracking] Live updates requested for task ${task.id} but no sink is available for source=${source}`);
|
|
298298
299283
|
}
|
|
298299
|
-
|
|
298300
|
-
|
|
299284
|
+
else if (liveUpdateManager) {
|
|
299285
|
+
logger_1.logger.info(`[TaskTracking] Live updates enabled for task ${task.id} (source=${source})`);
|
|
298301
299286
|
}
|
|
298302
|
-
//
|
|
298303
|
-
//
|
|
298304
|
-
|
|
298305
|
-
|
|
298306
|
-
|
|
299287
|
+
// Heartbeat: periodically touch updated_at so stale-task detection
|
|
299288
|
+
// can distinguish live tasks from orphans (works across nodes).
|
|
299289
|
+
const HEARTBEAT_INTERVAL = 60_000; // 1 minute
|
|
299290
|
+
const heartbeatTimer = setInterval(() => {
|
|
299291
|
+
try {
|
|
299292
|
+
taskStore.heartbeat(task.id);
|
|
299293
|
+
}
|
|
299294
|
+
catch {
|
|
299295
|
+
// best-effort — don't crash the task over a heartbeat failure
|
|
299296
|
+
}
|
|
299297
|
+
}, HEARTBEAT_INTERVAL);
|
|
298307
299298
|
try {
|
|
298308
|
-
|
|
298309
|
-
|
|
298310
|
-
|
|
298311
|
-
|
|
298312
|
-
|
|
298313
|
-
|
|
298314
|
-
|
|
298315
|
-
|
|
298316
|
-
|
|
298317
|
-
|
|
298318
|
-
|
|
298319
|
-
|
|
298320
|
-
|
|
298321
|
-
|
|
299299
|
+
if (liveUpdateManager) {
|
|
299300
|
+
await liveUpdateManager.start();
|
|
299301
|
+
}
|
|
299302
|
+
const result = await executor();
|
|
299303
|
+
// Now that execution is done, capture the trace ID from the active span.
|
|
299304
|
+
// At task creation time the span may not have been active yet, so we
|
|
299305
|
+
// update metadata post-execution to ensure trace_id is stored.
|
|
299306
|
+
try {
|
|
299307
|
+
const activeTraceId = lazy_otel_1.trace.getActiveSpan()?.spanContext().traceId;
|
|
299308
|
+
const persistedTraceId = (activeTraceId && activeTraceId !== '' ? activeTraceId : undefined) ||
|
|
299309
|
+
(await readTraceIdFromFallbackFile(traceFile));
|
|
299310
|
+
if (persistedTraceId && !task.metadata?.trace_id) {
|
|
299311
|
+
taskStore.updateMetadata(task.id, { trace_id: persistedTraceId });
|
|
299312
|
+
}
|
|
299313
|
+
}
|
|
299314
|
+
catch {
|
|
299315
|
+
// best-effort — don't fail the task over metadata
|
|
299316
|
+
}
|
|
299317
|
+
// Extract AI response text from the result.
|
|
299318
|
+
// result.reviewSummary.history is keyed by checkId with arrays of outputs.
|
|
299319
|
+
// We want the LAST check's text output (the final AI response), not the
|
|
299320
|
+
// first (which is typically the intent router).
|
|
299321
|
+
let responseText = 'Execution completed';
|
|
299322
|
+
try {
|
|
299323
|
+
const history = result?.reviewSummary?.history;
|
|
299324
|
+
if (history) {
|
|
299325
|
+
const entries = Object.values(history);
|
|
299326
|
+
// Iterate in reverse — last check output is the final response
|
|
299327
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
299328
|
+
const outputs = entries[i];
|
|
299329
|
+
if (!Array.isArray(outputs))
|
|
299330
|
+
continue;
|
|
299331
|
+
// Within a check, look at the last output first too
|
|
299332
|
+
for (let j = outputs.length - 1; j >= 0; j--) {
|
|
299333
|
+
const text = outputs[j]?.text;
|
|
299334
|
+
if (typeof text === 'string' && text.trim().length > 0) {
|
|
299335
|
+
responseText = text.trim();
|
|
299336
|
+
break;
|
|
299337
|
+
}
|
|
298322
299338
|
}
|
|
299339
|
+
if (responseText !== 'Execution completed')
|
|
299340
|
+
break;
|
|
298323
299341
|
}
|
|
298324
|
-
if (responseText !== 'Execution completed')
|
|
298325
|
-
break;
|
|
298326
299342
|
}
|
|
298327
299343
|
}
|
|
299344
|
+
catch {
|
|
299345
|
+
// ignore extraction errors
|
|
299346
|
+
}
|
|
299347
|
+
const completedMsg = {
|
|
299348
|
+
message_id: crypto_1.default.randomUUID(),
|
|
299349
|
+
role: 'agent',
|
|
299350
|
+
parts: [{ text: responseText }],
|
|
299351
|
+
};
|
|
299352
|
+
try {
|
|
299353
|
+
taskStore.updateTaskState(task.id, 'completed', completedMsg);
|
|
299354
|
+
logger_1.logger.info(`[TaskTracking] Task ${task.id} completed`);
|
|
299355
|
+
}
|
|
299356
|
+
catch (stateErr) {
|
|
299357
|
+
// Another process (e.g. stale sweep) may have already marked this task as failed.
|
|
299358
|
+
// Log a warning but do NOT re-throw — the execution itself succeeded.
|
|
299359
|
+
logger_1.logger.warn(`[TaskTracking] Task ${task.id} completed but state transition failed: ${stateErr instanceof Error ? stateErr.message : stateErr}`);
|
|
299360
|
+
}
|
|
299361
|
+
// Fire-and-forget LLM evaluation (non-blocking)
|
|
299362
|
+
// Enabled via opts.autoEvaluate (from config.task_evaluate) or VISOR_TASK_EVALUATE env var
|
|
299363
|
+
if (opts.autoEvaluate || process.env.VISOR_TASK_EVALUATE === 'true') {
|
|
299364
|
+
scheduleEvaluation(task.id, taskStore);
|
|
299365
|
+
}
|
|
299366
|
+
if (liveUpdateManager) {
|
|
299367
|
+
await liveUpdateManager.complete(responseText);
|
|
299368
|
+
}
|
|
299369
|
+
return { task, result };
|
|
298328
299370
|
}
|
|
298329
|
-
catch {
|
|
298330
|
-
|
|
298331
|
-
|
|
298332
|
-
|
|
298333
|
-
|
|
298334
|
-
|
|
298335
|
-
|
|
298336
|
-
|
|
298337
|
-
|
|
298338
|
-
|
|
298339
|
-
|
|
298340
|
-
|
|
298341
|
-
|
|
298342
|
-
|
|
298343
|
-
|
|
298344
|
-
|
|
298345
|
-
|
|
298346
|
-
|
|
298347
|
-
// Enabled via opts.autoEvaluate (from config.task_evaluate) or VISOR_TASK_EVALUATE env var
|
|
298348
|
-
if (opts.autoEvaluate || process.env.VISOR_TASK_EVALUATE === 'true') {
|
|
298349
|
-
scheduleEvaluation(task.id, taskStore);
|
|
298350
|
-
}
|
|
298351
|
-
return { task, result };
|
|
298352
|
-
}
|
|
298353
|
-
catch (err) {
|
|
298354
|
-
const errorText = err instanceof Error ? err.message : String(err);
|
|
298355
|
-
const failMessage = {
|
|
298356
|
-
message_id: crypto_1.default.randomUUID(),
|
|
298357
|
-
role: 'agent',
|
|
298358
|
-
parts: [{ text: errorText }],
|
|
298359
|
-
};
|
|
298360
|
-
try {
|
|
298361
|
-
taskStore.updateTaskState(task.id, 'failed', failMessage);
|
|
298362
|
-
logger_1.logger.info(`[TaskTracking] Task ${task.id} failed: ${errorText}`);
|
|
299371
|
+
catch (err) {
|
|
299372
|
+
const errorText = err instanceof Error ? err.message : String(err);
|
|
299373
|
+
const failMessage = {
|
|
299374
|
+
message_id: crypto_1.default.randomUUID(),
|
|
299375
|
+
role: 'agent',
|
|
299376
|
+
parts: [{ text: errorText }],
|
|
299377
|
+
};
|
|
299378
|
+
try {
|
|
299379
|
+
taskStore.updateTaskState(task.id, 'failed', failMessage);
|
|
299380
|
+
logger_1.logger.info(`[TaskTracking] Task ${task.id} failed: ${errorText}`);
|
|
299381
|
+
}
|
|
299382
|
+
catch {
|
|
299383
|
+
// ignore double-failure
|
|
299384
|
+
}
|
|
299385
|
+
if (liveUpdateManager) {
|
|
299386
|
+
await liveUpdateManager.fail(`:warning: ${errorText}`);
|
|
299387
|
+
}
|
|
299388
|
+
throw err; // re-throw to preserve original behavior
|
|
298363
299389
|
}
|
|
298364
|
-
|
|
298365
|
-
|
|
299390
|
+
finally {
|
|
299391
|
+
clearInterval(heartbeatTimer);
|
|
299392
|
+
liveUpdateManager?.stop();
|
|
298366
299393
|
}
|
|
298367
|
-
|
|
298368
|
-
}
|
|
298369
|
-
finally {
|
|
298370
|
-
clearInterval(heartbeatTimer);
|
|
298371
|
-
}
|
|
299394
|
+
});
|
|
298372
299395
|
}
|
|
298373
299396
|
// ---------------------------------------------------------------------------
|
|
298374
299397
|
// Non-blocking auto-evaluation
|
|
@@ -298376,14 +299399,16 @@ async function trackExecution(opts, executor) {
|
|
|
298376
299399
|
function scheduleEvaluation(taskId, taskStore) {
|
|
298377
299400
|
// Delay slightly to let OTEL spans flush before we try to read the trace
|
|
298378
299401
|
setTimeout(async () => {
|
|
298379
|
-
|
|
298380
|
-
|
|
298381
|
-
|
|
298382
|
-
|
|
298383
|
-
|
|
298384
|
-
|
|
298385
|
-
|
|
298386
|
-
|
|
299402
|
+
await logger_1.logger.withTaskContext(taskId, async () => {
|
|
299403
|
+
try {
|
|
299404
|
+
const { evaluateAndStore } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(53635)));
|
|
299405
|
+
await evaluateAndStore(taskId, taskStore);
|
|
299406
|
+
logger_1.logger.info(`[TaskEvaluator] Auto-evaluation completed for task ${taskId}`);
|
|
299407
|
+
}
|
|
299408
|
+
catch (err) {
|
|
299409
|
+
logger_1.logger.warn(`[TaskEvaluator] Auto-evaluation failed for task ${taskId}: ${err instanceof Error ? err.message : err}`);
|
|
299410
|
+
}
|
|
299411
|
+
});
|
|
298387
299412
|
}, 5000);
|
|
298388
299413
|
}
|
|
298389
299414
|
|
|
@@ -302814,6 +303839,8 @@ async function main() {
|
|
|
302814
303839
|
authTokenEnv: getArg('--auth-token-env'),
|
|
302815
303840
|
tlsCert: getArg('--tls-cert'),
|
|
302816
303841
|
tlsKey: getArg('--tls-key'),
|
|
303842
|
+
asyncMode: mcpArgs.includes('--async'),
|
|
303843
|
+
longPollTimeout: getArg('--poll-timeout') ? Number(getArg('--poll-timeout')) : undefined,
|
|
302817
303844
|
};
|
|
302818
303845
|
const { startMcpServer } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(93143)));
|
|
302819
303846
|
await startMcpServer(mcpOptions);
|
|
@@ -304288,6 +305315,7 @@ class CLI {
|
|
|
304288
305315
|
.option('--mcp', 'Enable MCP HTTP server runner (composable, requires --mcp-auth-token)')
|
|
304289
305316
|
.option('--mcp-port <port>', 'Port for MCP HTTP server (default: 8080)', value => parseInt(value, 10))
|
|
304290
305317
|
.option('--mcp-auth-token <token>', 'Bearer token for MCP HTTP server authentication')
|
|
305318
|
+
.option('--mcp-async', 'Enable async job mode for MCP (start_job/get_job pattern)')
|
|
304291
305319
|
.option('-c, --check <type>', 'Specify check type (can be used multiple times)', this.collectChecks, [])
|
|
304292
305320
|
.option('-o, --output <format>', 'Output format (table, json, markdown, sarif)', 'table')
|
|
304293
305321
|
.option('--output-file <path>', 'Write formatted output to a file instead of stdout')
|
|
@@ -304428,6 +305456,7 @@ class CLI {
|
|
|
304428
305456
|
mcp: Boolean(options.mcp),
|
|
304429
305457
|
mcpPort: options.mcpPort,
|
|
304430
305458
|
mcpAuthToken: options.mcpAuthToken,
|
|
305459
|
+
mcpAsync: Boolean(options.mcpAsync),
|
|
304431
305460
|
tui: Boolean(options.tui),
|
|
304432
305461
|
keepWorkspace: Boolean(options.keepWorkspace),
|
|
304433
305462
|
workspacePath: options.workspacePath,
|
|
@@ -306362,6 +307391,7 @@ class ConfigManager {
|
|
|
306362
307391
|
'sandbox',
|
|
306363
307392
|
'sandbox_defaults',
|
|
306364
307393
|
'policy',
|
|
307394
|
+
'task_live_updates',
|
|
306365
307395
|
// Workflow metadata fields used when configs are imported as reusable workflows
|
|
306366
307396
|
'id',
|
|
306367
307397
|
'name',
|
|
@@ -313538,6 +314568,8 @@ exports.SlackFrontend = void 0;
|
|
|
313538
314568
|
const client_1 = __nccwpck_require__(67681);
|
|
313539
314569
|
const markdown_1 = __nccwpck_require__(34907);
|
|
313540
314570
|
const lazy_otel_1 = __nccwpck_require__(21084);
|
|
314571
|
+
const task_live_updates_1 = __nccwpck_require__(5893);
|
|
314572
|
+
const logger_1 = __nccwpck_require__(86999);
|
|
313541
314573
|
class SlackFrontend {
|
|
313542
314574
|
name = 'slack';
|
|
313543
314575
|
subs = [];
|
|
@@ -313751,7 +314783,19 @@ class SlackFrontend {
|
|
|
313751
314783
|
return false;
|
|
313752
314784
|
}
|
|
313753
314785
|
}
|
|
314786
|
+
isLiveTaskUpdatesMode(ctx) {
|
|
314787
|
+
try {
|
|
314788
|
+
if (!this.getInboundSlackPayload(ctx))
|
|
314789
|
+
return false;
|
|
314790
|
+
return (0, task_live_updates_1.isFrontendLiveUpdatesEnabled)(ctx.config?.task_live_updates, 'slack');
|
|
314791
|
+
}
|
|
314792
|
+
catch {
|
|
314793
|
+
return false;
|
|
314794
|
+
}
|
|
314795
|
+
}
|
|
313754
314796
|
async maybePostError(ctx, title, message, checkId) {
|
|
314797
|
+
if (this.isLiveTaskUpdatesMode(ctx))
|
|
314798
|
+
return;
|
|
313755
314799
|
if (this.errorNotified)
|
|
313756
314800
|
return;
|
|
313757
314801
|
return this.postErrorToSlack(ctx, title, message, checkId);
|
|
@@ -313761,6 +314805,8 @@ class SlackFrontend {
|
|
|
313761
314805
|
* Used for fatal/shutdown errors that must always reach the user.
|
|
313762
314806
|
*/
|
|
313763
314807
|
async forcePostError(ctx, title, message, checkId) {
|
|
314808
|
+
if (this.isLiveTaskUpdatesMode(ctx))
|
|
314809
|
+
return;
|
|
313764
314810
|
return this.postErrorToSlack(ctx, title, message, checkId);
|
|
313765
314811
|
}
|
|
313766
314812
|
async postErrorToSlack(ctx, title, message, checkId) {
|
|
@@ -313784,9 +314830,9 @@ class SlackFrontend {
|
|
|
313784
314830
|
if (message)
|
|
313785
314831
|
text += `\n${message}`;
|
|
313786
314832
|
if (this.isTelemetryEnabled(ctx)) {
|
|
313787
|
-
const
|
|
313788
|
-
if (
|
|
313789
|
-
text += `\n\n
|
|
314833
|
+
const suffix = this.getExecutionReferenceSuffix();
|
|
314834
|
+
if (suffix) {
|
|
314835
|
+
text += `\n\n${suffix}`;
|
|
313790
314836
|
}
|
|
313791
314837
|
}
|
|
313792
314838
|
const formattedText = (0, markdown_1.formatSlackText)(text);
|
|
@@ -313821,6 +314867,8 @@ class SlackFrontend {
|
|
|
313821
314867
|
}
|
|
313822
314868
|
async maybePostExecutionFailure(ctx, checkId, result) {
|
|
313823
314869
|
try {
|
|
314870
|
+
if (this.isLiveTaskUpdatesMode(ctx))
|
|
314871
|
+
return;
|
|
313824
314872
|
if (this.errorNotified)
|
|
313825
314873
|
return;
|
|
313826
314874
|
const cfg = ctx.config || {};
|
|
@@ -313930,6 +314978,8 @@ class SlackFrontend {
|
|
|
313930
314978
|
*/
|
|
313931
314979
|
async maybePostDirectReply(ctx, checkId, result) {
|
|
313932
314980
|
try {
|
|
314981
|
+
if (this.isLiveTaskUpdatesMode(ctx))
|
|
314982
|
+
return;
|
|
313933
314983
|
const cfg = ctx.config || {};
|
|
313934
314984
|
const checkCfg = cfg.checks?.[checkId];
|
|
313935
314985
|
if (!checkCfg)
|
|
@@ -314108,9 +315158,8 @@ class SlackFrontend {
|
|
|
314108
315158
|
const telemetryEnabled = telemetryCfg === true ||
|
|
314109
315159
|
(telemetryCfg && typeof telemetryCfg === 'object' && telemetryCfg.enabled === true);
|
|
314110
315160
|
if (telemetryEnabled) {
|
|
314111
|
-
const
|
|
314112
|
-
if (
|
|
314113
|
-
const suffix = `\`trace_id: ${traceInfo.traceId}\``;
|
|
315161
|
+
const suffix = this.getExecutionReferenceSuffix();
|
|
315162
|
+
if (suffix) {
|
|
314114
315163
|
decoratedText = `${decoratedText}\n\n${suffix}`;
|
|
314115
315164
|
}
|
|
314116
315165
|
}
|
|
@@ -314157,6 +315206,20 @@ class SlackFrontend {
|
|
|
314157
315206
|
return null;
|
|
314158
315207
|
}
|
|
314159
315208
|
}
|
|
315209
|
+
getExecutionReferenceSuffix() {
|
|
315210
|
+
try {
|
|
315211
|
+
const taskId = logger_1.logger.getCurrentTaskId();
|
|
315212
|
+
if (taskId)
|
|
315213
|
+
return `\`task_id: ${taskId}\``;
|
|
315214
|
+
const traceInfo = this.getTraceInfo() || this.cachedTraceInfo;
|
|
315215
|
+
if (traceInfo?.traceId)
|
|
315216
|
+
return `\`trace_id: ${traceInfo.traceId}\``;
|
|
315217
|
+
return null;
|
|
315218
|
+
}
|
|
315219
|
+
catch {
|
|
315220
|
+
return null;
|
|
315221
|
+
}
|
|
315222
|
+
}
|
|
314160
315223
|
}
|
|
314161
315224
|
exports.SlackFrontend = SlackFrontend;
|
|
314162
315225
|
|
|
@@ -314172,6 +315235,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
314172
315235
|
exports.TeamsFrontend = void 0;
|
|
314173
315236
|
const client_1 = __nccwpck_require__(55391);
|
|
314174
315237
|
const markdown_1 = __nccwpck_require__(37349);
|
|
315238
|
+
const task_live_updates_1 = __nccwpck_require__(5893);
|
|
314175
315239
|
class TeamsFrontend {
|
|
314176
315240
|
name = 'teams';
|
|
314177
315241
|
subs = [];
|
|
@@ -314280,6 +315344,8 @@ class TeamsFrontend {
|
|
|
314280
315344
|
return;
|
|
314281
315345
|
if (checkCfg.criticality === 'internal')
|
|
314282
315346
|
return;
|
|
315347
|
+
if ((0, task_live_updates_1.isFrontendLiveUpdatesEnabled)(cfg.task_live_updates, 'teams'))
|
|
315348
|
+
return;
|
|
314283
315349
|
// For AI checks, only post simple schemas
|
|
314284
315350
|
if (isAi) {
|
|
314285
315351
|
const schema = checkCfg.schema;
|
|
@@ -314360,6 +315426,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
314360
315426
|
exports.TelegramFrontend = void 0;
|
|
314361
315427
|
const client_1 = __nccwpck_require__(68148);
|
|
314362
315428
|
const markdown_1 = __nccwpck_require__(21506);
|
|
315429
|
+
const task_live_updates_1 = __nccwpck_require__(5893);
|
|
314363
315430
|
class TelegramFrontend {
|
|
314364
315431
|
name = 'telegram';
|
|
314365
315432
|
subs = [];
|
|
@@ -314548,6 +315615,8 @@ class TelegramFrontend {
|
|
|
314548
315615
|
return;
|
|
314549
315616
|
if (checkCfg.criticality === 'internal')
|
|
314550
315617
|
return;
|
|
315618
|
+
if ((0, task_live_updates_1.isFrontendLiveUpdatesEnabled)(cfg.task_live_updates, 'telegram'))
|
|
315619
|
+
return;
|
|
314551
315620
|
// For AI checks, only post simple schemas
|
|
314552
315621
|
if (isAi) {
|
|
314553
315622
|
const schema = checkCfg.schema;
|
|
@@ -315039,6 +316108,17 @@ exports.configSchema = {
|
|
|
315039
316108
|
],
|
|
315040
316109
|
description: 'Automatically evaluate completed tasks using an LLM judge. Requires task_tracking to be enabled. Runs asynchronously after task completion. Set to `true` for defaults, or provide an object to configure.',
|
|
315041
316110
|
},
|
|
316111
|
+
task_live_updates: {
|
|
316112
|
+
anyOf: [
|
|
316113
|
+
{
|
|
316114
|
+
type: 'boolean',
|
|
316115
|
+
},
|
|
316116
|
+
{
|
|
316117
|
+
$ref: '#/definitions/TaskLiveUpdatesConfig',
|
|
316118
|
+
},
|
|
316119
|
+
],
|
|
316120
|
+
description: 'Live progress updates for long-running tracked tasks on supported frontends.',
|
|
316121
|
+
},
|
|
315042
316122
|
},
|
|
315043
316123
|
required: ['version'],
|
|
315044
316124
|
patternProperties: {
|
|
@@ -315910,7 +316990,7 @@ exports.configSchema = {
|
|
|
315910
316990
|
description: 'Arguments/inputs for the workflow',
|
|
315911
316991
|
},
|
|
315912
316992
|
overrides: {
|
|
315913
|
-
$ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-15521-30601-src_types_config.ts-0-
|
|
316993
|
+
$ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-15521-30601-src_types_config.ts-0-62422%3E%3E',
|
|
315914
316994
|
description: 'Override specific step configurations in the workflow',
|
|
315915
316995
|
},
|
|
315916
316996
|
output_mapping: {
|
|
@@ -315926,7 +317006,7 @@ exports.configSchema = {
|
|
|
315926
317006
|
description: 'Config file path - alternative to workflow ID (loads a Visor config file as workflow)',
|
|
315927
317007
|
},
|
|
315928
317008
|
workflow_overrides: {
|
|
315929
|
-
$ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-15521-30601-src_types_config.ts-0-
|
|
317009
|
+
$ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-15521-30601-src_types_config.ts-0-62422%3E%3E',
|
|
315930
317010
|
description: 'Alias for overrides - workflow step overrides (backward compatibility)',
|
|
315931
317011
|
},
|
|
315932
317012
|
ref: {
|
|
@@ -316654,7 +317734,7 @@ exports.configSchema = {
|
|
|
316654
317734
|
description: 'Custom output name (defaults to workflow name)',
|
|
316655
317735
|
},
|
|
316656
317736
|
overrides: {
|
|
316657
|
-
$ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-15521-30601-src_types_config.ts-0-
|
|
317737
|
+
$ref: '#/definitions/Record%3Cstring%2CPartial%3Cinterface-src_types_config.ts-15521-30601-src_types_config.ts-0-62422%3E%3E',
|
|
316658
317738
|
description: 'Step overrides',
|
|
316659
317739
|
},
|
|
316660
317740
|
output_mapping: {
|
|
@@ -316669,13 +317749,13 @@ exports.configSchema = {
|
|
|
316669
317749
|
'^x-': {},
|
|
316670
317750
|
},
|
|
316671
317751
|
},
|
|
316672
|
-
'Record<string,Partial<interface-src_types_config.ts-15521-30601-src_types_config.ts-0-
|
|
317752
|
+
'Record<string,Partial<interface-src_types_config.ts-15521-30601-src_types_config.ts-0-62422>>': {
|
|
316673
317753
|
type: 'object',
|
|
316674
317754
|
additionalProperties: {
|
|
316675
|
-
$ref: '#/definitions/Partial%3Cinterface-src_types_config.ts-15521-30601-src_types_config.ts-0-
|
|
317755
|
+
$ref: '#/definitions/Partial%3Cinterface-src_types_config.ts-15521-30601-src_types_config.ts-0-62422%3E',
|
|
316676
317756
|
},
|
|
316677
317757
|
},
|
|
316678
|
-
'Partial<interface-src_types_config.ts-15521-30601-src_types_config.ts-0-
|
|
317758
|
+
'Partial<interface-src_types_config.ts-15521-30601-src_types_config.ts-0-62422>': {
|
|
316679
317759
|
type: 'object',
|
|
316680
317760
|
additionalProperties: false,
|
|
316681
317761
|
},
|
|
@@ -318608,6 +319688,102 @@ exports.configSchema = {
|
|
|
318608
319688
|
'^x-': {},
|
|
318609
319689
|
},
|
|
318610
319690
|
},
|
|
319691
|
+
TaskLiveUpdatesConfig: {
|
|
319692
|
+
type: 'object',
|
|
319693
|
+
properties: {
|
|
319694
|
+
enabled: {
|
|
319695
|
+
type: 'boolean',
|
|
319696
|
+
description: 'Enable live task progress updates (default: true when config object is present)',
|
|
319697
|
+
},
|
|
319698
|
+
interval_seconds: {
|
|
319699
|
+
type: 'number',
|
|
319700
|
+
description: 'Update interval in seconds (default: 10)',
|
|
319701
|
+
},
|
|
319702
|
+
model: {
|
|
319703
|
+
type: 'string',
|
|
319704
|
+
description: 'LLM model to use for progress summarization',
|
|
319705
|
+
},
|
|
319706
|
+
provider: {
|
|
319707
|
+
type: 'string',
|
|
319708
|
+
description: 'AI provider to use for progress summarization',
|
|
319709
|
+
},
|
|
319710
|
+
prompt: {
|
|
319711
|
+
type: 'string',
|
|
319712
|
+
description: 'Custom system prompt for the progress summarizer',
|
|
319713
|
+
},
|
|
319714
|
+
initial_message: {
|
|
319715
|
+
type: 'string',
|
|
319716
|
+
description: 'Immediate placeholder text posted before the first summary is generated',
|
|
319717
|
+
},
|
|
319718
|
+
max_trace_chars: {
|
|
319719
|
+
type: 'number',
|
|
319720
|
+
description: 'Maximum serialized trace characters passed into the summarizer (default: 12000)',
|
|
319721
|
+
},
|
|
319722
|
+
frontends: {
|
|
319723
|
+
type: 'object',
|
|
319724
|
+
properties: {
|
|
319725
|
+
slack: {
|
|
319726
|
+
type: 'object',
|
|
319727
|
+
properties: {
|
|
319728
|
+
enabled: {
|
|
319729
|
+
type: 'boolean',
|
|
319730
|
+
},
|
|
319731
|
+
},
|
|
319732
|
+
additionalProperties: false,
|
|
319733
|
+
patternProperties: {
|
|
319734
|
+
'^x-': {},
|
|
319735
|
+
},
|
|
319736
|
+
},
|
|
319737
|
+
telegram: {
|
|
319738
|
+
type: 'object',
|
|
319739
|
+
properties: {
|
|
319740
|
+
enabled: {
|
|
319741
|
+
type: 'boolean',
|
|
319742
|
+
},
|
|
319743
|
+
},
|
|
319744
|
+
additionalProperties: false,
|
|
319745
|
+
patternProperties: {
|
|
319746
|
+
'^x-': {},
|
|
319747
|
+
},
|
|
319748
|
+
},
|
|
319749
|
+
teams: {
|
|
319750
|
+
type: 'object',
|
|
319751
|
+
properties: {
|
|
319752
|
+
enabled: {
|
|
319753
|
+
type: 'boolean',
|
|
319754
|
+
},
|
|
319755
|
+
},
|
|
319756
|
+
additionalProperties: false,
|
|
319757
|
+
patternProperties: {
|
|
319758
|
+
'^x-': {},
|
|
319759
|
+
},
|
|
319760
|
+
},
|
|
319761
|
+
whatsapp: {
|
|
319762
|
+
type: 'object',
|
|
319763
|
+
properties: {
|
|
319764
|
+
enabled: {
|
|
319765
|
+
type: 'boolean',
|
|
319766
|
+
},
|
|
319767
|
+
},
|
|
319768
|
+
additionalProperties: false,
|
|
319769
|
+
patternProperties: {
|
|
319770
|
+
'^x-': {},
|
|
319771
|
+
},
|
|
319772
|
+
},
|
|
319773
|
+
},
|
|
319774
|
+
additionalProperties: false,
|
|
319775
|
+
description: 'Per-frontend enablement overrides',
|
|
319776
|
+
patternProperties: {
|
|
319777
|
+
'^x-': {},
|
|
319778
|
+
},
|
|
319779
|
+
},
|
|
319780
|
+
},
|
|
319781
|
+
additionalProperties: false,
|
|
319782
|
+
description: 'Live task progress updates for supported interactive frontends.\n\nWhen enabled, Visor posts a "working on it" placeholder and periodically updates the same message using a cheap internal LLM summary of the current execution trace. The final answer replaces that same message.',
|
|
319783
|
+
patternProperties: {
|
|
319784
|
+
'^x-': {},
|
|
319785
|
+
},
|
|
319786
|
+
},
|
|
318611
319787
|
},
|
|
318612
319788
|
};
|
|
318613
319789
|
exports["default"] = exports.configSchema;
|
|
@@ -322522,6 +323698,7 @@ exports.configureLoggerFromCli = configureLoggerFromCli;
|
|
|
322522
323698
|
* - Supports levels: silent < error < warn < info < verbose < debug
|
|
322523
323699
|
* - Routes logs to stderr to keep stdout clean for machine-readable output
|
|
322524
323700
|
*/
|
|
323701
|
+
const node_async_hooks_1 = __nccwpck_require__(16698);
|
|
322525
323702
|
const lazy_otel_1 = __nccwpck_require__(21084);
|
|
322526
323703
|
function levelToNumber(level) {
|
|
322527
323704
|
switch (level) {
|
|
@@ -322549,6 +323726,7 @@ const OTEL_SEVERITY = {
|
|
|
322549
323726
|
debug: 5, // DEBUG
|
|
322550
323727
|
};
|
|
322551
323728
|
class Logger {
|
|
323729
|
+
taskContextStorage = new node_async_hooks_1.AsyncLocalStorage();
|
|
322552
323730
|
level = 'info';
|
|
322553
323731
|
isJsonLike = false;
|
|
322554
323732
|
isTTY = typeof process !== 'undefined' ? !!process.stderr.isTTY : false;
|
|
@@ -322605,11 +323783,25 @@ class Logger {
|
|
|
322605
323783
|
}
|
|
322606
323784
|
return true;
|
|
322607
323785
|
}
|
|
322608
|
-
|
|
323786
|
+
withTaskContext(taskId, fn) {
|
|
323787
|
+
const current = this.taskContextStorage.getStore() || {};
|
|
323788
|
+
return this.taskContextStorage.run({ ...current, taskId }, fn);
|
|
323789
|
+
}
|
|
323790
|
+
getCurrentTaskId() {
|
|
323791
|
+
return this.taskContextStorage.getStore()?.taskId;
|
|
323792
|
+
}
|
|
323793
|
+
getContextSuffix(msg) {
|
|
322609
323794
|
if (!msg)
|
|
322610
323795
|
return '';
|
|
322611
|
-
if (msg.includes('
|
|
323796
|
+
if (msg.includes('task_id=') ||
|
|
323797
|
+
msg.includes('task_id:') ||
|
|
323798
|
+
msg.includes('trace_id=') ||
|
|
323799
|
+
msg.includes('trace_id:')) {
|
|
322612
323800
|
return '';
|
|
323801
|
+
}
|
|
323802
|
+
const taskId = this.getCurrentTaskId();
|
|
323803
|
+
if (taskId)
|
|
323804
|
+
return ` [task_id=${taskId}]`;
|
|
322613
323805
|
try {
|
|
322614
323806
|
const span = lazy_otel_1.trace.getSpan(lazy_otel_1.context.active()) || lazy_otel_1.trace.getActiveSpan();
|
|
322615
323807
|
const ctx = span?.spanContext?.();
|
|
@@ -322639,12 +323831,14 @@ class Logger {
|
|
|
322639
323831
|
return;
|
|
322640
323832
|
const span = lazy_otel_1.trace.getSpan(lazy_otel_1.context.active()) || lazy_otel_1.trace.getActiveSpan();
|
|
322641
323833
|
const spanCtx = span?.spanContext?.();
|
|
323834
|
+
const taskId = this.getCurrentTaskId();
|
|
322642
323835
|
this.otelLogger.emit({
|
|
322643
323836
|
severityNumber: OTEL_SEVERITY[level] || 9,
|
|
322644
323837
|
severityText: level.toUpperCase(),
|
|
322645
323838
|
body: msg,
|
|
322646
323839
|
attributes: {
|
|
322647
323840
|
'visor.logger': true,
|
|
323841
|
+
...(taskId ? { task_id: taskId } : {}),
|
|
322648
323842
|
...(spanCtx?.traceId ? { trace_id: spanCtx.traceId, span_id: spanCtx.spanId } : {}),
|
|
322649
323843
|
},
|
|
322650
323844
|
});
|
|
@@ -322655,7 +323849,7 @@ class Logger {
|
|
|
322655
323849
|
}
|
|
322656
323850
|
write(msg, level) {
|
|
322657
323851
|
// Always route to stderr to keep stdout clean for results
|
|
322658
|
-
const suffix = this.
|
|
323852
|
+
const suffix = this.getContextSuffix(msg);
|
|
322659
323853
|
const decoratedMsg = suffix ? `${msg}${suffix}` : msg;
|
|
322660
323854
|
const lvl = level || 'info';
|
|
322661
323855
|
// Emit to OTel Logs pipeline (non-blocking, best-effort)
|
|
@@ -322781,6 +323975,337 @@ function configureLoggerFromCli(options) {
|
|
|
322781
323975
|
}
|
|
322782
323976
|
|
|
322783
323977
|
|
|
323978
|
+
/***/ }),
|
|
323979
|
+
|
|
323980
|
+
/***/ 70279:
|
|
323981
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
323982
|
+
|
|
323983
|
+
"use strict";
|
|
323984
|
+
|
|
323985
|
+
/**
|
|
323986
|
+
* MCP Job Manager — async job pattern for long-running MCP tool calls.
|
|
323987
|
+
*
|
|
323988
|
+
* Claude Code and other MCP clients have timeout issues with long-running tools.
|
|
323989
|
+
* This module provides a `start_job` / `get_job` pattern: the tool call returns
|
|
323990
|
+
* immediately with a job_id, and the client polls `get_job` until done.
|
|
323991
|
+
*
|
|
323992
|
+
* This is a thin wrapper over the existing TaskStore — jobs are persisted as
|
|
323993
|
+
* regular Visor tasks (visible via `visor tasks list`, `visor tasks show`).
|
|
323994
|
+
*/
|
|
323995
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
323996
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
323997
|
+
};
|
|
323998
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
323999
|
+
exports.JobManager = void 0;
|
|
324000
|
+
const crypto_1 = __importDefault(__nccwpck_require__(76982));
|
|
324001
|
+
const logger_1 = __nccwpck_require__(86999);
|
|
324002
|
+
/** Map TaskState → JobStatus for the MCP response. */
|
|
324003
|
+
function taskStateToJobStatus(state) {
|
|
324004
|
+
switch (state) {
|
|
324005
|
+
case 'submitted':
|
|
324006
|
+
return 'queued';
|
|
324007
|
+
case 'working':
|
|
324008
|
+
case 'input_required':
|
|
324009
|
+
case 'auth_required':
|
|
324010
|
+
return 'running';
|
|
324011
|
+
case 'completed':
|
|
324012
|
+
return 'completed';
|
|
324013
|
+
case 'failed':
|
|
324014
|
+
case 'canceled':
|
|
324015
|
+
case 'rejected':
|
|
324016
|
+
return 'failed';
|
|
324017
|
+
default:
|
|
324018
|
+
return 'running';
|
|
324019
|
+
}
|
|
324020
|
+
}
|
|
324021
|
+
/**
|
|
324022
|
+
* Build the standardized MCP job response from an AgentTask.
|
|
324023
|
+
*/
|
|
324024
|
+
function buildResponse(task) {
|
|
324025
|
+
const status = taskStateToJobStatus(task.status.state);
|
|
324026
|
+
const done = status === 'completed' || status === 'failed';
|
|
324027
|
+
const polling = done
|
|
324028
|
+
? { recommended_next_action: 'none', recommended_delay_seconds: 0 }
|
|
324029
|
+
: { recommended_next_action: 'get_job', recommended_delay_seconds: 0 };
|
|
324030
|
+
// Extract result text from task status message or artifacts
|
|
324031
|
+
let result = null;
|
|
324032
|
+
if (status === 'completed') {
|
|
324033
|
+
// The completed status message contains the AI response text
|
|
324034
|
+
const statusText = task.status.message?.parts?.[0]?.text;
|
|
324035
|
+
if (statusText) {
|
|
324036
|
+
result = statusText;
|
|
324037
|
+
}
|
|
324038
|
+
// Also check artifacts for richer output
|
|
324039
|
+
if (task.artifacts.length > 0) {
|
|
324040
|
+
const artifactTexts = task.artifacts
|
|
324041
|
+
.flatMap(a => a.parts)
|
|
324042
|
+
.filter(p => p.text)
|
|
324043
|
+
.map(p => p.text);
|
|
324044
|
+
if (artifactTexts.length > 0 && !result) {
|
|
324045
|
+
result = artifactTexts.join('\n');
|
|
324046
|
+
}
|
|
324047
|
+
}
|
|
324048
|
+
}
|
|
324049
|
+
// Extract error from failed status message
|
|
324050
|
+
let error = null;
|
|
324051
|
+
if (status === 'failed' && task.status.message) {
|
|
324052
|
+
const errorText = task.status.message.parts?.[0]?.text || 'Unknown error';
|
|
324053
|
+
error = {
|
|
324054
|
+
code: 'EXECUTION_ERROR',
|
|
324055
|
+
message: errorText,
|
|
324056
|
+
retryable: true,
|
|
324057
|
+
};
|
|
324058
|
+
}
|
|
324059
|
+
// Build progress
|
|
324060
|
+
let progress;
|
|
324061
|
+
switch (status) {
|
|
324062
|
+
case 'queued':
|
|
324063
|
+
progress = { percent: 0, step: 'queued', message: 'Job accepted and queued' };
|
|
324064
|
+
break;
|
|
324065
|
+
case 'running':
|
|
324066
|
+
progress = { percent: null, step: 'running', message: 'Job is executing' };
|
|
324067
|
+
break;
|
|
324068
|
+
case 'completed':
|
|
324069
|
+
progress = { percent: 100, step: 'completed', message: 'Job finished successfully' };
|
|
324070
|
+
break;
|
|
324071
|
+
case 'failed':
|
|
324072
|
+
progress = { percent: null, step: 'failed', message: 'The job failed before completion' };
|
|
324073
|
+
break;
|
|
324074
|
+
default:
|
|
324075
|
+
progress = { percent: null, step: status, message: `Job is ${status}` };
|
|
324076
|
+
}
|
|
324077
|
+
// Instructions for the model
|
|
324078
|
+
let userMessage;
|
|
324079
|
+
let nextInstruction;
|
|
324080
|
+
switch (status) {
|
|
324081
|
+
case 'queued':
|
|
324082
|
+
userMessage = 'The job has been queued.';
|
|
324083
|
+
nextInstruction =
|
|
324084
|
+
'Call get_job with this job_id. It will wait up to 59 seconds for the result. If it returns with done still false, call get_job again.';
|
|
324085
|
+
break;
|
|
324086
|
+
case 'running':
|
|
324087
|
+
userMessage = 'The job is still running.';
|
|
324088
|
+
nextInstruction =
|
|
324089
|
+
'Call get_job again with this job_id. It will wait up to 59 seconds for the result. If it returns with done still false, call get_job again.';
|
|
324090
|
+
break;
|
|
324091
|
+
case 'completed':
|
|
324092
|
+
userMessage = 'The result is ready.';
|
|
324093
|
+
nextInstruction = 'Use the result to answer the user.';
|
|
324094
|
+
break;
|
|
324095
|
+
case 'failed':
|
|
324096
|
+
userMessage = 'The job failed.';
|
|
324097
|
+
nextInstruction =
|
|
324098
|
+
'Explain the failure briefly. If the user still wants the result, start a new job.';
|
|
324099
|
+
break;
|
|
324100
|
+
default:
|
|
324101
|
+
userMessage = `Job status: ${status}`;
|
|
324102
|
+
nextInstruction = 'Call get_job again after 10 seconds.';
|
|
324103
|
+
}
|
|
324104
|
+
return {
|
|
324105
|
+
job_id: task.id.slice(0, 8),
|
|
324106
|
+
status,
|
|
324107
|
+
done,
|
|
324108
|
+
progress,
|
|
324109
|
+
polling,
|
|
324110
|
+
result,
|
|
324111
|
+
error,
|
|
324112
|
+
user_message: userMessage,
|
|
324113
|
+
next_instruction_for_model: nextInstruction,
|
|
324114
|
+
};
|
|
324115
|
+
}
|
|
324116
|
+
/** Build an "expired/not found" response. */
|
|
324117
|
+
function buildExpiredResponse(jobId) {
|
|
324118
|
+
return {
|
|
324119
|
+
job_id: jobId,
|
|
324120
|
+
status: 'expired',
|
|
324121
|
+
done: true,
|
|
324122
|
+
progress: { percent: null, step: 'expired', message: 'This job is no longer available' },
|
|
324123
|
+
polling: { recommended_next_action: 'none', recommended_delay_seconds: 0 },
|
|
324124
|
+
result: null,
|
|
324125
|
+
error: { code: 'JOB_EXPIRED', message: 'The job is no longer available', retryable: true },
|
|
324126
|
+
user_message: 'The previous job expired.',
|
|
324127
|
+
next_instruction_for_model: 'If the user still wants the result, start a new job.',
|
|
324128
|
+
};
|
|
324129
|
+
}
|
|
324130
|
+
/**
|
|
324131
|
+
* Manages async jobs for MCP tool calls, backed by the existing TaskStore.
|
|
324132
|
+
*
|
|
324133
|
+
* Jobs created here are visible via `visor tasks list` and `visor tasks show`.
|
|
324134
|
+
*/
|
|
324135
|
+
class JobManager {
|
|
324136
|
+
taskStore;
|
|
324137
|
+
longPollTimeoutMs;
|
|
324138
|
+
constructor(taskStore, opts) {
|
|
324139
|
+
this.taskStore = taskStore;
|
|
324140
|
+
this.longPollTimeoutMs = opts?.longPollTimeoutMs ?? 59_000;
|
|
324141
|
+
}
|
|
324142
|
+
/**
|
|
324143
|
+
* Start a new async job. Creates a task, runs the handler in the background,
|
|
324144
|
+
* and returns immediately with the task ID.
|
|
324145
|
+
*/
|
|
324146
|
+
startJob(handler, opts) {
|
|
324147
|
+
// Create task via trackExecution pattern (inline, since we need non-blocking)
|
|
324148
|
+
const { getInstanceId } = __nccwpck_require__(89942);
|
|
324149
|
+
const requestMessage = {
|
|
324150
|
+
message_id: crypto_1.default.randomUUID(),
|
|
324151
|
+
role: 'user',
|
|
324152
|
+
parts: [{ text: opts.messageText }],
|
|
324153
|
+
};
|
|
324154
|
+
const task = this.taskStore.createTask({
|
|
324155
|
+
contextId: crypto_1.default.randomUUID(),
|
|
324156
|
+
requestMessage,
|
|
324157
|
+
workflowId: opts.workflowId,
|
|
324158
|
+
requestMetadata: {
|
|
324159
|
+
source: 'mcp',
|
|
324160
|
+
instance_id: getInstanceId(),
|
|
324161
|
+
async_job: true,
|
|
324162
|
+
...opts.metadata,
|
|
324163
|
+
},
|
|
324164
|
+
});
|
|
324165
|
+
// Transition to working
|
|
324166
|
+
this.taskStore.updateTaskState(task.id, 'working');
|
|
324167
|
+
this.taskStore.claimTask(task.id, getInstanceId());
|
|
324168
|
+
logger_1.logger.info(`[MCP-AsyncJob] Job ${task.id.slice(0, 8)} started (workflow=${opts.workflowId || '-'})`);
|
|
324169
|
+
// Heartbeat timer
|
|
324170
|
+
const heartbeatTimer = setInterval(() => {
|
|
324171
|
+
try {
|
|
324172
|
+
this.taskStore.heartbeat(task.id);
|
|
324173
|
+
}
|
|
324174
|
+
catch {
|
|
324175
|
+
// best-effort
|
|
324176
|
+
}
|
|
324177
|
+
}, 60_000);
|
|
324178
|
+
if (heartbeatTimer.unref)
|
|
324179
|
+
heartbeatTimer.unref();
|
|
324180
|
+
// Run handler in background
|
|
324181
|
+
handler()
|
|
324182
|
+
.then(result => {
|
|
324183
|
+
clearInterval(heartbeatTimer);
|
|
324184
|
+
// Extract response text from the result (same logic as track-execution.ts)
|
|
324185
|
+
let responseText = 'Execution completed';
|
|
324186
|
+
try {
|
|
324187
|
+
// If result is an MCP content response, extract the text
|
|
324188
|
+
const content = result?.content;
|
|
324189
|
+
if (Array.isArray(content)) {
|
|
324190
|
+
const texts = content.filter((c) => c.type === 'text').map((c) => c.text);
|
|
324191
|
+
if (texts.length > 0)
|
|
324192
|
+
responseText = texts.join('\n');
|
|
324193
|
+
}
|
|
324194
|
+
else if (typeof result === 'string') {
|
|
324195
|
+
responseText = result;
|
|
324196
|
+
}
|
|
324197
|
+
else {
|
|
324198
|
+
// Try engine result format
|
|
324199
|
+
const history = result?.reviewSummary?.history;
|
|
324200
|
+
if (history) {
|
|
324201
|
+
const entries = Object.values(history);
|
|
324202
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
324203
|
+
const outputs = entries[i];
|
|
324204
|
+
if (!Array.isArray(outputs))
|
|
324205
|
+
continue;
|
|
324206
|
+
for (let j = outputs.length - 1; j >= 0; j--) {
|
|
324207
|
+
const text = outputs[j]?.text;
|
|
324208
|
+
if (typeof text === 'string' && text.trim().length > 0) {
|
|
324209
|
+
responseText = text.trim();
|
|
324210
|
+
break;
|
|
324211
|
+
}
|
|
324212
|
+
}
|
|
324213
|
+
if (responseText !== 'Execution completed')
|
|
324214
|
+
break;
|
|
324215
|
+
}
|
|
324216
|
+
}
|
|
324217
|
+
}
|
|
324218
|
+
}
|
|
324219
|
+
catch {
|
|
324220
|
+
// ignore extraction errors
|
|
324221
|
+
}
|
|
324222
|
+
const completedMsg = {
|
|
324223
|
+
message_id: crypto_1.default.randomUUID(),
|
|
324224
|
+
role: 'agent',
|
|
324225
|
+
parts: [{ text: responseText }],
|
|
324226
|
+
};
|
|
324227
|
+
try {
|
|
324228
|
+
this.taskStore.updateTaskState(task.id, 'completed', completedMsg);
|
|
324229
|
+
logger_1.logger.info(`[MCP-AsyncJob] Job ${task.id.slice(0, 8)} completed`);
|
|
324230
|
+
}
|
|
324231
|
+
catch (stateErr) {
|
|
324232
|
+
logger_1.logger.warn(`[MCP-AsyncJob] Job ${task.id.slice(0, 8)} completed but state transition failed: ${stateErr}`);
|
|
324233
|
+
}
|
|
324234
|
+
})
|
|
324235
|
+
.catch(err => {
|
|
324236
|
+
clearInterval(heartbeatTimer);
|
|
324237
|
+
const errorText = err instanceof Error ? err.message : String(err);
|
|
324238
|
+
const failMsg = {
|
|
324239
|
+
message_id: crypto_1.default.randomUUID(),
|
|
324240
|
+
role: 'agent',
|
|
324241
|
+
parts: [{ text: errorText }],
|
|
324242
|
+
};
|
|
324243
|
+
try {
|
|
324244
|
+
this.taskStore.updateTaskState(task.id, 'failed', failMsg);
|
|
324245
|
+
logger_1.logger.info(`[MCP-AsyncJob] Job ${task.id.slice(0, 8)} failed: ${errorText}`);
|
|
324246
|
+
}
|
|
324247
|
+
catch (stateErr) {
|
|
324248
|
+
logger_1.logger.warn(`[MCP-AsyncJob] Job ${task.id.slice(0, 8)} failed but could not update task state: ${stateErr}`);
|
|
324249
|
+
}
|
|
324250
|
+
});
|
|
324251
|
+
return buildResponse(task);
|
|
324252
|
+
}
|
|
324253
|
+
/**
|
|
324254
|
+
* Get the current state of a job by ID (supports both short and full IDs).
|
|
324255
|
+
*
|
|
324256
|
+
* Uses long polling: if the job is still running, waits up to 59 seconds
|
|
324257
|
+
* for it to finish before responding. Returns immediately if the job is
|
|
324258
|
+
* already in a terminal state (completed/failed).
|
|
324259
|
+
*/
|
|
324260
|
+
async getJob(jobId) {
|
|
324261
|
+
const resolvedTask = this.resolveTask(jobId);
|
|
324262
|
+
if (!resolvedTask) {
|
|
324263
|
+
return buildExpiredResponse(jobId);
|
|
324264
|
+
}
|
|
324265
|
+
// If already done, return immediately
|
|
324266
|
+
const initialStatus = taskStateToJobStatus(resolvedTask.status.state);
|
|
324267
|
+
if (initialStatus === 'completed' || initialStatus === 'failed') {
|
|
324268
|
+
return buildResponse(resolvedTask);
|
|
324269
|
+
}
|
|
324270
|
+
// Long poll: check every 500ms for up to the configured timeout
|
|
324271
|
+
const POLL_INTERVAL_MS = 500;
|
|
324272
|
+
const MAX_WAIT_MS = this.longPollTimeoutMs;
|
|
324273
|
+
const deadline = Date.now() + MAX_WAIT_MS;
|
|
324274
|
+
while (Date.now() < deadline) {
|
|
324275
|
+
await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
324276
|
+
const task = this.resolveTask(jobId);
|
|
324277
|
+
if (!task) {
|
|
324278
|
+
return buildExpiredResponse(jobId);
|
|
324279
|
+
}
|
|
324280
|
+
const status = taskStateToJobStatus(task.status.state);
|
|
324281
|
+
if (status === 'completed' || status === 'failed') {
|
|
324282
|
+
return buildResponse(task);
|
|
324283
|
+
}
|
|
324284
|
+
}
|
|
324285
|
+
// Timeout — return current state (still running)
|
|
324286
|
+
const finalTask = this.resolveTask(jobId);
|
|
324287
|
+
if (!finalTask) {
|
|
324288
|
+
return buildExpiredResponse(jobId);
|
|
324289
|
+
}
|
|
324290
|
+
return buildResponse(finalTask);
|
|
324291
|
+
}
|
|
324292
|
+
/**
|
|
324293
|
+
* Resolve a task by full UUID or short ID prefix.
|
|
324294
|
+
*/
|
|
324295
|
+
resolveTask(jobId) {
|
|
324296
|
+
// Try direct lookup first (full UUID)
|
|
324297
|
+
let task = this.taskStore.getTask(jobId);
|
|
324298
|
+
// If not found and looks like a short ID, search by prefix
|
|
324299
|
+
if (!task && jobId.length < 36) {
|
|
324300
|
+
const { tasks } = this.taskStore.listTasks({ limit: 200 });
|
|
324301
|
+
task = tasks.find(t => t.id.startsWith(jobId)) || null;
|
|
324302
|
+
}
|
|
324303
|
+
return task;
|
|
324304
|
+
}
|
|
324305
|
+
}
|
|
324306
|
+
exports.JobManager = JobManager;
|
|
324307
|
+
|
|
324308
|
+
|
|
322784
324309
|
/***/ }),
|
|
322785
324310
|
|
|
322786
324311
|
/***/ 93143:
|
|
@@ -323156,75 +324681,143 @@ async function executeWorkflow(args) {
|
|
|
323156
324681
|
}
|
|
323157
324682
|
}
|
|
323158
324683
|
/**
|
|
323159
|
-
* Zod schema for fixed workflow tool parameters (no workflow parameter).
|
|
324684
|
+
* Zod schema for fixed workflow tool parameters (no workflow parameter).
|
|
324685
|
+
*/
|
|
324686
|
+
exports.FixedWorkflowSchema = zod_1.z.object({
|
|
324687
|
+
message: zod_1.z
|
|
324688
|
+
.string()
|
|
324689
|
+
.optional()
|
|
324690
|
+
.describe('Optional human input message for workflows that include human-input checks. ' +
|
|
324691
|
+
'This is equivalent to the --message CLI argument. Use this to provide context, ' +
|
|
324692
|
+
'instructions, or answers to prompts that the workflow may request.'),
|
|
324693
|
+
checks: zod_1.z
|
|
324694
|
+
.array(zod_1.z.string())
|
|
324695
|
+
.optional()
|
|
324696
|
+
.describe('Optional list of specific check IDs to run from the workflow. ' +
|
|
324697
|
+
'If not provided, all checks defined in the workflow will be executed. ' +
|
|
324698
|
+
'Check IDs are the keys defined under the "checks:" section in the workflow YAML.'),
|
|
324699
|
+
format: zod_1.z
|
|
324700
|
+
.enum(['json', 'markdown', 'table'])
|
|
324701
|
+
.optional()
|
|
324702
|
+
.default('json')
|
|
324703
|
+
.describe('Output format for the results. "json" (default) returns structured data suitable for ' +
|
|
324704
|
+
'programmatic processing. "markdown" returns human-readable formatted output with ' +
|
|
324705
|
+
'severity icons. "table" returns a simple text table format.'),
|
|
324706
|
+
});
|
|
324707
|
+
/**
|
|
324708
|
+
* Execute a fixed workflow and return formatted results.
|
|
324709
|
+
*
|
|
324710
|
+
* @param args - The tool arguments (without workflow)
|
|
324711
|
+
* @param workflowPath - The pre-resolved workflow path
|
|
324712
|
+
* @returns MCP tool result with content
|
|
324713
|
+
*/
|
|
324714
|
+
async function executeFixedWorkflow(args, workflowPath) {
|
|
324715
|
+
try {
|
|
324716
|
+
// Build execution context with message for human-input checks
|
|
324717
|
+
const executionContext = {};
|
|
324718
|
+
if (args.message) {
|
|
324719
|
+
executionContext.cliMessage = args.message;
|
|
324720
|
+
}
|
|
324721
|
+
// Call runChecks() from SDK
|
|
324722
|
+
const result = await (0, sdk_1.runChecks)({
|
|
324723
|
+
configPath: workflowPath,
|
|
324724
|
+
checks: args.checks,
|
|
324725
|
+
output: { format: args.format || 'json' },
|
|
324726
|
+
executionContext,
|
|
324727
|
+
cwd: process.cwd(),
|
|
324728
|
+
});
|
|
324729
|
+
// Format output based on requested format
|
|
324730
|
+
const groupedResults = result;
|
|
324731
|
+
const formattedOutput = formatResults(groupedResults, args.format || 'json');
|
|
324732
|
+
return {
|
|
324733
|
+
content: [
|
|
324734
|
+
{
|
|
324735
|
+
type: 'text',
|
|
324736
|
+
text: formattedOutput,
|
|
324737
|
+
},
|
|
324738
|
+
],
|
|
324739
|
+
};
|
|
324740
|
+
}
|
|
324741
|
+
catch (error) {
|
|
324742
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
324743
|
+
return {
|
|
324744
|
+
content: [
|
|
324745
|
+
{
|
|
324746
|
+
type: 'text',
|
|
324747
|
+
text: `Error executing workflow: ${errorMessage}`,
|
|
324748
|
+
},
|
|
324749
|
+
],
|
|
324750
|
+
isError: true,
|
|
324751
|
+
};
|
|
324752
|
+
}
|
|
324753
|
+
}
|
|
324754
|
+
/**
|
|
324755
|
+
* Get or create a TaskStore for async job mode.
|
|
324756
|
+
* If one is provided in options, use it. Otherwise create a SQLite-backed store.
|
|
323160
324757
|
*/
|
|
323161
|
-
|
|
323162
|
-
|
|
323163
|
-
.
|
|
323164
|
-
|
|
323165
|
-
|
|
323166
|
-
|
|
323167
|
-
|
|
323168
|
-
|
|
323169
|
-
.array(zod_1.z.string())
|
|
323170
|
-
.optional()
|
|
323171
|
-
.describe('Optional list of specific check IDs to run from the workflow. ' +
|
|
323172
|
-
'If not provided, all checks defined in the workflow will be executed. ' +
|
|
323173
|
-
'Check IDs are the keys defined under the "checks:" section in the workflow YAML.'),
|
|
323174
|
-
format: zod_1.z
|
|
323175
|
-
.enum(['json', 'markdown', 'table'])
|
|
323176
|
-
.optional()
|
|
323177
|
-
.default('json')
|
|
323178
|
-
.describe('Output format for the results. "json" (default) returns structured data suitable for ' +
|
|
323179
|
-
'programmatic processing. "markdown" returns human-readable formatted output with ' +
|
|
323180
|
-
'severity icons. "table" returns a simple text table format.'),
|
|
323181
|
-
});
|
|
324758
|
+
async function getOrCreateTaskStore(options) {
|
|
324759
|
+
if (options.taskStore)
|
|
324760
|
+
return options.taskStore;
|
|
324761
|
+
const { SqliteTaskStore } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(24711)));
|
|
324762
|
+
const store = new SqliteTaskStore();
|
|
324763
|
+
await store.initialize();
|
|
324764
|
+
return store;
|
|
324765
|
+
}
|
|
323182
324766
|
/**
|
|
323183
|
-
*
|
|
324767
|
+
* Register async job tools (start_job / get_job) on an MCP server instance.
|
|
324768
|
+
* Used by both standalone and createHttpMcpServer when asyncMode is enabled.
|
|
323184
324769
|
*
|
|
323185
|
-
*
|
|
323186
|
-
*
|
|
323187
|
-
* @returns MCP tool result with content
|
|
324770
|
+
* Requires a TaskStore for persistence — jobs are stored as regular Visor tasks,
|
|
324771
|
+
* visible via `visor tasks list` and `visor tasks show`.
|
|
323188
324772
|
*/
|
|
323189
|
-
async function
|
|
323190
|
-
|
|
323191
|
-
|
|
323192
|
-
|
|
323193
|
-
|
|
323194
|
-
|
|
323195
|
-
|
|
323196
|
-
|
|
323197
|
-
|
|
323198
|
-
|
|
323199
|
-
|
|
323200
|
-
|
|
323201
|
-
|
|
323202
|
-
|
|
324773
|
+
async function registerAsyncJobTools(server, resolvedWorkflowPath, toolName, taskStore, longPollTimeoutMs) {
|
|
324774
|
+
const { JobManager } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(70279)));
|
|
324775
|
+
const jobManager = new JobManager(taskStore, { longPollTimeoutMs });
|
|
324776
|
+
const startJobName = toolName === 'run_workflow' || toolName === 'send_message' ? 'start_job' : `start_${toolName}`;
|
|
324777
|
+
const getJobName = 'get_job';
|
|
324778
|
+
const workflowId = resolvedWorkflowPath
|
|
324779
|
+
? path.basename(resolvedWorkflowPath, path.extname(resolvedWorkflowPath))
|
|
324780
|
+
: undefined;
|
|
324781
|
+
// Build start_job schema based on whether we have a fixed workflow
|
|
324782
|
+
if (resolvedWorkflowPath) {
|
|
324783
|
+
server.tool(startJobName, 'Start a long-running job. Returns immediately with a job_id. ' +
|
|
324784
|
+
'You MUST then call get_job with this job_id. get_job uses long polling (waits up to 59s). ' +
|
|
324785
|
+
'If done is still false, call get_job again.', {
|
|
324786
|
+
message: exports.FixedWorkflowSchema.shape.message,
|
|
324787
|
+
checks: exports.FixedWorkflowSchema.shape.checks,
|
|
324788
|
+
format: exports.FixedWorkflowSchema.shape.format,
|
|
324789
|
+
}, async (args) => {
|
|
324790
|
+
const response = jobManager.startJob(async () => executeFixedWorkflow(args, resolvedWorkflowPath), {
|
|
324791
|
+
messageText: args.message || `Run workflow: ${workflowId}`,
|
|
324792
|
+
workflowId,
|
|
324793
|
+
});
|
|
324794
|
+
return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] };
|
|
323203
324795
|
});
|
|
323204
|
-
// Format output based on requested format
|
|
323205
|
-
const groupedResults = result;
|
|
323206
|
-
const formattedOutput = formatResults(groupedResults, args.format || 'json');
|
|
323207
|
-
return {
|
|
323208
|
-
content: [
|
|
323209
|
-
{
|
|
323210
|
-
type: 'text',
|
|
323211
|
-
text: formattedOutput,
|
|
323212
|
-
},
|
|
323213
|
-
],
|
|
323214
|
-
};
|
|
323215
324796
|
}
|
|
323216
|
-
|
|
323217
|
-
|
|
323218
|
-
|
|
323219
|
-
|
|
323220
|
-
|
|
323221
|
-
|
|
323222
|
-
|
|
323223
|
-
|
|
323224
|
-
|
|
323225
|
-
|
|
323226
|
-
|
|
324797
|
+
else {
|
|
324798
|
+
server.tool(startJobName, 'Start a long-running job. Returns immediately with a job_id. ' +
|
|
324799
|
+
'You MUST then call get_job with this job_id. get_job uses long polling (waits up to 59s). ' +
|
|
324800
|
+
'If done is still false, call get_job again.', {
|
|
324801
|
+
workflow: exports.RunWorkflowSchema.shape.workflow,
|
|
324802
|
+
message: exports.RunWorkflowSchema.shape.message,
|
|
324803
|
+
checks: exports.RunWorkflowSchema.shape.checks,
|
|
324804
|
+
format: exports.RunWorkflowSchema.shape.format,
|
|
324805
|
+
}, async (args) => {
|
|
324806
|
+
const response = jobManager.startJob(async () => executeWorkflow(args), {
|
|
324807
|
+
messageText: args.message || `Run workflow: ${args.workflow}`,
|
|
324808
|
+
workflowId: args.workflow,
|
|
324809
|
+
});
|
|
324810
|
+
return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] };
|
|
324811
|
+
});
|
|
323227
324812
|
}
|
|
324813
|
+
// Register get_job tool
|
|
324814
|
+
server.tool(getJobName, 'Check the status of a running job using long polling. Waits up to 59 seconds for the job to finish. ' +
|
|
324815
|
+
'Returns immediately if the job is already done. If done is still false after the wait, call again.', {
|
|
324816
|
+
job_id: zod_1.z.string().describe('The job ID returned by start_job.'),
|
|
324817
|
+
}, async (args) => {
|
|
324818
|
+
const response = await jobManager.getJob(args.job_id);
|
|
324819
|
+
return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] };
|
|
324820
|
+
});
|
|
323228
324821
|
}
|
|
323229
324822
|
/**
|
|
323230
324823
|
* Validate a Bearer token from an HTTP request using timing-safe comparison.
|
|
@@ -323281,7 +324874,12 @@ async function createHttpMcpServer(options) {
|
|
|
323281
324874
|
const server = new mcp_js_1.McpServer({ name: exports.SERVER_INFO.name, version: exports.SERVER_INFO.version }, { capabilities: { tools: {} } });
|
|
323282
324875
|
const toolName = options.toolName || 'run_workflow';
|
|
323283
324876
|
const toolDescription = options.toolDescription || exports.RUN_WORKFLOW_DESCRIPTION;
|
|
323284
|
-
if (
|
|
324877
|
+
if (options.asyncMode) {
|
|
324878
|
+
const taskStore = await getOrCreateTaskStore(options);
|
|
324879
|
+
const longPollMs = options.longPollTimeout ? options.longPollTimeout * 1000 : undefined;
|
|
324880
|
+
await registerAsyncJobTools(server, resolvedWorkflowPath, toolName, taskStore, longPollMs);
|
|
324881
|
+
}
|
|
324882
|
+
else if (resolvedWorkflowPath) {
|
|
323285
324883
|
server.tool(toolName, toolDescription, {
|
|
323286
324884
|
message: exports.FixedWorkflowSchema.shape.message,
|
|
323287
324885
|
checks: exports.FixedWorkflowSchema.shape.checks,
|
|
@@ -323472,9 +325070,15 @@ async function startMcpServer(options = {}) {
|
|
|
323472
325070
|
// Determine tool name and description
|
|
323473
325071
|
const toolName = options.toolName || 'run_workflow';
|
|
323474
325072
|
const toolDescription = options.toolDescription || exports.RUN_WORKFLOW_DESCRIPTION;
|
|
323475
|
-
//
|
|
323476
|
-
if (
|
|
323477
|
-
|
|
325073
|
+
// Register tools based on mode
|
|
325074
|
+
if (options.asyncMode) {
|
|
325075
|
+
const taskStore = await getOrCreateTaskStore(options);
|
|
325076
|
+
const longPollMs = options.longPollTimeout ? options.longPollTimeout * 1000 : undefined;
|
|
325077
|
+
await registerAsyncJobTools(server, resolvedWorkflowPath, toolName, taskStore, longPollMs);
|
|
325078
|
+
console.error(`Visor MCP server started in async mode${resolvedWorkflowPath ? ` with fixed workflow: ${resolvedWorkflowPath}` : ''}`);
|
|
325079
|
+
}
|
|
325080
|
+
else if (resolvedWorkflowPath) {
|
|
325081
|
+
// Fixed workflow mode - tool without workflow parameter
|
|
323478
325082
|
server.tool(toolName, toolDescription, {
|
|
323479
325083
|
message: exports.FixedWorkflowSchema.shape.message,
|
|
323480
325084
|
checks: exports.FixedWorkflowSchema.shape.checks,
|
|
@@ -338660,9 +340264,9 @@ class WorkflowCheckProvider extends check_provider_interface_1.CheckProvider {
|
|
|
338660
340264
|
}
|
|
338661
340265
|
// Log final outputs
|
|
338662
340266
|
const outputKeys = Object.keys(outputs);
|
|
338663
|
-
const
|
|
338664
|
-
if (
|
|
338665
|
-
logger_1.logger.warn(`[WorkflowProvider] Workflow '${workflow.id}' has
|
|
340267
|
+
const undefinedOutputs = outputKeys.filter(k => outputs[k] === undefined);
|
|
340268
|
+
if (undefinedOutputs.length > 0) {
|
|
340269
|
+
logger_1.logger.warn(`[WorkflowProvider] Workflow '${workflow.id}' has undefined outputs: [${undefinedOutputs.join(', ')}]. ` +
|
|
338666
340270
|
`This may indicate value_js expressions are not finding expected data.`);
|
|
338667
340271
|
}
|
|
338668
340272
|
// Propagate _rawOutput from any step — this carries DSL output() content
|
|
@@ -339781,16 +341385,58 @@ class McpServerRunner {
|
|
|
339781
341385
|
'Send a message to the Visor assistant. The assistant will process your message ' +
|
|
339782
341386
|
'through the configured workflow and return a response. Use this for conversations, ' +
|
|
339783
341387
|
'questions, task requests, and any interaction with the assistant.';
|
|
339784
|
-
|
|
339785
|
-
|
|
339786
|
-
|
|
339787
|
-
|
|
339788
|
-
.
|
|
339789
|
-
.
|
|
339790
|
-
|
|
339791
|
-
|
|
339792
|
-
|
|
339793
|
-
|
|
341388
|
+
if (this.options.asyncMode) {
|
|
341389
|
+
// Async job mode: register start_job and get_job instead of blocking tool
|
|
341390
|
+
// Requires a TaskStore — jobs are stored as regular Visor tasks
|
|
341391
|
+
if (!this.taskStore) {
|
|
341392
|
+
const { SqliteTaskStore } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(24711)));
|
|
341393
|
+
this.taskStore = new SqliteTaskStore();
|
|
341394
|
+
await this.taskStore.initialize();
|
|
341395
|
+
}
|
|
341396
|
+
const { JobManager } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(70279)));
|
|
341397
|
+
const longPollMs = this.options.longPollTimeout
|
|
341398
|
+
? this.options.longPollTimeout * 1000
|
|
341399
|
+
: undefined;
|
|
341400
|
+
const jobManager = new JobManager(this.taskStore, { longPollTimeoutMs: longPollMs });
|
|
341401
|
+
const startJobName = toolName === 'send_message' ? 'start_job' : `start_${toolName}`;
|
|
341402
|
+
const allChecks = Object.keys(this.cfg.checks || {});
|
|
341403
|
+
mcpServer.tool(startJobName, 'Start a long-running job. Returns immediately with a job_id. ' +
|
|
341404
|
+
'You MUST then call get_job with this job_id. get_job uses long polling (waits up to 59s). ' +
|
|
341405
|
+
'If done is still false, call get_job again.', {
|
|
341406
|
+
message: zod_1.z.string().describe('The message to send to the assistant.'),
|
|
341407
|
+
session_id: zod_1.z
|
|
341408
|
+
.string()
|
|
341409
|
+
.optional()
|
|
341410
|
+
.describe('Optional conversation session ID for maintaining context across messages. ' +
|
|
341411
|
+
'If omitted, a new session is created.'),
|
|
341412
|
+
}, async (args) => {
|
|
341413
|
+
const response = jobManager.startJob(async () => this.handleMessage(args.message, args.session_id), {
|
|
341414
|
+
messageText: args.message,
|
|
341415
|
+
workflowId: allChecks.join(','),
|
|
341416
|
+
});
|
|
341417
|
+
return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] };
|
|
341418
|
+
});
|
|
341419
|
+
mcpServer.tool('get_job', 'Check the status of a running job using long polling. Waits up to 59 seconds for the job to finish. ' +
|
|
341420
|
+
'Returns immediately if the job is already done. If done is still false after the wait, call again.', {
|
|
341421
|
+
job_id: zod_1.z.string().describe('The job ID returned by start_job.'),
|
|
341422
|
+
}, async (args) => {
|
|
341423
|
+
const response = await jobManager.getJob(args.job_id);
|
|
341424
|
+
return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] };
|
|
341425
|
+
});
|
|
341426
|
+
console.error(`Visor MCP frontend started in async job mode`);
|
|
341427
|
+
}
|
|
341428
|
+
else {
|
|
341429
|
+
mcpServer.tool(toolName, toolDescription, {
|
|
341430
|
+
message: zod_1.z.string().describe('The message to send to the assistant.'),
|
|
341431
|
+
session_id: zod_1.z
|
|
341432
|
+
.string()
|
|
341433
|
+
.optional()
|
|
341434
|
+
.describe('Optional conversation session ID for maintaining context across messages. ' +
|
|
341435
|
+
'If omitted, a new session is created. Re-use the same session_id for follow-up messages.'),
|
|
341436
|
+
}, async (args) => {
|
|
341437
|
+
return this.handleMessage(args.message, args.session_id);
|
|
341438
|
+
});
|
|
341439
|
+
}
|
|
339794
341440
|
const { transports } = this;
|
|
339795
341441
|
const handleRequest = async (req, res) => {
|
|
339796
341442
|
try {
|
|
@@ -340814,6 +342460,11 @@ async function createRunner(name, engine, config, options) {
|
|
|
340814
342460
|
tlsKey: mcpAny.tls_key || process.env.VISOR_MCP_TLS_KEY,
|
|
340815
342461
|
toolName: mcpAny.tool_name || process.env.VISOR_MCP_TOOL_NAME,
|
|
340816
342462
|
toolDescription: mcpAny.tool_description || process.env.VISOR_MCP_TOOL_DESCRIPTION,
|
|
342463
|
+
asyncMode: options.mcpAsync || mcpAny.async_mode || process.env.VISOR_MCP_ASYNC === 'true',
|
|
342464
|
+
longPollTimeout: mcpAny.long_poll_timeout ||
|
|
342465
|
+
(process.env.VISOR_MCP_POLL_TIMEOUT
|
|
342466
|
+
? parseInt(process.env.VISOR_MCP_POLL_TIMEOUT)
|
|
342467
|
+
: undefined),
|
|
340817
342468
|
});
|
|
340818
342469
|
}
|
|
340819
342470
|
default:
|
|
@@ -347987,6 +349638,26 @@ class SlackClient {
|
|
|
347987
349638
|
};
|
|
347988
349639
|
}
|
|
347989
349640
|
},
|
|
349641
|
+
delete: async ({ channel, ts }) => {
|
|
349642
|
+
try {
|
|
349643
|
+
const resp = await this.api('chat.delete', { channel, ts });
|
|
349644
|
+
if (!resp || resp.ok !== true) {
|
|
349645
|
+
const err = (resp && resp.error) || 'unknown_error';
|
|
349646
|
+
console.warn(`Slack chat.delete failed (non-fatal): error=${err} channel=${channel} ts=${ts}`);
|
|
349647
|
+
return { ok: false, ts, error: err, data: resp };
|
|
349648
|
+
}
|
|
349649
|
+
return { ok: true, ts: resp.ts || ts, error: undefined, data: resp };
|
|
349650
|
+
}
|
|
349651
|
+
catch (e) {
|
|
349652
|
+
console.warn(`Slack chat.delete threw (non-fatal): channel=${channel} ts=${ts} error=${e instanceof Error ? e.message : String(e)}`);
|
|
349653
|
+
return {
|
|
349654
|
+
ok: false,
|
|
349655
|
+
ts,
|
|
349656
|
+
error: e instanceof Error ? e.message : String(e),
|
|
349657
|
+
data: undefined,
|
|
349658
|
+
};
|
|
349659
|
+
}
|
|
349660
|
+
},
|
|
347990
349661
|
};
|
|
347991
349662
|
async getBotUserId() {
|
|
347992
349663
|
const resp = await this.api('auth.test', {});
|
|
@@ -350110,6 +351781,13 @@ class SlackSocketRunner {
|
|
|
350110
351781
|
});
|
|
350111
351782
|
if (this.taskStore) {
|
|
350112
351783
|
const { trackExecution } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(7628)));
|
|
351784
|
+
const { isFrontendLiveUpdatesEnabled } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(5893)));
|
|
351785
|
+
const { SlackTaskLiveUpdateSink } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(90535)));
|
|
351786
|
+
const slackTelemetryCfg = cfgForRun?.slack?.telemetry ?? cfgForRun?.telemetry;
|
|
351787
|
+
const includeTraceId = slackTelemetryCfg === true ||
|
|
351788
|
+
(slackTelemetryCfg &&
|
|
351789
|
+
typeof slackTelemetryCfg === 'object' &&
|
|
351790
|
+
slackTelemetryCfg.enabled === true);
|
|
350113
351791
|
await trackExecution({
|
|
350114
351792
|
taskStore: this.taskStore,
|
|
350115
351793
|
source: 'slack',
|
|
@@ -350122,6 +351800,14 @@ class SlackSocketRunner {
|
|
|
350122
351800
|
slack_user: userId,
|
|
350123
351801
|
slack_trigger_text: String(ev.text || '').slice(0, 500),
|
|
350124
351802
|
},
|
|
351803
|
+
liveUpdates: {
|
|
351804
|
+
config: cfgForRun.task_live_updates,
|
|
351805
|
+
includeTraceId,
|
|
351806
|
+
sink: this.client &&
|
|
351807
|
+
isFrontendLiveUpdatesEnabled(cfgForRun.task_live_updates, 'slack')
|
|
351808
|
+
? new SlackTaskLiveUpdateSink(this.client, channelId, threadTs)
|
|
351809
|
+
: undefined,
|
|
351810
|
+
},
|
|
350125
351811
|
}, execFn);
|
|
350126
351812
|
}
|
|
350127
351813
|
else {
|
|
@@ -350322,6 +352008,13 @@ class SlackSocketRunner {
|
|
|
350322
352008
|
});
|
|
350323
352009
|
if (this.taskStore) {
|
|
350324
352010
|
const { trackExecution } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(7628)));
|
|
352011
|
+
const { isFrontendLiveUpdatesEnabled } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(5893)));
|
|
352012
|
+
const { SlackTaskLiveUpdateSink } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(90535)));
|
|
352013
|
+
const slackTelemetryCfg = cfgForRun?.slack?.telemetry ?? cfgForRun?.telemetry;
|
|
352014
|
+
const includeTraceId = slackTelemetryCfg === true ||
|
|
352015
|
+
(slackTelemetryCfg &&
|
|
352016
|
+
typeof slackTelemetryCfg === 'object' &&
|
|
352017
|
+
slackTelemetryCfg.enabled === true);
|
|
350325
352018
|
await trackExecution({
|
|
350326
352019
|
taskStore: this.taskStore,
|
|
350327
352020
|
source: 'slack',
|
|
@@ -350335,6 +352028,14 @@ class SlackSocketRunner {
|
|
|
350335
352028
|
slack_trigger_text: String(ev.text || '').slice(0, 500),
|
|
350336
352029
|
trigger_id: id,
|
|
350337
352030
|
},
|
|
352031
|
+
liveUpdates: {
|
|
352032
|
+
config: cfgForRun.task_live_updates,
|
|
352033
|
+
includeTraceId,
|
|
352034
|
+
sink: this.client &&
|
|
352035
|
+
isFrontendLiveUpdatesEnabled(cfgForRun.task_live_updates, 'slack')
|
|
352036
|
+
? new SlackTaskLiveUpdateSink(this.client, channel, threadTs || ts)
|
|
352037
|
+
: undefined,
|
|
352038
|
+
},
|
|
350338
352039
|
}, triggerExecFn);
|
|
350339
352040
|
}
|
|
350340
352041
|
else {
|
|
@@ -361373,6 +363074,44 @@ class TeamsClient {
|
|
|
361373
363074
|
}
|
|
361374
363075
|
return { ok: true, activityId: lastActivityId };
|
|
361375
363076
|
}
|
|
363077
|
+
/**
|
|
363078
|
+
* Update an existing bot message.
|
|
363079
|
+
* For safety, only supports single-activity payloads. Oversized content returns msg_too_long.
|
|
363080
|
+
*/
|
|
363081
|
+
async updateMessage(opts) {
|
|
363082
|
+
const chunks = (0, markdown_1.chunkText)(opts.text, 28000);
|
|
363083
|
+
if (chunks.length > 1) {
|
|
363084
|
+
return { ok: false, error: 'msg_too_long' };
|
|
363085
|
+
}
|
|
363086
|
+
try {
|
|
363087
|
+
await this.adapter.continueConversationAsync(this.appId, opts.conversationReference, async (turnContext) => {
|
|
363088
|
+
const activity = botbuilder_1.MessageFactory.text(chunks[0] || '');
|
|
363089
|
+
activity.id = opts.activityId;
|
|
363090
|
+
await turnContext.updateActivity(activity);
|
|
363091
|
+
});
|
|
363092
|
+
return { ok: true, activityId: opts.activityId };
|
|
363093
|
+
}
|
|
363094
|
+
catch (err) {
|
|
363095
|
+
return {
|
|
363096
|
+
ok: false,
|
|
363097
|
+
error: err instanceof Error ? err.message : String(err),
|
|
363098
|
+
};
|
|
363099
|
+
}
|
|
363100
|
+
}
|
|
363101
|
+
/**
|
|
363102
|
+
* Delete a previously sent bot message.
|
|
363103
|
+
*/
|
|
363104
|
+
async deleteMessage(opts) {
|
|
363105
|
+
try {
|
|
363106
|
+
await this.adapter.continueConversationAsync(this.appId, opts.conversationReference, async (turnContext) => {
|
|
363107
|
+
await turnContext.deleteActivity(opts.activityId);
|
|
363108
|
+
});
|
|
363109
|
+
return true;
|
|
363110
|
+
}
|
|
363111
|
+
catch {
|
|
363112
|
+
return false;
|
|
363113
|
+
}
|
|
363114
|
+
}
|
|
361376
363115
|
}
|
|
361377
363116
|
exports.TeamsClient = TeamsClient;
|
|
361378
363117
|
|
|
@@ -361726,6 +363465,8 @@ class TeamsWebhookRunner {
|
|
|
361726
363465
|
});
|
|
361727
363466
|
if (this.taskStore) {
|
|
361728
363467
|
const { trackExecution } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(7628)));
|
|
363468
|
+
const { isFrontendLiveUpdatesEnabled } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(5893)));
|
|
363469
|
+
const { TeamsTaskLiveUpdateSink } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(82309)));
|
|
361729
363470
|
await trackExecution({
|
|
361730
363471
|
taskStore: this.taskStore,
|
|
361731
363472
|
source: 'teams',
|
|
@@ -361737,6 +363478,12 @@ class TeamsWebhookRunner {
|
|
|
361737
363478
|
teams_conversation_type: msg.conversationType,
|
|
361738
363479
|
teams_from: msg.from.id,
|
|
361739
363480
|
},
|
|
363481
|
+
liveUpdates: {
|
|
363482
|
+
config: cfgForRun.task_live_updates,
|
|
363483
|
+
sink: isFrontendLiveUpdatesEnabled(cfgForRun.task_live_updates, 'teams')
|
|
363484
|
+
? new TeamsTaskLiveUpdateSink(this.client, msg.conversationReference, msg.activityId)
|
|
363485
|
+
: undefined,
|
|
363486
|
+
},
|
|
361740
363487
|
}, execFn);
|
|
361741
363488
|
}
|
|
361742
363489
|
else {
|
|
@@ -361994,6 +363741,40 @@ class TelegramClient {
|
|
|
361994
363741
|
return { ok: false, error: errMsg };
|
|
361995
363742
|
}
|
|
361996
363743
|
}
|
|
363744
|
+
/**
|
|
363745
|
+
* Edit an existing text message.
|
|
363746
|
+
* Returns ok=false if Telegram rejects the edit (e.g. message too old or unchanged).
|
|
363747
|
+
*/
|
|
363748
|
+
async editMessageText(opts) {
|
|
363749
|
+
try {
|
|
363750
|
+
const params = {
|
|
363751
|
+
link_preview_options: { is_disabled: true },
|
|
363752
|
+
};
|
|
363753
|
+
if (opts.parse_mode)
|
|
363754
|
+
params.parse_mode = opts.parse_mode;
|
|
363755
|
+
const msg = await this.bot.api.editMessageText(opts.chat_id, opts.message_id, opts.text, params);
|
|
363756
|
+
const messageId = msg?.message_id || opts.message_id;
|
|
363757
|
+
return { ok: true, message_id: messageId };
|
|
363758
|
+
}
|
|
363759
|
+
catch (err) {
|
|
363760
|
+
const errMsg = err?.description || err?.message || String(err);
|
|
363761
|
+
console.warn(`Telegram editMessageText failed (non-fatal): ${errMsg}`);
|
|
363762
|
+
return { ok: false, error: errMsg };
|
|
363763
|
+
}
|
|
363764
|
+
}
|
|
363765
|
+
/**
|
|
363766
|
+
* Delete a message.
|
|
363767
|
+
*/
|
|
363768
|
+
async deleteMessage(opts) {
|
|
363769
|
+
try {
|
|
363770
|
+
await this.bot.api.deleteMessage(opts.chat_id, opts.message_id);
|
|
363771
|
+
return true;
|
|
363772
|
+
}
|
|
363773
|
+
catch (err) {
|
|
363774
|
+
console.warn(`Telegram deleteMessage failed (non-fatal): ${err?.description || err?.message || String(err)}`);
|
|
363775
|
+
return false;
|
|
363776
|
+
}
|
|
363777
|
+
}
|
|
361997
363778
|
/**
|
|
361998
363779
|
* Send a document/file.
|
|
361999
363780
|
*/
|
|
@@ -362493,6 +364274,8 @@ class TelegramPollingRunner {
|
|
|
362493
364274
|
});
|
|
362494
364275
|
if (this.taskStore) {
|
|
362495
364276
|
const { trackExecution } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(7628)));
|
|
364277
|
+
const { isFrontendLiveUpdatesEnabled } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(5893)));
|
|
364278
|
+
const { TelegramTaskLiveUpdateSink } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(71872)));
|
|
362496
364279
|
await trackExecution({
|
|
362497
364280
|
taskStore: this.taskStore,
|
|
362498
364281
|
source: 'telegram',
|
|
@@ -362504,6 +364287,12 @@ class TelegramPollingRunner {
|
|
|
362504
364287
|
telegram_chat_type: msg.chat.type,
|
|
362505
364288
|
telegram_user: msg.from ? String(msg.from.id) : 'unknown',
|
|
362506
364289
|
},
|
|
364290
|
+
liveUpdates: {
|
|
364291
|
+
config: cfgForRun.task_live_updates,
|
|
364292
|
+
sink: isFrontendLiveUpdatesEnabled(cfgForRun.task_live_updates, 'telegram')
|
|
364293
|
+
? new TelegramTaskLiveUpdateSink(this.client, msg.chat.id, msg.message_id, msg.message_thread_id)
|
|
364294
|
+
: undefined,
|
|
364295
|
+
},
|
|
362507
364296
|
}, execFn);
|
|
362508
364297
|
}
|
|
362509
364298
|
else {
|
|
@@ -381344,6 +383133,14 @@ module.exports = require("net");
|
|
|
381344
383133
|
|
|
381345
383134
|
/***/ }),
|
|
381346
383135
|
|
|
383136
|
+
/***/ 16698:
|
|
383137
|
+
/***/ ((module) => {
|
|
383138
|
+
|
|
383139
|
+
"use strict";
|
|
383140
|
+
module.exports = require("node:async_hooks");
|
|
383141
|
+
|
|
383142
|
+
/***/ }),
|
|
383143
|
+
|
|
381347
383144
|
/***/ 4573:
|
|
381348
383145
|
/***/ ((module) => {
|
|
381349
383146
|
|
|
@@ -455959,6 +457756,70 @@ var init_extract = __esm({
|
|
|
455959
457756
|
}
|
|
455960
457757
|
});
|
|
455961
457758
|
|
|
457759
|
+
// src/symbols.js
|
|
457760
|
+
async function symbols(options) {
|
|
457761
|
+
if (!options) {
|
|
457762
|
+
throw new Error("Options object is required");
|
|
457763
|
+
}
|
|
457764
|
+
if (!options.files || !Array.isArray(options.files) || options.files.length === 0) {
|
|
457765
|
+
throw new Error("At least one file path is required");
|
|
457766
|
+
}
|
|
457767
|
+
const binaryPath = await getBinaryPath(options.binaryOptions || {});
|
|
457768
|
+
const cwd = await validateCwdPath(options.cwd);
|
|
457769
|
+
const args = ["symbols", "--format", "json"];
|
|
457770
|
+
if (options.allowTests) {
|
|
457771
|
+
args.push("--allow-tests");
|
|
457772
|
+
}
|
|
457773
|
+
for (const file2 of options.files) {
|
|
457774
|
+
args.push(escapeString(file2));
|
|
457775
|
+
}
|
|
457776
|
+
if (process.env.DEBUG === "1") {
|
|
457777
|
+
console.error(`
|
|
457778
|
+
Symbols: files="${options.files.join(", ")}" cwd="${cwd}"`);
|
|
457779
|
+
}
|
|
457780
|
+
return new Promise((resolve9, reject2) => {
|
|
457781
|
+
const childProcess = (0, import_child_process5.spawn)(binaryPath, args, {
|
|
457782
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
457783
|
+
cwd
|
|
457784
|
+
});
|
|
457785
|
+
let stdout = "";
|
|
457786
|
+
let stderr = "";
|
|
457787
|
+
childProcess.stdout.on("data", (data2) => {
|
|
457788
|
+
stdout += data2.toString();
|
|
457789
|
+
});
|
|
457790
|
+
childProcess.stderr.on("data", (data2) => {
|
|
457791
|
+
stderr += data2.toString();
|
|
457792
|
+
});
|
|
457793
|
+
childProcess.on("close", (code) => {
|
|
457794
|
+
if (stderr && process.env.DEBUG === "1") {
|
|
457795
|
+
console.error(`stderr: ${stderr}`);
|
|
457796
|
+
}
|
|
457797
|
+
if (code !== 0) {
|
|
457798
|
+
reject2(new Error(`Symbols command failed with exit code ${code}: ${stderr}`));
|
|
457799
|
+
return;
|
|
457800
|
+
}
|
|
457801
|
+
try {
|
|
457802
|
+
const result = JSON.parse(stdout);
|
|
457803
|
+
resolve9(result);
|
|
457804
|
+
} catch (error40) {
|
|
457805
|
+
reject2(new Error(`Failed to parse symbols output: ${error40.message}. Output: ${stdout.substring(0, 200)}`));
|
|
457806
|
+
}
|
|
457807
|
+
});
|
|
457808
|
+
childProcess.on("error", (error40) => {
|
|
457809
|
+
reject2(new Error(`Failed to spawn symbols process: ${error40.message}`));
|
|
457810
|
+
});
|
|
457811
|
+
});
|
|
457812
|
+
}
|
|
457813
|
+
var import_child_process5;
|
|
457814
|
+
var init_symbols = __esm({
|
|
457815
|
+
"src/symbols.js"() {
|
|
457816
|
+
"use strict";
|
|
457817
|
+
import_child_process5 = __nccwpck_require__(35317);
|
|
457818
|
+
init_utils();
|
|
457819
|
+
init_path_validation();
|
|
457820
|
+
}
|
|
457821
|
+
});
|
|
457822
|
+
|
|
455962
457823
|
// src/grep.js
|
|
455963
457824
|
async function grep(options) {
|
|
455964
457825
|
if (!options || !options.pattern) {
|
|
@@ -456002,14 +457863,14 @@ async function grep(options) {
|
|
|
456002
457863
|
throw new Error(`Grep failed: ${errorMessage}`);
|
|
456003
457864
|
}
|
|
456004
457865
|
}
|
|
456005
|
-
var
|
|
457866
|
+
var import_child_process6, import_util5, execFileAsync2, GREP_FLAG_MAP;
|
|
456006
457867
|
var init_grep = __esm({
|
|
456007
457868
|
"src/grep.js"() {
|
|
456008
457869
|
"use strict";
|
|
456009
|
-
|
|
457870
|
+
import_child_process6 = __nccwpck_require__(35317);
|
|
456010
457871
|
import_util5 = __nccwpck_require__(39023);
|
|
456011
457872
|
init_utils();
|
|
456012
|
-
execFileAsync2 = (0, import_util5.promisify)(
|
|
457873
|
+
execFileAsync2 = (0, import_util5.promisify)(import_child_process6.execFile);
|
|
456013
457874
|
GREP_FLAG_MAP = {
|
|
456014
457875
|
ignoreCase: "-i",
|
|
456015
457876
|
lineNumbers: "-n",
|
|
@@ -481417,6 +483278,9 @@ function createTools(configOptions) {
|
|
|
481417
483278
|
if (isToolAllowed("extract")) {
|
|
481418
483279
|
tools2.extractTool = extractTool(configOptions);
|
|
481419
483280
|
}
|
|
483281
|
+
if (isToolAllowed("symbols")) {
|
|
483282
|
+
tools2.symbolsTool = symbolsTool(configOptions);
|
|
483283
|
+
}
|
|
481420
483284
|
if (configOptions.enableDelegate && isToolAllowed("delegate")) {
|
|
481421
483285
|
tools2.delegateTool = delegateTool(configOptions);
|
|
481422
483286
|
}
|
|
@@ -481585,7 +483449,7 @@ function resolveTargetPath(target, cwd) {
|
|
|
481585
483449
|
}
|
|
481586
483450
|
return filePart + suffix;
|
|
481587
483451
|
}
|
|
481588
|
-
var import_path6, searchDelegateSchema, searchSchema, searchAllSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, listFilesSchema, searchFilesSchema, readImageSchema, readMediaSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, searchDescription, searchDelegateDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription;
|
|
483452
|
+
var import_path6, searchDelegateSchema, searchSchema, searchAllSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, listFilesSchema, searchFilesSchema, readImageSchema, readMediaSchema, symbolsSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, searchDescription, searchDelegateDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription;
|
|
481589
483453
|
var init_common = __esm({
|
|
481590
483454
|
"src/tools/common.js"() {
|
|
481591
483455
|
"use strict";
|
|
@@ -481644,6 +483508,9 @@ var init_common = __esm({
|
|
|
481644
483508
|
readMediaSchema = external_exports2.object({
|
|
481645
483509
|
path: external_exports2.string().describe("Path to the media file to read. Supports images (png, jpg, jpeg, webp, bmp, svg) and documents (pdf).")
|
|
481646
483510
|
});
|
|
483511
|
+
symbolsSchema = external_exports2.object({
|
|
483512
|
+
file: external_exports2.string().describe("Path to the file to list symbols from. Returns a hierarchical tree of functions, classes, structs, constants, etc. with line numbers and nesting (e.g., methods inside classes/impl blocks).")
|
|
483513
|
+
});
|
|
481647
483514
|
bashSchema = external_exports2.object({
|
|
481648
483515
|
command: external_exports2.string().describe("The bash command to execute"),
|
|
481649
483516
|
workingDirectory: external_exports2.string().optional().describe("Directory to execute the command in (optional)"),
|
|
@@ -489053,14 +490920,21 @@ function createWrappedTools(baseTools) {
|
|
|
489053
490920
|
baseTools.multiEditTool.execute
|
|
489054
490921
|
);
|
|
489055
490922
|
}
|
|
490923
|
+
if (baseTools.symbolsTool) {
|
|
490924
|
+
wrappedTools.symbolsToolInstance = wrapToolWithEmitter(
|
|
490925
|
+
baseTools.symbolsTool,
|
|
490926
|
+
"symbols",
|
|
490927
|
+
baseTools.symbolsTool.execute
|
|
490928
|
+
);
|
|
490929
|
+
}
|
|
489056
490930
|
return wrappedTools;
|
|
489057
490931
|
}
|
|
489058
|
-
var
|
|
490932
|
+
var import_child_process7, import_util13, import_crypto3, import_events, import_fs6, import_fs7, import_path8, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
|
|
489059
490933
|
var init_probeTool = __esm({
|
|
489060
490934
|
"src/agent/probeTool.js"() {
|
|
489061
490935
|
"use strict";
|
|
489062
490936
|
init_index();
|
|
489063
|
-
|
|
490937
|
+
import_child_process7 = __nccwpck_require__(35317);
|
|
489064
490938
|
import_util13 = __nccwpck_require__(39023);
|
|
489065
490939
|
import_crypto3 = __nccwpck_require__(76982);
|
|
489066
490940
|
import_events = __nccwpck_require__(24434);
|
|
@@ -527710,6 +529584,7 @@ CRITICAL - ALWAYS search before answering:
|
|
|
527710
529584
|
You must NEVER answer questions about the codebase from memory or general knowledge. ALWAYS use the search and extract tools first to find the actual code, then base your answer ONLY on what you found. Even if you think you know the answer, you MUST verify it against the actual code. Your answers must be grounded in code evidence, not assumptions.
|
|
527711
529585
|
|
|
527712
529586
|
When exploring code:
|
|
529587
|
+
- Use the symbols tool to get a quick overview of a file's structure (functions, classes, constants) before diving into details with extract
|
|
527713
529588
|
- Provide clear, concise explanations based on user request
|
|
527714
529589
|
- Find and highlight the most relevant code snippets, if required
|
|
527715
529590
|
- Trace function calls and data flow through the system \u2014 follow the FULL call chain, not just the entry point
|
|
@@ -527740,6 +529615,7 @@ You think like a code explorer \u2014 you understand that codebases have layers:
|
|
|
527740
529615
|
|
|
527741
529616
|
When searching:
|
|
527742
529617
|
- Search for the MAIN concept first, then think: "what RELATED subsystems would a real codebase have?"
|
|
529618
|
+
- Use symbols to get a file's table of contents (functions, classes, constants with line numbers) before extracting \u2014 it helps you pick the right symbols to extract
|
|
527743
529619
|
- Use extract to READ the code you find \u2014 look for function calls, type references, and imports that point to OTHER relevant code
|
|
527744
529620
|
- If you find middleware, check: are there org-level or tenant-level variants?
|
|
527745
529621
|
- If you find algorithms, check: are there different storage backends?
|
|
@@ -527783,6 +529659,7 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
527783
529659
|
- Do not add code comments unless the logic is genuinely complex and non-obvious.
|
|
527784
529660
|
|
|
527785
529661
|
# Before Implementation
|
|
529662
|
+
- Use symbols to get a quick overview of file structure (functions, classes, constants with line numbers) before reading or editing files.
|
|
527786
529663
|
- Read tests first \u2014 find existing test files for the module you're changing. They reveal expected behavior, edge cases, and the project's testing patterns.
|
|
527787
529664
|
- Read neighboring files \u2014 understand naming conventions, error handling patterns, import style, and existing utilities before creating new ones.
|
|
527788
529665
|
- Trace the call chain \u2014 follow how the code you're changing is called and what depends on it. Check interfaces, types, and consumers.
|
|
@@ -527819,7 +529696,7 @@ Use the right tool:
|
|
|
527819
529696
|
1. To MODIFY existing code \u2192 \`edit\` tool (old_string \u2192 new_string, or start_line/end_line)
|
|
527820
529697
|
2. To CREATE a new file \u2192 \`create\` tool
|
|
527821
529698
|
3. To CHANGE multiple files at once \u2192 \`multi_edit\` tool
|
|
527822
|
-
4. To READ code \u2192 \`extract\` or \`search\` tools
|
|
529699
|
+
4. To READ code \u2192 \`extract\` or \`search\` tools. Use \`symbols\` to get a file's table of contents (functions, classes, constants with line numbers) before extracting.
|
|
527823
529700
|
5. If \`edit\` fails with "file has not been read yet" \u2192 use \`extract\` with the EXACT same file path you will pass to \`edit\`. Relative vs absolute path mismatch causes this error. Use the same path format consistently. If it still fails, use bash \`cat\` to read the file, then use \`create\` to write the entire modified file. Do NOT fall back to sed.
|
|
527824
529701
|
|
|
527825
529702
|
Bash is fine for: formatters (gofmt, prettier, black), build/test/lint commands, git operations, and read-only file inspection (cat, head, tail). sed/awk should ONLY be used for trivial non-code tasks (e.g., config file tweaks) where the replacement is a simple literal string swap.
|
|
@@ -527831,6 +529708,8 @@ Bash is fine for: formatters (gofmt, prettier, black), build/test/lint commands,
|
|
|
527831
529708
|
- Never expose secrets, API keys, or credentials in generated code. Never log sensitive information.
|
|
527832
529709
|
- Do not surprise the user with unrequested changes. Do what was asked, including reasonable follow-up actions, but do not refactor surrounding code or add features that were not requested.
|
|
527833
529710
|
- When editing files, keep edits focused and minimal. For changes spanning more than a few lines, prefer line-targeted editing (start_line/end_line) over text replacement (old_string) \u2014 it constrains scope and prevents accidental removal of adjacent content. Never include unrelated sections in an edit operation.
|
|
529711
|
+
- In line-targeted mode, omitting position means replace/update the addressed lines. To insert code near an existing line, you MUST use position="before" or position="after". Never express insertion as end_line < start_line.
|
|
529712
|
+
- To remove lines with line-targeted mode, target the exact start_line/end_line range and set new_string to the empty string "".
|
|
527834
529713
|
- After every significant change, verify the project still builds and passes linting. Do not wait until the end to discover breakage.
|
|
527835
529714
|
|
|
527836
529715
|
# Writing Tests
|
|
@@ -530273,6 +532152,7 @@ var require_stringify = __commonJS({
|
|
|
530273
532152
|
nullStr: "null",
|
|
530274
532153
|
simpleKeys: false,
|
|
530275
532154
|
singleQuote: null,
|
|
532155
|
+
trailingComma: false,
|
|
530276
532156
|
trueStr: "true",
|
|
530277
532157
|
verifyAliasOrder: true
|
|
530278
532158
|
}, doc.schema.toStringOptions, options);
|
|
@@ -530790,12 +532670,19 @@ ${indent}${line}` : "\n";
|
|
|
530790
532670
|
if (comment)
|
|
530791
532671
|
reqNewline = true;
|
|
530792
532672
|
let str = stringify.stringify(item, itemCtx, () => comment = null);
|
|
530793
|
-
|
|
532673
|
+
reqNewline || (reqNewline = lines.length > linesAtValue || str.includes("\n"));
|
|
532674
|
+
if (i < items.length - 1) {
|
|
530794
532675
|
str += ",";
|
|
532676
|
+
} else if (ctx.options.trailingComma) {
|
|
532677
|
+
if (ctx.options.lineWidth > 0) {
|
|
532678
|
+
reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth);
|
|
532679
|
+
}
|
|
532680
|
+
if (reqNewline) {
|
|
532681
|
+
str += ",";
|
|
532682
|
+
}
|
|
532683
|
+
}
|
|
530795
532684
|
if (comment)
|
|
530796
532685
|
str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
|
|
530797
|
-
if (!reqNewline && (lines.length > linesAtValue || str.includes("\n")))
|
|
530798
|
-
reqNewline = true;
|
|
530799
532686
|
lines.push(str);
|
|
530800
532687
|
linesAtValue = lines.length;
|
|
530801
532688
|
}
|
|
@@ -533809,17 +535696,22 @@ var require_compose_node = __commonJS({
|
|
|
533809
535696
|
case "block-map":
|
|
533810
535697
|
case "block-seq":
|
|
533811
535698
|
case "flow-collection":
|
|
533812
|
-
|
|
533813
|
-
|
|
533814
|
-
|
|
535699
|
+
try {
|
|
535700
|
+
node = composeCollection.composeCollection(CN, ctx, token, props, onError);
|
|
535701
|
+
if (anchor)
|
|
535702
|
+
node.anchor = anchor.source.substring(1);
|
|
535703
|
+
} catch (error40) {
|
|
535704
|
+
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
535705
|
+
onError(token, "RESOURCE_EXHAUSTION", message);
|
|
535706
|
+
}
|
|
533815
535707
|
break;
|
|
533816
535708
|
default: {
|
|
533817
535709
|
const message = token.type === "error" ? token.message : `Unsupported token (type: ${token.type})`;
|
|
533818
535710
|
onError(token, "UNEXPECTED_TOKEN", message);
|
|
533819
|
-
node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError);
|
|
533820
535711
|
isSrcToken = false;
|
|
533821
535712
|
}
|
|
533822
535713
|
}
|
|
535714
|
+
node ?? (node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError));
|
|
533823
535715
|
if (anchor && node.anchor === "")
|
|
533824
535716
|
onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
|
|
533825
535717
|
if (atKey && ctx.options.stringKeys && (!identity2.isScalar(node) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) {
|
|
@@ -548808,7 +550700,7 @@ async function executeBashCommand(command, options = {}) {
|
|
|
548808
550700
|
[cmd, ...cmdArgs] = args;
|
|
548809
550701
|
useShell = false;
|
|
548810
550702
|
}
|
|
548811
|
-
const child = (0,
|
|
550703
|
+
const child = (0, import_child_process8.spawn)(cmd, cmdArgs, {
|
|
548812
550704
|
cwd,
|
|
548813
550705
|
env: processEnv,
|
|
548814
550706
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -549004,11 +550896,11 @@ function validateExecutionOptions(options = {}) {
|
|
|
549004
550896
|
warnings
|
|
549005
550897
|
};
|
|
549006
550898
|
}
|
|
549007
|
-
var
|
|
550899
|
+
var import_child_process8, import_path13, import_fs10;
|
|
549008
550900
|
var init_bashExecutor = __esm({
|
|
549009
550901
|
"src/agent/bashExecutor.js"() {
|
|
549010
550902
|
"use strict";
|
|
549011
|
-
|
|
550903
|
+
import_child_process8 = __nccwpck_require__(35317);
|
|
549012
550904
|
import_path13 = __nccwpck_require__(16928);
|
|
549013
550905
|
import_fs10 = __nccwpck_require__(79896);
|
|
549014
550906
|
init_bashCommandUtils();
|
|
@@ -550534,7 +552426,7 @@ ${opts.schema}`;
|
|
|
550534
552426
|
}
|
|
550535
552427
|
}
|
|
550536
552428
|
const toolCollector = [];
|
|
550537
|
-
const proc2 = (0,
|
|
552429
|
+
const proc2 = (0, import_child_process9.spawn)("sh", ["-c", shellCmd], {
|
|
550538
552430
|
env: { ...process.env, FORCE_COLOR: "0" },
|
|
550539
552431
|
stdio: ["ignore", "pipe", "pipe"]
|
|
550540
552432
|
// Ignore stdin since echo handles it
|
|
@@ -550889,11 +552781,11 @@ function combinePrompts(systemPrompt, customPrompt, agent) {
|
|
|
550889
552781
|
}
|
|
550890
552782
|
return systemPrompt || "";
|
|
550891
552783
|
}
|
|
550892
|
-
var
|
|
552784
|
+
var import_child_process9, import_crypto6, import_promises5, import_path15, import_os5, import_events3;
|
|
550893
552785
|
var init_enhanced_claude_code = __esm({
|
|
550894
552786
|
"src/agent/engines/enhanced-claude-code.js"() {
|
|
550895
552787
|
"use strict";
|
|
550896
|
-
|
|
552788
|
+
import_child_process9 = __nccwpck_require__(35317);
|
|
550897
552789
|
import_crypto6 = __nccwpck_require__(76982);
|
|
550898
552790
|
import_promises5 = __toESM(__nccwpck_require__(91943), 1);
|
|
550899
552791
|
import_path15 = __toESM(__nccwpck_require__(16928), 1);
|
|
@@ -550935,7 +552827,7 @@ async function createCodexEngine(options = {}) {
|
|
|
550935
552827
|
if (debug) {
|
|
550936
552828
|
console.log("[DEBUG] Starting Codex MCP server...");
|
|
550937
552829
|
}
|
|
550938
|
-
const codexProcess = (0,
|
|
552830
|
+
const codexProcess = (0, import_child_process10.spawn)("codex", ["mcp-server"], {
|
|
550939
552831
|
stdio: ["pipe", "pipe", "pipe"]
|
|
550940
552832
|
});
|
|
550941
552833
|
let requestId = 0;
|
|
@@ -551167,11 +553059,11 @@ function combinePrompts2(systemPrompt, customPrompt, agent) {
|
|
|
551167
553059
|
}
|
|
551168
553060
|
return systemPrompt || "";
|
|
551169
553061
|
}
|
|
551170
|
-
var
|
|
553062
|
+
var import_child_process10, import_crypto7, import_readline;
|
|
551171
553063
|
var init_codex = __esm({
|
|
551172
553064
|
"src/agent/engines/codex.js"() {
|
|
551173
553065
|
"use strict";
|
|
551174
|
-
|
|
553066
|
+
import_child_process10 = __nccwpck_require__(35317);
|
|
551175
553067
|
import_crypto7 = __nccwpck_require__(76982);
|
|
551176
553068
|
import_readline = __nccwpck_require__(23785);
|
|
551177
553069
|
init_built_in_server();
|
|
@@ -551937,6 +553829,9 @@ var init_ProbeAgent = __esm({
|
|
|
551937
553829
|
if (isToolAllowed("searchFiles")) {
|
|
551938
553830
|
this.toolImplementations.searchFiles = searchFilesToolInstance;
|
|
551939
553831
|
}
|
|
553832
|
+
if (wrappedTools.symbolsToolInstance && isToolAllowed("symbols")) {
|
|
553833
|
+
this.toolImplementations.symbols = wrappedTools.symbolsToolInstance;
|
|
553834
|
+
}
|
|
551940
553835
|
if (this.enableSkills) {
|
|
551941
553836
|
const registry2 = this._getSkillsRegistry();
|
|
551942
553837
|
const { listSkillsToolInstance, useSkillToolInstance } = createSkillToolInstances({
|
|
@@ -552968,6 +554863,10 @@ var init_ProbeAgent = __esm({
|
|
|
552968
554863
|
schema: searchFilesSchema,
|
|
552969
554864
|
description: "Find files matching a glob pattern with recursive search capability."
|
|
552970
554865
|
},
|
|
554866
|
+
symbols: {
|
|
554867
|
+
schema: symbolsSchema,
|
|
554868
|
+
description: "List all symbols (functions, classes, structs, constants, etc.) in a file. Returns a hierarchical tree with line numbers \u2014 like a table of contents for code."
|
|
554869
|
+
},
|
|
552971
554870
|
readMedia: {
|
|
552972
554871
|
schema: readMediaSchema,
|
|
552973
554872
|
description: "Read and load a media file (image or PDF document) for AI analysis. Supports: png, jpg, jpeg, webp, bmp, svg, pdf."
|
|
@@ -553623,7 +555522,8 @@ ${this.architectureContext.content}
|
|
|
553623
555522
|
${searchToolDesc1}
|
|
553624
555523
|
- extract: Extract specific code sections with context
|
|
553625
555524
|
- listFiles: Browse directory contents
|
|
553626
|
-
- searchFiles: Find files by name patterns
|
|
555525
|
+
- searchFiles: Find files by name patterns
|
|
555526
|
+
- symbols: List all symbols in a file (functions, classes, constants, etc.) with line numbers`;
|
|
553627
555527
|
if (this.enableBash) {
|
|
553628
555528
|
systemPrompt += `
|
|
553629
555529
|
- bash: Execute bash commands for system operations (building, running tests, git, etc.). NEVER use bash for code exploration (no grep, cat, find, head, tail) \u2014 always use search and extract tools instead, they are faster and more accurate.`;
|
|
@@ -553678,7 +555578,8 @@ Workspace: ${this.allowedFolders.join(", ")}`;
|
|
|
553678
555578
|
${searchToolDesc2}
|
|
553679
555579
|
- extract: Extract specific code sections with context
|
|
553680
555580
|
- listFiles: Browse directory contents
|
|
553681
|
-
- searchFiles: Find files by name patterns
|
|
555581
|
+
- searchFiles: Find files by name patterns
|
|
555582
|
+
- symbols: List all symbols in a file (functions, classes, constants, etc.) with line numbers`;
|
|
553682
555583
|
if (this.enableBash) {
|
|
553683
555584
|
systemPrompt += `
|
|
553684
555585
|
- bash: Execute bash commands for system operations (building, running tests, git, etc.). NEVER use bash for code exploration (no grep, cat, find, head, tail) \u2014 always use search and extract tools instead, they are faster and more accurate.`;
|
|
@@ -553752,6 +555653,8 @@ Follow these instructions carefully:
|
|
|
553752
555653
|
7. When modifying files, choose the appropriate tool:
|
|
553753
555654
|
- Use 'edit' for all code modifications:
|
|
553754
555655
|
* PREFERRED: Use start_line (and optionally end_line) for line-targeted editing \u2014 this is the safest and most precise approach.${this.hashLines ? ' Use the line:hash references from extract/search output (e.g. "42:ab") for integrity verification.' : ""} Always use extract first to see line numbers${this.hashLines ? " and hashes" : ""}, then edit by line reference.
|
|
555656
|
+
* In line-targeted mode, omitting position means replace/update the addressed lines. To insert new code near a line, you MUST set position="before" or position="after". Never express insertion as end_line < start_line.
|
|
555657
|
+
* To delete lines in line-targeted mode, target the exact start_line/end_line range and set new_string to the empty string "".
|
|
553755
555658
|
* For editing inside large functions: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers${this.hashLines ? " and hashes" : ""}, then use start_line/end_line to surgically edit specific lines within it.
|
|
553756
555659
|
* For rewriting entire functions/classes/methods, use the symbol parameter instead (no exact text matching needed).
|
|
553757
555660
|
* FALLBACK ONLY: Use old_string + new_string for simple single-line changes where the text is unique. Copy old_string verbatim from the file. Keep old_string as small as possible.
|
|
@@ -557123,7 +559026,7 @@ The "searches" field helps the caller understand what was attempted.
|
|
|
557123
559026
|
- Deduplicate files across groups.
|
|
557124
559027
|
</output-rules>`;
|
|
557125
559028
|
}
|
|
557126
|
-
var import_ai5, import_fs12, CODE_SEARCH_SCHEMA, searchTool, queryTool, extractTool, delegateTool, analyzeAllTool;
|
|
559029
|
+
var import_ai5, import_fs12, CODE_SEARCH_SCHEMA, searchTool, queryTool, extractTool, delegateTool, analyzeAllTool, symbolsTool;
|
|
557127
559030
|
var init_vercel = __esm({
|
|
557128
559031
|
"src/tools/vercel.js"() {
|
|
557129
559032
|
"use strict";
|
|
@@ -557131,6 +559034,7 @@ var init_vercel = __esm({
|
|
|
557131
559034
|
init_search();
|
|
557132
559035
|
init_query();
|
|
557133
559036
|
init_extract();
|
|
559037
|
+
init_symbols();
|
|
557134
559038
|
init_delegate();
|
|
557135
559039
|
init_analyzeAll();
|
|
557136
559040
|
init_common();
|
|
@@ -557853,6 +559757,36 @@ Do NOT search for analogies or loosely related concepts. If the feature does not
|
|
|
557853
559757
|
}
|
|
557854
559758
|
});
|
|
557855
559759
|
};
|
|
559760
|
+
symbolsTool = (options = {}) => {
|
|
559761
|
+
return (0, import_ai5.tool)({
|
|
559762
|
+
name: "symbols",
|
|
559763
|
+
description: "List all symbols (functions, classes, structs, constants, etc.) in a file. Returns a hierarchical tree with line numbers \u2014 like a table of contents for code files.",
|
|
559764
|
+
inputSchema: symbolsSchema,
|
|
559765
|
+
execute: async ({ file: file2 }) => {
|
|
559766
|
+
try {
|
|
559767
|
+
let filePath = file2;
|
|
559768
|
+
if (options.cwd) {
|
|
559769
|
+
const resolvedPaths = parseAndResolvePaths(file2, options.cwd);
|
|
559770
|
+
if (resolvedPaths.length > 0) {
|
|
559771
|
+
filePath = resolvedPaths[0];
|
|
559772
|
+
}
|
|
559773
|
+
}
|
|
559774
|
+
const result = await symbols({
|
|
559775
|
+
files: [filePath],
|
|
559776
|
+
cwd: options.cwd,
|
|
559777
|
+
binaryOptions: options.binaryOptions
|
|
559778
|
+
});
|
|
559779
|
+
if (result && result.length > 0) {
|
|
559780
|
+
return JSON.stringify(result[0], null, 2);
|
|
559781
|
+
}
|
|
559782
|
+
return JSON.stringify({ file: file2, symbols: [] }, null, 2);
|
|
559783
|
+
} catch (error40) {
|
|
559784
|
+
console.error("Error executing symbols:", error40);
|
|
559785
|
+
return formatErrorForAI(error40);
|
|
559786
|
+
}
|
|
559787
|
+
}
|
|
559788
|
+
});
|
|
559789
|
+
};
|
|
557856
559790
|
}
|
|
557857
559791
|
});
|
|
557858
559792
|
|
|
@@ -558253,10 +560187,11 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
558253
560187
|
const startLine = startRef.line;
|
|
558254
560188
|
const endLine = endRef ? endRef.line : startLine;
|
|
558255
560189
|
if (endLine < startLine) {
|
|
558256
|
-
|
|
560190
|
+
const insertionHint = endLine === startLine - 1 ? ` This looks like an insertion between lines ${endLine} and ${startLine}. To insert there without replacing existing code, use start_line="${startLine}" with position="before" or start_line="${endLine}" with position="after".` : ' To insert new code, choose a single anchor line in start_line and set position to "before" or "after" instead of using an inverted range.';
|
|
560191
|
+
return `Error editing file: end_line (${endLine}) must be >= start_line (${startLine}). Omitting position means replace/update the addressed lines, not insert.${insertionHint} To delete lines, use new_string as the empty string "" with a valid non-inverted range.`;
|
|
558257
560192
|
}
|
|
558258
560193
|
if (position !== void 0 && position !== null && position !== "before" && position !== "after") {
|
|
558259
|
-
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before
|
|
560194
|
+
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before start_line, position="after" to insert after start_line, or omit position to replace/update the addressed lines.';
|
|
558260
560195
|
}
|
|
558261
560196
|
const content = await import_fs13.promises.readFile(resolvedPath, "utf-8");
|
|
558262
560197
|
const fileLines = content.split("\n");
|
|
@@ -558313,7 +560248,7 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
558313
560248
|
return buildLineEditResponse(file_path, startLine, endLine, newLines.length, fileLines, startLine - 1, action, modifications);
|
|
558314
560249
|
}
|
|
558315
560250
|
}
|
|
558316
|
-
var import_ai6, import_fs13, import_path17, import_fs14, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
|
|
560251
|
+
var import_ai6, import_fs13, import_path17, import_fs14, lineTargetedModeGuidance, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
|
|
558317
560252
|
var init_edit = __esm({
|
|
558318
560253
|
"src/tools/edit.js"() {
|
|
558319
560254
|
"use strict";
|
|
@@ -558326,27 +560261,35 @@ var init_edit = __esm({
|
|
|
558326
560261
|
init_symbolEdit();
|
|
558327
560262
|
init_hashline();
|
|
558328
560263
|
init_lineEditHeuristics();
|
|
560264
|
+
lineTargetedModeGuidance = `Line-targeted mode has three explicit behaviors:
|
|
560265
|
+
- Replace/update lines: provide start_line and optionally end_line, and omit position
|
|
560266
|
+
- Insert near a line: provide start_line and set position to "before" or "after"
|
|
560267
|
+
- Delete lines: provide start_line/end_line for the exact range and set new_string to empty string ""
|
|
560268
|
+
|
|
560269
|
+
Inverted ranges (end_line < start_line) are always invalid and are never treated as insertion.`;
|
|
558329
560270
|
editTool = (options = {}) => {
|
|
558330
560271
|
const { debug, allowedFolders, cwd, workspaceRoot } = parseFileToolOptions(options);
|
|
558331
560272
|
return (0, import_ai6.tool)({
|
|
558332
560273
|
name: "edit",
|
|
558333
|
-
description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted
|
|
560274
|
+
description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted line replacement/insertion/deletion.
|
|
558334
560275
|
|
|
558335
560276
|
Modes:
|
|
558336
560277
|
1. Text edit: Provide old_string + new_string to find and replace text (with fuzzy matching fallback)
|
|
558337
560278
|
2. Symbol replace: Provide symbol + new_string to replace an entire function/class/method by name
|
|
558338
560279
|
3. Symbol insert: Provide symbol + new_string + position to insert code before/after a symbol
|
|
558339
|
-
4. Line-targeted edit: Provide start_line + new_string to
|
|
560280
|
+
4. Line-targeted edit: Provide start_line + new_string to replace/update, insert, or delete lines by line number (from extract/search output)
|
|
560281
|
+
|
|
560282
|
+
${lineTargetedModeGuidance}
|
|
558340
560283
|
|
|
558341
560284
|
Parameters:
|
|
558342
560285
|
- file_path: Path to the file to edit (absolute or relative)
|
|
558343
|
-
- new_string: Replacement text or new code content
|
|
560286
|
+
- new_string: Replacement text or new code content. Use empty string "" to delete the targeted line range.
|
|
558344
560287
|
- old_string: (optional) Text to find and replace. If omitted, symbol or start_line must be provided.
|
|
558345
560288
|
- replace_all: (optional) Replace all occurrences (text mode only)
|
|
558346
560289
|
- symbol: (optional) Symbol name for AST-aware editing (e.g. "myFunction", "MyClass.myMethod")
|
|
558347
|
-
- position: (optional) "before" or "after" \u2014 insert code near a symbol or line instead of replacing it
|
|
558348
|
-
- start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing
|
|
558349
|
-
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd")
|
|
560290
|
+
- position: (optional) "before" or "after" \u2014 insert code near a symbol or line instead of replacing it. Omit position to replace/update.
|
|
560291
|
+
- start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing. With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.
|
|
560292
|
+
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Must be >= start_line. Omit for single-line updates. Do not use inverted ranges for insertion.`,
|
|
558350
560293
|
inputSchema: {
|
|
558351
560294
|
type: "object",
|
|
558352
560295
|
properties: {
|
|
@@ -558360,7 +560303,7 @@ Parameters:
|
|
|
558360
560303
|
},
|
|
558361
560304
|
new_string: {
|
|
558362
560305
|
type: "string",
|
|
558363
|
-
description:
|
|
560306
|
+
description: 'Replacement text or new code content. Use empty string "" to delete the targeted line range.'
|
|
558364
560307
|
},
|
|
558365
560308
|
replace_all: {
|
|
558366
560309
|
type: "boolean",
|
|
@@ -558374,15 +560317,15 @@ Parameters:
|
|
|
558374
560317
|
position: {
|
|
558375
560318
|
type: "string",
|
|
558376
560319
|
enum: ["before", "after"],
|
|
558377
|
-
description: "Insert before/after
|
|
560320
|
+
description: "Insert before/after the target symbol or start_line anchor. Omit position to replace/update the addressed symbol or line range."
|
|
558378
560321
|
},
|
|
558379
560322
|
start_line: {
|
|
558380
560323
|
type: "string",
|
|
558381
|
-
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
|
|
560324
|
+
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.'
|
|
558382
560325
|
},
|
|
558383
560326
|
end_line: {
|
|
558384
560327
|
type: "string",
|
|
558385
|
-
description: '
|
|
560328
|
+
description: 'Inclusive end of the line range to replace/delete (e.g. "55" or "55:cd"). Must be >= start_line. Defaults to start_line.'
|
|
558386
560329
|
}
|
|
558387
560330
|
},
|
|
558388
560331
|
required: ["file_path", "new_string"]
|
|
@@ -558633,7 +560576,7 @@ Important:
|
|
|
558633
560576
|
},
|
|
558634
560577
|
new_string: {
|
|
558635
560578
|
type: "string",
|
|
558636
|
-
description:
|
|
560579
|
+
description: 'Replacement text or new code content. Use empty string "" to delete the targeted line range.'
|
|
558637
560580
|
},
|
|
558638
560581
|
replace_all: {
|
|
558639
560582
|
type: "boolean",
|
|
@@ -558646,15 +560589,15 @@ Important:
|
|
|
558646
560589
|
position: {
|
|
558647
560590
|
type: "string",
|
|
558648
560591
|
enum: ["before", "after"],
|
|
558649
|
-
description: "Insert before/after
|
|
560592
|
+
description: "Insert before/after the target symbol or start_line anchor. Omit position to replace/update the addressed symbol or line range."
|
|
558650
560593
|
},
|
|
558651
560594
|
start_line: {
|
|
558652
560595
|
type: "string",
|
|
558653
|
-
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
|
|
560596
|
+
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.'
|
|
558654
560597
|
},
|
|
558655
560598
|
end_line: {
|
|
558656
560599
|
type: "string",
|
|
558657
|
-
description: '
|
|
560600
|
+
description: 'Inclusive end of the line range to replace/delete (e.g. "55" or "55:cd"). Must be >= start_line. Defaults to start_line.'
|
|
558658
560601
|
}
|
|
558659
560602
|
},
|
|
558660
560603
|
required: ["file_path", "new_string"]
|
|
@@ -558687,7 +560630,7 @@ Important:
|
|
|
558687
560630
|
},
|
|
558688
560631
|
required: ["edits"]
|
|
558689
560632
|
};
|
|
558690
|
-
editDescription = "Edit files using text replacement, AST-aware symbol operations, or line-targeted
|
|
560633
|
+
editDescription = "Edit files using text replacement, AST-aware symbol operations, or line-targeted replacement/insertion/deletion. Supports fuzzy matching for text edits and optional hash-based integrity verification for line edits.";
|
|
558691
560634
|
createDescription = "Create new files with specified content. Will create parent directories if needed.";
|
|
558692
560635
|
multiEditDescription = "Apply multiple file edits in a single tool call. Accepts a JSON array of edit operations, each supporting the same modes as the edit tool.";
|
|
558693
560636
|
editToolDefinition = `
|
|
@@ -558704,15 +560647,21 @@ Four editing modes \u2014 choose based on the scope of your change:
|
|
|
558704
560647
|
|
|
558705
560648
|
4. **Line-targeted edit** (start_line + new_string): For precise edits using line numbers from extract/search output. Use start_line with a line number (e.g. "42") or line:hash (e.g. "42:ab") for integrity verification. Add end_line for multi-line ranges. Use position="before" or "after" to insert instead of replace.
|
|
558706
560649
|
|
|
560650
|
+
How line-targeted mode behaves:
|
|
560651
|
+
- Replace/update lines: provide start_line and optionally end_line, and omit position
|
|
560652
|
+
- Insert near a line: provide start_line and set position to "before" or "after"
|
|
560653
|
+
- Delete lines: provide start_line/end_line for the exact range and set new_string to empty string ""
|
|
560654
|
+
- Inverted ranges are invalid: end_line must be >= start_line and is never treated as insertion
|
|
560655
|
+
|
|
558707
560656
|
Parameters:
|
|
558708
560657
|
- file_path: (required) Path to the file to edit
|
|
558709
|
-
- new_string: (required) Replacement text or new code content
|
|
560658
|
+
- new_string: (required) Replacement text or new code content. Use empty string "" to delete the targeted line range.
|
|
558710
560659
|
- old_string: (optional) Text to find and replace \u2014 copy verbatim from the file, do not paraphrase or reformat
|
|
558711
560660
|
- replace_all: (optional, default: false) Replace all occurrences of old_string (text mode only)
|
|
558712
560661
|
- symbol: (optional) Name of a code symbol (e.g. "myFunction", "MyClass.myMethod") \u2014 must match a function, class, or method definition
|
|
558713
|
-
- position: (optional) "before" or "after" \u2014 insert new_string near the symbol or line instead of replacing it
|
|
558714
|
-
- start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab")
|
|
558715
|
-
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line.
|
|
560662
|
+
- position: (optional) "before" or "after" \u2014 insert new_string near the symbol or line instead of replacing it. Omit position to replace/update.
|
|
560663
|
+
- start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab"). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.
|
|
560664
|
+
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line. Must be >= start_line. Use it for replace/update/delete ranges, not insertion.
|
|
558716
560665
|
|
|
558717
560666
|
Mode selection rules (priority order):
|
|
558718
560667
|
- If symbol is provided, symbol mode is used (old_string and start_line are ignored)
|
|
@@ -558724,12 +560673,15 @@ When to use each mode:
|
|
|
558724
560673
|
- Small edits (a line or a few lines): use text mode with old_string
|
|
558725
560674
|
- Replacing entire functions/classes/methods: use symbol mode \u2014 no exact text matching needed
|
|
558726
560675
|
- Editing specific lines from extract/search output: use line-targeted mode with start_line
|
|
560676
|
+
- Adding a new block near an existing line: use line-targeted mode with start_line plus position="before" or position="after"
|
|
560677
|
+
- Removing lines entirely: use line-targeted mode with start_line/end_line and new_string=""
|
|
558727
560678
|
- Editing inside large functions without rewriting them entirely: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers, then use start_line/end_line to edit specific lines within it
|
|
558728
560679
|
|
|
558729
560680
|
Error handling:
|
|
558730
560681
|
- If an edit fails, read the error message carefully \u2014 it contains specific instructions for how to fix the call and retry
|
|
558731
560682
|
- Common fixes: use 'search'/'extract' to get exact file content, add more context to old_string, switch between text and symbol modes
|
|
558732
560683
|
- Line-targeted hash mismatch: the file changed since last read; the error provides updated line:hash references
|
|
560684
|
+
- Inverted line ranges are invalid; the error explains how to express insertion with position="before"/"after"
|
|
558733
560685
|
|
|
558734
560686
|
Examples:
|
|
558735
560687
|
|
|
@@ -558783,6 +560735,22 @@ Line-targeted edit (replace a range of lines):
|
|
|
558783
560735
|
return processItems(order.items);</new_string>
|
|
558784
560736
|
</edit>
|
|
558785
560737
|
|
|
560738
|
+
Line-targeted edit (insert before a line without replacing it):
|
|
560739
|
+
<edit>
|
|
560740
|
+
<file_path>src/main.js</file_path>
|
|
560741
|
+
<start_line>42</start_line>
|
|
560742
|
+
<position>before</position>
|
|
560743
|
+
<new_string> logger.debug("starting process");</new_string>
|
|
560744
|
+
</edit>
|
|
560745
|
+
|
|
560746
|
+
Line-targeted edit (delete a range of lines):
|
|
560747
|
+
<edit>
|
|
560748
|
+
<file_path>src/main.js</file_path>
|
|
560749
|
+
<start_line>42</start_line>
|
|
560750
|
+
<end_line>45</end_line>
|
|
560751
|
+
<new_string></new_string>
|
|
560752
|
+
</edit>
|
|
560753
|
+
|
|
558786
560754
|
Line-targeted edit with hash verification:
|
|
558787
560755
|
<edit>
|
|
558788
560756
|
<file_path>src/main.js</file_path>
|
|
@@ -559013,6 +560981,10 @@ You are Probe, a specialized code intelligence assistant. Your objective is to a
|
|
|
559013
560981
|
* **Purpose:** Retrieve specific code blocks or entire files *after* \`search\` or \`query\` identifies the target.
|
|
559014
560982
|
* **Syntax:** Optional \`#symbol\` (e.g., \`#MyClass\`), \`#Lstart-Lend\` (e.g., \`#L50-L75\`).
|
|
559015
560983
|
* **Mandatory Argument:** \`path\` (specific file path, e.g., \`"src/utils/helpers.go"\`, or dependency file like \`"go:github.com/gin-gonic/gin/context.go"\`).
|
|
560984
|
+
* \`symbols\`
|
|
560985
|
+
* **Purpose:** List all symbols (functions, classes, structs, constants, etc.) in a file \u2014 a table of contents with line numbers and nesting.
|
|
560986
|
+
* **Syntax:** \`file\` (path to the file to list symbols from).
|
|
560987
|
+
* **Use When:** You need to understand a file's structure before extracting specific parts, or to find the right symbol name/line number for \`extract\`.
|
|
559016
560988
|
|
|
559017
560989
|
[Examples]
|
|
559018
560990
|
|
|
@@ -559147,6 +561119,8 @@ __export(tools_exports, {
|
|
|
559147
561119
|
searchFilesSchema: () => searchFilesSchema,
|
|
559148
561120
|
searchSchema: () => searchSchema,
|
|
559149
561121
|
searchTool: () => searchTool,
|
|
561122
|
+
symbolsSchema: () => symbolsSchema,
|
|
561123
|
+
symbolsTool: () => symbolsTool,
|
|
559150
561124
|
tools: () => tools,
|
|
559151
561125
|
useSkillSchema: () => useSkillSchema
|
|
559152
561126
|
});
|
|
@@ -559270,16 +561244,16 @@ function shouldIgnore(filePath, ignorePatterns) {
|
|
|
559270
561244
|
}
|
|
559271
561245
|
return false;
|
|
559272
561246
|
}
|
|
559273
|
-
var import_fs15, import_path18, import_util14,
|
|
561247
|
+
var import_fs15, import_path18, import_util14, import_child_process11, execAsync3;
|
|
559274
561248
|
var init_file_lister = __esm({
|
|
559275
561249
|
"src/utils/file-lister.js"() {
|
|
559276
561250
|
"use strict";
|
|
559277
561251
|
import_fs15 = __toESM(__nccwpck_require__(79896), 1);
|
|
559278
561252
|
import_path18 = __toESM(__nccwpck_require__(16928), 1);
|
|
559279
561253
|
import_util14 = __nccwpck_require__(39023);
|
|
559280
|
-
|
|
561254
|
+
import_child_process11 = __nccwpck_require__(35317);
|
|
559281
561255
|
init_symlink_utils();
|
|
559282
|
-
execAsync3 = (0, import_util14.promisify)(
|
|
561256
|
+
execAsync3 = (0, import_util14.promisify)(import_child_process11.exec);
|
|
559283
561257
|
}
|
|
559284
561258
|
});
|
|
559285
561259
|
|
|
@@ -559355,6 +561329,9 @@ __export(index_exports, {
|
|
|
559355
561329
|
searchSchema: () => searchSchema,
|
|
559356
561330
|
searchTool: () => searchTool,
|
|
559357
561331
|
setBinaryPath: () => setBinaryPath,
|
|
561332
|
+
symbols: () => symbols,
|
|
561333
|
+
symbolsSchema: () => symbolsSchema,
|
|
561334
|
+
symbolsTool: () => symbolsTool,
|
|
559358
561335
|
taskSchema: () => taskSchema,
|
|
559359
561336
|
taskSystemPrompt: () => taskSystemPrompt,
|
|
559360
561337
|
tools: () => tools_exports,
|
|
@@ -559368,6 +561345,7 @@ var init_index = __esm({
|
|
|
559368
561345
|
init_search();
|
|
559369
561346
|
init_query();
|
|
559370
561347
|
init_extract();
|
|
561348
|
+
init_symbols();
|
|
559371
561349
|
init_grep();
|
|
559372
561350
|
init_delegate();
|
|
559373
561351
|
init_utils();
|
|
@@ -627561,7 +629539,7 @@ module.exports = /*#__PURE__*/JSON.parse('["aaa","aarp","abb","abbott","abbvie",
|
|
|
627561
629539
|
/***/ ((module) => {
|
|
627562
629540
|
|
|
627563
629541
|
"use strict";
|
|
627564
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@probelabs/visor","version":"0.1.42","main":"dist/index.js","bin":{"visor":"./dist/index.js"},"exports":{".":{"require":"./dist/index.js","import":"./dist/index.js"},"./sdk":{"types":"./dist/sdk/sdk.d.ts","import":"./dist/sdk/sdk.mjs","require":"./dist/sdk/sdk.js"},"./cli":{"require":"./dist/index.js"}},"files":["dist/","defaults/","action.yml","README.md","LICENSE"],"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"build:cli":"ncc build src/index.ts -o dist && cp -r defaults dist/ && cp -r output dist/ && cp -r docs dist/ && cp -r examples dist/ && cp -r src/debug-visualizer/ui dist/debug-visualizer/ && node scripts/inject-version.js && echo \'#!/usr/bin/env node\' | cat - dist/index.js > temp && mv temp dist/index.js && chmod +x dist/index.js","build:sdk":"tsup src/sdk.ts --dts --sourcemap --format esm,cjs --out-dir dist/sdk","build":"./scripts/build-oss.sh","build:ee":"npm run build:cli && npm run build:sdk","test":"jest && npm run test:yaml","test:unit":"jest","prepublishOnly":"npm run build","test:watch":"jest --watch","test:coverage":"jest --coverage","test:ee":"jest --testPathPatterns=\'tests/ee\' --testPathIgnorePatterns=\'/node_modules/\' --no-coverage","test:manual:bash":"RUN_MANUAL_TESTS=true jest tests/manual/bash-config-manual.test.ts","lint":"eslint src tests --ext .ts","lint:fix":"eslint src tests --ext .ts --fix","format":"prettier --write src tests","format:check":"prettier --check src tests","clean":"","clean:traces":"node scripts/clean-traces.js","prebuild":"npm run clean && node scripts/generate-config-schema.js","pretest":"npm run clean:traces && node scripts/generate-config-schema.js && npm run build:cli","pretest:unit":"npm run clean:traces && node scripts/generate-config-schema.js && npm run build:cli","test:with-build":"npm run build:cli && jest","test:yaml":"node dist/index.js test --progress compact","test:yaml:parallel":"node dist/index.js test --progress compact --max-parallel 4","prepare":"husky","pre-commit":"lint-staged","deploy:site":"cd site && npx wrangler pages deploy . --project-name=visor-site --commit-dirty=true","deploy:worker":"npx wrangler deploy","deploy":"npm run deploy:site && npm run deploy:worker","publish:ee":"./scripts/publish-ee.sh","release":"./scripts/release.sh","release:patch":"./scripts/release.sh patch","release:minor":"./scripts/release.sh minor","release:major":"./scripts/release.sh major","release:prerelease":"./scripts/release.sh prerelease","docs:validate":"node scripts/validate-readme-links.js","workshop:setup":"npm install -D reveal-md@6.1.2","workshop:serve":"cd workshop && reveal-md slides.md -w","workshop:export":"reveal-md workshop/slides.md --static workshop/build","workshop:pdf":"reveal-md workshop/slides.md --print workshop/Visor-Workshop.pdf --print-size letter","workshop:pdf:ci":"reveal-md workshop/slides.md --print workshop/Visor-Workshop.pdf --print-size letter --puppeteer-launch-args=\\"--no-sandbox --disable-dev-shm-usage\\"","workshop:pdf:a4":"reveal-md workshop/slides.md --print workshop/Visor-Workshop-A4.pdf --print-size A4","workshop:build":"npm run workshop:export && npm run workshop:pdf","simulate:issue":"TS_NODE_TRANSPILE_ONLY=1 ts-node scripts/simulate-gh-run.ts --event issues --action opened --debug","simulate:comment":"TS_NODE_TRANSPILE_ONLY=1 ts-node scripts/simulate-gh-run.ts --event issue_comment --action created --debug"},"keywords":["code-review","ai","github-action","cli","pr-review","visor"],"author":"Probe Labs","license":"MIT","description":"AI workflow engine for code review, assistants, and automation — orchestrate checks, MCP tools, and AI providers with YAML-driven pipelines","repository":{"type":"git","url":"git+https://github.com/probelabs/visor.git"},"bugs":{"url":"https://github.com/probelabs/visor/issues"},"homepage":"https://github.com/probelabs/visor#readme","dependencies":{"@actions/core":"^1.11.1","@apidevtools/swagger-parser":"^12.1.0","@grammyjs/runner":"^2.0.3","@modelcontextprotocol/sdk":"^1.25.3","@nyariv/sandboxjs":"github:probelabs/SandboxJS#23c4bb611f7d05f3cb8c523917b5f57103e48108","@octokit/action":"^8.0.2","@octokit/auth-app":"^8.1.0","@octokit/core":"^7.0.3","@octokit/rest":"^22.0.0","@opentelemetry/api":"^1.9.0","@opentelemetry/api-logs":"^0.203.0","@opentelemetry/core":"^1.30.1","@opentelemetry/exporter-logs-otlp-http":"^0.203.0","@opentelemetry/exporter-metrics-otlp-http":"^0.203.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.203.0","@opentelemetry/exporter-trace-otlp-http":"^0.203.0","@opentelemetry/instrumentation":"^0.203.0","@opentelemetry/resources":"^1.30.1","@opentelemetry/sdk-logs":"^0.203.0","@opentelemetry/sdk-metrics":"^1.30.1","@opentelemetry/sdk-node":"^0.203.0","@opentelemetry/sdk-trace-base":"^1.30.1","@opentelemetry/semantic-conventions":"^1.30.1","@probelabs/probe":"^0.6.0-
|
|
629542
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@probelabs/visor","version":"0.1.42","main":"dist/index.js","bin":{"visor":"./dist/index.js"},"exports":{".":{"require":"./dist/index.js","import":"./dist/index.js"},"./sdk":{"types":"./dist/sdk/sdk.d.ts","import":"./dist/sdk/sdk.mjs","require":"./dist/sdk/sdk.js"},"./cli":{"require":"./dist/index.js"}},"files":["dist/","defaults/","action.yml","README.md","LICENSE"],"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"build:cli":"ncc build src/index.ts -o dist && cp -r defaults dist/ && cp -r output dist/ && cp -r docs dist/ && cp -r examples dist/ && cp -r src/debug-visualizer/ui dist/debug-visualizer/ && node scripts/inject-version.js && echo \'#!/usr/bin/env node\' | cat - dist/index.js > temp && mv temp dist/index.js && chmod +x dist/index.js","build:sdk":"tsup src/sdk.ts --dts --sourcemap --format esm,cjs --out-dir dist/sdk","build":"npm run build:oss","build:oss":"./scripts/build-oss.sh","build:ee":"npm run build:cli && npm run build:sdk","test":"jest && npm run test:yaml","test:unit":"jest","prepublishOnly":"npm run build","test:watch":"jest --watch","test:coverage":"jest --coverage","test:ee":"jest --testPathPatterns=\'tests/ee\' --testPathIgnorePatterns=\'/node_modules/\' --no-coverage","test:manual:bash":"RUN_MANUAL_TESTS=true jest tests/manual/bash-config-manual.test.ts","lint":"eslint src tests --ext .ts","lint:fix":"eslint src tests --ext .ts --fix","format":"prettier --write src tests","format:check":"prettier --check src tests","clean":"","clean:traces":"node scripts/clean-traces.js","prebuild":"npm run clean && node scripts/generate-config-schema.js","pretest":"npm run clean:traces && node scripts/generate-config-schema.js && npm run build:cli","pretest:unit":"npm run clean:traces && node scripts/generate-config-schema.js && npm run build:cli","test:with-build":"npm run build:cli && jest","test:yaml":"node dist/index.js test --progress compact","test:yaml:parallel":"node dist/index.js test --progress compact --max-parallel 4","prepare":"husky","pre-commit":"lint-staged","deploy:site":"cd site && npx wrangler pages deploy . --project-name=visor-site --commit-dirty=true","deploy:worker":"npx wrangler deploy","deploy":"npm run deploy:site && npm run deploy:worker","publish:ee":"./scripts/publish-ee.sh","release":"./scripts/release.sh","release:patch":"./scripts/release.sh patch","release:minor":"./scripts/release.sh minor","release:major":"./scripts/release.sh major","release:prerelease":"./scripts/release.sh prerelease","docs:validate":"node scripts/validate-readme-links.js","workshop:setup":"npm install -D reveal-md@6.1.2","workshop:serve":"cd workshop && reveal-md slides.md -w","workshop:export":"reveal-md workshop/slides.md --static workshop/build","workshop:pdf":"reveal-md workshop/slides.md --print workshop/Visor-Workshop.pdf --print-size letter","workshop:pdf:ci":"reveal-md workshop/slides.md --print workshop/Visor-Workshop.pdf --print-size letter --puppeteer-launch-args=\\"--no-sandbox --disable-dev-shm-usage\\"","workshop:pdf:a4":"reveal-md workshop/slides.md --print workshop/Visor-Workshop-A4.pdf --print-size A4","workshop:build":"npm run workshop:export && npm run workshop:pdf","simulate:issue":"TS_NODE_TRANSPILE_ONLY=1 ts-node scripts/simulate-gh-run.ts --event issues --action opened --debug","simulate:comment":"TS_NODE_TRANSPILE_ONLY=1 ts-node scripts/simulate-gh-run.ts --event issue_comment --action created --debug"},"keywords":["code-review","ai","github-action","cli","pr-review","visor"],"author":"Probe Labs","license":"MIT","description":"AI workflow engine for code review, assistants, and automation — orchestrate checks, MCP tools, and AI providers with YAML-driven pipelines","repository":{"type":"git","url":"git+https://github.com/probelabs/visor.git"},"bugs":{"url":"https://github.com/probelabs/visor/issues"},"homepage":"https://github.com/probelabs/visor#readme","dependencies":{"@actions/core":"^1.11.1","@apidevtools/swagger-parser":"^12.1.0","@grammyjs/runner":"^2.0.3","@modelcontextprotocol/sdk":"^1.25.3","@nyariv/sandboxjs":"github:probelabs/SandboxJS#23c4bb611f7d05f3cb8c523917b5f57103e48108","@octokit/action":"^8.0.2","@octokit/auth-app":"^8.1.0","@octokit/core":"^7.0.3","@octokit/rest":"^22.0.0","@opentelemetry/api":"^1.9.0","@opentelemetry/api-logs":"^0.203.0","@opentelemetry/core":"^1.30.1","@opentelemetry/exporter-logs-otlp-http":"^0.203.0","@opentelemetry/exporter-metrics-otlp-http":"^0.203.0","@opentelemetry/exporter-trace-otlp-grpc":"^0.203.0","@opentelemetry/exporter-trace-otlp-http":"^0.203.0","@opentelemetry/instrumentation":"^0.203.0","@opentelemetry/resources":"^1.30.1","@opentelemetry/sdk-logs":"^0.203.0","@opentelemetry/sdk-metrics":"^1.30.1","@opentelemetry/sdk-node":"^0.203.0","@opentelemetry/sdk-trace-base":"^1.30.1","@opentelemetry/semantic-conventions":"^1.30.1","@probelabs/probe":"^0.6.0-rc311","@types/commander":"^2.12.0","@types/uuid":"^10.0.0","@utcp/file":"^1.1.0","@utcp/http":"^1.1.0","@utcp/sdk":"^1.1.0","@utcp/text":"^1.1.0","acorn":"^8.16.0","acorn-walk":"^8.3.5","ajv":"^8.17.1","ajv-formats":"^3.0.1","better-sqlite3":"^11.0.0","blessed":"^0.1.81","botbuilder":"^4.23.3","botframework-connector":"^4.23.3","cli-table3":"^0.6.5","commander":"^14.0.0","deepmerge":"^4.3.1","dotenv":"^17.2.3","grammy":"^1.41.1","ignore":"^7.0.5","imapflow":"^1.2.12","js-yaml":"^4.1.0","jsonpath-plus":"^10.4.0","liquidjs":"^10.21.1","mailparser":"^3.9.3","minimatch":"^10.2.2","node-cron":"^3.0.3","nodemailer":"^8.0.1","open":"^9.1.0","resend":"^6.9.3","simple-git":"^3.28.0","uuid":"^11.1.0","ws":"^8.18.3"},"optionalDependencies":{"@anthropic/claude-code-sdk":"npm:null@*","@open-policy-agent/opa-wasm":"^1.10.0","knex":"^3.1.0","mysql2":"^3.11.0","pg":"^8.13.0","tedious":"^19.0.0"},"devDependencies":{"@eslint/js":"^9.34.0","@kie/act-js":"^2.6.2","@kie/mock-github":"^2.0.1","@swc/core":"^1.13.2","@swc/jest":"^0.2.37","@types/better-sqlite3":"^7.6.0","@types/blessed":"^0.1.27","@types/jest":"^30.0.0","@types/js-yaml":"^4.0.9","@types/mailparser":"^3.4.6","@types/node":"^24.3.0","@types/node-cron":"^3.0.11","@types/nodemailer":"^7.0.11","@types/ws":"^8.18.1","@typescript-eslint/eslint-plugin":"^8.42.0","@typescript-eslint/parser":"^8.42.0","@vercel/ncc":"^0.38.4","eslint":"^9.34.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4","husky":"^9.1.7","jest":"^30.1.3","lint-staged":"^16.1.6","prettier":"^3.6.2","reveal-md":"^6.1.2","ts-json-schema-generator":"^1.5.1","ts-node":"^10.9.2","tsup":"^8.5.0","typescript":"^5.9.2","wrangler":"^3.0.0"},"peerDependenciesMeta":{"@anthropic/claude-code-sdk":{"optional":true}},"directories":{"test":"tests"},"lint-staged":{"src/**/*.{ts,js}":["eslint --fix","prettier --write"],"tests/**/*.{ts,js}":["eslint --fix","prettier --write"],"*.{json,md,yml,yaml}":["prettier --write"]}}');
|
|
627565
629543
|
|
|
627566
629544
|
/***/ })
|
|
627567
629545
|
|