aws-runtime-bridge 1.9.79 → 1.9.81
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/adapter/AcodeSdkAdapter.d.ts +0 -1
- package/dist/adapter/AcodeSdkAdapter.js +11 -1986
- package/dist/adapter/AdapterRegistry.d.ts +0 -1
- package/dist/adapter/AdapterRegistry.js +2 -100
- package/dist/adapter/ClaudeSdkAdapter.d.ts +0 -1
- package/dist/adapter/ClaudeSdkAdapter.js +4 -1300
- package/dist/adapter/CodexSdkAdapter.d.ts +0 -1
- package/dist/adapter/CodexSdkAdapter.js +4 -836
- package/dist/adapter/OpencodeSdkAdapter.d.ts +0 -1
- package/dist/adapter/OpencodeSdkAdapter.js +4 -879
- package/dist/adapter/SdkProviderSpi.d.ts +0 -1
- package/dist/adapter/SdkProviderSpi.js +2 -55
- package/dist/adapter/acode-tool-names.d.ts +0 -1
- package/dist/adapter/acode-tool-names.js +2 -37
- package/dist/adapter/idle-poll-loop.d.ts +0 -1
- package/dist/adapter/idle-poll-loop.js +2 -59
- package/dist/adapter/index.d.ts +0 -1
- package/dist/adapter/index.js +2 -11
- package/dist/adapter/instance-ai-config-resolver.d.ts +0 -1
- package/dist/adapter/instance-ai-config-resolver.js +2 -46
- package/dist/adapter/types.d.ts +0 -1
- package/dist/adapter/types.js +2 -443
- package/dist/adapters/cc-switch/common.d.ts +0 -1
- package/dist/adapters/cc-switch/common.js +2 -61
- package/dist/adapters/cc-switch/index.d.ts +0 -1
- package/dist/adapters/cc-switch/index.js +2 -57
- package/dist/adapters/cc-switch/mcp-acode.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-acode.js +2 -71
- package/dist/adapters/cc-switch/mcp-claude.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-claude.js +2 -89
- package/dist/adapters/cc-switch/mcp-claudecode.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-claudecode.js +2 -77
- package/dist/adapters/cc-switch/mcp-codex.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-codex.js +11 -249
- package/dist/adapters/cc-switch/mcp-opencode.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-opencode.js +2 -97
- package/dist/adapters/cc-switch/mcp-placeholder.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-placeholder.js +2 -19
- package/dist/adapters/cc-switch/skill-acode.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-acode.js +2 -12
- package/dist/adapters/cc-switch/skill-claude.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-claude.js +2 -11
- package/dist/adapters/cc-switch/skill-claudecode.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-claudecode.js +2 -11
- package/dist/adapters/cc-switch/skill-codex.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-codex.js +2 -6
- package/dist/adapters/cc-switch/skill-directory.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-directory.js +3 -137
- package/dist/adapters/cc-switch/skill-opencode.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-opencode.js +2 -11
- package/dist/adapters/cc-switch/skill-placeholder.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-placeholder.js +2 -19
- package/dist/config.d.ts +0 -1
- package/dist/config.js +2 -290
- package/dist/index.d.ts +0 -1
- package/dist/index.js +2 -573
- package/dist/middleware/auth.d.ts +0 -1
- package/dist/middleware/auth.js +2 -98
- package/dist/routes/acode-todos.d.ts +0 -1
- package/dist/routes/acode-todos.js +2 -75
- package/dist/routes/ai-sources.d.ts +0 -1
- package/dist/routes/ai-sources.js +2 -132
- package/dist/routes/dashboard.d.ts +0 -1
- package/dist/routes/dashboard.js +182 -649
- package/dist/routes/events.d.ts +0 -1
- package/dist/routes/events.js +2 -22
- package/dist/routes/file-browser.d.ts +0 -1
- package/dist/routes/file-browser.js +2 -781
- package/dist/routes/file-diff-rollback.d.ts +0 -1
- package/dist/routes/file-diff-rollback.js +2 -301
- package/dist/routes/file-snapshot.d.ts +0 -1
- package/dist/routes/file-snapshot.js +2 -156
- package/dist/routes/git.d.ts +0 -1
- package/dist/routes/git.js +28 -1900
- package/dist/routes/instance.d.ts +0 -1
- package/dist/routes/instance.js +3 -748
- package/dist/routes/mcp.d.ts +0 -1
- package/dist/routes/mcp.js +2 -196
- package/dist/routes/processes.d.ts +0 -1
- package/dist/routes/processes.js +2 -252
- package/dist/routes/properties.d.ts +0 -1
- package/dist/routes/properties.js +2 -72
- package/dist/routes/pty.d.ts +0 -1
- package/dist/routes/pty.js +6 -560
- package/dist/routes/runtime-binding.d.ts +0 -1
- package/dist/routes/runtime-binding.js +2 -263
- package/dist/routes/sessions.d.ts +0 -1
- package/dist/routes/sessions.js +2 -758
- package/dist/routes/skills.d.ts +0 -1
- package/dist/routes/skills.js +2 -187
- package/dist/routes/sub-agents.d.ts +0 -1
- package/dist/routes/sub-agents.js +20 -279
- package/dist/routes/system-metrics.d.ts +0 -1
- package/dist/routes/system-metrics.js +2 -20
- package/dist/routes/task-context.d.ts +0 -1
- package/dist/routes/task-context.js +2 -78
- package/dist/routes/terminal.d.ts +0 -1
- package/dist/routes/terminal.js +54 -2882
- package/dist/routes/yml.d.ts +0 -1
- package/dist/routes/yml.js +2 -223
- package/dist/services/acode-package.d.ts +0 -1
- package/dist/services/acode-package.js +2 -111
- package/dist/services/agent-event-store.d.ts +0 -1
- package/dist/services/agent-event-store.js +2 -81
- package/dist/services/agent-process-manager.d.ts +0 -1
- package/dist/services/agent-process-manager.js +2 -796
- package/dist/services/ai-source-apply.d.ts +0 -1
- package/dist/services/ai-source-apply.js +2 -83
- package/dist/services/auto-register.d.ts +5 -1
- package/dist/services/auto-register.js +2 -1053
- package/dist/services/aws-client-agent-mcp.d.ts +0 -1
- package/dist/services/aws-client-agent-mcp.js +3 -337
- package/dist/services/bridge-package-publish-hooks.d.ts +0 -1
- package/dist/services/bridge-package-publish-hooks.js +2 -115
- package/dist/services/cc-switch-sdk.d.ts +0 -1
- package/dist/services/cc-switch-sdk.js +2 -135
- package/dist/services/cli-commands.d.ts +6 -1
- package/dist/services/cli-commands.js +6 -645
- package/dist/services/event-delta-pusher.d.ts +0 -1
- package/dist/services/event-delta-pusher.js +2 -95
- package/dist/services/fileSnapshotStore.d.ts +0 -1
- package/dist/services/fileSnapshotStore.js +2 -500
- package/dist/services/instance-ai-config-service.d.ts +0 -1
- package/dist/services/instance-ai-config-service.js +2 -174
- package/dist/services/instance-init-service.d.ts +0 -1
- package/dist/services/instance-init-service.js +2 -193
- package/dist/services/instance-service.d.ts +0 -1
- package/dist/services/instance-service.js +2 -237
- package/dist/services/instance-state.d.ts +0 -1
- package/dist/services/instance-state.js +2 -94
- package/dist/services/legacy-path-migration.d.ts +0 -1
- package/dist/services/legacy-path-migration.js +2 -66
- package/dist/services/lifecycle-state.d.ts +0 -1
- package/dist/services/lifecycle-state.js +3 -110
- package/dist/services/mcp-launch-binding-queue.d.ts +0 -1
- package/dist/services/mcp-launch-binding-queue.js +2 -175
- package/dist/services/orphan-monitor.d.ts +0 -1
- package/dist/services/orphan-monitor.js +2 -382
- package/dist/services/panel-auth.d.ts +0 -1
- package/dist/services/panel-auth.js +2 -168
- package/dist/services/process-detector.d.ts +0 -1
- package/dist/services/process-detector.js +18 -1019
- package/dist/services/process-registry.d.ts +0 -1
- package/dist/services/process-registry.js +2 -375
- package/dist/services/ring-buffer.d.ts +0 -1
- package/dist/services/ring-buffer.js +2 -103
- package/dist/services/runtime-binding.d.ts +0 -1
- package/dist/services/runtime-binding.js +6 -363
- package/dist/services/runtime-lifecycle-policy.d.ts +0 -1
- package/dist/services/runtime-lifecycle-policy.js +2 -35
- package/dist/services/session-output.d.ts +0 -1
- package/dist/services/session-output.js +5 -539
- package/dist/services/startup-config-wizard.d.ts +0 -1
- package/dist/services/startup-config-wizard.js +14 -258
- package/dist/services/sub-agent-manager-instance.d.ts +0 -1
- package/dist/services/sub-agent-manager-instance.js +2 -12
- package/dist/services/system-metrics.d.ts +0 -1
- package/dist/services/system-metrics.js +2 -252
- package/dist/services/terminal-persistence.d.ts +0 -1
- package/dist/services/terminal-persistence.js +2 -176
- package/dist/services/tool-installer.d.ts +0 -1
- package/dist/services/tool-installer.js +5 -751
- package/dist/services/tunnel-client.d.ts +0 -1
- package/dist/services/tunnel-client.js +2 -402
- package/dist/services/windows-service-manager.d.ts +3 -3
- package/dist/services/windows-service-manager.js +2 -59
- package/dist/services/workspace-files.d.ts +0 -1
- package/dist/services/workspace-files.js +2 -1275
- package/dist/services/workspace-watch.d.ts +0 -1
- package/dist/services/workspace-watch.js +2 -123
- package/dist/services/workspaceTaskChangeWatcher.d.ts +0 -1
- package/dist/services/workspaceTaskChangeWatcher.js +2 -483
- package/dist/types.d.ts +0 -1
- package/dist/types.js +1 -1
- package/dist/utils/file-utils.d.ts +0 -1
- package/dist/utils/file-utils.js +3 -208
- package/dist/utils/instance-ai-config-debug-logger.d.ts +0 -1
- package/dist/utils/instance-ai-config-debug-logger.js +4 -63
- package/dist/utils/logger.d.ts +0 -1
- package/dist/utils/logger.js +2 -154
- package/dist/utils/mcp-utils.d.ts +0 -1
- package/dist/utils/mcp-utils.js +2 -187
- package/dist/utils/path-utils.d.ts +0 -1
- package/dist/utils/path-utils.js +2 -44
- package/dist/utils/sdk-package-loader.d.ts +0 -1
- package/dist/utils/sdk-package-loader.js +2 -78
- package/dist/utils/validation.d.ts +0 -1
- package/dist/utils/validation.js +2 -53
- package/dist/utils/yaml-utils.d.ts +0 -1
- package/dist/utils/yaml-utils.js +2 -312
- package/node_modules/@cc-switch/sdk/dist/constants.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/constants.js +2 -63
- package/node_modules/@cc-switch/sdk/dist/errors.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/errors.js +2 -8
- package/node_modules/@cc-switch/sdk/dist/index.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/index.js +2 -9
- package/node_modules/@cc-switch/sdk/dist/schemas.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/schemas.js +2 -38
- package/node_modules/@cc-switch/sdk/dist/sdk.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/sdk.js +2 -470
- package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.js +4 -307
- package/node_modules/@cc-switch/sdk/dist/services/mcp-model.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/mcp-model.js +2 -37
- package/node_modules/@cc-switch/sdk/dist/services/mcp-service.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/mcp-service.js +2 -9
- package/node_modules/@cc-switch/sdk/dist/services/skill-model.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/skill-model.js +2 -41
- package/node_modules/@cc-switch/sdk/dist/services/skill-service.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/skill-service.js +2 -9
- package/node_modules/@cc-switch/sdk/dist/state.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/state.js +2 -19
- package/node_modules/@cc-switch/sdk/dist/types.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/types.js +1 -1
- package/node_modules/@cc-switch/sdk/dist/utils/fs.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/utils/fs.js +3 -114
- package/node_modules/@cc-switch/sdk/dist/utils/id.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/utils/id.js +2 -12
- package/node_modules/@cc-switch/sdk/package.json +1 -1
- package/package/acode/dist/ask-user-question-tool.d.ts +0 -1
- package/package/acode/dist/ask-user-question-tool.js +4 -233
- package/package/acode/dist/built-in-file-tools.d.ts +0 -1
- package/package/acode/dist/built-in-file-tools.js +4 -966
- package/package/acode/dist/built-in-symbols-tool.d.ts +0 -1
- package/package/acode/dist/built-in-symbols-tool.js +2 -117
- package/package/acode/dist/builtins/commandArtifacts.d.ts +0 -1
- package/package/acode/dist/builtins/commandArtifacts.js +9 -97
- package/package/acode/dist/builtins/commandOutputEvents.d.ts +0 -1
- package/package/acode/dist/builtins/commandOutputEvents.js +2 -56
- package/package/acode/dist/builtins/shellCommandPreparation.d.ts +0 -1
- package/package/acode/dist/builtins/shellCommandPreparation.js +5 -44
- package/package/acode/dist/builtins/shellCommandResult.d.ts +0 -1
- package/package/acode/dist/builtins/shellCommandResult.js +2 -71
- package/package/acode/dist/builtins/shellCommandRunner.d.ts +0 -1
- package/package/acode/dist/builtins/shellCommandRunner.js +2 -115
- package/package/acode/dist/builtins/shellOutputDecoder.d.ts +0 -1
- package/package/acode/dist/builtins/shellOutputDecoder.js +2 -94
- package/package/acode/dist/cli.d.ts +0 -1
- package/package/acode/dist/cli.js +4 -38
- package/package/acode/dist/commands/commandLoader.d.ts +0 -1
- package/package/acode/dist/commands/commandLoader.js +2 -33
- package/package/acode/dist/commands/commandParser.d.ts +0 -1
- package/package/acode/dist/commands/commandParser.js +3 -77
- package/package/acode/dist/commands/commandRegistry.d.ts +0 -1
- package/package/acode/dist/commands/commandRegistry.js +2 -30
- package/package/acode/dist/compaction.d.ts +0 -1
- package/package/acode/dist/compaction.js +7 -919
- package/package/acode/dist/config.d.ts +0 -1
- package/package/acode/dist/config.js +5 -105
- package/package/acode/dist/fs-utils.d.ts +0 -1
- package/package/acode/dist/fs-utils.js +2 -79
- package/package/acode/dist/hooks/hookBus.d.ts +0 -1
- package/package/acode/dist/hooks/hookBus.js +2 -40
- package/package/acode/dist/index.d.ts +0 -1
- package/package/acode/dist/index.js +2 -19
- package/package/acode/dist/mcpToolNames.d.ts +0 -1
- package/package/acode/dist/mcpToolNames.js +2 -17
- package/package/acode/dist/parsers/ast-cache.d.ts +0 -1
- package/package/acode/dist/parsers/ast-cache.js +2 -76
- package/package/acode/dist/parsers/language-detector.d.ts +0 -1
- package/package/acode/dist/parsers/language-detector.js +2 -44
- package/package/acode/dist/parsers/language-queries.d.ts +0 -1
- package/package/acode/dist/parsers/language-queries.js +12 -602
- package/package/acode/dist/parsers/symbol-extractor.d.ts +0 -1
- package/package/acode/dist/parsers/symbol-extractor.js +3 -164
- package/package/acode/dist/parsers/tree-sitter-loader.d.ts +0 -1
- package/package/acode/dist/parsers/tree-sitter-loader.js +2 -64
- package/package/acode/dist/parsers/types.d.ts +0 -1
- package/package/acode/dist/parsers/types.js +1 -7
- package/package/acode/dist/runtime.d.ts +0 -1
- package/package/acode/dist/runtime.js +86 -3771
- package/package/acode/dist/skill-tool.d.ts +0 -1
- package/package/acode/dist/skill-tool.js +5 -174
- package/package/acode/dist/sub-agent-manager.d.ts +0 -1
- package/package/acode/dist/sub-agent-manager.js +2 -1159
- package/package/acode/dist/sub-agent-store.d.ts +0 -1
- package/package/acode/dist/sub-agent-store.js +4 -236
- package/package/acode/dist/sub-agent-tools.d.ts +0 -1
- package/package/acode/dist/sub-agent-tools.js +15 -369
- package/package/acode/dist/sub-agent-types.d.ts +0 -1
- package/package/acode/dist/sub-agent-types.js +1 -8
- package/package/acode/dist/todo-store.d.ts +0 -1
- package/package/acode/dist/todo-store.js +2 -73
- package/package/acode/dist/todo-tool.d.ts +0 -1
- package/package/acode/dist/todo-tool.js +5 -121
- package/package/acode/dist/types.d.ts +0 -1
- package/package/acode/dist/types.js +1 -1
- package/package/acode/package.json +2 -2
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.js +2 -890
- package/package/aws-client-agent-mcp/dist/agent-client.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/config.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/config.js +2 -243
- package/package/aws-client-agent-mcp/dist/config.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/config.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/constants.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/constants.js +2 -24
- package/package/aws-client-agent-mcp/dist/context-manager.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.js +2 -477
- package/package/aws-client-agent-mcp/dist/context-manager.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.js +2 -446
- package/package/aws-client-agent-mcp/dist/http-client.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/index.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/index.js +2 -34
- package/package/aws-client-agent-mcp/dist/logger.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/logger.js +3 -178
- package/package/aws-client-agent-mcp/dist/logger.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/logger.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.js +38 -2709
- package/package/aws-client-agent-mcp/dist/mcp-server.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +22 -562
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.js +4 -826
- package/package/aws-client-agent-mcp/dist/memory-store.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.js +31 -294
- package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.js +2 -288
- package/package/aws-client-agent-mcp/dist/message-buffer.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/messageContent.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/messageContent.js +2 -125
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +2 -103
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.js +2 -96
- package/package/aws-client-agent-mcp/dist/status-reporter.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.js +3 -327
- package/package/aws-client-agent-mcp/dist/status-reporter.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/types.js +2 -9
- package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.js +2 -677
- package/package/aws-client-agent-mcp/dist/websocket-client.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.test.js +0 -1
- package/package/aws-client-agent-mcp/package.json +1 -1
- package/package/cc-switch-sdk/dist/constants.d.ts +0 -1
- package/package/cc-switch-sdk/dist/constants.js +2 -63
- package/package/cc-switch-sdk/dist/errors.d.ts +0 -1
- package/package/cc-switch-sdk/dist/errors.js +2 -8
- package/package/cc-switch-sdk/dist/index.d.ts +0 -1
- package/package/cc-switch-sdk/dist/index.js +2 -9
- package/package/cc-switch-sdk/dist/schemas.d.ts +0 -1
- package/package/cc-switch-sdk/dist/schemas.js +2 -38
- package/package/cc-switch-sdk/dist/sdk.d.ts +0 -1
- package/package/cc-switch-sdk/dist/sdk.js +2 -470
- package/package/cc-switch-sdk/dist/services/ai-config-service.d.ts +0 -1
- package/package/cc-switch-sdk/dist/services/ai-config-service.js +4 -307
- package/package/cc-switch-sdk/dist/services/mcp-model.d.ts +0 -1
- package/package/cc-switch-sdk/dist/services/mcp-model.js +2 -37
- package/package/cc-switch-sdk/dist/services/mcp-service.d.ts +0 -1
- package/package/cc-switch-sdk/dist/services/mcp-service.js +2 -9
- package/package/cc-switch-sdk/dist/services/skill-model.d.ts +0 -1
- package/package/cc-switch-sdk/dist/services/skill-model.js +2 -41
- package/package/cc-switch-sdk/dist/services/skill-service.d.ts +0 -1
- package/package/cc-switch-sdk/dist/services/skill-service.js +2 -9
- package/package/cc-switch-sdk/dist/state.d.ts +0 -1
- package/package/cc-switch-sdk/dist/state.js +2 -19
- package/package/cc-switch-sdk/dist/types.d.ts +0 -1
- package/package/cc-switch-sdk/dist/types.js +1 -1
- package/package/cc-switch-sdk/dist/utils/fs.d.ts +0 -1
- package/package/cc-switch-sdk/dist/utils/fs.js +3 -114
- package/package/cc-switch-sdk/dist/utils/id.d.ts +0 -1
- package/package/cc-switch-sdk/dist/utils/id.js +2 -12
- package/package/cc-switch-sdk/package.json +1 -1
- package/package.json +4 -2
- package/dist/adapter/AcodeSdkAdapter.d.ts.map +0 -1
- package/dist/adapter/AdapterRegistry.d.ts.map +0 -1
- package/dist/adapter/ClaudeSdkAdapter.d.ts.map +0 -1
- package/dist/adapter/CodexSdkAdapter.d.ts.map +0 -1
- package/dist/adapter/OpencodeSdkAdapter.d.ts.map +0 -1
- package/dist/adapter/SdkProviderSpi.d.ts.map +0 -1
- package/dist/adapter/acode-tool-names.d.ts.map +0 -1
- package/dist/adapter/idle-poll-loop.d.ts.map +0 -1
- package/dist/adapter/index.d.ts.map +0 -1
- package/dist/adapter/instance-ai-config-resolver.d.ts.map +0 -1
- package/dist/adapter/types.d.ts.map +0 -1
- package/dist/adapters/cc-switch/common.d.ts.map +0 -1
- package/dist/adapters/cc-switch/index.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-acode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-claude.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-claudecode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-codex.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-opencode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-placeholder.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-acode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-claude.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-claudecode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-codex.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-directory.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-opencode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-placeholder.d.ts.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/middleware/auth.d.ts.map +0 -1
- package/dist/routes/acode-todos.d.ts.map +0 -1
- package/dist/routes/ai-sources.d.ts.map +0 -1
- package/dist/routes/dashboard.d.ts.map +0 -1
- package/dist/routes/events.d.ts.map +0 -1
- package/dist/routes/file-browser.d.ts.map +0 -1
- package/dist/routes/file-diff-rollback.d.ts.map +0 -1
- package/dist/routes/file-snapshot.d.ts.map +0 -1
- package/dist/routes/git.d.ts.map +0 -1
- package/dist/routes/instance.d.ts.map +0 -1
- package/dist/routes/mcp.d.ts.map +0 -1
- package/dist/routes/processes.d.ts.map +0 -1
- package/dist/routes/properties.d.ts.map +0 -1
- package/dist/routes/pty.d.ts.map +0 -1
- package/dist/routes/runtime-binding.d.ts.map +0 -1
- package/dist/routes/sessions.d.ts.map +0 -1
- package/dist/routes/skills.d.ts.map +0 -1
- package/dist/routes/sub-agents.d.ts.map +0 -1
- package/dist/routes/system-metrics.d.ts.map +0 -1
- package/dist/routes/task-context.d.ts.map +0 -1
- package/dist/routes/terminal.d.ts.map +0 -1
- package/dist/routes/yml.d.ts.map +0 -1
- package/dist/services/acode-package.d.ts.map +0 -1
- package/dist/services/agent-event-store.d.ts.map +0 -1
- package/dist/services/agent-process-manager.d.ts.map +0 -1
- package/dist/services/ai-source-apply.d.ts.map +0 -1
- package/dist/services/auto-register.d.ts.map +0 -1
- package/dist/services/aws-client-agent-mcp.d.ts.map +0 -1
- package/dist/services/bridge-package-publish-hooks.d.ts.map +0 -1
- package/dist/services/cc-switch-sdk.d.ts.map +0 -1
- package/dist/services/cli-commands.d.ts.map +0 -1
- package/dist/services/event-delta-pusher.d.ts.map +0 -1
- package/dist/services/fileSnapshotStore.d.ts.map +0 -1
- package/dist/services/instance-ai-config-service.d.ts.map +0 -1
- package/dist/services/instance-init-service.d.ts.map +0 -1
- package/dist/services/instance-service.d.ts.map +0 -1
- package/dist/services/instance-state.d.ts.map +0 -1
- package/dist/services/legacy-path-migration.d.ts.map +0 -1
- package/dist/services/lifecycle-state.d.ts.map +0 -1
- package/dist/services/mcp-launch-binding-queue.d.ts.map +0 -1
- package/dist/services/orphan-monitor.d.ts.map +0 -1
- package/dist/services/panel-auth.d.ts.map +0 -1
- package/dist/services/process-detector.d.ts.map +0 -1
- package/dist/services/process-registry.d.ts.map +0 -1
- package/dist/services/ring-buffer.d.ts.map +0 -1
- package/dist/services/runtime-binding.d.ts.map +0 -1
- package/dist/services/runtime-lifecycle-policy.d.ts.map +0 -1
- package/dist/services/session-output.d.ts.map +0 -1
- package/dist/services/startup-config-wizard.d.ts.map +0 -1
- package/dist/services/sub-agent-manager-instance.d.ts.map +0 -1
- package/dist/services/system-metrics.d.ts.map +0 -1
- package/dist/services/terminal-persistence.d.ts.map +0 -1
- package/dist/services/tool-installer.d.ts.map +0 -1
- package/dist/services/tunnel-client.d.ts.map +0 -1
- package/dist/services/windows-service-manager.d.ts.map +0 -1
- package/dist/services/workspace-files.d.ts.map +0 -1
- package/dist/services/workspace-watch.d.ts.map +0 -1
- package/dist/services/workspaceTaskChangeWatcher.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/utils/file-utils.d.ts.map +0 -1
- package/dist/utils/instance-ai-config-debug-logger.d.ts.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/mcp-utils.d.ts.map +0 -1
- package/dist/utils/path-utils.d.ts.map +0 -1
- package/dist/utils/sdk-package-loader.d.ts.map +0 -1
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/yaml-utils.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/constants.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/errors.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/index.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/schemas.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/sdk.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/mcp-model.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/mcp-service.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/skill-model.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/skill-service.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/state.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/types.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/utils/fs.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/utils/id.d.ts.map +0 -1
- package/package/acode/dist/ask-user-question-tool.d.ts.map +0 -1
- package/package/acode/dist/built-in-file-tools.d.ts.map +0 -1
- package/package/acode/dist/built-in-symbols-tool.d.ts.map +0 -1
- package/package/acode/dist/builtins/commandArtifacts.d.ts.map +0 -1
- package/package/acode/dist/builtins/commandOutputEvents.d.ts.map +0 -1
- package/package/acode/dist/builtins/shellCommandPreparation.d.ts.map +0 -1
- package/package/acode/dist/builtins/shellCommandResult.d.ts.map +0 -1
- package/package/acode/dist/builtins/shellCommandRunner.d.ts.map +0 -1
- package/package/acode/dist/builtins/shellOutputDecoder.d.ts.map +0 -1
- package/package/acode/dist/cli.d.ts.map +0 -1
- package/package/acode/dist/commands/commandLoader.d.ts.map +0 -1
- package/package/acode/dist/commands/commandParser.d.ts.map +0 -1
- package/package/acode/dist/commands/commandRegistry.d.ts.map +0 -1
- package/package/acode/dist/compaction.d.ts.map +0 -1
- package/package/acode/dist/config.d.ts.map +0 -1
- package/package/acode/dist/fs-utils.d.ts.map +0 -1
- package/package/acode/dist/hooks/hookBus.d.ts.map +0 -1
- package/package/acode/dist/index.d.ts.map +0 -1
- package/package/acode/dist/mcpToolNames.d.ts.map +0 -1
- package/package/acode/dist/parsers/ast-cache.d.ts.map +0 -1
- package/package/acode/dist/parsers/language-detector.d.ts.map +0 -1
- package/package/acode/dist/parsers/language-queries.d.ts.map +0 -1
- package/package/acode/dist/parsers/symbol-extractor.d.ts.map +0 -1
- package/package/acode/dist/parsers/tree-sitter-loader.d.ts.map +0 -1
- package/package/acode/dist/parsers/types.d.ts.map +0 -1
- package/package/acode/dist/runtime.d.ts.map +0 -1
- package/package/acode/dist/skill-tool.d.ts.map +0 -1
- package/package/acode/dist/sub-agent-manager.d.ts.map +0 -1
- package/package/acode/dist/sub-agent-store.d.ts.map +0 -1
- package/package/acode/dist/sub-agent-tools.d.ts.map +0 -1
- package/package/acode/dist/sub-agent-types.d.ts.map +0 -1
- package/package/acode/dist/todo-store.d.ts.map +0 -1
- package/package/acode/dist/todo-tool.d.ts.map +0 -1
- package/package/acode/dist/types.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/config.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/config.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/config.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/config.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/constants.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/constants.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/index.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/index.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/logger.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/logger.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/logger.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/logger.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/messageContent.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/messageContent.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/types.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +0 -1
- package/package/cc-switch-sdk/dist/constants.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/errors.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/index.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/schemas.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/sdk.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/services/ai-config-service.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/services/mcp-model.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/services/mcp-service.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/services/skill-model.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/services/skill-service.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/state.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/types.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/utils/fs.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/utils/id.d.ts.map +0 -1
|
@@ -1,653 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
import { execSync, exec } from 'child_process';
|
|
7
|
-
import { promisify } from 'util';
|
|
8
|
-
const execAsync = promisify(exec);
|
|
9
|
-
import os from 'os';
|
|
10
|
-
import { createLogger } from '../utils/logger.js';
|
|
11
|
-
const log = createLogger('process-detector');
|
|
12
|
-
/**
|
|
13
|
-
* 在 Windows 上执行 PowerShell 命令
|
|
14
|
-
*
|
|
15
|
-
* 使用 -EncodedCommand 传递 Base64 编码的命令,
|
|
16
|
-
* 彻底避免 cmd.exe 对管道符 |、引号、$ 等特殊字符的转义破坏。
|
|
17
|
-
*
|
|
18
|
-
* @param psScript PowerShell 脚本内容(UTF-16LE 编码后 Base64)
|
|
19
|
-
* @param timeout 超时时间(毫秒)
|
|
20
|
-
* @returns 命令输出
|
|
21
|
-
*/
|
|
22
|
-
function execPowerShell(psScript, timeout = 15000) {
|
|
23
|
-
// PowerShell -EncodedCommand 需要 UTF-16LE 编码的 Base64
|
|
24
|
-
const buffer = Buffer.from(psScript, 'utf16le');
|
|
25
|
-
const encoded = buffer.toString('base64');
|
|
26
|
-
const output = execSync(`powershell -NoProfile -NonInteractive -EncodedCommand ${encoded}`, { encoding: 'utf8', timeout, windowsHide: true });
|
|
27
|
-
// ★ 过滤 PowerShell CLIXML 噪音(进度信息等 stderr 混入 stdout 的内容)
|
|
28
|
-
// CLIXML 格式:#< CLIXML <Objs ...>...</Objs>
|
|
29
|
-
return output.replace(/#\s*<\s*CLIXML[\s\S]*?(?=#<\s*CLIXML|$)/g, '').trim();
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* 异步版 PowerShell 命令执行(防止阻塞事件循环)
|
|
33
|
-
*
|
|
34
|
-
* @param psScript PowerShell 脚本
|
|
35
|
-
* @param timeout 超时时间(毫秒)
|
|
36
|
-
* @returns 命令输出
|
|
37
|
-
*/
|
|
38
|
-
async function execPowerShellAsync(psScript, timeout = 15000) {
|
|
39
|
-
const buffer = Buffer.from(psScript, 'utf16le');
|
|
40
|
-
const encoded = buffer.toString('base64');
|
|
41
|
-
const { stdout } = await execAsync(`powershell -NoProfile -NonInteractive -EncodedCommand ${encoded}`, { encoding: 'utf8', timeout, windowsHide: true, maxBuffer: 10 * 1024 * 1024 });
|
|
42
|
-
// ★ 过滤 PowerShell CLIXML 噪音
|
|
43
|
-
return stdout.replace(/#\s*<\s*CLIXML[\s\S]*?(?=#<\s*CLIXML|$)/g, '').trim();
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* 异步检测进程是否存活(防止阻塞事件循环)
|
|
47
|
-
*
|
|
48
|
-
* @param pid 进程 ID
|
|
49
|
-
* @returns 是否存活
|
|
50
|
-
*/
|
|
51
|
-
export async function isProcessRunningAsync(pid) {
|
|
52
|
-
try {
|
|
53
|
-
if (os.platform() === 'win32') {
|
|
54
|
-
const { stdout } = await execAsync(`tasklist /FI "PID eq ${pid}" /NH /FO CSV`, { encoding: 'utf8', timeout: 5000, windowsHide: true });
|
|
55
|
-
return stdout.includes(String(pid));
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
process.kill(pid, 0);
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* 检测进程是否存活
|
|
68
|
-
*
|
|
69
|
-
* @param pid 进程 ID
|
|
70
|
-
* @returns 是否存活
|
|
71
|
-
*/
|
|
72
|
-
export function isProcessRunning(pid) {
|
|
73
|
-
try {
|
|
74
|
-
if (os.platform() === 'win32') {
|
|
75
|
-
// Windows: 使用 tasklist 检测,比 process.kill(pid, 0) 更可靠
|
|
76
|
-
// process.kill(pid, 0) 在 Windows 上对某些子进程可能权限不足
|
|
77
|
-
const output = execSync(`tasklist /FI "PID eq ${pid}" /NH /FO CSV`, { encoding: 'utf8', timeout: 5000, windowsHide: true });
|
|
78
|
-
// tasklist 返回中包含 PID 则进程存活
|
|
79
|
-
return output.includes(String(pid));
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
// Unix: 发送信号 0 检测进程是否存活
|
|
83
|
-
process.kill(pid, 0);
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
// 进程不存在或无法访问
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* 查找 Agent 相关的进程(Claude Code、OpenCode 等)
|
|
94
|
-
*
|
|
95
|
-
* @returns 匹配的进程列表
|
|
96
|
-
*/
|
|
97
|
-
export async function findClaudeCodeProcesses() {
|
|
98
|
-
const platform = os.platform();
|
|
99
|
-
const results = [];
|
|
100
|
-
try {
|
|
101
|
-
if (platform === 'win32') {
|
|
102
|
-
// Windows: 优先使用 PowerShell(wmic 已弃用)
|
|
103
|
-
results.push(...await findProcessesWindows());
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
// macOS/Linux: 使用 ps
|
|
107
|
-
results.push(...await findProcessesUnix());
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
// 命令执行失败,可能没有匹配的进程
|
|
112
|
-
log.debug('Failed to list processes:', error);
|
|
113
|
-
}
|
|
114
|
-
return results;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Windows: 使用 PowerShell 查找 Agent 进程
|
|
118
|
-
* PowerShell 比 wmic 更可靠(wmic 在 Win10 21H1+ 已弃用)
|
|
119
|
-
*/
|
|
120
|
-
async function findProcessesWindows() {
|
|
121
|
-
const results = [];
|
|
122
|
-
try {
|
|
123
|
-
const psScript = `Get-CimInstance Win32_Process -Filter "Name LIKE '%node%' OR Name LIKE '%claude%' OR Name LIKE '%opencode%' OR Name LIKE '%python%'" | Select-Object ProcessId, CommandLine | ConvertTo-Json -Compress`;
|
|
124
|
-
const output = await execPowerShellAsync(psScript, 10000);
|
|
125
|
-
if (!output || !output.trim())
|
|
126
|
-
return results;
|
|
127
|
-
let processes;
|
|
128
|
-
try {
|
|
129
|
-
const parsed = JSON.parse(output);
|
|
130
|
-
// PowerShell 单条结果返回对象,多条返回数组
|
|
131
|
-
processes = Array.isArray(parsed) ? parsed : [parsed];
|
|
132
|
-
}
|
|
133
|
-
catch {
|
|
134
|
-
return results;
|
|
135
|
-
}
|
|
136
|
-
for (const proc of processes) {
|
|
137
|
-
if (!proc.ProcessId || !proc.CommandLine)
|
|
138
|
-
continue;
|
|
139
|
-
const cmd = proc.CommandLine;
|
|
140
|
-
if (isAgentProcess(cmd)) {
|
|
141
|
-
const agentId = extractAgentId(cmd);
|
|
142
|
-
results.push({
|
|
143
|
-
pid: proc.ProcessId,
|
|
144
|
-
command: cmd,
|
|
145
|
-
agentId,
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
catch (error) {
|
|
151
|
-
// PowerShell 失败,回退到 wmic
|
|
152
|
-
log.debug('PowerShell process query failed, trying wmic fallback:', error);
|
|
153
|
-
results.push(...await findProcessesWindowsWmic());
|
|
154
|
-
}
|
|
155
|
-
return results;
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Windows: wmic 回退方案
|
|
159
|
-
*/
|
|
160
|
-
async function findProcessesWindowsWmic() {
|
|
161
|
-
const results = [];
|
|
162
|
-
try {
|
|
163
|
-
const { stdout } = await execAsync('wmic process where "name like \'%node%\' or name like \'%claude%\' or name like \'%opencode%\'" get processid,commandline /format:list', { encoding: 'utf8', timeout: 5000, windowsHide: true });
|
|
164
|
-
const lines = stdout.split('\n');
|
|
165
|
-
let currentPid = null;
|
|
166
|
-
let currentCmd = null;
|
|
167
|
-
for (const line of lines) {
|
|
168
|
-
const trimmed = line.trim();
|
|
169
|
-
if (trimmed.startsWith('CommandLine=')) {
|
|
170
|
-
currentCmd = trimmed.substring('CommandLine='.length);
|
|
171
|
-
}
|
|
172
|
-
else if (trimmed.startsWith('ProcessId=')) {
|
|
173
|
-
currentPid = trimmed.substring('ProcessId='.length);
|
|
174
|
-
}
|
|
175
|
-
if (currentPid && currentCmd) {
|
|
176
|
-
if (isAgentProcess(currentCmd)) {
|
|
177
|
-
const agentId = extractAgentId(currentCmd);
|
|
178
|
-
results.push({
|
|
179
|
-
pid: parseInt(currentPid, 10),
|
|
180
|
-
command: currentCmd,
|
|
181
|
-
agentId,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
currentPid = null;
|
|
185
|
-
currentCmd = null;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
catch (error) {
|
|
190
|
-
log.debug('wmic process query failed:', error);
|
|
191
|
-
}
|
|
192
|
-
return results;
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Unix: 使用 ps 查找 Agent 进程
|
|
196
|
-
*/
|
|
197
|
-
async function findProcessesUnix() {
|
|
198
|
-
const results = [];
|
|
199
|
-
try {
|
|
200
|
-
const { stdout } = await execAsync('ps aux | grep -E "claude|claude-code|opencode" | grep -v grep', { encoding: 'utf8', timeout: 5000 });
|
|
201
|
-
const lines = stdout.split('\n').filter((l) => l.trim());
|
|
202
|
-
for (const line of lines) {
|
|
203
|
-
const parts = line.trim().split(/\s+/);
|
|
204
|
-
if (parts.length >= 2) {
|
|
205
|
-
const pid = parseInt(parts[1], 10);
|
|
206
|
-
const cmd = parts.slice(10).join(' ');
|
|
207
|
-
if (isAgentProcess(cmd)) {
|
|
208
|
-
const agentId = extractAgentId(cmd);
|
|
209
|
-
results.push({
|
|
210
|
-
pid,
|
|
211
|
-
command: cmd,
|
|
212
|
-
agentId,
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
catch (error) {
|
|
219
|
-
log.debug('ps process query failed:', error);
|
|
220
|
-
}
|
|
221
|
-
return results;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* 检查命令行是否是 Agent 相关进程
|
|
225
|
-
* 包含 Claude Code、OpenCode 等各种 Agent 进程特征
|
|
226
|
-
*
|
|
227
|
-
* @param cmd 命令行
|
|
228
|
-
* @returns 是否匹配
|
|
229
|
-
*/
|
|
230
|
-
function isAgentProcess(cmd) {
|
|
231
|
-
if (!cmd)
|
|
232
|
-
return false;
|
|
233
|
-
const lowerCmd = cmd.toLowerCase();
|
|
234
|
-
// Claude Code 相关特征(精确匹配,避免误匹配普通 node 进程)
|
|
235
|
-
if (lowerCmd.includes('claude') ||
|
|
236
|
-
lowerCmd.includes('@anthropic-ai/claude-code')) {
|
|
237
|
-
return true;
|
|
238
|
-
}
|
|
239
|
-
// OpenCode 相关特征
|
|
240
|
-
if (lowerCmd.includes('opencode') ||
|
|
241
|
-
lowerCmd.includes('open-code') ||
|
|
242
|
-
lowerCmd.includes('opencode.exe') ||
|
|
243
|
-
lowerCmd.includes('opencode.cmd')) {
|
|
244
|
-
return true;
|
|
245
|
-
}
|
|
246
|
-
// AWS Agent MCP 客户端特征(aws-client-agent-mcp 包)
|
|
247
|
-
if (lowerCmd.includes('aws-client-agent-mcp') ||
|
|
248
|
-
lowerCmd.includes('aws-client-agent')) {
|
|
249
|
-
return true;
|
|
250
|
-
}
|
|
251
|
-
// ACode SDK 特征
|
|
252
|
-
if (lowerCmd.includes('acode') && lowerCmd.includes('sdk')) {
|
|
253
|
-
return true;
|
|
254
|
-
}
|
|
255
|
-
// CC-Switch SDK 特征
|
|
256
|
-
if (lowerCmd.includes('cc-switch-sdk') || lowerCmd.includes('cc-switch')) {
|
|
257
|
-
return true;
|
|
258
|
-
}
|
|
259
|
-
return false;
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* 从命令行提取 Agent ID
|
|
263
|
-
*
|
|
264
|
-
* 支持多种提取模式:
|
|
265
|
-
* - 环境变量形式:AWS_AGENT_ID=xxx
|
|
266
|
-
* - 命令行参数:--agent-id=xxx 或 --agent-id xxx
|
|
267
|
-
* - 配置/标识参数:--id=xxx(agent CLI 常用)
|
|
268
|
-
*
|
|
269
|
-
* @param cmd 命令行
|
|
270
|
-
* @returns Agent ID 或 undefined
|
|
271
|
-
*/
|
|
272
|
-
function extractAgentId(cmd) {
|
|
273
|
-
if (!cmd)
|
|
274
|
-
return undefined;
|
|
275
|
-
// 尝试匹配 AWS_AGENT_ID 环境变量(某些情况下 wmic/PowerShell 会包含环境变量)
|
|
276
|
-
const envMatch = cmd.match(/AWS_AGENT_ID=(\S+)/);
|
|
277
|
-
if (envMatch) {
|
|
278
|
-
return stripQuotes(envMatch[1]);
|
|
279
|
-
}
|
|
280
|
-
// 尝试匹配 --agent-id 参数(= 或空格分隔)
|
|
281
|
-
const argMatch = cmd.match(/--agent-id[=\s]+(\S+)/);
|
|
282
|
-
if (argMatch) {
|
|
283
|
-
return stripQuotes(argMatch[1]);
|
|
284
|
-
}
|
|
285
|
-
// 尝试匹配 --id 参数(部分 CLI 使用简短形式)
|
|
286
|
-
const idMatch = cmd.match(/--id[=\s]+(\S+)/);
|
|
287
|
-
if (idMatch) {
|
|
288
|
-
return stripQuotes(idMatch[1]);
|
|
289
|
-
}
|
|
290
|
-
return undefined;
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* 去除字符串首尾引号
|
|
294
|
-
*/
|
|
295
|
-
function stripQuotes(value) {
|
|
296
|
-
if (!value)
|
|
297
|
-
return value;
|
|
298
|
-
const first = value[0];
|
|
299
|
-
const last = value[value.length - 1];
|
|
300
|
-
if ((first === '"' || first === "'") && first === last) {
|
|
301
|
-
return value.slice(1, -1);
|
|
302
|
-
}
|
|
303
|
-
return value;
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* 根据 agentId 查找孤儿进程
|
|
307
|
-
*
|
|
308
|
-
* 检测策略(按优先级):
|
|
309
|
-
* 1. 通过命令行中的 agentId 直接匹配
|
|
310
|
-
* 2. Windows: 通过 PowerShell 在命令行中模糊搜索 agentId
|
|
311
|
-
* 3. Windows: 通过进程树搜索,覆盖 agentId 仅存在于祖先进程环境变量中的场景
|
|
312
|
-
*
|
|
313
|
-
* @param agentId Agent ID
|
|
314
|
-
* @returns 进程信息或 undefined
|
|
315
|
-
*/
|
|
316
|
-
export async function findOrphanProcessByAgentId(agentId) {
|
|
317
|
-
// 1. 先通过命令行匹配
|
|
318
|
-
const processes = await findClaudeCodeProcesses();
|
|
319
|
-
const cmdMatch = processes.find(p => p.agentId === agentId);
|
|
320
|
-
if (cmdMatch)
|
|
321
|
-
return cmdMatch;
|
|
322
|
-
// 2. Windows 特有:在命令行中模糊搜索 agentId
|
|
323
|
-
if (os.platform() === 'win32') {
|
|
324
|
-
const envMatch = await findProcessByEnvVarWindows(agentId);
|
|
325
|
-
if (envMatch)
|
|
326
|
-
return envMatch;
|
|
327
|
-
// ★ 3. Windows: 进程树搜索 —— 遍历所有 Agent 进程,
|
|
328
|
-
// 检查其祖先进程中是否有 node(runtime-bridge) → shell 的模式
|
|
329
|
-
const treeMatch = await findOrphanByAncestorEnvSearch(agentId);
|
|
330
|
-
if (treeMatch)
|
|
331
|
-
return treeMatch;
|
|
332
|
-
}
|
|
333
|
-
return undefined;
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Windows: 通过进程环境变量查找包含 AWS_AGENT_ID 的进程
|
|
337
|
-
*
|
|
338
|
-
* 策略:在所有 node/claude/opencode 进程的命令行中模糊搜索 agentId
|
|
339
|
-
*/
|
|
340
|
-
async function findProcessByEnvVarWindows(agentId) {
|
|
341
|
-
try {
|
|
342
|
-
const psScript = `$targetId = '${agentId}'; $procs = Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -and ($_.Name -like '*node*' -or $_.Name -like '*claude*' -or $_.Name -like '*opencode*') }; foreach ($proc in $procs) { if ($proc.CommandLine -like "*$targetId*") { @{ProcessId=$proc.ProcessId; CommandLine=$proc.CommandLine; AgentId=$targetId} | ConvertTo-Json -Compress } }`;
|
|
343
|
-
const output = await execPowerShellAsync(psScript, 10000);
|
|
344
|
-
if (!output || !output.trim())
|
|
345
|
-
return undefined;
|
|
346
|
-
const lines = output.trim().split('\n').filter(l => l.trim());
|
|
347
|
-
for (const line of lines) {
|
|
348
|
-
try {
|
|
349
|
-
const parsed = JSON.parse(line.trim());
|
|
350
|
-
if (parsed.ProcessId) {
|
|
351
|
-
return {
|
|
352
|
-
pid: parsed.ProcessId,
|
|
353
|
-
command: parsed.CommandLine || '',
|
|
354
|
-
agentId: parsed.AgentId || agentId,
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
catch {
|
|
359
|
-
// 跳过无法解析的行
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
catch (error) {
|
|
364
|
-
log.debug('PowerShell env var query failed:', error);
|
|
365
|
-
}
|
|
366
|
-
return undefined;
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Windows: 通过祖先环境变量搜索孤儿进程。
|
|
370
|
-
*
|
|
371
|
-
* 场景说明:
|
|
372
|
-
* runtime-bridge 或其子进程可能把 AWS_AGENT_ID 传给 shell/agent 祖先进程,
|
|
373
|
-
* 最终运行的 claude/opencode/codex 进程命令行里不一定包含 agentId。
|
|
374
|
-
*
|
|
375
|
-
* 此时:
|
|
376
|
-
* - findProcessesWindows() 能找到 agent CLI 进程,但 extractAgentId() 提取不到 agentId
|
|
377
|
-
* - findProcessByEnvVarWindows() 在命令行中搜不到 agentId(环境变量不在命令行中)
|
|
378
|
-
*
|
|
379
|
-
* 策略:用极简 PowerShell 获取全量进程树数据 → 在 Node.js 层做祖先链匹配
|
|
380
|
-
*/
|
|
381
|
-
async function findOrphanByAncestorEnvSearch(agentId) {
|
|
382
|
-
try {
|
|
383
|
-
// ★ 极简 PowerShell —— 只做数据采集,不做任何逻辑判断
|
|
384
|
-
const psScript = `Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, CommandLine | ConvertTo-Json -Compress`;
|
|
385
|
-
const output = await execPowerShellAsync(psScript, 15000);
|
|
386
|
-
if (!output || !output.trim())
|
|
387
|
-
return undefined;
|
|
388
|
-
// ★ 所有逻辑在 Node.js 层执行
|
|
389
|
-
return await searchOrphanInProcessTree(output.trim(), agentId);
|
|
390
|
-
}
|
|
391
|
-
catch (error) {
|
|
392
|
-
log.debug('[findOrphanByAncestorEnvSearch] Failed:', error);
|
|
393
|
-
}
|
|
394
|
-
return undefined;
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* 在进程树中搜索孤儿 Agent 进程(纯 Node.js 逻辑)
|
|
398
|
-
*
|
|
399
|
-
* 核心思路:
|
|
400
|
-
* 1. 解析全部 Windows 进程列表
|
|
401
|
-
* 2. 找出所有 Agent 候选进程(claude.exe / opencode.exe / 含特征的 node 进程)
|
|
402
|
-
* 3. 对每个候选向上遍历祖先链
|
|
403
|
-
* 4. 如果祖先链中出现 node(runtime-bridge) → powershell/cmd 的模式 → 判定为孤儿
|
|
404
|
-
*/
|
|
405
|
-
async function searchOrphanInProcessTree(rawJson, agentId) {
|
|
406
|
-
let allProcs;
|
|
407
|
-
try {
|
|
408
|
-
// ★ 过滤 CLIXML 噪音后再解析 JSON
|
|
409
|
-
const cleaned = rawJson.replace(/#\s*<\s*CLIXML[\s\S]*?(?=\{|\[|$)/g, '').trim();
|
|
410
|
-
const jsonStr = extractJsonFromOutput(cleaned);
|
|
411
|
-
const parsed = JSON.parse(jsonStr);
|
|
412
|
-
allProcs = Array.isArray(parsed) ? parsed : [parsed];
|
|
413
|
-
}
|
|
414
|
-
catch (e) {
|
|
415
|
-
log.debug(`[searchOrphanInProcessTree] JSON parse failed, raw length=${rawJson.length}`, e);
|
|
416
|
-
return undefined;
|
|
417
|
-
}
|
|
418
|
-
if (!allProcs.length)
|
|
419
|
-
return undefined;
|
|
420
|
-
// 构建快速查找表
|
|
421
|
-
const procMap = new Map();
|
|
422
|
-
for (const p of allProcs) {
|
|
423
|
-
if (p.processId) {
|
|
424
|
-
procMap.set(p.processId, p);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
/**
|
|
428
|
-
* 检查进程是否是 Agent 相关进程
|
|
429
|
-
*/
|
|
430
|
-
function isCandidate(p) {
|
|
431
|
-
const nameLower = p.name.toLowerCase();
|
|
432
|
-
const cmd = (p.commandLine || '').toLowerCase();
|
|
433
|
-
// Claude Code 进程
|
|
434
|
-
if (nameLower.includes('claude'))
|
|
435
|
-
return true;
|
|
436
|
-
if (cmd.includes('claude') || cmd.includes('@anthropic-ai/claude-code') || cmd.includes('cli.js'))
|
|
437
|
-
return true;
|
|
438
|
-
// OpenCode 进程
|
|
439
|
-
if (nameLower.includes('opencode'))
|
|
440
|
-
return true;
|
|
441
|
-
if (cmd.includes('opencode'))
|
|
442
|
-
return true;
|
|
443
|
-
// serve --port 模式
|
|
444
|
-
if (cmd.includes('serve') && cmd.includes('--port'))
|
|
445
|
-
return true;
|
|
446
|
-
return false;
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* 检查进程名是否为 Shell 类型
|
|
450
|
-
*/
|
|
451
|
-
function isShell(name) {
|
|
452
|
-
const n = name.toLowerCase();
|
|
453
|
-
return n === 'powershell.exe' || n === 'cmd.exe' || n === 'pwsh.exe' || n === 'bash.exe';
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* 向上追踪祖先链,查找 node(bridge) → shell 的模式
|
|
457
|
-
* ★ 改进:返回匹配的 shell 进程 PID,用于后续 agentId 验证
|
|
458
|
-
*/
|
|
459
|
-
function findAncestorShell(pid) {
|
|
460
|
-
let currentPid = pid;
|
|
461
|
-
const maxDepth = 10;
|
|
462
|
-
for (let depth = 0; depth < maxDepth; depth++) {
|
|
463
|
-
const ancestor = procMap.get(currentPid);
|
|
464
|
-
if (!ancestor)
|
|
465
|
-
break;
|
|
466
|
-
// 如果祖先是 shell 进程
|
|
467
|
-
if (isShell(ancestor.name)) {
|
|
468
|
-
// 检查 shell 的父进程是否是 node(runtime-bridge 是 node 进程)
|
|
469
|
-
const shellParent = procMap.get(ancestor.parentProcessId);
|
|
470
|
-
if (shellParent && shellParent.name.toLowerCase() === 'node.exe') {
|
|
471
|
-
const nodeCmd = (shellParent.commandLine || '').toLowerCase();
|
|
472
|
-
// 验证这个 node 是否是 runtime-bridge
|
|
473
|
-
if (nodeCmd.includes('runtime-bridge') || nodeCmd.includes('agentswork')) {
|
|
474
|
-
log.debug(`[searchOrphanInProcessTree] Found bridge ancestor chain: agent(${pid}) -> shell(${ancestor.processId}) -> node(${shellParent.processId})`);
|
|
475
|
-
return { shellPid: ancestor.processId, shellCmd: ancestor.commandLine || '' };
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
currentPid = ancestor.parentProcessId;
|
|
480
|
-
if (currentPid <= 0)
|
|
481
|
-
break;
|
|
482
|
-
}
|
|
483
|
-
return null;
|
|
484
|
-
}
|
|
485
|
-
// ★ 策略1:遍历所有进程,找 Agent 候选并检查其祖先链
|
|
486
|
-
// 然后通过 shell 的命令行或环境变量验证 agentId
|
|
487
|
-
for (const proc of allProcs) {
|
|
488
|
-
if (!isCandidate(proc))
|
|
489
|
-
continue;
|
|
490
|
-
const shellInfo = findAncestorShell(proc.processId);
|
|
491
|
-
if (shellInfo) {
|
|
492
|
-
// ★ 验证 agentId:检查 shell 命令行中是否包含目标 agentId
|
|
493
|
-
// shell 的命令行中不一定直接包含 agentId,但可以尝试匹配。
|
|
494
|
-
const shellCmdLower = shellInfo.shellCmd.toLowerCase();
|
|
495
|
-
const cmdLineIncludesAgentId = shellCmdLower.includes(agentId.toLowerCase());
|
|
496
|
-
if (cmdLineIncludesAgentId) {
|
|
497
|
-
log.info(`[searchOrphanInProcessTree] Found orphan by tree search (agentId verified): agentId=${agentId}, pid=${proc.processId}, name=${proc.name}`);
|
|
498
|
-
return {
|
|
499
|
-
pid: proc.processId,
|
|
500
|
-
command: proc.commandLine || '',
|
|
501
|
-
agentId,
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
// ★ 如果只有一个候选进程匹配 runtime-bridge 祖先链,直接返回
|
|
505
|
-
// (没有其他 agent 竞争时无需精确验证)
|
|
506
|
-
const allCandidates = allProcs.filter(p => isCandidate(p) && findAncestorShell(p.processId));
|
|
507
|
-
if (allCandidates.length === 1) {
|
|
508
|
-
log.info(`[searchOrphanInProcessTree] Found orphan by tree search (single candidate): agentId=${agentId}, pid=${proc.processId}, name=${proc.name}`);
|
|
509
|
-
return {
|
|
510
|
-
pid: proc.processId,
|
|
511
|
-
command: proc.commandLine || '',
|
|
512
|
-
agentId,
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
// 多个候选时,尝试通过进程命令行中的工作目录匹配
|
|
516
|
-
log.debug(`[searchOrphanInProcessTree] Multiple candidates found (${allCandidates.length}), cannot determine which belongs to agentId=${agentId}`);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
// ★ 策略2:宽松搜索 —— 查找所有不在已知会话中的 Agent 候选进程
|
|
520
|
-
// 当进程树断链时(shell 父进程已死,agent 被 reparent),走这个策略
|
|
521
|
-
// 通过直接读取进程的环境变量来验证 agentId
|
|
522
|
-
const candidateWithoutBridge = allProcs.filter(p => isCandidate(p) && !findAncestorShell(p.processId));
|
|
523
|
-
for (const proc of candidateWithoutBridge) {
|
|
524
|
-
// 尝试通过读取进程环境变量来验证 agentId
|
|
525
|
-
const verified = await verifyProcessAgentId(proc.processId, agentId);
|
|
526
|
-
if (verified) {
|
|
527
|
-
log.info(`[searchOrphanInProcessTree] Found orphan by env verification: agentId=${agentId}, pid=${proc.processId}, name=${proc.name}`);
|
|
528
|
-
return {
|
|
529
|
-
pid: proc.processId,
|
|
530
|
-
command: proc.commandLine || '',
|
|
531
|
-
agentId,
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
return undefined;
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* 从混合输出中提取 JSON 字符串
|
|
539
|
-
* 处理 CLIXML 噪音、进度信息等 PowerShell 杂讯
|
|
540
|
-
*/
|
|
541
|
-
function extractJsonFromOutput(output) {
|
|
542
|
-
// 找到第一个 [ 或 { 开始的位置
|
|
543
|
-
const arrayStart = output.indexOf('[');
|
|
544
|
-
const objStart = output.indexOf('{');
|
|
545
|
-
let start = -1;
|
|
546
|
-
if (arrayStart >= 0 && objStart >= 0) {
|
|
547
|
-
start = Math.min(arrayStart, objStart);
|
|
548
|
-
}
|
|
549
|
-
else if (arrayStart >= 0) {
|
|
550
|
-
start = arrayStart;
|
|
551
|
-
}
|
|
552
|
-
else if (objStart >= 0) {
|
|
553
|
-
start = objStart;
|
|
554
|
-
}
|
|
555
|
-
if (start < 0)
|
|
556
|
-
return output;
|
|
557
|
-
return output.substring(start);
|
|
558
|
-
}
|
|
559
|
-
/**
|
|
560
|
-
* 通过读取进程环境变量来验证 agentId
|
|
561
|
-
*
|
|
562
|
-
* Windows 下无法直接读取其他进程的环境变量,但可以通过以下方式间接验证:
|
|
563
|
-
* 1. 检查进程命令行中是否包含 agentId
|
|
564
|
-
* 2. 检查父进程命令行中是否包含 agentId
|
|
565
|
-
* 3. 检查进程的整个祖先链中是否有匹配的 runtime-bridge 启动的 shell
|
|
566
|
-
*
|
|
567
|
-
* @param pid 进程 PID
|
|
568
|
-
* @param targetAgentId 目标 Agent ID
|
|
569
|
-
* @returns 是否匹配
|
|
570
|
-
*/
|
|
571
|
-
async function verifyProcessAgentId(pid, targetAgentId) {
|
|
572
|
-
try {
|
|
573
|
-
// 策略1:检查进程命令行是否包含 agentId
|
|
574
|
-
const psScript = `
|
|
1
|
+
import{execSync as L,exec as O}from"child_process";import{promisify as b}from"util";const h=b(O);import g from"os";import{createLogger as k}from"../utils/logger.js";const a=k("process-detector");function z(n,t=15e3){const r=Buffer.from(n,"utf16le").toString("base64");return L(`powershell -NoProfile -NonInteractive -EncodedCommand ${r}`,{encoding:"utf8",timeout:t,windowsHide:!0}).replace(/#\s*<\s*CLIXML[\s\S]*?(?=#<\s*CLIXML|$)/g,"").trim()}async function f(n,t=15e3){const r=Buffer.from(n,"utf16le").toString("base64"),{stdout:s}=await h(`powershell -NoProfile -NonInteractive -EncodedCommand ${r}`,{encoding:"utf8",timeout:t,windowsHide:!0,maxBuffer:10*1024*1024});return s.replace(/#\s*<\s*CLIXML[\s\S]*?(?=#<\s*CLIXML|$)/g,"").trim()}async function w(n){try{if(g.platform()==="win32"){const{stdout:t}=await h(`tasklist /FI "PID eq ${n}" /NH /FO CSV`,{encoding:"utf8",timeout:5e3,windowsHide:!0});return t.includes(String(n))}else return process.kill(n,0),!0}catch{return!1}}function X(n){try{return g.platform()==="win32"?L(`tasklist /FI "PID eq ${n}" /NH /FO CSV`,{encoding:"utf8",timeout:5e3,windowsHide:!0}).includes(String(n)):(process.kill(n,0),!0)}catch{return!1}}async function P(){const n=g.platform(),t=[];try{n==="win32"?t.push(...await A()):t.push(...await F())}catch(e){a.debug("Failed to list processes:",e)}return t}async function A(){const n=[];try{const e=await f(`Get-CimInstance Win32_Process -Filter "Name LIKE '%node%' OR Name LIKE '%claude%' OR Name LIKE '%opencode%' OR Name LIKE '%python%'" | Select-Object ProcessId, CommandLine | ConvertTo-Json -Compress`,1e4);if(!e||!e.trim())return n;let r;try{const s=JSON.parse(e);r=Array.isArray(s)?s:[s]}catch{return n}for(const s of r){if(!s.ProcessId||!s.CommandLine)continue;const i=s.CommandLine;if($(i)){const d=y(i);n.push({pid:s.ProcessId,command:i,agentId:d})}}}catch(t){a.debug("PowerShell process query failed, trying wmic fallback:",t),n.push(...await N())}return n}async function N(){const n=[];try{const{stdout:t}=await h(`wmic process where "name like '%node%' or name like '%claude%' or name like '%opencode%'" get processid,commandline /format:list`,{encoding:"utf8",timeout:5e3,windowsHide:!0}),e=t.split(`
|
|
2
|
+
`);let r=null,s=null;for(const i of e){const d=i.trim();if(d.startsWith("CommandLine=")?s=d.substring(12):d.startsWith("ProcessId=")&&(r=d.substring(10)),r&&s){if($(s)){const c=y(s);n.push({pid:parseInt(r,10),command:s,agentId:c})}r=null,s=null}}}catch(t){a.debug("wmic process query failed:",t)}return n}async function F(){const n=[];try{const{stdout:t}=await h('ps aux | grep -E "claude|claude-code|opencode" | grep -v grep',{encoding:"utf8",timeout:5e3}),e=t.split(`
|
|
3
|
+
`).filter(r=>r.trim());for(const r of e){const s=r.trim().split(/\s+/);if(s.length>=2){const i=parseInt(s[1],10),d=s.slice(10).join(" ");if($(d)){const c=y(d);n.push({pid:i,command:d,agentId:c})}}}}catch(t){a.debug("ps process query failed:",t)}return n}function $(n){if(!n)return!1;const t=n.toLowerCase();return!!(t.includes("claude")||t.includes("@anthropic-ai/claude-code")||t.includes("opencode")||t.includes("open-code")||t.includes("opencode.exe")||t.includes("opencode.cmd")||t.includes("aws-client-agent-mcp")||t.includes("aws-client-agent")||t.includes("acode")&&t.includes("sdk")||t.includes("cc-switch-sdk")||t.includes("cc-switch"))}function y(n){if(!n)return;const t=n.match(/AWS_AGENT_ID=(\S+)/);if(t)return C(t[1]);const e=n.match(/--agent-id[=\s]+(\S+)/);if(e)return C(e[1]);const r=n.match(/--id[=\s]+(\S+)/);if(r)return C(r[1])}function C(n){if(!n)return n;const t=n[0],e=n[n.length-1];return(t==='"'||t==="'")&&t===e?n.slice(1,-1):n}async function x(n){const e=(await P()).find(r=>r.agentId===n);if(e)return e;if(g.platform()==="win32"){const r=await T(n);if(r)return r;const s=await R(n);if(s)return s}}async function T(n){try{const t=`$targetId = '${n}'; $procs = Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -and ($_.Name -like '*node*' -or $_.Name -like '*claude*' -or $_.Name -like '*opencode*') }; foreach ($proc in $procs) { if ($proc.CommandLine -like "*$targetId*") { @{ProcessId=$proc.ProcessId; CommandLine=$proc.CommandLine; AgentId=$targetId} | ConvertTo-Json -Compress } }`,e=await f(t,1e4);if(!e||!e.trim())return;const r=e.trim().split(`
|
|
4
|
+
`).filter(s=>s.trim());for(const s of r)try{const i=JSON.parse(s.trim());if(i.ProcessId)return{pid:i.ProcessId,command:i.CommandLine||"",agentId:i.AgentId||n}}catch{}}catch(t){a.debug("PowerShell env var query failed:",t)}}async function R(n){try{const e=await f("Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, CommandLine | ConvertTo-Json -Compress",15e3);return!e||!e.trim()?void 0:await W(e.trim(),n)}catch(t){a.debug("[findOrphanByAncestorEnvSearch] Failed:",t)}}async function W(n,t){let e;try{const o=n.replace(/#\s*<\s*CLIXML[\s\S]*?(?=\{|\[|$)/g,"").trim(),u=B(o),l=JSON.parse(u);e=Array.isArray(l)?l:[l]}catch(o){a.debug(`[searchOrphanInProcessTree] JSON parse failed, raw length=${n.length}`,o);return}if(!e.length)return;const r=new Map;for(const o of e)o.processId&&r.set(o.processId,o);function s(o){const u=o.name.toLowerCase(),l=(o.commandLine||"").toLowerCase();return!!(u.includes("claude")||l.includes("claude")||l.includes("@anthropic-ai/claude-code")||l.includes("cli.js")||u.includes("opencode")||l.includes("opencode")||l.includes("serve")&&l.includes("--port"))}function i(o){const u=o.toLowerCase();return u==="powershell.exe"||u==="cmd.exe"||u==="pwsh.exe"||u==="bash.exe"}function d(o){let u=o;const l=10;for(let I=0;I<l;I++){const p=r.get(u);if(!p)break;if(i(p.name)){const m=r.get(p.parentProcessId);if(m&&m.name.toLowerCase()==="node.exe"){const S=(m.commandLine||"").toLowerCase();if(S.includes("runtime-bridge")||S.includes("agentswork"))return a.debug(`[searchOrphanInProcessTree] Found bridge ancestor chain: agent(${o}) -> shell(${p.processId}) -> node(${m.processId})`),{shellPid:p.processId,shellCmd:p.commandLine||""}}}if(u=p.parentProcessId,u<=0)break}return null}for(const o of e){if(!s(o))continue;const u=d(o.processId);if(u){if(u.shellCmd.toLowerCase().includes(t.toLowerCase()))return a.info(`[searchOrphanInProcessTree] Found orphan by tree search (agentId verified): agentId=${t}, pid=${o.processId}, name=${o.name}`),{pid:o.processId,command:o.commandLine||"",agentId:t};const p=e.filter(m=>s(m)&&d(m.processId));if(p.length===1)return a.info(`[searchOrphanInProcessTree] Found orphan by tree search (single candidate): agentId=${t}, pid=${o.processId}, name=${o.name}`),{pid:o.processId,command:o.commandLine||"",agentId:t};a.debug(`[searchOrphanInProcessTree] Multiple candidates found (${p.length}), cannot determine which belongs to agentId=${t}`)}}const c=e.filter(o=>s(o)&&!d(o.processId));for(const o of c)if(await _(o.processId,t))return a.info(`[searchOrphanInProcessTree] Found orphan by env verification: agentId=${t}, pid=${o.processId}, name=${o.name}`),{pid:o.processId,command:o.commandLine||"",agentId:t}}function B(n){const t=n.indexOf("["),e=n.indexOf("{");let r=-1;return t>=0&&e>=0?r=Math.min(t,e):t>=0?r=t:e>=0&&(r=e),r<0?n:n.substring(r)}async function _(n,t){try{const e=`
|
|
575
5
|
try {
|
|
576
|
-
$proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${
|
|
577
|
-
if ($proc -and $proc.CommandLine -like '*${
|
|
6
|
+
$proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${n}" -ErrorAction SilentlyContinue
|
|
7
|
+
if ($proc -and $proc.CommandLine -like '*${t}*') { 'MATCH' } else { 'NOMATCH' }
|
|
578
8
|
} catch { 'ERROR' }
|
|
579
|
-
`;
|
|
580
|
-
const result = (await execPowerShellAsync(psScript, 5000)).trim();
|
|
581
|
-
if (result === 'MATCH')
|
|
582
|
-
return true;
|
|
583
|
-
// 策略2:检查父进程命令行是否包含 agentId
|
|
584
|
-
const parentPsScript = `
|
|
9
|
+
`;if((await f(e,5e3)).trim()==="MATCH")return!0;const s=`
|
|
585
10
|
try {
|
|
586
|
-
$proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${
|
|
11
|
+
$proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${n}" -ErrorAction SilentlyContinue
|
|
587
12
|
if ($proc) {
|
|
588
13
|
$parentPid = $proc.ParentProcessId
|
|
589
14
|
$parent = Get-CimInstance Win32_Process -Filter "ProcessId = $parentPid" -ErrorAction SilentlyContinue
|
|
590
|
-
if ($parent -and $parent.CommandLine -like '*${
|
|
15
|
+
if ($parent -and $parent.CommandLine -like '*${t}*') { 'MATCH' } else { 'NOMATCH' }
|
|
591
16
|
} else { 'NOPROC' }
|
|
592
17
|
} catch { 'ERROR' }
|
|
593
|
-
`;
|
|
594
|
-
const parentResult = (await execPowerShellAsync(parentPsScript, 5000)).trim();
|
|
595
|
-
if (parentResult === 'MATCH')
|
|
596
|
-
return true;
|
|
597
|
-
// 策略3:检查祖父进程(node → powershell → claude 三级链中,agentId 在 shell 命令行中)
|
|
598
|
-
const grandParentPsScript = `
|
|
18
|
+
`;if((await f(s,5e3)).trim()==="MATCH")return!0;const d=`
|
|
599
19
|
try {
|
|
600
|
-
$proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${
|
|
20
|
+
$proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${n}" -ErrorAction SilentlyContinue
|
|
601
21
|
if ($proc) {
|
|
602
22
|
$parentPid = $proc.ParentProcessId
|
|
603
23
|
$parent = Get-CimInstance Win32_Process -Filter "ProcessId = $parentPid" -ErrorAction SilentlyContinue
|
|
604
24
|
if ($parent) {
|
|
605
25
|
$grandParentPid = $parent.ParentProcessId
|
|
606
26
|
$grandParent = Get-CimInstance Win32_Process -Filter "ProcessId = $grandParentPid" -ErrorAction SilentlyContinue
|
|
607
|
-
if ($grandParent -and $grandParent.CommandLine -like '*${
|
|
27
|
+
if ($grandParent -and $grandParent.CommandLine -like '*${t}*') { 'MATCH' } else { 'NOMATCH' }
|
|
608
28
|
} else { 'NOPARENT' }
|
|
609
29
|
} else { 'NOPROC' }
|
|
610
30
|
} catch { 'ERROR' }
|
|
611
|
-
`;
|
|
612
|
-
|
|
613
|
-
return grandParentResult === 'MATCH';
|
|
614
|
-
}
|
|
615
|
-
catch (error) {
|
|
616
|
-
log.debug(`[verifyProcessAgentId] Failed for pid=${pid}, agentId=${targetAgentId}:`, error);
|
|
617
|
-
return false;
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
/**
|
|
621
|
-
* 通过工作目录路径查找孤儿进程
|
|
622
|
-
*
|
|
623
|
-
* 当 agentId 无法匹配到进程时,通过工作目录路径做宽泛搜索。
|
|
624
|
-
* 适用于以下场景:
|
|
625
|
-
* - runtime-bridge 重启后持久化会话丢失
|
|
626
|
-
* - agentId 可能仅在祖先进程环境变量中,命令行搜索不到
|
|
627
|
-
* - 进程树断链,无法通过祖先链匹配
|
|
628
|
-
*
|
|
629
|
-
* @param workspacePath 工作目录路径
|
|
630
|
-
* @returns 匹配的进程信息或 undefined
|
|
631
|
-
*/
|
|
632
|
-
export async function findOrphanProcessByWorkspace(workspacePath) {
|
|
633
|
-
if (!workspacePath)
|
|
634
|
-
return undefined;
|
|
635
|
-
try {
|
|
636
|
-
const processes = await findClaudeCodeProcesses();
|
|
637
|
-
// 在匹配的进程命令行中搜索工作目录路径
|
|
638
|
-
const normalizedPath = workspacePath.replace(/\\/g, '/').toLowerCase();
|
|
639
|
-
for (const proc of processes) {
|
|
640
|
-
const cmdNormalized = proc.command.replace(/\\/g, '/').toLowerCase();
|
|
641
|
-
if (cmdNormalized.includes(normalizedPath)) {
|
|
642
|
-
log.info(`[findOrphanProcessByWorkspace] Found process by workspace: pid=${proc.pid}, workspace=${workspacePath}`);
|
|
643
|
-
return proc;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
// ★ Windows 特有:通过 PowerShell 搜索工作目录匹配的进程
|
|
647
|
-
if (os.platform() === 'win32') {
|
|
648
|
-
const escapedPath = workspacePath.replace(/'/g, "''");
|
|
649
|
-
const psScript = `
|
|
650
|
-
$targetPath = '${escapedPath}'.ToLower().Replace('\\', '/')
|
|
31
|
+
`;return(await f(d,5e3)).trim()==="MATCH"}catch(e){return a.debug(`[verifyProcessAgentId] Failed for pid=${n}, agentId=${t}:`,e),!1}}async function K(n){if(n)try{const t=await P(),e=n.replace(/\\/g,"/").toLowerCase();for(const r of t)if(r.command.replace(/\\/g,"/").toLowerCase().includes(e))return a.info(`[findOrphanProcessByWorkspace] Found process by workspace: pid=${r.pid}, workspace=${n}`),r;if(g.platform()==="win32"){const s=`
|
|
32
|
+
$targetPath = '${n.replace(/'/g,"''")}'.ToLower().Replace('\\', '/')
|
|
651
33
|
$procs = Get-CimInstance Win32_Process | Where-Object {
|
|
652
34
|
$_.CommandLine -and ($_.Name -like '*node*' -or $_.Name -like '*claude*' -or $_.Name -like '*opencode*')
|
|
653
35
|
}
|
|
@@ -657,390 +39,7 @@ export async function findOrphanProcessByWorkspace(workspacePath) {
|
|
|
657
39
|
@{ProcessId=$proc.ProcessId; CommandLine=$proc.CommandLine} | ConvertTo-Json -Compress
|
|
658
40
|
}
|
|
659
41
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
for (const line of lines) {
|
|
665
|
-
try {
|
|
666
|
-
const parsed = JSON.parse(line.trim());
|
|
667
|
-
if (parsed.ProcessId) {
|
|
668
|
-
log.info(`[findOrphanProcessByWorkspace] Found process by PowerShell workspace search: pid=${parsed.ProcessId}`);
|
|
669
|
-
return {
|
|
670
|
-
pid: parsed.ProcessId,
|
|
671
|
-
command: parsed.CommandLine || '',
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
catch {
|
|
676
|
-
// 跳过无法解析的行
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
catch (error) {
|
|
683
|
-
log.debug('[findOrphanProcessByWorkspace] Failed:', error);
|
|
684
|
-
}
|
|
685
|
-
return undefined;
|
|
686
|
-
}
|
|
687
|
-
/**
|
|
688
|
-
* 根据 PID 终止进程
|
|
689
|
-
*
|
|
690
|
-
* @param pid 进程 ID
|
|
691
|
-
* @returns 是否成功
|
|
692
|
-
*/
|
|
693
|
-
export function terminateProcess(pid) {
|
|
694
|
-
try {
|
|
695
|
-
process.kill(pid, 'SIGTERM');
|
|
696
|
-
return true;
|
|
697
|
-
}
|
|
698
|
-
catch (error) {
|
|
699
|
-
log.warn(`Failed to terminate process ${pid}:`, error);
|
|
700
|
-
return false;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
/**
|
|
704
|
-
* 终止进程树(包括所有子进程)
|
|
705
|
-
*
|
|
706
|
-
* 跨平台实现:
|
|
707
|
-
* - Windows: 使用 taskkill /T 终止整个进程树
|
|
708
|
-
* - Unix: 递归获取所有子进程并逐个终止
|
|
709
|
-
*
|
|
710
|
-
* @param pid 进程 ID
|
|
711
|
-
* @returns { terminated: 成功终止的进程数,failed: 失败的进程数 }
|
|
712
|
-
*/
|
|
713
|
-
export async function terminateProcessTree(pid) {
|
|
714
|
-
const result = { terminated: 0, failed: 0 };
|
|
715
|
-
if (os.platform() === 'win32') {
|
|
716
|
-
// Windows: 使用 taskkill /T /F 终止进程树
|
|
717
|
-
try {
|
|
718
|
-
await execAsync(`taskkill /PID ${pid} /T /F`, { encoding: 'utf8', timeout: 5000, windowsHide: true });
|
|
719
|
-
result.terminated++;
|
|
720
|
-
log.info(`Terminated process tree for pid=${pid}`);
|
|
721
|
-
}
|
|
722
|
-
catch (error) {
|
|
723
|
-
const err = error;
|
|
724
|
-
log.warn(`Failed to terminate process tree for pid=${pid}:`, err.message);
|
|
725
|
-
result.failed++;
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
else {
|
|
729
|
-
// Unix: 递归获取所有子进程并终止
|
|
730
|
-
const childPids = await getChildProcesses(pid);
|
|
731
|
-
log.debug(`Found ${childPids.length} child processes for pid=${pid}`);
|
|
732
|
-
// 先终止所有子进程
|
|
733
|
-
for (const childPid of childPids) {
|
|
734
|
-
const childResult = await terminateProcessTree(childPid);
|
|
735
|
-
result.terminated += childResult.terminated;
|
|
736
|
-
result.failed += childResult.failed;
|
|
737
|
-
}
|
|
738
|
-
// 然后终止父进程
|
|
739
|
-
if (terminateProcess(pid)) {
|
|
740
|
-
result.terminated++;
|
|
741
|
-
}
|
|
742
|
-
else {
|
|
743
|
-
result.failed++;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
return result;
|
|
747
|
-
}
|
|
748
|
-
/**
|
|
749
|
-
* Unix: 获取进程的所有子进程(递归)
|
|
750
|
-
*
|
|
751
|
-
* @param pid 父进程 ID
|
|
752
|
-
* @returns 子进程 PID 列表
|
|
753
|
-
*/
|
|
754
|
-
async function getChildProcesses(pid) {
|
|
755
|
-
try {
|
|
756
|
-
const { stdout } = await execAsync(`pgrep -P ${pid}`, { encoding: 'utf8', timeout: 3000 });
|
|
757
|
-
const children = stdout.trim().split('\n').filter(Boolean).map(Number);
|
|
758
|
-
// 递归获取孙进程
|
|
759
|
-
const allDescendants = [];
|
|
760
|
-
for (const childPid of children) {
|
|
761
|
-
allDescendants.push(childPid);
|
|
762
|
-
allDescendants.push(...await getChildProcesses(childPid));
|
|
763
|
-
}
|
|
764
|
-
return allDescendants;
|
|
765
|
-
}
|
|
766
|
-
catch {
|
|
767
|
-
// pgrep 失败(无子进程或命令不存在)
|
|
768
|
-
return [];
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
/**
|
|
772
|
-
* 等待进程完全终止(轮询检测)
|
|
773
|
-
*
|
|
774
|
-
* @param pid 进程 ID
|
|
775
|
-
* @param timeoutMs 超时时间(毫秒)
|
|
776
|
-
* @returns 是否成功终止
|
|
777
|
-
*/
|
|
778
|
-
export async function waitForProcessExit(pid, timeoutMs = 5000) {
|
|
779
|
-
const startTime = Date.now();
|
|
780
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
781
|
-
if (!await isProcessRunningAsync(pid)) {
|
|
782
|
-
return true;
|
|
783
|
-
}
|
|
784
|
-
// 等待 100ms 后重试
|
|
785
|
-
const delay = Math.min(100, timeoutMs - (Date.now() - startTime));
|
|
786
|
-
if (delay > 0) {
|
|
787
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
return false;
|
|
791
|
-
}
|
|
792
|
-
/**
|
|
793
|
-
* 检测并收集所有孤儿进程信息
|
|
794
|
-
* 用于 runtime-bridge 启动时恢复控制
|
|
795
|
-
*
|
|
796
|
-
* 改进策略:
|
|
797
|
-
* 1. 检查持久化会话中的 PID 是否仍在运行(使用可靠的 isProcessRunning)
|
|
798
|
-
* 2. PID 存活时,优先从进程列表匹配详细信息,匹配不到则用持久化信息构造
|
|
799
|
-
* 3. 对于没有 PID 的会话,通过 agentId 搜索进程(包括环境变量搜索)
|
|
800
|
-
*
|
|
801
|
-
* @param persistedSessions 持久化的会话列表(包含 PID 信息)
|
|
802
|
-
* @returns 孤儿进程列表
|
|
803
|
-
*/
|
|
804
|
-
export async function detectOrphanProcesses(persistedSessions) {
|
|
805
|
-
const orphans = [];
|
|
806
|
-
// 1. 首先检查持久化会话中的 PID 是否仍在运行
|
|
807
|
-
for (const session of persistedSessions) {
|
|
808
|
-
if (session.pid && await isProcessRunningAsync(session.pid)) {
|
|
809
|
-
// PID 存活,尝试获取详细进程信息
|
|
810
|
-
const processes = await findClaudeCodeProcesses();
|
|
811
|
-
const matched = processes.find(p => p.pid === session.pid);
|
|
812
|
-
if (matched) {
|
|
813
|
-
orphans.push({
|
|
814
|
-
agentId: session.agentId,
|
|
815
|
-
process: matched,
|
|
816
|
-
sessionInfo: {
|
|
817
|
-
workspacePath: session.workspacePath,
|
|
818
|
-
command: session.command,
|
|
819
|
-
},
|
|
820
|
-
});
|
|
821
|
-
log.info(`Found orphan process by PID: agentId=${session.agentId}, pid=${session.pid}`);
|
|
822
|
-
}
|
|
823
|
-
else {
|
|
824
|
-
// ★ PID 存活但进程列表匹配不到(可能是命令行特征未被识别)
|
|
825
|
-
// 仍然报告为孤儿进程,用持久化信息构造 ProcessInfo
|
|
826
|
-
orphans.push({
|
|
827
|
-
agentId: session.agentId,
|
|
828
|
-
process: {
|
|
829
|
-
pid: session.pid,
|
|
830
|
-
command: session.command || '(unknown - persisted session)',
|
|
831
|
-
agentId: session.agentId,
|
|
832
|
-
},
|
|
833
|
-
sessionInfo: {
|
|
834
|
-
workspacePath: session.workspacePath,
|
|
835
|
-
command: session.command,
|
|
836
|
-
},
|
|
837
|
-
});
|
|
838
|
-
log.info(`Found orphan process by PID (no cmd match): agentId=${session.agentId}, pid=${session.pid}`);
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
// 2. 对于没有 PID 但有 agentId 的会话,尝试通过 agentId 搜索进程
|
|
843
|
-
for (const session of persistedSessions) {
|
|
844
|
-
if (!session.pid && session.agentId) {
|
|
845
|
-
const process = await findOrphanProcessByAgentId(session.agentId);
|
|
846
|
-
if (process && !orphans.some(o => o.agentId === session.agentId)) {
|
|
847
|
-
orphans.push({
|
|
848
|
-
agentId: session.agentId,
|
|
849
|
-
process,
|
|
850
|
-
sessionInfo: {
|
|
851
|
-
workspacePath: session.workspacePath,
|
|
852
|
-
command: session.command,
|
|
853
|
-
},
|
|
854
|
-
});
|
|
855
|
-
log.info(`Found orphan process by agentId: agentId=${session.agentId}, pid=${process.pid}`);
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
return orphans;
|
|
860
|
-
}
|
|
861
|
-
/**
|
|
862
|
-
* 检测进程健康状态
|
|
863
|
-
*
|
|
864
|
-
* @param pid 进程 ID
|
|
865
|
-
* @param agentId Agent ID
|
|
866
|
-
* @returns 健康状态
|
|
867
|
-
*/
|
|
868
|
-
export async function checkProcessHealth(pid, agentId) {
|
|
869
|
-
const status = {
|
|
870
|
-
pid,
|
|
871
|
-
agentId,
|
|
872
|
-
alive: false,
|
|
873
|
-
cpu: 0,
|
|
874
|
-
memoryMB: 0,
|
|
875
|
-
status: 'dead',
|
|
876
|
-
lastUpdate: new Date(),
|
|
877
|
-
};
|
|
878
|
-
try {
|
|
879
|
-
// 检查进程是否存在
|
|
880
|
-
if (!await isProcessRunningAsync(pid)) {
|
|
881
|
-
status.status = 'dead';
|
|
882
|
-
log.debug(`Process ${pid} is not running`);
|
|
883
|
-
return status;
|
|
884
|
-
}
|
|
885
|
-
status.alive = true;
|
|
886
|
-
// 获取进程资源使用情况
|
|
887
|
-
const { cpu, memoryMB } = await getProcessResources(pid);
|
|
888
|
-
status.cpu = cpu;
|
|
889
|
-
status.memoryMB = memoryMB;
|
|
890
|
-
// 判断状态
|
|
891
|
-
if (memoryMB > 2048) {
|
|
892
|
-
status.status = 'high_memory';
|
|
893
|
-
}
|
|
894
|
-
else if (cpu > 100) {
|
|
895
|
-
status.status = 'high_cpu';
|
|
896
|
-
}
|
|
897
|
-
else {
|
|
898
|
-
status.status = 'healthy';
|
|
899
|
-
}
|
|
900
|
-
log.debug(`Process ${pid} health: CPU=${cpu}%, Memory=${memoryMB}MB, Status=${status.status}`);
|
|
901
|
-
return status;
|
|
902
|
-
}
|
|
903
|
-
catch (error) {
|
|
904
|
-
log.warn(`Failed to check health for process ${pid}:`, error);
|
|
905
|
-
status.status = 'dead';
|
|
906
|
-
return status;
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
/**
|
|
910
|
-
* 获取进程资源使用情况
|
|
911
|
-
*
|
|
912
|
-
* @param pid 进程 ID
|
|
913
|
-
* @returns { cpu: CPU使用率, memoryMB: 内存使用(MB) }
|
|
914
|
-
*/
|
|
915
|
-
async function getProcessResources(pid) {
|
|
916
|
-
const platform = os.platform();
|
|
917
|
-
if (platform === 'win32') {
|
|
918
|
-
// Windows: 使用 PowerShell 获取进程资源
|
|
919
|
-
const psScript = `Get-CimInstance Win32_Process -Filter "ProcessId=${pid}" | Select-Object @{Name='CPU';Expression={$_.WorkingSetSize/1MB}}, @{Name='Mem';Expression={$_.WorkingSetSize/1MB}} | ConvertTo-Json -Compress`;
|
|
920
|
-
try {
|
|
921
|
-
const output = await execPowerShellAsync(psScript, 5000);
|
|
922
|
-
if (!output || !output.trim()) {
|
|
923
|
-
return { cpu: 0, memoryMB: 0 };
|
|
924
|
-
}
|
|
925
|
-
const parsed = JSON.parse(output);
|
|
926
|
-
// WorkingSetSize 是内存使用
|
|
927
|
-
return {
|
|
928
|
-
cpu: 0, // Windows 难以准确获取 CPU 使用率
|
|
929
|
-
memoryMB: Math.round((parsed.WorkingSetSize || 0) / 1024 / 1024),
|
|
930
|
-
};
|
|
931
|
-
}
|
|
932
|
-
catch {
|
|
933
|
-
return { cpu: 0, memoryMB: 0 };
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
else {
|
|
937
|
-
// Unix: 使用 ps 获取资源
|
|
938
|
-
try {
|
|
939
|
-
const { stdout } = await execAsync(`ps -p ${pid} -o %cpu=,rss=`, { encoding: 'utf8', timeout: 5000 });
|
|
940
|
-
const parts = stdout.trim().split(/\s+/);
|
|
941
|
-
if (parts.length >= 2) {
|
|
942
|
-
return {
|
|
943
|
-
cpu: parseFloat(parts[0]) || 0,
|
|
944
|
-
memoryMB: Math.round(parseInt(parts[1], 10) / 1024), // RSS is KB
|
|
945
|
-
};
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
catch {
|
|
949
|
-
return { cpu: 0, memoryMB: 0 };
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
return { cpu: 0, memoryMB: 0 };
|
|
953
|
-
}
|
|
954
|
-
/**
|
|
955
|
-
* 批量检测会话健康状态
|
|
956
|
-
*
|
|
957
|
-
* @param sessions 持久化会话列表
|
|
958
|
-
* @returns 健康状态列表
|
|
959
|
-
*/
|
|
960
|
-
export async function checkAllSessionsHealth(sessions) {
|
|
961
|
-
const results = new Map();
|
|
962
|
-
const promises = sessions
|
|
963
|
-
.filter(s => s.pid)
|
|
964
|
-
.map(async (session) => {
|
|
965
|
-
// s.pid is guaranteed to exist after filter
|
|
966
|
-
const health = await checkProcessHealth(session.pid, session.agentId);
|
|
967
|
-
results.set(session.agentId, health);
|
|
968
|
-
});
|
|
969
|
-
await Promise.all(promises);
|
|
970
|
-
return results;
|
|
971
|
-
}
|
|
972
|
-
/**
|
|
973
|
-
* 全局发现:扫描机器上所有 Agent 进程,并标注管理状态
|
|
974
|
-
*
|
|
975
|
-
* 返回三类进程:
|
|
976
|
-
* - managed: 在注册表中且进程存活
|
|
977
|
-
* - orphan: 进程存在但不在注册表中(脱离控制)
|
|
978
|
-
* - unknown: 在注册表中但进程已死亡
|
|
979
|
-
*
|
|
980
|
-
* @param managedPids 已知被管理的 PID 集合(来自 ProcessRegistry)
|
|
981
|
-
* @returns 发现的进程列表
|
|
982
|
-
*/
|
|
983
|
-
export async function discoverAllProcesses(managedPids = new Set(), managedAgentIds = new Set()) {
|
|
984
|
-
const results = [];
|
|
985
|
-
// 1. 扫描机器上所有 Agent 进程
|
|
986
|
-
const allAgentProcesses = await findClaudeCodeProcesses();
|
|
987
|
-
for (const proc of allAgentProcesses) {
|
|
988
|
-
const isManaged = managedPids.has(proc.pid);
|
|
989
|
-
const isAgentManaged = proc.agentId ? managedAgentIds.has(proc.agentId) : false;
|
|
990
|
-
results.push({
|
|
991
|
-
...proc,
|
|
992
|
-
isRunning: true,
|
|
993
|
-
managementStatus: isManaged || isAgentManaged ? 'managed' : 'orphan',
|
|
994
|
-
sessionId: undefined,
|
|
995
|
-
lastSeen: new Date().toISOString(),
|
|
996
|
-
});
|
|
997
|
-
}
|
|
998
|
-
// 2. 找出在注册表中但未被扫描到的进程(可能已死亡)
|
|
999
|
-
// 这部分由调用方(AgentProcessManager)补充
|
|
1000
|
-
return results;
|
|
1001
|
-
}
|
|
1002
|
-
/**
|
|
1003
|
-
* 批量发现:扫描所有进程并补充注册表中缺失的进程状态
|
|
1004
|
-
*
|
|
1005
|
-
* @param registryExport 注册表导出的进程记录(含 agentId, pid)
|
|
1006
|
-
* @returns 完整的发现结果
|
|
1007
|
-
*/
|
|
1008
|
-
export async function discoverAllProcessesFull(registryExport) {
|
|
1009
|
-
const managedPids = new Set(registryExport.map(r => r.pid));
|
|
1010
|
-
const managedAgentIds = new Set(registryExport.map(r => r.agentId));
|
|
1011
|
-
const pidToRecord = new Map(registryExport.map(r => [r.pid, r]));
|
|
1012
|
-
const results = [];
|
|
1013
|
-
const seenPids = new Set();
|
|
1014
|
-
// 1. 扫描实际运行的进程
|
|
1015
|
-
const runningProcesses = await findClaudeCodeProcesses();
|
|
1016
|
-
for (const proc of runningProcesses) {
|
|
1017
|
-
seenPids.add(proc.pid);
|
|
1018
|
-
const isManaged = managedPids.has(proc.pid);
|
|
1019
|
-
const isAgentManaged = proc.agentId ? managedAgentIds.has(proc.agentId) : false;
|
|
1020
|
-
const recordByPid = pidToRecord.get(proc.pid);
|
|
1021
|
-
// ★ 关键修复:当命令行中无法提取 agentId 但 PID 匹配注册表时,继承注册表的 agentId
|
|
1022
|
-
const resolvedAgentId = proc.agentId || recordByPid?.agentId;
|
|
1023
|
-
results.push({
|
|
1024
|
-
...proc,
|
|
1025
|
-
agentId: resolvedAgentId,
|
|
1026
|
-
isRunning: true,
|
|
1027
|
-
managementStatus: isManaged || isAgentManaged ? 'managed' : 'orphan',
|
|
1028
|
-
sessionId: undefined,
|
|
1029
|
-
lastSeen: new Date().toISOString(),
|
|
1030
|
-
});
|
|
1031
|
-
}
|
|
1032
|
-
// 2. 注册表中存在但进程已死亡的记录(仅保留近期死亡的,过滤陈旧条目)
|
|
1033
|
-
for (const record of registryExport) {
|
|
1034
|
-
if (!seenPids.has(record.pid) && !await isProcessRunningAsync(record.pid)) {
|
|
1035
|
-
results.push({
|
|
1036
|
-
pid: record.pid,
|
|
1037
|
-
command: '(process exited)',
|
|
1038
|
-
agentId: record.agentId,
|
|
1039
|
-
isRunning: false,
|
|
1040
|
-
managementStatus: 'unknown',
|
|
1041
|
-
lastSeen: undefined,
|
|
1042
|
-
});
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
return results;
|
|
1046
|
-
}
|
|
42
|
+
`,i=await f(s,1e4);if(i&&i.trim()){const d=i.trim().split(`
|
|
43
|
+
`).filter(c=>c.trim());for(const c of d)try{const o=JSON.parse(c.trim());if(o.ProcessId)return a.info(`[findOrphanProcessByWorkspace] Found process by PowerShell workspace search: pid=${o.ProcessId}`),{pid:o.ProcessId,command:o.CommandLine||""}}catch{}}}}catch(t){a.debug("[findOrphanProcessByWorkspace] Failed:",t)}}function v(n){try{return process.kill(n,"SIGTERM"),!0}catch(t){return a.warn(`Failed to terminate process ${n}:`,t),!1}}async function E(n){const t={terminated:0,failed:0};if(g.platform()==="win32")try{await h(`taskkill /PID ${n} /T /F`,{encoding:"utf8",timeout:5e3,windowsHide:!0}),t.terminated++,a.info(`Terminated process tree for pid=${n}`)}catch(e){const r=e;a.warn(`Failed to terminate process tree for pid=${n}:`,r.message),t.failed++}else{const e=await M(n);a.debug(`Found ${e.length} child processes for pid=${n}`);for(const r of e){const s=await E(r);t.terminated+=s.terminated,t.failed+=s.failed}v(n)?t.terminated++:t.failed++}return t}async function M(n){try{const{stdout:t}=await h(`pgrep -P ${n}`,{encoding:"utf8",timeout:3e3}),e=t.trim().split(`
|
|
44
|
+
`).filter(Boolean).map(Number),r=[];for(const s of e)r.push(s),r.push(...await M(s));return r}catch{return[]}}async function U(n,t=5e3){const e=Date.now();for(;Date.now()-e<t;){if(!await w(n))return!0;const r=Math.min(100,t-(Date.now()-e));r>0&&await new Promise(s=>setTimeout(s,r))}return!1}async function V(n){const t=[];for(const e of n)if(e.pid&&await w(e.pid)){const s=(await P()).find(i=>i.pid===e.pid);s?(t.push({agentId:e.agentId,process:s,sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),a.info(`Found orphan process by PID: agentId=${e.agentId}, pid=${e.pid}`)):(t.push({agentId:e.agentId,process:{pid:e.pid,command:e.command||"(unknown - persisted session)",agentId:e.agentId},sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),a.info(`Found orphan process by PID (no cmd match): agentId=${e.agentId}, pid=${e.pid}`))}for(const e of n)if(!e.pid&&e.agentId){const r=await x(e.agentId);r&&!t.some(s=>s.agentId===e.agentId)&&(t.push({agentId:e.agentId,process:r,sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),a.info(`Found orphan process by agentId: agentId=${e.agentId}, pid=${r.pid}`))}return t}async function H(n,t){const e={pid:n,agentId:t,alive:!1,cpu:0,memoryMB:0,status:"dead",lastUpdate:new Date};try{if(!await w(n))return e.status="dead",a.debug(`Process ${n} is not running`),e;e.alive=!0;const{cpu:r,memoryMB:s}=await D(n);return e.cpu=r,e.memoryMB=s,s>2048?e.status="high_memory":r>100?e.status="high_cpu":e.status="healthy",a.debug(`Process ${n} health: CPU=${r}%, Memory=${s}MB, Status=${e.status}`),e}catch(r){return a.warn(`Failed to check health for process ${n}:`,r),e.status="dead",e}}async function D(n){if(g.platform()==="win32"){const e=`Get-CimInstance Win32_Process -Filter "ProcessId=${n}" | Select-Object @{Name='CPU';Expression={$_.WorkingSetSize/1MB}}, @{Name='Mem';Expression={$_.WorkingSetSize/1MB}} | ConvertTo-Json -Compress`;try{const r=await f(e,5e3);if(!r||!r.trim())return{cpu:0,memoryMB:0};const s=JSON.parse(r);return{cpu:0,memoryMB:Math.round((s.WorkingSetSize||0)/1024/1024)}}catch{return{cpu:0,memoryMB:0}}}else try{const{stdout:e}=await h(`ps -p ${n} -o %cpu=,rss=`,{encoding:"utf8",timeout:5e3}),r=e.trim().split(/\s+/);if(r.length>=2)return{cpu:parseFloat(r[0])||0,memoryMB:Math.round(parseInt(r[1],10)/1024)}}catch{return{cpu:0,memoryMB:0}}return{cpu:0,memoryMB:0}}async function Q(n){const t=new Map,e=n.filter(r=>r.pid).map(async r=>{const s=await H(r.pid,r.agentId);t.set(r.agentId,s)});return await Promise.all(e),t}async function Y(n=new Set,t=new Set){const e=[],r=await P();for(const s of r){const i=n.has(s.pid),d=s.agentId?t.has(s.agentId):!1;e.push({...s,isRunning:!0,managementStatus:i||d?"managed":"orphan",sessionId:void 0,lastSeen:new Date().toISOString()})}return e}async function Z(n){const t=new Set(n.map(c=>c.pid)),e=new Set(n.map(c=>c.agentId)),r=new Map(n.map(c=>[c.pid,c])),s=[],i=new Set,d=await P();for(const c of d){i.add(c.pid);const o=t.has(c.pid),u=c.agentId?e.has(c.agentId):!1,l=r.get(c.pid),I=c.agentId||l?.agentId;s.push({...c,agentId:I,isRunning:!0,managementStatus:o||u?"managed":"orphan",sessionId:void 0,lastSeen:new Date().toISOString()})}for(const c of n)!i.has(c.pid)&&!await w(c.pid)&&s.push({pid:c.pid,command:"(process exited)",agentId:c.agentId,isRunning:!1,managementStatus:"unknown",lastSeen:void 0});return s}export{Q as checkAllSessionsHealth,H as checkProcessHealth,V as detectOrphanProcesses,Y as discoverAllProcesses,Z as discoverAllProcessesFull,P as findClaudeCodeProcesses,x as findOrphanProcessByAgentId,K as findOrphanProcessByWorkspace,X as isProcessRunning,w as isProcessRunningAsync,v as terminateProcess,E as terminateProcessTree,U as waitForProcessExit};
|
|
45
|
+
|