@xyagent/cli 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +860 -0
- package/bin/agentlink +8585 -0
- package/bin/agentlink-agent +7 -0
- package/bin/agentlink-mcp-stdio +173 -0
- package/docs/LOGGING.md +159 -0
- package/package.json +38 -0
- package/src/core.mjs +320 -0
- package/src/tunnel.mjs +291 -0
- package/src/tunnel_proxy.mjs +913 -0
- package/src/tunnel_service.mjs +699 -0
- package/src/tunnel_state.mjs +301 -0
- package/src/unified_producer.mjs +259 -0
- package/src-ext/README.md +75 -0
- package/src-ext/bin.mjs +128 -0
- package/src-ext/commands/agent.mjs +66 -0
- package/src-ext/commands/help.mjs +31 -0
- package/src-ext/commands/pair.mjs +455 -0
- package/src-ext/commands/reload.mjs +78 -0
- package/src-ext/commands/service.mjs +64 -0
- package/src-ext/core/accountResolver.mjs +137 -0
- package/src-ext/core/activeRuns.mjs +76 -0
- package/src-ext/core/agentlinkToolsBootstrap.mjs +75 -0
- package/src-ext/core/agentlinkToolsRegistry.mjs +323 -0
- package/src-ext/core/agentlinkToolsServer.mjs +109 -0
- package/src-ext/core/approvalGateway.mjs +132 -0
- package/src-ext/core/attachAuditLog.mjs +79 -0
- package/src-ext/core/attachDenylist.mjs +128 -0
- package/src-ext/core/autoTunnelDetector.mjs +98 -0
- package/src-ext/core/autoTunnelGateway.mjs +393 -0
- package/src-ext/core/autoTunnelWiring.mjs +184 -0
- package/src-ext/core/boundedMap.mjs +98 -0
- package/src-ext/core/bridgeAttachAutoScanner.mjs +237 -0
- package/src-ext/core/bridgeHooks.mjs +168 -0
- package/src-ext/core/bridgeSelfUninstall.mjs +133 -0
- package/src-ext/core/claudeTrust.mjs +74 -0
- package/src-ext/core/codexTrust.mjs +77 -0
- package/src-ext/core/cosUploadClient.mjs +326 -0
- package/src-ext/core/createWorkspace.mjs +170 -0
- package/src-ext/core/daemonRestart.mjs +49 -0
- package/src-ext/core/defaultWorkspace.mjs +65 -0
- package/src-ext/core/ensureGitRepo.mjs +57 -0
- package/src-ext/core/hermesProfile.mjs +75 -0
- package/src-ext/core/interruptGateway.mjs +119 -0
- package/src-ext/core/interruptRunListener.mjs +106 -0
- package/src-ext/core/mcpRuntimeFanout.mjs +236 -0
- package/src-ext/core/mcpStdioClient.mjs +316 -0
- package/src-ext/core/openclawGatewayClient.mjs +230 -0
- package/src-ext/core/pairCodeClient.mjs +331 -0
- package/src-ext/core/pairInventory.mjs +59 -0
- package/src-ext/core/pathExpand.mjs +34 -0
- package/src-ext/core/preprocessAttachments.mjs +113 -0
- package/src-ext/core/relayWorker.mjs +284 -0
- package/src-ext/core/relayWorkerHttp.mjs +58 -0
- package/src-ext/core/scanWorkspaces.mjs +842 -0
- package/src-ext/core/sessionSlot.mjs +70 -0
- package/src-ext/core/stateMachine.mjs +85 -0
- package/src-ext/core/toolsServerLifecycle.mjs +169 -0
- package/src-ext/core/unifiedDispatchHandler.mjs +439 -0
- package/src-ext/core/usageReporter.mjs +207 -0
- package/src-ext/openclaw-plugin/envelope-builder.cjs +619 -0
- package/src-ext/openclaw-plugin/index.cjs +1919 -0
- package/src-ext/openclaw-plugin/openclaw.plugin.json +20 -0
- package/src-ext/openclaw-plugin/package.json +12 -0
- package/src-ext/openclaw-plugin/relay-defaults.json +3 -0
- package/src-ext/openclaw-plugin/todoTranslatorUtils.cjs +101 -0
- package/src-ext/runtime/_shared/cliExec.mjs +138 -0
- package/src-ext/runtime/_shared/cosTextRefs.mjs +120 -0
- package/src-ext/runtime/_shared/fetchAndBase64Encode.mjs +52 -0
- package/src-ext/runtime/_shared/relayObjectToBlock.mjs +307 -0
- package/src-ext/runtime/_shared/sessionPicker.mjs +418 -0
- package/src-ext/runtime/_shared/slashCommandRouter.mjs +1346 -0
- package/src-ext/runtime/_shared/todoTranslatorUtils.mjs +94 -0
- package/src-ext/runtime/claude/askUserQuestionTranslator.mjs +241 -0
- package/src-ext/runtime/claude/customCommandsCollector.mjs +132 -0
- package/src-ext/runtime/claude/handleRequest.mjs +1418 -0
- package/src-ext/runtime/claude/index.mjs +160 -0
- package/src-ext/runtime/claude/internalCommandNames.mjs +58 -0
- package/src-ext/runtime/claude/launcher.mjs +313 -0
- package/src-ext/runtime/claude/mcpConfigAdapter.mjs +174 -0
- package/src-ext/runtime/claude/mcpConfigWriter.mjs +57 -0
- package/src-ext/runtime/claude/modelContextWindow.mjs +30 -0
- package/src-ext/runtime/claude/modelScanner.mjs +257 -0
- package/src-ext/runtime/claude/permissionInterruptBlock.mjs +86 -0
- package/src-ext/runtime/claude/permissionPromptServer.mjs +170 -0
- package/src-ext/runtime/claude/permissionPromptServerWorker.mjs +214 -0
- package/src-ext/runtime/claude/preflight.mjs +62 -0
- package/src-ext/runtime/claude/stdoutParser.mjs +365 -0
- package/src-ext/runtime/claude/todoTranslator.mjs +66 -0
- package/src-ext/runtime/claude/usageProbe.mjs +576 -0
- package/src-ext/runtime/claude/usageProbeStrip.mjs +14 -0
- package/src-ext/runtime/codex/codexCustomCommandsCollector.mjs +87 -0
- package/src-ext/runtime/codex/elicitationHandler.mjs +91 -0
- package/src-ext/runtime/codex/eventMapper.mjs +154 -0
- package/src-ext/runtime/codex/handleRequest.mjs +1152 -0
- package/src-ext/runtime/codex/index.mjs +142 -0
- package/src-ext/runtime/codex/mcpConfigAdapter.mjs +155 -0
- package/src-ext/runtime/codex/modelScanner.mjs +305 -0
- package/src-ext/runtime/codex/planNotificationHandler.mjs +61 -0
- package/src-ext/runtime/codex/preflight.mjs +67 -0
- package/src-ext/runtime/hermes/commandBackend.mjs +117 -0
- package/src-ext/runtime/hermes/envSetup.mjs +229 -0
- package/src-ext/runtime/hermes/gatewayManager.mjs +625 -0
- package/src-ext/runtime/hermes/handleRequest.mjs +1257 -0
- package/src-ext/runtime/hermes/httpBackend.mjs +219 -0
- package/src-ext/runtime/hermes/index.mjs +196 -0
- package/src-ext/runtime/hermes/mcpConfigAdapter.mjs +189 -0
- package/src-ext/runtime/hermes/preflight.mjs +359 -0
- package/src-ext/runtime/hermes/responsesBackend.mjs +276 -0
- package/src-ext/runtime/hermes/sessionStore.mjs +78 -0
- package/src-ext/runtime/hermes/todoTranslator.mjs +90 -0
- package/src-ext/runtime/hermes/workspaceRpc.mjs +124 -0
- package/src-ext/runtime/openclaw/buildOpenclawDaemonInput.mjs +143 -0
- package/src-ext/runtime/openclaw/mcpConfigAdapter.mjs +91 -0
- package/src-ext/runtime/openclaw/openclawConfig.mjs +145 -0
- package/src-ext/runtime/picoclaw/constants.mjs +39 -0
- package/src-ext/runtime/picoclaw/handleRequest.mjs +289 -0
- package/src-ext/runtime/picoclaw/index.mjs +314 -0
- package/src-ext/runtime/picoclaw/pairFlow.mjs +224 -0
- package/src-ext/runtime/picoclaw/state.mjs +78 -0
- package/src-ext/runtime/picoclaw/todoTranslator.mjs +67 -0
- package/src-ext/runtime/picoclaw/translator.mjs +272 -0
- package/src-ext/runtime/picoclaw/wsClient.mjs +129 -0
- package/src-ext/service/serviceManager.mjs +521 -0
- package/src-shared/README.md +44 -0
- package/src-shared/chat_push_normalizer.mjs +113 -0
- package/src-shared/correlation.mjs +25 -0
- package/src-shared/envelope_builder.mjs +612 -0
- package/src-shared/logger.mjs +167 -0
- package/src-shared/relay-defaults.json +3 -0
- package/src-shared/relay_revoke.mjs +46 -0
- package/src-shared/vendor/README.md +60 -0
- package/src-shared/vendor/smol-toml/LICENSE +24 -0
- package/src-shared/vendor/smol-toml/README.md +236 -0
- package/src-shared/vendor/smol-toml/VENDORED.md +37 -0
- package/src-shared/vendor/smol-toml/dist/date.d.ts +41 -0
- package/src-shared/vendor/smol-toml/dist/date.js +127 -0
- package/src-shared/vendor/smol-toml/dist/error.d.ts +38 -0
- package/src-shared/vendor/smol-toml/dist/error.js +63 -0
- package/src-shared/vendor/smol-toml/dist/extract.d.ts +30 -0
- package/src-shared/vendor/smol-toml/dist/extract.js +109 -0
- package/src-shared/vendor/smol-toml/dist/index.cjs +900 -0
- package/src-shared/vendor/smol-toml/dist/index.d.ts +43 -0
- package/src-shared/vendor/smol-toml/dist/index.js +33 -0
- package/src-shared/vendor/smol-toml/dist/parse.d.ts +37 -0
- package/src-shared/vendor/smol-toml/dist/parse.js +148 -0
- package/src-shared/vendor/smol-toml/dist/primitive.d.ts +31 -0
- package/src-shared/vendor/smol-toml/dist/primitive.js +178 -0
- package/src-shared/vendor/smol-toml/dist/stringify.d.ts +31 -0
- package/src-shared/vendor/smol-toml/dist/stringify.js +163 -0
- package/src-shared/vendor/smol-toml/dist/struct.d.ts +32 -0
- package/src-shared/vendor/smol-toml/dist/struct.js +194 -0
- package/src-shared/vendor/smol-toml/dist/util.d.ts +42 -0
- package/src-shared/vendor/smol-toml/dist/util.js +100 -0
- package/src-shared/vendor/smol-toml/package.json +54 -0
- package/src-shared/vendor/yaml/LICENSE +13 -0
- package/src-shared/vendor/yaml/README.md +155 -0
- package/src-shared/vendor/yaml/VENDORED.md +29 -0
- package/src-shared/vendor/yaml/bin.mjs +11 -0
- package/src-shared/vendor/yaml/browser/dist/compose/compose-collection.js +88 -0
- package/src-shared/vendor/yaml/browser/dist/compose/compose-doc.js +42 -0
- package/src-shared/vendor/yaml/browser/dist/compose/compose-node.js +92 -0
- package/src-shared/vendor/yaml/browser/dist/compose/compose-scalar.js +80 -0
- package/src-shared/vendor/yaml/browser/dist/compose/composer.js +217 -0
- package/src-shared/vendor/yaml/browser/dist/compose/resolve-block-map.js +113 -0
- package/src-shared/vendor/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
- package/src-shared/vendor/yaml/browser/dist/compose/resolve-block-seq.js +47 -0
- package/src-shared/vendor/yaml/browser/dist/compose/resolve-end.js +37 -0
- package/src-shared/vendor/yaml/browser/dist/compose/resolve-flow-collection.js +203 -0
- package/src-shared/vendor/yaml/browser/dist/compose/resolve-flow-scalar.js +223 -0
- package/src-shared/vendor/yaml/browser/dist/compose/resolve-props.js +148 -0
- package/src-shared/vendor/yaml/browser/dist/compose/util-contains-newline.js +34 -0
- package/src-shared/vendor/yaml/browser/dist/compose/util-empty-scalar-position.js +27 -0
- package/src-shared/vendor/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
- package/src-shared/vendor/yaml/browser/dist/compose/util-map-includes.js +17 -0
- package/src-shared/vendor/yaml/browser/dist/doc/Document.js +334 -0
- package/src-shared/vendor/yaml/browser/dist/doc/anchors.js +72 -0
- package/src-shared/vendor/yaml/browser/dist/doc/applyReviver.js +55 -0
- package/src-shared/vendor/yaml/browser/dist/doc/createNode.js +89 -0
- package/src-shared/vendor/yaml/browser/dist/doc/directives.js +176 -0
- package/src-shared/vendor/yaml/browser/dist/errors.js +57 -0
- package/src-shared/vendor/yaml/browser/dist/index.js +17 -0
- package/src-shared/vendor/yaml/browser/dist/log.js +14 -0
- package/src-shared/vendor/yaml/browser/dist/nodes/Alias.js +101 -0
- package/src-shared/vendor/yaml/browser/dist/nodes/Collection.js +147 -0
- package/src-shared/vendor/yaml/browser/dist/nodes/Node.js +38 -0
- package/src-shared/vendor/yaml/browser/dist/nodes/Pair.js +36 -0
- package/src-shared/vendor/yaml/browser/dist/nodes/Scalar.js +24 -0
- package/src-shared/vendor/yaml/browser/dist/nodes/YAMLMap.js +144 -0
- package/src-shared/vendor/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
- package/src-shared/vendor/yaml/browser/dist/nodes/addPairToJSMap.js +104 -0
- package/src-shared/vendor/yaml/browser/dist/nodes/identity.js +36 -0
- package/src-shared/vendor/yaml/browser/dist/nodes/toJS.js +37 -0
- package/src-shared/vendor/yaml/browser/dist/parse/cst-scalar.js +214 -0
- package/src-shared/vendor/yaml/browser/dist/parse/cst-stringify.js +61 -0
- package/src-shared/vendor/yaml/browser/dist/parse/cst-visit.js +97 -0
- package/src-shared/vendor/yaml/browser/dist/parse/cst.js +98 -0
- package/src-shared/vendor/yaml/browser/dist/parse/lexer.js +717 -0
- package/src-shared/vendor/yaml/browser/dist/parse/line-counter.js +39 -0
- package/src-shared/vendor/yaml/browser/dist/parse/parser.js +954 -0
- package/src-shared/vendor/yaml/browser/dist/public-api.js +99 -0
- package/src-shared/vendor/yaml/browser/dist/schema/Schema.js +38 -0
- package/src-shared/vendor/yaml/browser/dist/schema/common/map.js +17 -0
- package/src-shared/vendor/yaml/browser/dist/schema/common/null.js +15 -0
- package/src-shared/vendor/yaml/browser/dist/schema/common/seq.js +17 -0
- package/src-shared/vendor/yaml/browser/dist/schema/common/string.js +14 -0
- package/src-shared/vendor/yaml/browser/dist/schema/core/bool.js +19 -0
- package/src-shared/vendor/yaml/browser/dist/schema/core/float.js +43 -0
- package/src-shared/vendor/yaml/browser/dist/schema/core/int.js +38 -0
- package/src-shared/vendor/yaml/browser/dist/schema/core/schema.js +23 -0
- package/src-shared/vendor/yaml/browser/dist/schema/json/schema.js +62 -0
- package/src-shared/vendor/yaml/browser/dist/schema/tags.js +83 -0
- package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/binary.js +66 -0
- package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
- package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
- package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
- package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
- package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
- package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/schema.js +37 -0
- package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
- package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
- package/src-shared/vendor/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
- package/src-shared/vendor/yaml/browser/dist/stringify/stringify.js +124 -0
- package/src-shared/vendor/yaml/browser/dist/stringify/stringifyCollection.js +143 -0
- package/src-shared/vendor/yaml/browser/dist/stringify/stringifyComment.js +20 -0
- package/src-shared/vendor/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
- package/src-shared/vendor/yaml/browser/dist/stringify/stringifyNumber.js +24 -0
- package/src-shared/vendor/yaml/browser/dist/stringify/stringifyPair.js +150 -0
- package/src-shared/vendor/yaml/browser/dist/stringify/stringifyString.js +328 -0
- package/src-shared/vendor/yaml/browser/dist/util.js +11 -0
- package/src-shared/vendor/yaml/browser/dist/visit.js +233 -0
- package/src-shared/vendor/yaml/browser/index.js +5 -0
- package/src-shared/vendor/yaml/browser/package.json +3 -0
- package/src-shared/vendor/yaml/dist/cli.d.ts +8 -0
- package/src-shared/vendor/yaml/dist/cli.mjs +199 -0
- package/src-shared/vendor/yaml/dist/compose/compose-collection.d.ts +11 -0
- package/src-shared/vendor/yaml/dist/compose/compose-collection.js +90 -0
- package/src-shared/vendor/yaml/dist/compose/compose-doc.d.ts +7 -0
- package/src-shared/vendor/yaml/dist/compose/compose-doc.js +44 -0
- package/src-shared/vendor/yaml/dist/compose/compose-node.d.ts +28 -0
- package/src-shared/vendor/yaml/dist/compose/compose-node.js +95 -0
- package/src-shared/vendor/yaml/dist/compose/compose-scalar.d.ts +5 -0
- package/src-shared/vendor/yaml/dist/compose/compose-scalar.js +82 -0
- package/src-shared/vendor/yaml/dist/compose/composer.d.ts +62 -0
- package/src-shared/vendor/yaml/dist/compose/composer.js +221 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-block-map.d.ts +6 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-block-map.js +115 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-block-scalar.js +200 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-block-seq.js +49 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-end.d.ts +6 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-end.js +39 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-flow-collection.js +205 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-flow-scalar.js +225 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-props.d.ts +23 -0
- package/src-shared/vendor/yaml/dist/compose/resolve-props.js +150 -0
- package/src-shared/vendor/yaml/dist/compose/util-contains-newline.d.ts +2 -0
- package/src-shared/vendor/yaml/dist/compose/util-contains-newline.js +36 -0
- package/src-shared/vendor/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
- package/src-shared/vendor/yaml/dist/compose/util-empty-scalar-position.js +29 -0
- package/src-shared/vendor/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
- package/src-shared/vendor/yaml/dist/compose/util-flow-indent-check.js +17 -0
- package/src-shared/vendor/yaml/dist/compose/util-map-includes.d.ts +4 -0
- package/src-shared/vendor/yaml/dist/compose/util-map-includes.js +19 -0
- package/src-shared/vendor/yaml/dist/doc/Document.d.ts +141 -0
- package/src-shared/vendor/yaml/dist/doc/Document.js +336 -0
- package/src-shared/vendor/yaml/dist/doc/anchors.d.ts +24 -0
- package/src-shared/vendor/yaml/dist/doc/anchors.js +77 -0
- package/src-shared/vendor/yaml/dist/doc/applyReviver.d.ts +9 -0
- package/src-shared/vendor/yaml/dist/doc/applyReviver.js +57 -0
- package/src-shared/vendor/yaml/dist/doc/createNode.d.ts +17 -0
- package/src-shared/vendor/yaml/dist/doc/createNode.js +91 -0
- package/src-shared/vendor/yaml/dist/doc/directives.d.ts +49 -0
- package/src-shared/vendor/yaml/dist/doc/directives.js +178 -0
- package/src-shared/vendor/yaml/dist/errors.d.ts +21 -0
- package/src-shared/vendor/yaml/dist/errors.js +62 -0
- package/src-shared/vendor/yaml/dist/index.d.ts +22 -0
- package/src-shared/vendor/yaml/dist/index.js +50 -0
- package/src-shared/vendor/yaml/dist/log.d.ts +3 -0
- package/src-shared/vendor/yaml/dist/log.js +17 -0
- package/src-shared/vendor/yaml/dist/nodes/Alias.d.ts +28 -0
- package/src-shared/vendor/yaml/dist/nodes/Alias.js +103 -0
- package/src-shared/vendor/yaml/dist/nodes/Collection.d.ts +73 -0
- package/src-shared/vendor/yaml/dist/nodes/Collection.js +151 -0
- package/src-shared/vendor/yaml/dist/nodes/Node.d.ts +47 -0
- package/src-shared/vendor/yaml/dist/nodes/Node.js +40 -0
- package/src-shared/vendor/yaml/dist/nodes/Pair.d.ts +21 -0
- package/src-shared/vendor/yaml/dist/nodes/Pair.js +39 -0
- package/src-shared/vendor/yaml/dist/nodes/Scalar.d.ts +42 -0
- package/src-shared/vendor/yaml/dist/nodes/Scalar.js +27 -0
- package/src-shared/vendor/yaml/dist/nodes/YAMLMap.d.ts +53 -0
- package/src-shared/vendor/yaml/dist/nodes/YAMLMap.js +147 -0
- package/src-shared/vendor/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
- package/src-shared/vendor/yaml/dist/nodes/YAMLSeq.js +115 -0
- package/src-shared/vendor/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
- package/src-shared/vendor/yaml/dist/nodes/addPairToJSMap.js +106 -0
- package/src-shared/vendor/yaml/dist/nodes/identity.d.ts +23 -0
- package/src-shared/vendor/yaml/dist/nodes/identity.js +53 -0
- package/src-shared/vendor/yaml/dist/nodes/toJS.d.ts +27 -0
- package/src-shared/vendor/yaml/dist/nodes/toJS.js +39 -0
- package/src-shared/vendor/yaml/dist/options.d.ts +338 -0
- package/src-shared/vendor/yaml/dist/parse/cst-scalar.d.ts +64 -0
- package/src-shared/vendor/yaml/dist/parse/cst-scalar.js +218 -0
- package/src-shared/vendor/yaml/dist/parse/cst-stringify.d.ts +8 -0
- package/src-shared/vendor/yaml/dist/parse/cst-stringify.js +63 -0
- package/src-shared/vendor/yaml/dist/parse/cst-visit.d.ts +39 -0
- package/src-shared/vendor/yaml/dist/parse/cst-visit.js +99 -0
- package/src-shared/vendor/yaml/dist/parse/cst.d.ts +108 -0
- package/src-shared/vendor/yaml/dist/parse/cst.js +112 -0
- package/src-shared/vendor/yaml/dist/parse/lexer.d.ts +87 -0
- package/src-shared/vendor/yaml/dist/parse/lexer.js +719 -0
- package/src-shared/vendor/yaml/dist/parse/line-counter.d.ts +22 -0
- package/src-shared/vendor/yaml/dist/parse/line-counter.js +41 -0
- package/src-shared/vendor/yaml/dist/parse/parser.d.ts +84 -0
- package/src-shared/vendor/yaml/dist/parse/parser.js +958 -0
- package/src-shared/vendor/yaml/dist/public-api.d.ts +43 -0
- package/src-shared/vendor/yaml/dist/public-api.js +104 -0
- package/src-shared/vendor/yaml/dist/schema/Schema.d.ts +18 -0
- package/src-shared/vendor/yaml/dist/schema/Schema.js +40 -0
- package/src-shared/vendor/yaml/dist/schema/common/map.d.ts +2 -0
- package/src-shared/vendor/yaml/dist/schema/common/map.js +19 -0
- package/src-shared/vendor/yaml/dist/schema/common/null.d.ts +4 -0
- package/src-shared/vendor/yaml/dist/schema/common/null.js +17 -0
- package/src-shared/vendor/yaml/dist/schema/common/seq.d.ts +2 -0
- package/src-shared/vendor/yaml/dist/schema/common/seq.js +19 -0
- package/src-shared/vendor/yaml/dist/schema/common/string.d.ts +2 -0
- package/src-shared/vendor/yaml/dist/schema/common/string.js +16 -0
- package/src-shared/vendor/yaml/dist/schema/core/bool.d.ts +4 -0
- package/src-shared/vendor/yaml/dist/schema/core/bool.js +21 -0
- package/src-shared/vendor/yaml/dist/schema/core/float.d.ts +4 -0
- package/src-shared/vendor/yaml/dist/schema/core/float.js +47 -0
- package/src-shared/vendor/yaml/dist/schema/core/int.d.ts +4 -0
- package/src-shared/vendor/yaml/dist/schema/core/int.js +42 -0
- package/src-shared/vendor/yaml/dist/schema/core/schema.d.ts +1 -0
- package/src-shared/vendor/yaml/dist/schema/core/schema.js +25 -0
- package/src-shared/vendor/yaml/dist/schema/json/schema.d.ts +2 -0
- package/src-shared/vendor/yaml/dist/schema/json/schema.js +64 -0
- package/src-shared/vendor/yaml/dist/schema/json-schema.d.ts +69 -0
- package/src-shared/vendor/yaml/dist/schema/tags.d.ts +40 -0
- package/src-shared/vendor/yaml/dist/schema/tags.js +86 -0
- package/src-shared/vendor/yaml/dist/schema/types.d.ts +90 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/binary.js +68 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/bool.js +29 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/float.js +50 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/int.js +76 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/omap.d.ts +28 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/omap.js +77 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/schema.js +39 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/set.js +96 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
- package/src-shared/vendor/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
- package/src-shared/vendor/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
- package/src-shared/vendor/yaml/dist/stringify/foldFlowLines.js +151 -0
- package/src-shared/vendor/yaml/dist/stringify/stringify.d.ts +21 -0
- package/src-shared/vendor/yaml/dist/stringify/stringify.js +127 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyCollection.js +145 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyComment.d.ts +10 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyComment.js +24 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyDocument.js +87 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyNumber.js +26 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyPair.d.ts +3 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyPair.js +152 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyString.d.ts +9 -0
- package/src-shared/vendor/yaml/dist/stringify/stringifyString.js +330 -0
- package/src-shared/vendor/yaml/dist/test-events.d.ts +4 -0
- package/src-shared/vendor/yaml/dist/test-events.js +134 -0
- package/src-shared/vendor/yaml/dist/util.d.ts +12 -0
- package/src-shared/vendor/yaml/dist/util.js +28 -0
- package/src-shared/vendor/yaml/dist/visit.d.ts +102 -0
- package/src-shared/vendor/yaml/dist/visit.js +236 -0
- package/src-shared/vendor/yaml/package.json +96 -0
- package/src-shared/vendor/yaml/util.js +2 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// Claude 桥接入口 — long-poll worker 模式。
|
|
2
|
+
//
|
|
3
|
+
// 核心流程:
|
|
4
|
+
// 1. preflight(claude 二进制 + 版本)
|
|
5
|
+
// 2. consume pair code 拿 (gw_id, bridge_token)
|
|
6
|
+
// 3. 起 relayWorker,进入 long-poll 主循环
|
|
7
|
+
// 4. 每条 in-flight user request:
|
|
8
|
+
// a. 抽 user text → spawn `claude --print` 子进程
|
|
9
|
+
// b. 写入 stdin(user message stream-json)
|
|
10
|
+
// c. 监听 stdout 行 → 直接以 {event:"chunk", data:<line>} 推回服务端
|
|
11
|
+
// 服务端 claude adapter 用 native stream-json 形态消化
|
|
12
|
+
// d. 子进程退出 → publish {event:"end"}
|
|
13
|
+
//
|
|
14
|
+
// 设计简化:long-poll 模式下 claude 子进程是"单次 turn"语义,不再持有跨 turn
|
|
15
|
+
// 的 SSE 订阅 / hookServer / 审批闸门。这些能力将在后续版本以"反向 worker push"
|
|
16
|
+
// 端点单独引入(与 long-poll 同一通道,但是另一类 request kind)。
|
|
17
|
+
|
|
18
|
+
import process from "node:process";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
|
|
21
|
+
import { createSessionSlot, SESSION_STATES } from "../../core/sessionSlot.mjs";
|
|
22
|
+
import { createRelayWorker } from "../../core/relayWorker.mjs";
|
|
23
|
+
import { bootstrapAgentlinkTools } from "../../core/agentlinkToolsBootstrap.mjs";
|
|
24
|
+
import { installAutoTunnel } from "../../core/autoTunnelWiring.mjs";
|
|
25
|
+
import { resolveSession } from "../../core/pairCodeClient.mjs";
|
|
26
|
+
import { createUsageReporter } from "../../core/usageReporter.mjs";
|
|
27
|
+
import { runWorkerWithRevokeHandling } from "../../core/bridgeSelfUninstall.mjs";
|
|
28
|
+
|
|
29
|
+
import { claudePreflight } from "./preflight.mjs";
|
|
30
|
+
import { createClaudeHandleRequest } from "./handleRequest.mjs";
|
|
31
|
+
import { createApprovalGateway } from "../../core/approvalGateway.mjs";
|
|
32
|
+
|
|
33
|
+
export async function runClaudeBridge({ options, positional, log }) {
|
|
34
|
+
const cwd = path.resolve(options.cwd || process.cwd());
|
|
35
|
+
|
|
36
|
+
// 1. preflight
|
|
37
|
+
const pre = claudePreflight({ log });
|
|
38
|
+
if (!pre.ok) {
|
|
39
|
+
process.stderr.write(`claude preflight failed: ${pre.error}\n`);
|
|
40
|
+
if (pre.hint) process.stderr.write(`${pre.hint}\n`);
|
|
41
|
+
process.exit(65);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 2. resolve session
|
|
45
|
+
let gwId, relayBase, bridgeToken;
|
|
46
|
+
try {
|
|
47
|
+
const r = await resolveSession({ runtime: "claude", options, log });
|
|
48
|
+
gwId = r.gwId;
|
|
49
|
+
relayBase = r.relayUrl;
|
|
50
|
+
bridgeToken = r.bridgeToken;
|
|
51
|
+
log.info("bridge.preflight.pass", "claude runtime entry reached", {
|
|
52
|
+
cwd, relay: relayBase, gw_id: gwId, source: r.source, has_bridge_token: !!bridgeToken,
|
|
53
|
+
});
|
|
54
|
+
} catch (err) {
|
|
55
|
+
process.stderr.write(`${err?.message || err}\n`);
|
|
56
|
+
process.exit(65);
|
|
57
|
+
}
|
|
58
|
+
if (!bridgeToken) {
|
|
59
|
+
process.stderr.write("缺少 bridge_token,请重新运行 agentlink pair <code> -r claude\n");
|
|
60
|
+
process.exit(65);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const sessLog = log.child({ gw: gwId });
|
|
64
|
+
|
|
65
|
+
// 5.1 实例化 approvalGateway(approval 模式下用于审批桥接)
|
|
66
|
+
const approvalGateway = createApprovalGateway({ log: sessLog });
|
|
67
|
+
// 5.4 approval 模式启动日志
|
|
68
|
+
const permissionMode = process.env.AGENTLINK_CLAUDE_PERMISSION_MODE || "bypassPermissions";
|
|
69
|
+
if (permissionMode === "approval" || permissionMode === "default") {
|
|
70
|
+
sessLog.info("bridge.approval_mode.enabled", "claude bridge approval mode enabled", {
|
|
71
|
+
permission_mode: permissionMode,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const worker = createRelayWorker({
|
|
76
|
+
relayUrl: relayBase, gwId, bridgeToken, runtime: "claude", log: sessLog,
|
|
77
|
+
});
|
|
78
|
+
installAutoTunnel({ relayUrl: relayBase, log: sessLog });
|
|
79
|
+
|
|
80
|
+
let lastRequestId = null;
|
|
81
|
+
const usage = createUsageReporter({
|
|
82
|
+
runtime: "claude", log: sessLog,
|
|
83
|
+
publishEvent: (event) => {
|
|
84
|
+
if (!lastRequestId) return Promise.resolve(false);
|
|
85
|
+
return worker.publishEvent(lastRequestId, event);
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
// Claude 4.x 默认 200k context window。token_count 事件 finalize 时会按实际值精确化。
|
|
89
|
+
usage.setContextWindow(200_000);
|
|
90
|
+
|
|
91
|
+
const slot = createSessionSlot({ log: sessLog, name: "claude" });
|
|
92
|
+
slot.transition(SESSION_STATES.READY, "worker-ready");
|
|
93
|
+
|
|
94
|
+
// 拉起 agentlinkToolsServer + 写 discovery 文件,让 4 个 runtime 的 MCP 客户端
|
|
95
|
+
// 都能通过 agentlink-mcp-stdio 访问 agentlink 自定义工具(change_title /
|
|
96
|
+
// notify_user / attach_file)。失败不致命:tools server 出问题不应该让 bridge
|
|
97
|
+
// 整体启动失败,只是 agentlink 工具暂时不可用。
|
|
98
|
+
let toolsLifecycle = null;
|
|
99
|
+
try {
|
|
100
|
+
toolsLifecycle = await bootstrapAgentlinkTools({
|
|
101
|
+
runtime: "claude", gwId, relayUrl: relayBase, bridgeToken,
|
|
102
|
+
worker, log: sessLog, version: pre?.version || "",
|
|
103
|
+
getLastRequestId: () => lastRequestId,
|
|
104
|
+
});
|
|
105
|
+
} catch (err) {
|
|
106
|
+
sessLog.warn("agentlink_tools.bootstrap.failed",
|
|
107
|
+
"agentlink tools server failed to start; continuing without tools", { err: err?.message });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let shuttingDown = false;
|
|
111
|
+
async function shutdown(reason) {
|
|
112
|
+
if (shuttingDown) return;
|
|
113
|
+
shuttingDown = true;
|
|
114
|
+
sessLog.info("bridge.shutdown", "shutting down", { reason });
|
|
115
|
+
worker.stop(reason);
|
|
116
|
+
try { usage.dispose(); } catch {}
|
|
117
|
+
if (toolsLifecycle?.stop) {
|
|
118
|
+
try { await toolsLifecycle.stop(); } catch {}
|
|
119
|
+
}
|
|
120
|
+
// 5.3 dispose approvalGateway:pending 审批全部 reject(bridge 关闭时防止 claude 子进程永久挂起)
|
|
121
|
+
try { approvalGateway.dispose("bridge-shutdown"); } catch {}
|
|
122
|
+
}
|
|
123
|
+
process.once("SIGINT", () => { void shutdown("SIGINT").then(() => process.exit(0)); });
|
|
124
|
+
process.once("SIGTERM", () => { void shutdown("SIGTERM").then(() => process.exit(0)); });
|
|
125
|
+
|
|
126
|
+
// ---- handler:每条 in-flight 请求一次完整 turn ----
|
|
127
|
+
// D-C2.3.3: 替换内联 handleRequest,改为 createClaudeHandleRequest 工厂函数
|
|
128
|
+
const _handleRequestImpl = createClaudeHandleRequest({
|
|
129
|
+
cwd,
|
|
130
|
+
log: sessLog,
|
|
131
|
+
usage,
|
|
132
|
+
bridgeCtx: {
|
|
133
|
+
version: pre?.version || "",
|
|
134
|
+
gwId,
|
|
135
|
+
model: null, // claude CLI 默认模型 bridge 没主动捕获,留空 → /model slash 走"未知"分支
|
|
136
|
+
},
|
|
137
|
+
dispatchHandlerOptions: {
|
|
138
|
+
relayUrl: relayBase,
|
|
139
|
+
bridgeToken,
|
|
140
|
+
// 5.2 传入 approvalGateway(approval 模式时生效)
|
|
141
|
+
approvalGateway,
|
|
142
|
+
},
|
|
143
|
+
scanner: toolsLifecycle?.scanner ?? null,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
async function handleRequest(request, ctx) {
|
|
147
|
+
lastRequestId = ctx.requestId;
|
|
148
|
+
return _handleRequestImpl(request, ctx);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
sessLog.info("bridge.loop.entered", "claude worker entering long-poll loop", {
|
|
152
|
+
gw_id: gwId, cwd, version: pre.version || "",
|
|
153
|
+
});
|
|
154
|
+
// 双向解绑:收到 App 端 deleteContact 触发的 HTTP 404 时自动清状态 + 卸 plist。
|
|
155
|
+
await runWorkerWithRevokeHandling({
|
|
156
|
+
worker, handler: handleRequest, runtime: "claude", log: sessLog,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// helpers 已移入 handleRequest.mjs
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* internalCommandNames.mjs
|
|
3
|
+
*
|
|
4
|
+
* 导出 claude 内置命令名集合的只读引用,供 customCommandsCollector 计算差集。
|
|
5
|
+
* 与 slashCommandRouter.mjs 保持同步——每次新增/删除内置命令时两处都要更新。
|
|
6
|
+
*
|
|
7
|
+
* 注:不直接从 slashCommandRouter 导入是为了避免循环依赖(router 同时依赖 cliExec,
|
|
8
|
+
* 而 cliExec 有 spawn 副作用,单元测试不希望引入)。
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* claude CLI 在 `--print --input-format stream-json` 下真实执行的命令(透传)。
|
|
13
|
+
* 同步自 slashCommandRouter.mjs CLAUDE_CLI_HANDLED。
|
|
14
|
+
*/
|
|
15
|
+
export const CLAUDE_CLI_HANDLED = new Set([
|
|
16
|
+
"/compact",
|
|
17
|
+
"/context",
|
|
18
|
+
"/init",
|
|
19
|
+
"/review",
|
|
20
|
+
"/security-review",
|
|
21
|
+
"/cost",
|
|
22
|
+
"/usage",
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* TUI 对齐命令——改写为自然语言 prompt 真跑。
|
|
27
|
+
* 同步自 slashCommandRouter.mjs CLAUDE_PROMPT_REWRITES(仅键名)。
|
|
28
|
+
*/
|
|
29
|
+
export const CLAUDE_PROMPT_REWRITES = {
|
|
30
|
+
"/diff": true,
|
|
31
|
+
"/recap": true,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* bridge 有等价合成实现的命令(含 __default__)。
|
|
36
|
+
* 同步自 slashCommandRouter.mjs CLAUDE_HANDLERS(仅键名)。
|
|
37
|
+
*/
|
|
38
|
+
export const CLAUDE_HANDLERS = {
|
|
39
|
+
"/help": true,
|
|
40
|
+
"/status": true,
|
|
41
|
+
"/model": true,
|
|
42
|
+
"/version": true,
|
|
43
|
+
"/agents": true,
|
|
44
|
+
"/skills": true,
|
|
45
|
+
"/memory": true,
|
|
46
|
+
"/permissions": true,
|
|
47
|
+
"/resume": true,
|
|
48
|
+
"/rewind": true,
|
|
49
|
+
"/branch": true,
|
|
50
|
+
"/config": true,
|
|
51
|
+
"/hooks": true,
|
|
52
|
+
"/mcp": true,
|
|
53
|
+
"/doctor": true,
|
|
54
|
+
"/export": true,
|
|
55
|
+
"/rename": true,
|
|
56
|
+
"/feedback": true,
|
|
57
|
+
"__default__": true,
|
|
58
|
+
};
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
// Claude 子进程启动器。
|
|
2
|
+
//
|
|
3
|
+
// 直接 spawn `claude` 二进制(而不是 happy-cli 风格的 node + wrapper)——
|
|
4
|
+
// 依赖少、跨平台干净。stream-json 模式下 stdin/stdout 是标准 JSON 行。
|
|
5
|
+
//
|
|
6
|
+
// stdin 格式(Claude 接受):
|
|
7
|
+
// {"type":"user","message":{"role":"user","content":[{"type":"text","text":"..."}]}}\n
|
|
8
|
+
//
|
|
9
|
+
// stdout 格式见 stdoutParser.mjs。
|
|
10
|
+
//
|
|
11
|
+
// 生命周期由 caller (sessionManager) 控制。launcher 只管起、终、管道。
|
|
12
|
+
|
|
13
|
+
import { spawn } from "node:child_process";
|
|
14
|
+
import process from "node:process";
|
|
15
|
+
import { fetchAndBase64Encode } from "../_shared/fetchAndBase64Encode.mjs";
|
|
16
|
+
import { relayObjectToBlock } from "../_shared/relayObjectToBlock.mjs";
|
|
17
|
+
|
|
18
|
+
const DEFAULT_ARGS = [
|
|
19
|
+
"--print", // 打印完成后自动退出(而非交互 REPL)
|
|
20
|
+
"--verbose", // stream-json 需要 verbose
|
|
21
|
+
"--output-format", "stream-json",
|
|
22
|
+
"--input-format", "stream-json",
|
|
23
|
+
// 不加这个 flag 时,claude CLI 会把整段 assistant 攒成一条 stream-json 行
|
|
24
|
+
// 在末尾才吐 → App 端表现是"憋一下整段刷出来"。开启后 claude 会以
|
|
25
|
+
// stream_event 形式(content_block_delta + text_delta)逐 token 推送,
|
|
26
|
+
// stdoutParser 把它翻译成 assistant_text 增量,flusher 一条一发,
|
|
27
|
+
// App SSE 拿到一条渲染一条 → 真正的流式体验。
|
|
28
|
+
"--include-partial-messages",
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 启动 claude 子进程并返回 { child, kill }。
|
|
33
|
+
* @param {{ cwd: string, resumeSessionId?: string, extraArgs?: string[], env?: object, log: any, signal?: AbortSignal }} opts
|
|
34
|
+
*/
|
|
35
|
+
export function spawnClaude(opts) {
|
|
36
|
+
const { cwd, resumeSessionId, extraArgs = [], env, log, signal, cwdSource } = opts;
|
|
37
|
+
if (!log) throw new Error("spawnClaude: log required");
|
|
38
|
+
if (!cwd) throw new Error("spawnClaude: cwd required");
|
|
39
|
+
|
|
40
|
+
const isWin = process.platform === "win32";
|
|
41
|
+
|
|
42
|
+
const args = [...DEFAULT_ARGS];
|
|
43
|
+
// P0#16/#26: --print 模式下没有 canUseTool 桥接,default 权限模式会把需授权
|
|
44
|
+
// 的工具(WebSearch / Bash 写操作等)直接拒绝("This command requires
|
|
45
|
+
// approval"),而 App 端没有任何审批弹窗可弹。按产品既有口径(bridge /help、
|
|
46
|
+
// /permissions 文案承诺的默认 bypassPermissions)显式传参;需要更严格模式时
|
|
47
|
+
// 用 AGENTLINK_CLAUDE_PERMISSION_MODE 覆盖:
|
|
48
|
+
// - "bypassPermissions"(默认):跳过所有权限检查。
|
|
49
|
+
// - "inherit":不传 --permission-mode,沿用 claude 本机配置。
|
|
50
|
+
// - "approval"/"default":启用审批弹窗模式(permission-prompt-tool MCP 桥接)。
|
|
51
|
+
// 此模式下 handleRequest.mjs 额外注入:
|
|
52
|
+
// --permission-mode default
|
|
53
|
+
// --permission-prompt-tool mcp__agentlink-permission__agentlink_permission_prompt
|
|
54
|
+
// --setting-sources project
|
|
55
|
+
// --mcp-config <tmp-file>
|
|
56
|
+
// ⚠️ 副作用:--setting-sources project 排除用户级(~/.claude/settings.json)的
|
|
57
|
+
// 工具 allow 规则(如 Bash(*))。如需在 approval 模式下自动放行某些工具,
|
|
58
|
+
// 请在工作区的 .claude/settings.json 中配置而非 ~/.claude/settings.json。
|
|
59
|
+
// extraArgs(由 handleRequest.mjs approval 模式注入)优先于此处的 --permission-mode。
|
|
60
|
+
const permissionMode = process.env.AGENTLINK_CLAUDE_PERMISSION_MODE || "bypassPermissions";
|
|
61
|
+
// approval/default 模式由 handleRequest.mjs 通过 extraArgs 注入完整参数;
|
|
62
|
+
// 此处只处理 bypass / inherit / 其他标准模式。
|
|
63
|
+
const isApprovalModeExternal = permissionMode === "approval" || permissionMode === "default";
|
|
64
|
+
if (!isApprovalModeExternal && permissionMode !== "inherit") args.push("--permission-mode", permissionMode);
|
|
65
|
+
if (resumeSessionId) args.push("--resume", resumeSessionId);
|
|
66
|
+
for (const a of extraArgs) args.push(a);
|
|
67
|
+
|
|
68
|
+
const mergedEnv = { ...process.env, ...(env || {}) };
|
|
69
|
+
// 防止 claude 自己再注册 SIGINT → 子进程退出时 parent 收到多余信号
|
|
70
|
+
// 交给 sessionManager 精确控制
|
|
71
|
+
|
|
72
|
+
const child = spawn("claude", args, {
|
|
73
|
+
cwd,
|
|
74
|
+
env: mergedEnv,
|
|
75
|
+
// stdio: [stdin, stdout, stderr]
|
|
76
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
77
|
+
shell: isWin ? true : false,
|
|
78
|
+
windowsHide: true,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const cLog = log.child({ comp: "child", pid: child.pid });
|
|
82
|
+
cLog.info("child.spawn", "claude spawned", {
|
|
83
|
+
cwd, args: args.join(" "), resume: resumeSessionId || null,
|
|
84
|
+
source: cwdSource || "default",
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// 将 stderr 尾部周期性上报 —— 仅在出现问题时。存入一个 ring buffer。
|
|
88
|
+
const stderrRing = createRing(4096);
|
|
89
|
+
child.stderr.on("data", (buf) => stderrRing.push(buf.toString("utf8")));
|
|
90
|
+
|
|
91
|
+
// 外部 signal 触发 kill
|
|
92
|
+
if (signal) {
|
|
93
|
+
if (signal.aborted) {
|
|
94
|
+
safeKill(child, cLog, "aborted-before-spawn");
|
|
95
|
+
} else {
|
|
96
|
+
signal.addEventListener("abort", () => safeKill(child, cLog, "signal-abort"), { once: true });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let exited = false;
|
|
101
|
+
child.once("exit", (code, sig) => {
|
|
102
|
+
exited = true;
|
|
103
|
+
cLog.info("child.exit", "claude exited", {
|
|
104
|
+
code, signal: sig, stderr_tail: stderrRing.tail(800),
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
child.once("error", (err) => {
|
|
108
|
+
cLog.error("child.error", "claude emit error", {
|
|
109
|
+
err: err?.message || String(err), code: err?.code || "",
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
child,
|
|
115
|
+
getStderrTail: (n = 800) => stderrRing.tail(n),
|
|
116
|
+
isExited: () => exited,
|
|
117
|
+
kill: (reason = "manual") => safeKill(child, cLog, reason),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* safeKill:先 SIGTERM,2s 未死再 SIGKILL。Windows 上两者都走 taskkill。
|
|
123
|
+
*/
|
|
124
|
+
function safeKill(child, log, reason) {
|
|
125
|
+
if (!child || child.killed) return;
|
|
126
|
+
try {
|
|
127
|
+
log.info("child.kill.term", "sending SIGTERM", { reason });
|
|
128
|
+
child.kill("SIGTERM");
|
|
129
|
+
} catch (err) {
|
|
130
|
+
log.warn("child.kill.term.failed", "SIGTERM failed", { err: err?.message || String(err) });
|
|
131
|
+
}
|
|
132
|
+
const deadline = setTimeout(() => {
|
|
133
|
+
if (child.exitCode === null && !child.killed) {
|
|
134
|
+
log.warn("child.kill.force", "SIGKILL after timeout", { reason });
|
|
135
|
+
try { child.kill("SIGKILL"); } catch {}
|
|
136
|
+
}
|
|
137
|
+
}, 2000);
|
|
138
|
+
deadline.unref?.();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function createRing(capacity) {
|
|
142
|
+
let buf = "";
|
|
143
|
+
return {
|
|
144
|
+
push(s) {
|
|
145
|
+
buf += s;
|
|
146
|
+
if (buf.length > capacity) buf = buf.slice(-capacity);
|
|
147
|
+
},
|
|
148
|
+
tail(n) {
|
|
149
|
+
return buf.slice(-n);
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* 向 claude stdin 写 AskUserQuestion 的 tool_result 回填消息。
|
|
156
|
+
* stream-json 协议:一行 JSON,紧跟 \n。
|
|
157
|
+
*
|
|
158
|
+
* Claude SDK 要求 AskUserQuestion tool_result 格式:
|
|
159
|
+
* content[0].type = "tool_result"
|
|
160
|
+
* content[0].tool_use_id = <被拦截工具的 tool_id>
|
|
161
|
+
* content[0].content[0].type = "text"
|
|
162
|
+
* content[0].content[0].text = JSON.stringify({ questions, answers })
|
|
163
|
+
*
|
|
164
|
+
* @param {object} child claude 子进程
|
|
165
|
+
* @param {string} toolUseId AskUserQuestion 的 tool_id
|
|
166
|
+
* @param {object} value 回填内容({ questions, answers } 或 { questions, canceled: true })
|
|
167
|
+
*/
|
|
168
|
+
export function writeToolResult(child, toolUseId, value) {
|
|
169
|
+
if (!child || !child.stdin || child.stdin.destroyed) {
|
|
170
|
+
throw new Error("writeToolResult: stdin not available");
|
|
171
|
+
}
|
|
172
|
+
const payload = {
|
|
173
|
+
type: "user",
|
|
174
|
+
message: {
|
|
175
|
+
role: "user",
|
|
176
|
+
content: [
|
|
177
|
+
{
|
|
178
|
+
type: "tool_result",
|
|
179
|
+
tool_use_id: toolUseId,
|
|
180
|
+
content: [
|
|
181
|
+
{
|
|
182
|
+
type: "text",
|
|
183
|
+
text: JSON.stringify(value),
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
const line = JSON.stringify(payload) + "\n";
|
|
191
|
+
return new Promise((resolve, reject) => {
|
|
192
|
+
child.stdin.write(line, (err) => (err ? reject(err) : resolve()));
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* 向 claude stdin 写一条 user message。
|
|
198
|
+
* stream-json 协议:一行 JSON,紧跟 \n。
|
|
199
|
+
*
|
|
200
|
+
* Phase 5 (multimodal-attachment-llm-dispatch): 迁移到 relayObjectToBlock 共享模块。
|
|
201
|
+
* 通过 relayObjectToBlock 处理 relay_object blocks(含 attachment_kind 字段),
|
|
202
|
+
* 并将结果转换为 Anthropic Messages API 格式。
|
|
203
|
+
*
|
|
204
|
+
* content array 构造规则(Anthropic Messages API 格式):
|
|
205
|
+
* 1. 若 text 非空,加 {type:"text", text} block
|
|
206
|
+
* 2. 遍历 blocks 中 source.kind=url 的 relay_object block,通过 relayObjectToBlock 转换:
|
|
207
|
+
* - input_image → {type:"image", source:{type:"base64", media_type, data}}
|
|
208
|
+
* - input_file → {type:"document", source:{type:"base64", media_type, data}}
|
|
209
|
+
* - input_text → {type:"text", text}
|
|
210
|
+
* - error → {type:"text", text:"[<kind>] (encoding failed: <error>)"}
|
|
211
|
+
* 3. 后向兼容:非 relay_object blocks(source.kind≠url)被忽略
|
|
212
|
+
* 纯图片/纯 PDF 场景(text 为空):content array 只含对应 block,不含空 text block
|
|
213
|
+
*
|
|
214
|
+
* @param {object} child - claude 子进程
|
|
215
|
+
* @param {string} text - 用户文字 prompt
|
|
216
|
+
* @param {any[]} blocks - dispatch payload blocks 数组(可选)
|
|
217
|
+
* @param {{ _fetchAndBase64Encode?: Function }} opts - 注入选项(测试用)
|
|
218
|
+
*/
|
|
219
|
+
export async function writeUserMessage(child, text, blocks = [], { _fetchAndBase64Encode } = {}) {
|
|
220
|
+
if (!child || !child.stdin || child.stdin.destroyed) {
|
|
221
|
+
throw new Error("writeUserMessage: stdin not available");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const doFetchAndBase64 = _fetchAndBase64Encode ?? fetchAndBase64Encode;
|
|
225
|
+
|
|
226
|
+
const content = [];
|
|
227
|
+
|
|
228
|
+
// 1. text block(非空时)
|
|
229
|
+
if (text) {
|
|
230
|
+
content.push({ type: "text", text: String(text) });
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// 2. relay_object blocks(type=image または type=attachment、source.kind=url)
|
|
234
|
+
// → relayObjectToBlock → Anthropic Messages API 形式に変換
|
|
235
|
+
// claude は全 modalities 対応なので modelCaps を最大に設定
|
|
236
|
+
// type=video / type=text 等の非 relay_object block は除外する
|
|
237
|
+
const relayBlocks = (blocks ?? []).filter(
|
|
238
|
+
(b) =>
|
|
239
|
+
(b?.type === "image" || b?.type === "attachment") &&
|
|
240
|
+
b?.source?.kind === "url" &&
|
|
241
|
+
b?.source?.url,
|
|
242
|
+
);
|
|
243
|
+
for (const block of relayBlocks) {
|
|
244
|
+
const result = await relayObjectToBlock(block, {
|
|
245
|
+
runtimeHint: "claude",
|
|
246
|
+
modelCaps: ["text", "image", "pdf"],
|
|
247
|
+
fetchAndBase64Encode: doFetchAndBase64,
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
if (result.error) {
|
|
251
|
+
// エラーはフォールバック text block にする(既存の動作と一致)
|
|
252
|
+
const name = block?.name ?? block?.source?.media_type ?? "file";
|
|
253
|
+
content.push({
|
|
254
|
+
type: "text",
|
|
255
|
+
text: `[${block?.type === "image" ? "image" : `file: ${name}`}] (encoding failed: ${result.error.message})`,
|
|
256
|
+
});
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// input_text(PDF text fallback 含む)のうち "PDF content could not be extracted" を
|
|
261
|
+
// "encoding failed" に変換して既存テストとの互換性を保つ
|
|
262
|
+
if (result.type === "input_text" && result.text.includes("PDF content could not be extracted")) {
|
|
263
|
+
const name = block?.name ?? "file.pdf";
|
|
264
|
+
content.push({
|
|
265
|
+
type: "text",
|
|
266
|
+
text: `[file: ${name}] (encoding failed: PDF content could not be extracted)`,
|
|
267
|
+
});
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// relayObjectToBlock の結果を Anthropic Messages API 形式に変換
|
|
272
|
+
switch (result.type) {
|
|
273
|
+
case "input_image":
|
|
274
|
+
content.push({
|
|
275
|
+
type: "image",
|
|
276
|
+
source: result.source,
|
|
277
|
+
});
|
|
278
|
+
break;
|
|
279
|
+
case "input_file":
|
|
280
|
+
content.push({
|
|
281
|
+
type: "document",
|
|
282
|
+
source: result.source,
|
|
283
|
+
});
|
|
284
|
+
break;
|
|
285
|
+
case "input_text":
|
|
286
|
+
content.push({ type: "text", text: result.text });
|
|
287
|
+
break;
|
|
288
|
+
case "url_ref":
|
|
289
|
+
// picoclaw only — claude runtime never returns url_ref from relayObjectToBlock;
|
|
290
|
+
// if this branch is somehow hit, drop to a safe description with NO URL in LLM context
|
|
291
|
+
// (铁律 #1: signed URL must not appear in LLM input). (CR-003)
|
|
292
|
+
content.push({ type: "text", text: `[image] (preview unavailable for this runtime)` });
|
|
293
|
+
break;
|
|
294
|
+
default:
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// 纯文字回退:如果 content 为空(text 为空且没有 blocks),加空 text block
|
|
300
|
+
// 保持与旧路径兼容(claude 需要至少一个 content block)
|
|
301
|
+
if (content.length === 0) {
|
|
302
|
+
content.push({ type: "text", text: "" });
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const payload = {
|
|
306
|
+
type: "user",
|
|
307
|
+
message: { role: "user", content },
|
|
308
|
+
};
|
|
309
|
+
const line = JSON.stringify(payload) + "\n";
|
|
310
|
+
return new Promise((resolve, reject) => {
|
|
311
|
+
child.stdin.write(line, (err) => (err ? reject(err) : resolve()));
|
|
312
|
+
});
|
|
313
|
+
}
|