claude-code-session-manager 0.111.0 → 0.113.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/dist/assets/{AgentLibrary-rBO1daqM.js → AgentLibrary-wvrcLGGS.js} +2 -2
- package/dist/assets/{Button-DsEYRZg0.js → Button-B6h0F0XT.js} +1 -1
- package/dist/assets/{DataModel-D8sbvvBC.js → DataModel-C5pW9E3u.js} +1 -1
- package/dist/assets/{History-BEHLtxia.js → History-BV4e8YOM.js} +2 -2
- package/dist/assets/{Hooks-CKpvlXrg.js → Hooks-CrFSv4x1.js} +3 -3
- package/dist/assets/{Library-CeF4qh9d.js → Library-D-GIt3EY.js} +5 -5
- package/dist/assets/{ListDetail-DcfmxPFk.js → ListDetail-Bco_wfs6.js} +1 -1
- package/dist/assets/{MarkdownEditor-CvK1pyto.js → MarkdownEditor-C-yHSXNV.js} +1 -1
- package/dist/assets/{McpServers-D-h2ihzJ.js → McpServers-CfDekadG.js} +2 -2
- package/dist/assets/{Memory-BnF89x8v.js → Memory-CGGLexkR.js} +4 -4
- package/dist/assets/{Panel-CQY5zano.js → Panel-DGMEuYYG.js} +1 -1
- package/dist/assets/{Permissions-DLukmmsz.js → Permissions-Cx2zjtYZ.js} +3 -3
- package/dist/assets/{Plugins-0Pf0OZ4l.js → Plugins-Bc_W3IyR.js} +2 -2
- package/dist/assets/ProvenanceBadge-DiKAUR1u.js +1 -0
- package/dist/assets/RemoteMachines-8_77-WPD.js +3 -0
- package/dist/assets/{SaveBar-DjijiUb0.js → SaveBar-Blpzdq1R.js} +1 -1
- package/dist/assets/{Scheduler-Cm3EXZvE.js → Scheduler-Bd70AM4X.js} +9 -9
- package/dist/assets/{ScopeSwitcher-B-P-kSfq.js → ScopeSwitcher-wxN0h4YW.js} +1 -1
- package/dist/assets/Settings-CQ7DA3zW.js +4 -0
- package/dist/assets/{SkillReferenceGraph-Epv2GJmj.js → SkillReferenceGraph-DH1NLOiS.js} +1 -1
- package/dist/assets/Skills-CmyRyu4_.js +2 -0
- package/dist/assets/SystemPrompt-KAc3UMCd.js +1 -0
- package/dist/assets/TagLibrary-C8EvHnpg.js +1 -0
- package/dist/assets/{TiptapBody-DAMO3DhO.js → TiptapBody-d423mH6D.js} +1 -1
- package/dist/assets/{Toggle-Ba_f7q_m.js → Toggle-D1wsGE9S.js} +1 -1
- package/dist/assets/{ViewTabs-CGX6MAhc.js → ViewTabs-CjHw3kGY.js} +1 -1
- package/dist/assets/{historyTotals-vgfk8EOL.js → historyTotals-DFHzqLt7.js} +1 -1
- package/dist/assets/{index-CPieAFsl.js → index-Ci1u018F.js} +266 -266
- package/dist/assets/{settingsSchema-D0FxNrTy.js → settingsSchema-Ctf3pZVI.js} +1 -1
- package/dist/assets/{useAgentsDirWatch-DCu6BNYN.js → useAgentsDirWatch-B1NBmOAe.js} +1 -1
- package/dist/assets/{useRemotePeers-D4cdJDyh.js → useRemotePeers-BHjSJs9D.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +3 -2
- package/plugins/CLAUDE.md +5 -8
- package/plugins/session-manager-dev/.claude-plugin/plugin.json +3 -6
- package/plugins/session-manager-dev/skills/builder/1-classify-and-bump/SKILL.md +2 -2
- package/plugins/session-manager-dev/skills/builder/SKILL.md +2 -3
- package/plugins/session-manager-dev/skills/develop/SKILL.md +1 -1
- package/plugins/session-manager-dev/skills/develop/standards.md +3 -3
- package/plugins/session-manager-dev/skills/send-feedback/SKILL.md +13 -0
- package/scripts/README.md +3 -3
- package/scripts/audit-ops-hygiene.cjs +4 -4
- package/scripts/hooks/guard-destructive-git.cjs +4 -4
- package/scripts/hooks/guard-inline-implementation.cjs +1 -1
- package/scripts/hooks/guard-prd-writes.cjs +2 -2
- package/scripts/hooks/lib/guard-destructive-git-policy.cjs +1 -1
- package/scripts/mint-epic.cjs +2 -2
- package/scripts/scheduler-mcp-server.cjs +27 -9
- package/src/main/agentLibrary.cjs +5 -5
- package/src/main/agentsIpc.cjs +76 -0
- package/src/main/build-info.json +4 -4
- package/src/main/chatRunner.cjs +30 -13
- package/src/main/config.cjs +20 -3
- package/src/main/crashDiagnostics.cjs +2 -2
- package/src/main/docEdit.cjs +5 -5
- package/src/main/files.cjs +2 -2
- package/src/main/git.cjs +1 -1
- package/src/main/health.cjs +20 -18
- package/src/main/heapSnapshot.cjs +1 -1
- package/src/main/historyAggregator.cjs +2 -2
- package/src/main/index.cjs +50 -132
- package/src/main/ipcSchemas.cjs +13 -10
- package/src/main/lib/CLAUDE.md +48 -0
- package/src/main/lib/activeSessions.cjs +14 -1
- package/src/main/lib/classifyPromptTicket.cjs +2 -2
- package/src/main/lib/{agentModelResolve.cjs → claude/agentModelResolve.cjs} +7 -7
- package/src/main/lib/{claudeBin.cjs → claude/claudeBin.cjs} +4 -4
- package/src/main/lib/{effectiveModelInfo.cjs → claude/effectiveModelInfo.cjs} +9 -9
- package/src/main/lib/{modelCatalog.cjs → claude/modelCatalog.cjs} +3 -3
- package/src/main/lib/claude/rateLimitDetect.cjs +54 -0
- package/src/main/lib/{rateLimitWindow.cjs → claude/rateLimitWindow.cjs} +24 -12
- package/src/main/lib/{runClaudeP.cjs → claude/runClaudeP.cjs} +1 -1
- package/src/main/lib/credentials.cjs +18 -92
- package/src/main/lib/cwdClassify.cjs +1 -1
- package/src/main/lib/{activeIndexMerge.cjs → epic/activeIndexMerge.cjs} +3 -3
- package/src/main/lib/{activeIndexRebuild.cjs → epic/activeIndexRebuild.cjs} +1 -1
- package/src/main/lib/{delegationReadiness.cjs → epic/delegationReadiness.cjs} +21 -29
- package/src/main/lib/{epicContextDigest.cjs → epic/epicContextDigest.cjs} +1 -1
- package/src/main/lib/{epicDelegationStats.cjs → epic/epicDelegationStats.cjs} +2 -2
- package/src/main/lib/{epicMint.cjs → epic/epicMint.cjs} +11 -11
- package/src/main/lib/{epicSpawnPlan.cjs → epic/epicSpawnPlan.cjs} +3 -3
- package/src/main/lib/{epicStatusMirror.cjs → epic/epicStatusMirror.cjs} +2 -2
- package/src/main/lib/{epicTranscriptDiagnostic.cjs → epic/epicTranscriptDiagnostic.cjs} +2 -2
- package/src/main/lib/{epicTranscriptPath.cjs → epic/epicTranscriptPath.cjs} +2 -2
- package/src/main/lib/{epicValidationHook.cjs → epic/epicValidationHook.cjs} +3 -3
- package/src/main/lib/{epicWorktreeBoot.cjs → epic/epicWorktreeBoot.cjs} +1 -1
- package/src/main/lib/{epicWorktreeMerge.cjs → epic/epicWorktreeMerge.cjs} +3 -3
- package/src/main/lib/{epicWorktreeMint.cjs → epic/epicWorktreeMint.cjs} +3 -3
- package/src/main/lib/{epicWorktreeProjectConfig.cjs → epic/epicWorktreeProjectConfig.cjs} +4 -4
- package/src/main/lib/{promptSessionsCreateEpic.cjs → epic/promptSessionsCreateEpic.cjs} +4 -4
- package/src/main/lib/{crossProjectFeedback.cjs → feedback-remote/crossProjectFeedback.cjs} +114 -16
- package/src/main/lib/{customerFeedbackClient.cjs → feedback-remote/customerFeedbackClient.cjs} +3 -3
- package/src/main/lib/{customerFeedbackInbox.cjs → feedback-remote/customerFeedbackInbox.cjs} +2 -2
- package/src/main/lib/{customerFeedbackIpc.cjs → feedback-remote/customerFeedbackIpc.cjs} +1 -1
- package/src/main/lib/feedback-remote/humanPromptLedger.cjs +93 -0
- package/src/main/lib/{localAdminHttp.cjs → feedback-remote/localAdminHttp.cjs} +2 -2
- package/src/main/lib/{macroAdminRoutes.cjs → feedback-remote/macroAdminRoutes.cjs} +1 -1
- package/src/main/lib/{projectHomeAdminRoutes.cjs → feedback-remote/projectHomeAdminRoutes.cjs} +4 -4
- package/src/main/lib/{relayClientAuth.cjs → feedback-remote/relayClientAuth.cjs} +2 -2
- package/src/main/lib/{remoteClientSessions.cjs → feedback-remote/remoteClientSessions.cjs} +1 -1
- package/src/main/lib/{gitWorktree.cjs → git/gitWorktree.cjs} +7 -7
- package/src/main/lib/historyRollup.cjs +1 -1
- package/src/main/lib/importReferences.cjs +1 -1
- package/src/main/lib/machineProfile.cjs +1 -1
- package/src/main/lib/mcpToolCatalog.cjs +9 -3
- package/src/main/lib/openExternalApp.cjs +1 -1
- package/src/main/lib/opsOwnership.cjs +3 -3
- package/src/main/lib/{agentPersonaSchema.cjs → persona-macro/agentPersonaSchema.cjs} +2 -2
- package/src/main/lib/{macroLibrary.cjs → persona-macro/macroLibrary.cjs} +5 -5
- package/src/main/lib/{personaMerge.cjs → persona-macro/personaMerge.cjs} +4 -4
- package/src/main/lib/{depSlugResolve.cjs → prd/depSlugResolve.cjs} +16 -1
- package/src/main/lib/{prdAdminRoutes.cjs → prd/prdAdminRoutes.cjs} +7 -7
- package/src/main/lib/{prdAgentType.cjs → prd/prdAgentType.cjs} +3 -3
- package/src/main/lib/{prdCreate.cjs → prd/prdCreate.cjs} +12 -12
- package/src/main/lib/{prdDeclaredPaths.cjs → prd/prdDeclaredPaths.cjs} +1 -1
- package/src/main/lib/{prdGateFiles.cjs → prd/prdGateFiles.cjs} +1 -1
- package/src/main/lib/{prdLocations.cjs → prd/prdLocations.cjs} +2 -2
- package/src/main/lib/{prdMigration.cjs → prd/prdMigration.cjs} +3 -3
- package/src/main/lib/prereqs.cjs +2 -2
- package/src/main/lib/{instanceLock.cjs → process/instanceLock.cjs} +4 -11
- package/src/main/lib/{pidAlive.cjs → process/pidAlive.cjs} +1 -1
- package/src/main/lib/{procName.cjs → process/procName.cjs} +2 -2
- package/src/main/lib/{timeoutShim.cjs → process/timeoutShim.cjs} +1 -1
- package/src/main/lib/projectRootResolve.cjs +1 -1
- package/src/main/lib/promptSessionSchema.cjs +1 -1
- package/src/main/lib/{definitionOfDone.cjs → scheduler/definitionOfDone.cjs} +6 -12
- package/src/main/lib/scheduler/finalizeReason.cjs +30 -0
- package/src/main/lib/{fixChainDepth.cjs → scheduler/fixChainDepth.cjs} +1 -1
- package/src/main/lib/scheduler/flatSweepThrottle.cjs +17 -0
- package/src/main/lib/{jobDirtFilter.cjs → scheduler/jobDirtFilter.cjs} +1 -1
- package/src/main/lib/{jobSupervisorRecord.cjs → scheduler/jobSupervisorRecord.cjs} +1 -1
- package/src/main/lib/{launchFailure.cjs → scheduler/launchFailure.cjs} +2 -2
- package/src/main/lib/{queueStore.cjs → scheduler/queueStore.cjs} +6 -6
- package/src/main/lib/{quietMachineLease.cjs → scheduler/quietMachineLease.cjs} +1 -1
- package/src/main/lib/{rcaReport.cjs → scheduler/rcaReport.cjs} +4 -4
- package/src/main/lib/{reaperHelpers.cjs → scheduler/reaperHelpers.cjs} +3 -3
- package/src/main/lib/{reservationExpiry.cjs → scheduler/reservationExpiry.cjs} +4 -11
- package/src/main/lib/{reviewNotice.cjs → scheduler/reviewNotice.cjs} +1 -1
- package/src/main/lib/{runLogRetention.cjs → scheduler/runLogRetention.cjs} +34 -13
- package/src/main/lib/{scheduleJobTransitions.cjs → scheduler/scheduleJobTransitions.cjs} +3 -3
- package/src/main/lib/{schedulerBatch.cjs → scheduler/schedulerBatch.cjs} +9 -13
- package/src/main/lib/{schedulerConfig.cjs → scheduler/schedulerConfig.cjs} +1 -1
- package/src/main/lib/{schedulerRuntimeState.cjs → scheduler/schedulerRuntimeState.cjs} +1 -1
- package/src/main/lib/{sessionSlots.cjs → scheduler/sessionSlots.cjs} +2 -2
- package/src/main/lib/{upgradeDrain.cjs → scheduler/upgradeDrain.cjs} +8 -11
- package/src/main/lib/{watchdogHelpers.cjs → scheduler/watchdogHelpers.cjs} +5 -19
- package/src/main/lib/{auditLog.cjs → telemetry/auditLog.cjs} +1 -1
- package/src/main/lib/{opsErrorLog.cjs → telemetry/opsErrorLog.cjs} +4 -4
- package/src/main/lib/{telemetryBacklog.cjs → telemetry/telemetryBacklog.cjs} +4 -4
- package/src/main/lib/{telemetryBoot.cjs → telemetry/telemetryBoot.cjs} +1 -1
- package/src/main/lib/{telemetryClient.cjs → telemetry/telemetryClient.cjs} +12 -8
- package/src/main/lib/{telemetrySettings.cjs → telemetry/telemetrySettings.cjs} +1 -1
- package/src/main/lib/{atomicFs.cjs → util/atomicFs.cjs} +42 -0
- package/src/main/lib/{loopDelay.cjs → util/loopDelay.cjs} +1 -1
- package/src/main/logs.cjs +1 -1
- package/src/main/mcpStatus.cjs +2 -2
- package/src/main/memoryAggregate.cjs +3 -3
- package/src/main/memoryTool.cjs +1 -1
- package/src/main/otel.cjs +2 -2
- package/src/main/pluginInstall.cjs +29 -3
- package/src/main/projectBrief.cjs +6 -6
- package/src/main/projectPages.cjs +1 -1
- package/src/main/promptSessionEvents.cjs +2 -2
- package/src/main/pty.cjs +7 -7
- package/src/main/queueOps.cjs +6 -6
- package/src/main/remoteClient.cjs +4 -4
- package/src/main/remoteClientIpc.cjs +1 -1
- package/src/main/runVerify.cjs +6 -3
- package/src/main/scheduler/CLAUDE.md +26 -0
- package/src/main/scheduler/budget.cjs +576 -0
- package/src/main/scheduler/gitTreeGuard.cjs +672 -0
- package/src/main/scheduler/prdParser.cjs +4 -4
- package/src/main/scheduler/prdPaths.cjs +487 -0
- package/src/main/scheduler/reviewLadder.cjs +1011 -0
- package/src/main/scheduler/starvation.cjs +390 -0
- package/src/main/scheduler.cjs +331 -3320
- package/src/main/seedAgentPersonas.cjs +5 -5
- package/src/main/seedDevPlugin.cjs +70 -3
- package/src/main/seedSchedulerMcp.cjs +2 -2
- package/src/main/supervisor.cjs +50 -27
- package/src/main/telemetryIpc.cjs +51 -0
- package/src/main/transcripts.cjs +3 -3
- package/src/main/updaterIpc.cjs +1 -1
- package/src/main/usage.cjs +1 -1
- package/src/main/watchers.cjs +1 -1
- package/src/main/webRemote.cjs +22 -7
- package/src/preload/api.d.ts +14 -8
- package/src/preload/index.cjs +9 -3
- package/dist/assets/ProvenanceBadge-vC7Tj-JP.js +0 -1
- package/dist/assets/RemoteMachines-CWnKbFHc.js +0 -3
- package/dist/assets/Settings-DYDlp2m_.js +0 -4
- package/dist/assets/Skills-DHO0N0C2.js +0 -2
- package/dist/assets/SystemPrompt-DxeNofL9.js +0 -1
- package/dist/assets/TagLibrary-QOAs7ISO.js +0 -1
- package/plugins/session-manager-dev/skills/blog-for-project-feature/0-select/SKILL.md +0 -39
- package/plugins/session-manager-dev/skills/blog-for-project-feature/1-research/SKILL.md +0 -37
- package/plugins/session-manager-dev/skills/blog-for-project-feature/2-storyboard/SKILL.md +0 -64
- package/plugins/session-manager-dev/skills/blog-for-project-feature/3-capture/SKILL.md +0 -52
- package/plugins/session-manager-dev/skills/blog-for-project-feature/4-draft-copy/SKILL.md +0 -37
- package/plugins/session-manager-dev/skills/blog-for-project-feature/5-illustrate/SKILL.md +0 -50
- package/plugins/session-manager-dev/skills/blog-for-project-feature/6-compose/SKILL.md +0 -51
- package/plugins/session-manager-dev/skills/blog-for-project-feature/7-review/SKILL.md +0 -54
- package/plugins/session-manager-dev/skills/blog-for-project-feature/SKILL.md +0 -144
- package/plugins/session-manager-dev/skills/blog-for-project-feature/feature.config.yaml +0 -90
- package/plugins/session-manager-dev/skills/discover-features/SKILL.md +0 -95
- package/plugins/session-manager-dev/skills/explain-to-me/SKILL.md +0 -205
- package/plugins/session-manager-dev/skills/explain-to-me/assets/style-reference.html +0 -163
- package/plugins/session-manager-dev/skills/find-opportunity/SKILL.md +0 -83
- package/plugins/session-manager-dev/skills/issue-address/0-select/0-fetch-pool/SKILL.md +0 -38
- package/plugins/session-manager-dev/skills/issue-address/0-select/1-reject-fixed/SKILL.md +0 -64
- package/plugins/session-manager-dev/skills/issue-address/0-select/2-reject-claimed/SKILL.md +0 -71
- package/plugins/session-manager-dev/skills/issue-address/0-select/3-rank-impact/SKILL.md +0 -39
- package/plugins/session-manager-dev/skills/issue-address/0-select/SKILL.md +0 -75
- package/plugins/session-manager-dev/skills/issue-address/1-confirm-open/SKILL.md +0 -39
- package/plugins/session-manager-dev/skills/issue-address/2-claim/SKILL.md +0 -57
- package/plugins/session-manager-dev/skills/issue-address/3-reproduce/SKILL.md +0 -40
- package/plugins/session-manager-dev/skills/issue-address/4-fix/SKILL.md +0 -33
- package/plugins/session-manager-dev/skills/issue-address/5-verify/SKILL.md +0 -40
- package/plugins/session-manager-dev/skills/issue-address/SKILL.md +0 -120
- package/plugins/session-manager-dev/skills/local-project-health/SKILL.md +0 -58
- package/plugins/session-manager-dev/skills/memory-sanitation/SKILL.md +0 -147
- package/plugins/session-manager-dev/skills/ops-sweep/SKILL.md +0 -137
- package/plugins/session-manager-dev/skills/pr-review-sweep/0-fetch/SKILL.md +0 -41
- package/plugins/session-manager-dev/skills/pr-review-sweep/1-classify/SKILL.md +0 -56
- package/plugins/session-manager-dev/skills/pr-review-sweep/2-check-fixed/SKILL.md +0 -49
- package/plugins/session-manager-dev/skills/pr-review-sweep/3-queue/SKILL.md +0 -57
- package/plugins/session-manager-dev/skills/pr-review-sweep/4-land-and-resolve/SKILL.md +0 -60
- package/plugins/session-manager-dev/skills/pr-review-sweep/SKILL.md +0 -124
- package/plugins/session-manager-dev/skills/pr-signal/SKILL.md +0 -67
- package/plugins/session-manager-dev/skills/project-status/SKILL.md +0 -243
- package/plugins/session-manager-dev/skills/requesting-code-review/SKILL.md +0 -98
- package/plugins/session-manager-dev/skills/requesting-code-review/code-reviewer.md +0 -146
- package/src/main/lib/rateLimitDetect.cjs +0 -35
- /package/src/main/lib/{agentEffortResolve.cjs → claude/agentEffortResolve.cjs} +0 -0
- /package/src/main/lib/{claudeCliCaps.cjs → claude/claudeCliCaps.cjs} +0 -0
- /package/src/main/lib/{usageCircuit.cjs → claude/usageCircuit.cjs} +0 -0
- /package/src/main/lib/{epicSpawnCwd.cjs → epic/epicSpawnCwd.cjs} +0 -0
- /package/src/main/lib/{customerFeedbackAdminRoutes.cjs → feedback-remote/customerFeedbackAdminRoutes.cjs} +0 -0
- /package/src/main/lib/{remoteE2eCrypto.cjs → feedback-remote/remoteE2eCrypto.cjs} +0 -0
- /package/src/main/lib/{branchSweep.cjs → git/branchSweep.cjs} +0 -0
- /package/src/main/lib/{gitExec.cjs → git/gitExec.cjs} +0 -0
- /package/src/main/lib/{jobWorktree.cjs → git/jobWorktree.cjs} +0 -0
- /package/src/main/lib/{jobWorktreeBootLive.cjs → git/jobWorktreeBootLive.cjs} +0 -0
- /package/src/main/lib/{jobWorktreeTerminalOrphanLive.cjs → git/jobWorktreeTerminalOrphanLive.cjs} +0 -0
- /package/src/main/lib/{builtinMacros.cjs → persona-macro/builtinMacros.cjs} +0 -0
- /package/src/main/lib/{personaImportHealth.cjs → persona-macro/personaImportHealth.cjs} +0 -0
- /package/src/main/lib/{shippedPersonaSeeds.cjs → persona-macro/shippedPersonaSeeds.cjs} +0 -0
- /package/src/main/lib/{planValidator.cjs → prd/planValidator.cjs} +0 -0
- /package/src/main/lib/{prdAuthoringSeed.cjs → prd/prdAuthoringSeed.cjs} +0 -0
- /package/src/main/lib/{prdDisposition.cjs → prd/prdDisposition.cjs} +0 -0
- /package/src/main/lib/{prdFrontmatter.cjs → prd/prdFrontmatter.cjs} +0 -0
- /package/src/main/lib/{prdSizing.cjs → prd/prdSizing.cjs} +0 -0
- /package/src/main/lib/{workTypeLibrary.cjs → prd/workTypeLibrary.cjs} +0 -0
- /package/src/main/lib/{childWithLog.cjs → process/childWithLog.cjs} +0 -0
- /package/src/main/lib/{cleanEnv.cjs → process/cleanEnv.cjs} +0 -0
- /package/src/main/lib/{defaultShell.cjs → process/defaultShell.cjs} +0 -0
- /package/src/main/lib/{killTree.cjs → process/killTree.cjs} +0 -0
- /package/src/main/lib/{loginShellPath.cjs → process/loginShellPath.cjs} +0 -0
- /package/src/main/lib/{procIdentity.cjs → process/procIdentity.cjs} +0 -0
- /package/src/main/lib/{singleInstanceGuard.cjs → process/singleInstanceGuard.cjs} +0 -0
- /package/src/main/lib/{smProcNames.cjs → process/smProcNames.cjs} +0 -0
- /package/src/main/lib/{timeoutShimScript.cjs → process/timeoutShimScript.cjs} +0 -0
- /package/src/main/lib/{winSpawn.cjs → process/winSpawn.cjs} +0 -0
- /package/src/main/lib/{adoptedRunSupervisor.cjs → scheduler/adoptedRunSupervisor.cjs} +0 -0
- /package/src/main/lib/{dispatchLoop.cjs → scheduler/dispatchLoop.cjs} +0 -0
- /package/src/main/lib/{dodDrainHook.cjs → scheduler/dodDrainHook.cjs} +0 -0
- /package/src/main/lib/{fixPlanSlug.cjs → scheduler/fixPlanSlug.cjs} +0 -0
- /package/src/main/lib/{gateAuthority.cjs → scheduler/gateAuthority.cjs} +0 -0
- /package/src/main/lib/{landedSinceRun.cjs → scheduler/landedSinceRun.cjs} +0 -0
- /package/src/main/lib/{loadGate.cjs → scheduler/loadGate.cjs} +0 -0
- /package/src/main/lib/{needsReviewLedger.cjs → scheduler/needsReviewLedger.cjs} +0 -0
- /package/src/main/lib/{queueHealth.cjs → scheduler/queueHealth.cjs} +0 -0
- /package/src/main/lib/{queueHistory.cjs → scheduler/queueHistory.cjs} +0 -0
- /package/src/main/lib/{scheduleJobSchema.cjs → scheduler/scheduleJobSchema.cjs} +0 -0
- /package/src/main/lib/{schedulerPaths.cjs → scheduler/schedulerPaths.cjs} +0 -0
- /package/src/main/lib/{terminalRunOutcome.cjs → scheduler/terminalRunOutcome.cjs} +0 -0
- /package/src/main/lib/{validationSentinels.cjs → scheduler/validationSentinels.cjs} +0 -0
- /package/src/main/lib/{crashTelemetry.cjs → telemetry/crashTelemetry.cjs} +0 -0
- /package/src/main/lib/{otlpTraceExporter.cjs → telemetry/otlpTraceExporter.cjs} +0 -0
- /package/src/main/lib/{telemetryConsent.cjs → telemetry/telemetryConsent.cjs} +0 -0
- /package/src/main/lib/{telemetryCounters.cjs → telemetry/telemetryCounters.cjs} +0 -0
- /package/src/main/lib/{encodeCwd.cjs → util/encodeCwd.cjs} +0 -0
- /package/src/main/lib/{expandHome.cjs → util/expandHome.cjs} +0 -0
- /package/src/main/lib/{extractJson.cjs → util/extractJson.cjs} +0 -0
- /package/src/main/lib/{fileTail.cjs → util/fileTail.cjs} +0 -0
- /package/src/main/lib/{headTailBuffer.cjs → util/headTailBuffer.cjs} +0 -0
- /package/src/main/lib/{kebabCase.cjs → util/kebabCase.cjs} +0 -0
- /package/src/main/lib/{lruCache.cjs → util/lruCache.cjs} +0 -0
- /package/src/main/lib/{withTimeout.cjs → util/withTimeout.cjs} +0 -0
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* `seedVersion` frontmatter stamp (missing counts as 1) against the
|
|
13
13
|
* bundled file's own stamp. Same or higher stays untouched. Lower checks
|
|
14
14
|
* the installed file's body against every body this app has ever shipped
|
|
15
|
-
* for that persona (`lib/shippedPersonaSeeds.cjs`). No match means a
|
|
15
|
+
* for that persona (`lib/persona-macro/shippedPersonaSeeds.cjs`). No match means a
|
|
16
16
|
* person wrote or edited that file; it is left alone and the skip is
|
|
17
17
|
* logged. Why: a lower stamp alone does not prove the file is a stale
|
|
18
18
|
* shipped copy — only a body match does. A match replaces the installed
|
|
@@ -77,8 +77,8 @@ const path = require('node:path');
|
|
|
77
77
|
const os = require('node:os');
|
|
78
78
|
const crypto = require('node:crypto');
|
|
79
79
|
const { writeJsonSync, writeTextAtomic, validatePath, validateWrite } = require('./config.cjs');
|
|
80
|
-
const { splitFrontmatter } = require('./lib/prdFrontmatter.cjs');
|
|
81
|
-
const { SHIPPED_PERSONA_SEEDS } = require('./lib/shippedPersonaSeeds.cjs');
|
|
80
|
+
const { splitFrontmatter } = require('./lib/prd/prdFrontmatter.cjs');
|
|
81
|
+
const { SHIPPED_PERSONA_SEEDS } = require('./lib/persona-macro/shippedPersonaSeeds.cjs');
|
|
82
82
|
|
|
83
83
|
const PERSONAS = ['architect', 'dev-lead', 'project-home-builder', 'validator', 'demo-video-builder'];
|
|
84
84
|
// What `{ done: true }` (the pre-seeded-set marker format) meant: only these two personas existed
|
|
@@ -140,7 +140,7 @@ function normalizeNewlines(text) {
|
|
|
140
140
|
return text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
/** sha256 hex of a persona's body only (frontmatter stripped, newlines normalized, trimmed) — the key the upgrade pass matches against `lib/shippedPersonaSeeds.cjs`. */
|
|
143
|
+
/** sha256 hex of a persona's body only (frontmatter stripped, newlines normalized, trimmed) — the key the upgrade pass matches against `lib/persona-macro/shippedPersonaSeeds.cjs`. */
|
|
144
144
|
function personaBodyHash(text) {
|
|
145
145
|
const { body } = splitFrontmatter(normalizeNewlines(text));
|
|
146
146
|
return crypto.createHash('sha256').update(body.trim()).digest('hex');
|
|
@@ -269,7 +269,7 @@ function buildUpgradedPersona(bundledText, installedText, matches) {
|
|
|
269
269
|
* Replaces a stale installed persona with the current bundled one, once per
|
|
270
270
|
* boot, for every name in `PERSONAS` whose installed file is both PRESENT
|
|
271
271
|
* and behind the bundled `seedVersion` AND whose body matches a body this
|
|
272
|
-
* app has shipped before (`shippedSeeds`, normally `lib/shippedPersonaSeeds.cjs`
|
|
272
|
+
* app has shipped before (`shippedSeeds`, normally `lib/persona-macro/shippedPersonaSeeds.cjs`
|
|
273
273
|
* — injectable so tests can supply a fake list). See this file's header for
|
|
274
274
|
* the full rule, and `buildUpgradedPersona` for how frontmatter keys merge.
|
|
275
275
|
* Never overwrites a same-or-newer installed file, or one whose body never
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* First-boot seeder for the bundled `session-manager-dev` plugin.
|
|
3
3
|
*
|
|
4
|
-
* The plugin (
|
|
4
|
+
* The plugin (3 skills under plugins/session-manager-dev/skills: builder, develop, send-feedback) ships inside the npx distribution. To make it
|
|
5
5
|
* a true default, the app installs it on first launch from its own bundled
|
|
6
6
|
* marketplace (offline — no GitHub/registry). Idempotent two ways:
|
|
7
7
|
*
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
* plugin is already enabled (e.g. installed by hand), we just write the
|
|
17
17
|
* marker and skip the install.
|
|
18
18
|
*
|
|
19
|
+
* Stay-current pass (`upgradeIfStale`, like seedAgentPersonas' upgrade pass): runs on EVERY
|
|
20
|
+
* call, independent of the done-marker. If the plugin is installed AND enabled at a version
|
|
21
|
+
* older than the bundled plugin.json version, it runs the claude CLI marketplace update +
|
|
22
|
+
* plugin update. Never acts when not installed, disabled (a deliberate disable stays), or
|
|
23
|
+
* versions are equal/newer. Failures are logged, never thrown.
|
|
24
|
+
*
|
|
19
25
|
* Fire-and-forget: called post-window from index.cjs. Errors are logged, never
|
|
20
26
|
* thrown. Kill-switch: SM_SEED_DEV_PLUGIN_DISABLE=1.
|
|
21
27
|
*/
|
|
@@ -23,7 +29,7 @@
|
|
|
23
29
|
const fs = require('node:fs');
|
|
24
30
|
const path = require('node:path');
|
|
25
31
|
const os = require('node:os');
|
|
26
|
-
const { install } = require('./pluginInstall.cjs');
|
|
32
|
+
const { install, update } = require('./pluginInstall.cjs');
|
|
27
33
|
|
|
28
34
|
const PLUGIN_SLUG = 'session-manager-dev';
|
|
29
35
|
const MARKETPLACE = { add: 'bundled', name: 'session-manager' };
|
|
@@ -65,8 +71,69 @@ function writeMarker(state) {
|
|
|
65
71
|
}
|
|
66
72
|
}
|
|
67
73
|
|
|
74
|
+
/** Compare dotted numeric versions (pre-release suffixes ignored). <0, 0, >0. */
|
|
75
|
+
function compareSemver(a, b) {
|
|
76
|
+
const parse = (v) => String(v).split('-')[0].split('.').map((n) => Number(n) || 0);
|
|
77
|
+
const pa = parse(a);
|
|
78
|
+
const pb = parse(b);
|
|
79
|
+
for (let i = 0; i < Math.max(pa.length, pb.length, 3); i++) {
|
|
80
|
+
const d = (pa[i] || 0) - (pb[i] || 0);
|
|
81
|
+
if (d !== 0) return d;
|
|
82
|
+
}
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function readJson(p) {
|
|
87
|
+
try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function bundledVersion() {
|
|
91
|
+
const m = readJson(path.join(__dirname, '..', '..', 'plugins', PLUGIN_SLUG, '.claude-plugin', 'plugin.json'));
|
|
92
|
+
return typeof m?.version === 'string' ? m.version : null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Stay-current pass. Update the installed plugin when older than the bundled one.
|
|
97
|
+
* Never throws. Deps injectable for tests.
|
|
98
|
+
*/
|
|
99
|
+
async function upgradeIfStale({
|
|
100
|
+
logger = console,
|
|
101
|
+
writeLog = () => {},
|
|
102
|
+
home = os.homedir(),
|
|
103
|
+
bundledVersion: bundled = bundledVersion(),
|
|
104
|
+
runUpdate = update,
|
|
105
|
+
} = {}) {
|
|
106
|
+
if (process.env.SM_SEED_DEV_PLUGIN_DISABLE === '1') return;
|
|
107
|
+
try {
|
|
108
|
+
const entries = readJson(path.join(home, '.claude', 'plugins', 'installed_plugins.json'))?.plugins?.[ENABLED_KEY];
|
|
109
|
+
const installedVersion = Array.isArray(entries) ? entries[0]?.version : null;
|
|
110
|
+
if (!installedVersion || !bundled) return; // not installed / no bundle
|
|
111
|
+
const enabled = readJson(path.join(home, '.claude', 'settings.json'))?.enabledPlugins;
|
|
112
|
+
if (!enabled?.[ENABLED_KEY]) return; // deliberate disable stays
|
|
113
|
+
if (compareSemver(installedVersion, bundled) >= 0) return; // current or newer
|
|
114
|
+
logger.log?.(`[seedDevPlugin] updating ${ENABLED_KEY} ${installedVersion} → ${bundled}`);
|
|
115
|
+
const r = await runUpdate({ slug: PLUGIN_SLUG, marketplaceName: MARKETPLACE.name });
|
|
116
|
+
if (!r?.ok) {
|
|
117
|
+
writeLog({
|
|
118
|
+
scope: 'seed-dev-plugin',
|
|
119
|
+
level: 'error',
|
|
120
|
+
message: 'upgrade failed',
|
|
121
|
+
meta: { exitCode: r?.exitCode, error: r?.error, from: installedVersion, to: bundled },
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
} catch (err) {
|
|
125
|
+
writeLog({
|
|
126
|
+
scope: 'seed-dev-plugin',
|
|
127
|
+
level: 'error',
|
|
128
|
+
message: 'upgrade error',
|
|
129
|
+
meta: { error: err?.message ?? String(err) },
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
68
134
|
async function seedDevPlugin({ logger = console, writeLog = () => {} } = {}) {
|
|
69
135
|
if (process.env.SM_SEED_DEV_PLUGIN_DISABLE === '1') return;
|
|
136
|
+
await upgradeIfStale({ logger, writeLog });
|
|
70
137
|
const marker = readMarker();
|
|
71
138
|
if (marker.done) return; // succeeded before — leave it alone.
|
|
72
139
|
if (marker.attempts >= MAX_ATTEMPTS) return; // gave up — manual install only.
|
|
@@ -104,4 +171,4 @@ async function seedDevPlugin({ logger = console, writeLog = () => {} } = {}) {
|
|
|
104
171
|
}
|
|
105
172
|
}
|
|
106
173
|
|
|
107
|
-
module.exports = { seedDevPlugin, markerPath, MAX_ATTEMPTS };
|
|
174
|
+
module.exports = { seedDevPlugin, upgradeIfStale, compareSemver, markerPath, MAX_ATTEMPTS };
|
|
@@ -35,8 +35,8 @@ const fs = require('node:fs');
|
|
|
35
35
|
const path = require('node:path');
|
|
36
36
|
const os = require('node:os');
|
|
37
37
|
const { spawn } = require('node:child_process');
|
|
38
|
-
const { resolveClaudeBin, claudeSpawnTarget } = require('./lib/claudeBin.cjs');
|
|
39
|
-
const { cleanChildEnv, pathWithUserBins } = require('./lib/cleanEnv.cjs');
|
|
38
|
+
const { resolveClaudeBin, claudeSpawnTarget } = require('./lib/claude/claudeBin.cjs');
|
|
39
|
+
const { cleanChildEnv, pathWithUserBins } = require('./lib/process/cleanEnv.cjs');
|
|
40
40
|
const { writeJsonSync } = require('./config.cjs');
|
|
41
41
|
const { nodeSpawnSpec } = require('./lib/appRuntime.cjs');
|
|
42
42
|
|
package/src/main/supervisor.cjs
CHANGED
|
@@ -16,10 +16,10 @@ const path = require('node:path');
|
|
|
16
16
|
const os = require('node:os');
|
|
17
17
|
const { spawn, execFileSync } = require('node:child_process');
|
|
18
18
|
const { ipcMain } = require('electron');
|
|
19
|
-
const { resolveClaudeBin, claudeSpawnTarget } = require('./lib/claudeBin.cjs');
|
|
20
|
-
const { headlessPermissionArgs, ensureCliCapsProbed } = require('./lib/claudeCliCaps.cjs');
|
|
21
|
-
const { withProcRole } = require('./lib/cleanEnv.cjs');
|
|
22
|
-
const schedulerPaths = require('./lib/schedulerPaths.cjs');
|
|
19
|
+
const { resolveClaudeBin, claudeSpawnTarget } = require('./lib/claude/claudeBin.cjs');
|
|
20
|
+
const { headlessPermissionArgs, ensureCliCapsProbed } = require('./lib/claude/claudeCliCaps.cjs');
|
|
21
|
+
const { withProcRole } = require('./lib/process/cleanEnv.cjs');
|
|
22
|
+
const schedulerPaths = require('./lib/scheduler/schedulerPaths.cjs');
|
|
23
23
|
|
|
24
24
|
const HOME = os.homedir();
|
|
25
25
|
const SUPERVISOR_LOG_PATH = path.join(HOME, '.claude', 'session-manager', 'supervisor.log');
|
|
@@ -103,7 +103,7 @@ function getChildBashCmdlines(jobPid) {
|
|
|
103
103
|
|
|
104
104
|
// ─── Log tail helpers ───────────────────────────────────────────────────────
|
|
105
105
|
|
|
106
|
-
const { readTail: readTailBytes } = require('./lib/fileTail.cjs');
|
|
106
|
+
const { readTail: readTailBytes } = require('./lib/util/fileTail.cjs');
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
109
|
* Skim the last 16 KB of a run log for the most recent assistant/user/result
|
|
@@ -205,6 +205,41 @@ Decision rules:
|
|
|
205
205
|
- "stuck"/kill-agent only if the agent itself is wedged (no child processes, no recent log events, > 60 min stale). Set targetPid to the claude root pid.`;
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Parse `claude -p --output-format json` stdout from a probe.
|
|
210
|
+
* @param {string} stdout
|
|
211
|
+
* @returns {{ verdictObj: any, costUsd: number|null, errorSubtype: string|null }}
|
|
212
|
+
*/
|
|
213
|
+
function parseProbeOutput(stdout) {
|
|
214
|
+
let costUsd = null;
|
|
215
|
+
let verdictObj = null;
|
|
216
|
+
let errorSubtype = null;
|
|
217
|
+
|
|
218
|
+
// --output-format json emits a single JSON result object.
|
|
219
|
+
// The `result` field contains the assistant's raw text response.
|
|
220
|
+
for (const line of String(stdout).split('\n').reverse()) {
|
|
221
|
+
const trimmed = line.trim();
|
|
222
|
+
if (!trimmed) continue;
|
|
223
|
+
try {
|
|
224
|
+
const obj = JSON.parse(trimmed);
|
|
225
|
+
if (!obj || typeof obj !== 'object') continue;
|
|
226
|
+
if (typeof obj.total_cost_usd === 'number') costUsd = obj.total_cost_usd;
|
|
227
|
+
if (obj.is_error === true || (typeof obj.subtype === 'string' && obj.subtype !== 'success')) {
|
|
228
|
+
errorSubtype = typeof obj.subtype === 'string' && obj.subtype ? obj.subtype : 'error';
|
|
229
|
+
}
|
|
230
|
+
// Extract verdict from the result text field (assistant's response).
|
|
231
|
+
if (obj.result && typeof obj.result === 'string') {
|
|
232
|
+
const m = obj.result.match(/\{[^{}]+\}/);
|
|
233
|
+
if (m) {
|
|
234
|
+
try { verdictObj = JSON.parse(m[0]); } catch { /* */ }
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} catch { /* not JSON */ }
|
|
238
|
+
if (verdictObj) break;
|
|
239
|
+
}
|
|
240
|
+
return { verdictObj, costUsd, errorSubtype };
|
|
241
|
+
}
|
|
242
|
+
|
|
208
243
|
async function runProbe(claudeBin, prompt) {
|
|
209
244
|
await ensureCliCapsProbed();
|
|
210
245
|
return new Promise((resolve) => {
|
|
@@ -213,10 +248,10 @@ async function runProbe(claudeBin, prompt) {
|
|
|
213
248
|
const target = claudeSpawnTarget('aux', 'supervisor', claudeBin);
|
|
214
249
|
child = spawn(target.command, [
|
|
215
250
|
'-p', prompt,
|
|
216
|
-
'--model', 'claude-
|
|
251
|
+
'--model', 'claude-haiku-5-5',
|
|
217
252
|
'--no-session-persistence',
|
|
218
253
|
'--output-format', 'json',
|
|
219
|
-
'--max-budget-usd', '0.
|
|
254
|
+
'--max-budget-usd', '0.50',
|
|
220
255
|
'--dangerously-skip-permissions',
|
|
221
256
|
...headlessPermissionArgs(),
|
|
222
257
|
'--allowedTools', 'Bash',
|
|
@@ -254,26 +289,13 @@ async function runProbe(claudeBin, prompt) {
|
|
|
254
289
|
child.on('exit', () => {
|
|
255
290
|
clearTimers();
|
|
256
291
|
const stdout = Buffer.concat(stdoutChunks).toString('utf8');
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (!trimmed) continue;
|
|
265
|
-
try {
|
|
266
|
-
const obj = JSON.parse(trimmed);
|
|
267
|
-
if (typeof obj.total_cost_usd === 'number') costUsd = obj.total_cost_usd;
|
|
268
|
-
// Extract verdict from the result text field (assistant's response).
|
|
269
|
-
if (obj.result && typeof obj.result === 'string') {
|
|
270
|
-
const m = obj.result.match(/\{[^{}]+\}/);
|
|
271
|
-
if (m) {
|
|
272
|
-
try { verdictObj = JSON.parse(m[0]); } catch { /* */ }
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
} catch { /* not JSON */ }
|
|
276
|
-
if (verdictObj) break;
|
|
292
|
+
const { verdictObj, costUsd, errorSubtype } = parseProbeOutput(stdout);
|
|
293
|
+
|
|
294
|
+
if ((!verdictObj || !verdictObj.verdict) && errorSubtype) {
|
|
295
|
+
// Budget cap / CLI error exit: record it distinctly, never as a real verdict.
|
|
296
|
+
console.warn('[supervisor] probe error exit (treating as ok):', errorSubtype);
|
|
297
|
+
resolve({ verdict: 'ok', action: 'none', targetPid: null, reason: `probe_error:${errorSubtype}`, costUsd });
|
|
298
|
+
return;
|
|
277
299
|
}
|
|
278
300
|
|
|
279
301
|
if (!verdictObj || !verdictObj.verdict) {
|
|
@@ -506,4 +528,5 @@ module.exports = {
|
|
|
506
528
|
supervisorTick,
|
|
507
529
|
applyAction,
|
|
508
530
|
registerHandlers,
|
|
531
|
+
parseProbeOutput,
|
|
509
532
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* telemetryIpc.cjs — registers the `otel:*` and `telemetry:*` IPC handlers. Moved verbatim out of
|
|
5
|
+
* index.cjs; channel names and handler bodies are unchanged.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { schemas, validated } = require('./ipcSchemas.cjs');
|
|
9
|
+
const otel = require('./otel.cjs');
|
|
10
|
+
const otelSettings = require('./otelSettings.cjs');
|
|
11
|
+
const telemetrySettings = require('./lib/telemetry/telemetrySettings.cjs');
|
|
12
|
+
const telemetryClient = require('./lib/telemetry/telemetryClient.cjs');
|
|
13
|
+
const telemetryBacklog = require('./lib/telemetry/telemetryBacklog.cjs');
|
|
14
|
+
const telemetryConsent = require('./lib/telemetry/telemetryConsent.cjs');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {{ ipcMain: any }} opts
|
|
18
|
+
*/
|
|
19
|
+
function registerTelemetryHandlers({ ipcMain }) {
|
|
20
|
+
// OTEL telemetry export (opt-in via ~/.claude/session-manager/otel.json).
|
|
21
|
+
ipcMain.handle('otel:get-config', async () => otelSettings.load());
|
|
22
|
+
ipcMain.handle('otel:set-config', async (_e, cfg) => {
|
|
23
|
+
if (!otelSettings.isValid(cfg)) {
|
|
24
|
+
return { ok: false, error: 'invalid config' };
|
|
25
|
+
}
|
|
26
|
+
const saved = await otelSettings.save(cfg);
|
|
27
|
+
const result = await otel.applyConfig(saved);
|
|
28
|
+
return { ok: !!result?.ok, error: result?.error ?? null, config: saved, status: otel.status() };
|
|
29
|
+
});
|
|
30
|
+
ipcMain.handle('otel:status', () => otel.status());
|
|
31
|
+
ipcMain.handle('otel:config-path', () => otelSettings.storePath());
|
|
32
|
+
|
|
33
|
+
// Product telemetry (bilko.run) — anonymous, on-by-default, opt-out consent
|
|
34
|
+
// UX + inspector over the client PRDs above wired. Settings > Telemetry's
|
|
35
|
+
// "Product telemetry" section is the sole UI surface for this; see
|
|
36
|
+
// session-manager-operations/architecture/telemetry.md for the data model.
|
|
37
|
+
ipcMain.handle('telemetry:get-config', async () => telemetrySettings.load());
|
|
38
|
+
ipcMain.handle('telemetry:set-config', validated(schemas.telemetrySetConfig, async (cfg) => {
|
|
39
|
+
const saved = await telemetryConsent.applyConsentUpdate(cfg, { telemetrySettings, telemetryClient });
|
|
40
|
+
return { ok: true, config: saved, status: telemetryClient.status() };
|
|
41
|
+
}));
|
|
42
|
+
ipcMain.handle('telemetry:status', () => ({
|
|
43
|
+
...telemetryClient.status(),
|
|
44
|
+
backlog: telemetryBacklog.lastRunSummary(),
|
|
45
|
+
}));
|
|
46
|
+
ipcMain.handle('telemetry:config-path', () => telemetrySettings.storePath());
|
|
47
|
+
ipcMain.handle('telemetry:recent-records', () => telemetryClient.recentRecords());
|
|
48
|
+
ipcMain.handle('telemetry:flush-now', () => telemetryClient.flush('manual'));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = { registerTelemetryHandlers };
|
package/src/main/transcripts.cjs
CHANGED
|
@@ -36,10 +36,10 @@ function attachWindow(w) {
|
|
|
36
36
|
window = w;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
const { encodeCwd } = require('./lib/encodeCwd.cjs');
|
|
40
|
-
const { LRUCache } = require('./lib/lruCache.cjs');
|
|
39
|
+
const { encodeCwd } = require('./lib/util/encodeCwd.cjs');
|
|
40
|
+
const { LRUCache } = require('./lib/util/lruCache.cjs');
|
|
41
41
|
const { classifyLine } = require('./lib/classifyTranscriptLine.cjs');
|
|
42
|
-
const { resolveEpicTranscriptPath } = require('./lib/epicTranscriptPath.cjs');
|
|
42
|
+
const { resolveEpicTranscriptPath } = require('./lib/epic/epicTranscriptPath.cjs');
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Where the CLI's JSONL for this session lives. Epic sessions run in a
|
package/src/main/updaterIpc.cjs
CHANGED
|
@@ -28,7 +28,7 @@ function defaultDeps() {
|
|
|
28
28
|
platform: process.platform,
|
|
29
29
|
env: process.env,
|
|
30
30
|
settings: require('./lib/updaterSettings.cjs'),
|
|
31
|
-
sessionSlots: require('./lib/sessionSlots.cjs'),
|
|
31
|
+
sessionSlots: require('./lib/scheduler/sessionSlots.cjs'),
|
|
32
32
|
currentVersion: () => require('electron').app.getVersion(),
|
|
33
33
|
log: (message, meta) => {
|
|
34
34
|
try {
|
package/src/main/usage.cjs
CHANGED
|
@@ -23,7 +23,7 @@ const os = require('node:os');
|
|
|
23
23
|
const { ipcMain } = require('electron');
|
|
24
24
|
const { refreshIfNeeded, expiresAtMs } = require('./lib/credentials.cjs');
|
|
25
25
|
const { writeJson } = require('./config.cjs');
|
|
26
|
-
const { createUsageCircuit, singleFlight } = require('./lib/usageCircuit.cjs');
|
|
26
|
+
const { createUsageCircuit, singleFlight } = require('./lib/claude/usageCircuit.cjs');
|
|
27
27
|
|
|
28
28
|
const USAGE_URL = 'https://api.anthropic.com/api/oauth/usage';
|
|
29
29
|
|
package/src/main/watchers.cjs
CHANGED
|
@@ -14,7 +14,7 @@ const crypto = require('node:crypto');
|
|
|
14
14
|
const path = require('node:path');
|
|
15
15
|
const os = require('node:os');
|
|
16
16
|
const fs = require('node:fs');
|
|
17
|
-
const { cleanChildEnv } = require('./lib/cleanEnv.cjs');
|
|
17
|
+
const { cleanChildEnv } = require('./lib/process/cleanEnv.cjs');
|
|
18
18
|
const { checkInsideHome } = require('./lib/insideHome.cjs');
|
|
19
19
|
const { sendIfAlive } = require('./lib/sendToRenderer.cjs');
|
|
20
20
|
|
package/src/main/webRemote.cjs
CHANGED
|
@@ -27,11 +27,11 @@ const fs = require('node:fs');
|
|
|
27
27
|
const { writeTextAtomic, validatePath } = require('./config.cjs');
|
|
28
28
|
const logs = require('./logs.cjs');
|
|
29
29
|
const { sendIfAlive } = require('./lib/sendToRenderer.cjs');
|
|
30
|
-
const { claudeHome } = require('./lib/schedulerPaths.cjs');
|
|
30
|
+
const { claudeHome } = require('./lib/scheduler/schedulerPaths.cjs');
|
|
31
31
|
const { schemas } = require('./ipcSchemas.cjs');
|
|
32
32
|
const { summarize: _sharedSummarize } = require('./lib/summarize.cjs');
|
|
33
33
|
const { makeState, confirmSas: confirmSasLogic } = require('./lib/e2eStateMachine.cjs');
|
|
34
|
-
const { createClientSessions, LEGACY_CLIENT_KEY } = require('./lib/remoteClientSessions.cjs');
|
|
34
|
+
const { createClientSessions, LEGACY_CLIENT_KEY } = require('./lib/feedback-remote/remoteClientSessions.cjs');
|
|
35
35
|
|
|
36
36
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
37
37
|
|
|
@@ -69,8 +69,8 @@ const MSG_MAX_BYTES = 256 * 1024;
|
|
|
69
69
|
const { ALLOWED_COMMANDS, MUTATE_COMMANDS, SAS_GATED_READS } = require('./ipcSchemas.cjs');
|
|
70
70
|
|
|
71
71
|
// ─── E2E encryption helpers (P-256 ECDH + AES-256-GCM, ADR §5.2) ────────────
|
|
72
|
-
// Implemented in ./lib/remoteE2eCrypto.cjs (shared with the desktop client role).
|
|
73
|
-
const { generateE2EKeyPair, deriveSessionKey, deriveSas, encryptBox, decryptBox } = require('./lib/remoteE2eCrypto.cjs');
|
|
72
|
+
// Implemented in ./lib/feedback-remote/remoteE2eCrypto.cjs (shared with the desktop client role).
|
|
73
|
+
const { generateE2EKeyPair, deriveSessionKey, deriveSas, encryptBox, decryptBox } = require('./lib/feedback-remote/remoteE2eCrypto.cjs');
|
|
74
74
|
|
|
75
75
|
// ─── Module state ────────────────────────────────────────────────────────────
|
|
76
76
|
|
|
@@ -83,6 +83,7 @@ let _pongTimer = null;
|
|
|
83
83
|
let _missedPongs = 0;
|
|
84
84
|
let _configCache = null;
|
|
85
85
|
let _configCacheAt = 0;
|
|
86
|
+
let _repairNeeded = false; // relay rejected the device token (invalid_token / 401): terminal until re-pair
|
|
86
87
|
let _destroyed = false; // set at app shutdown to stop reconnect loops
|
|
87
88
|
|
|
88
89
|
// E2E session state — reset on each new WS connection.
|
|
@@ -274,6 +275,7 @@ function computeStatus(cfg) {
|
|
|
274
275
|
enabled: cfg.remoteEnabled,
|
|
275
276
|
remoteControlEnabled: cfg.remoteControlEnabled ?? false,
|
|
276
277
|
connected,
|
|
278
|
+
linkState: _repairNeeded ? 'repair-needed' : 'ok',
|
|
277
279
|
e2eActive: connected && _clients.values().some((r) => r.e2e.sessionKey !== null),
|
|
278
280
|
e2eAuthenticated: connected && authed !== null,
|
|
279
281
|
e2eState: connected ? e2eState : 'idle',
|
|
@@ -389,9 +391,18 @@ async function connect() {
|
|
|
389
391
|
scope: 'webRemote', level: 'warn',
|
|
390
392
|
message: 'device ticket request failed', meta: { error: e?.message },
|
|
391
393
|
});
|
|
394
|
+
// invalid_token / 401 is final (device unpaired server-side): retrying only
|
|
395
|
+
// spams the relay. Park in repair-needed until a new pair stores a fresh token.
|
|
396
|
+
if (e?.message === 'invalid_token' || e?.message === 'HTTP 401') {
|
|
397
|
+
cancelReconnect();
|
|
398
|
+
_repairNeeded = true;
|
|
399
|
+
broadcastStatus();
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
392
402
|
scheduleReconnect();
|
|
393
403
|
return;
|
|
394
404
|
}
|
|
405
|
+
_repairNeeded = false;
|
|
395
406
|
|
|
396
407
|
// Step 2: open WSS connection with the ticket.
|
|
397
408
|
let ws;
|
|
@@ -735,7 +746,7 @@ async function pushSessionList() {
|
|
|
735
746
|
const data = await sessionsStore.load();
|
|
736
747
|
// Tabs + their ACTIVE Epics → SessionMeta. tabId === claude sessionId so it
|
|
737
748
|
// matches the transcript JSONL name used by cmd:session:subscribe.
|
|
738
|
-
const { readActiveIndex } = require('./lib/epicMint.cjs');
|
|
749
|
+
const { readActiveIndex } = require('./lib/epic/epicMint.cjs');
|
|
739
750
|
const sessions = buildRemoteSessionList(data?.tabs ?? [], readActiveIndex).map((s) => ({
|
|
740
751
|
...s,
|
|
741
752
|
state: _sessionWatchers.get(s.tabId)?.state ?? null,
|
|
@@ -1092,7 +1103,7 @@ function getDispatchMap() {
|
|
|
1092
1103
|
sessionsStore.load(),
|
|
1093
1104
|
|
|
1094
1105
|
'cmd:sessions:list': async () => {
|
|
1095
|
-
const { readActiveIndex } = require('./lib/epicMint.cjs');
|
|
1106
|
+
const { readActiveIndex } = require('./lib/epic/epicMint.cjs');
|
|
1096
1107
|
const data = await sessionsStore.load();
|
|
1097
1108
|
return {
|
|
1098
1109
|
sessions: buildRemoteSessionList(data?.tabs ?? [], readActiveIndex),
|
|
@@ -1196,7 +1207,7 @@ function getDispatchMap() {
|
|
|
1196
1207
|
'cmd:session:options': async () => {
|
|
1197
1208
|
const { EpicTagSchema } = require('./lib/promptSessionSchema.cjs');
|
|
1198
1209
|
const agentLibrary = require('./agentLibrary.cjs');
|
|
1199
|
-
const macroLibrary = require('./lib/macroLibrary.cjs');
|
|
1210
|
+
const macroLibrary = require('./lib/persona-macro/macroLibrary.cjs');
|
|
1200
1211
|
const { tabs } = await sessionsStore.load();
|
|
1201
1212
|
const personas = await agentLibrary.listPersonas();
|
|
1202
1213
|
return {
|
|
@@ -1278,6 +1289,7 @@ async function pair(otp) {
|
|
|
1278
1289
|
}];
|
|
1279
1290
|
|
|
1280
1291
|
await saveConfig({ ...cfg, devices });
|
|
1292
|
+
_repairNeeded = false;
|
|
1281
1293
|
|
|
1282
1294
|
if (cfg.remoteEnabled) {
|
|
1283
1295
|
connect().catch(() => {});
|
|
@@ -1480,6 +1492,9 @@ module.exports = {
|
|
|
1480
1492
|
getDispatchMap,
|
|
1481
1493
|
buildRemoteSessionList,
|
|
1482
1494
|
setWs: (ws) => { _ws = ws; },
|
|
1495
|
+
connect,
|
|
1496
|
+
hasReconnectTimer: () => _reconnectTimer !== null,
|
|
1497
|
+
cancelReconnect,
|
|
1483
1498
|
invalidateConfigCache,
|
|
1484
1499
|
setE2eAuthenticated: (key, clientKey = LEGACY_CLIENT_KEY) => {
|
|
1485
1500
|
_clients.getOrCreate(clientKey).e2e = makeState('authenticated', key, null);
|
package/src/preload/api.d.ts
CHANGED
|
@@ -254,7 +254,7 @@ export interface McpCatalogResult {
|
|
|
254
254
|
recipes: McpRecipe[];
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
/** Mirrors WorkType (src/main/lib/workTypeLibrary.cjs) / EpicTag (tagLibrary.ts) — the
|
|
257
|
+
/** Mirrors WorkType (src/main/lib/prd/workTypeLibrary.cjs) / EpicTag (tagLibrary.ts) — the
|
|
258
258
|
* same Epic-mission taxonomy, reused here since an Agent persona's `tags` field is that
|
|
259
259
|
* same concept, not a free-form string list. */
|
|
260
260
|
export type AgentPersonaTag = 'feature' | 'bug' | 'discussion' | 'build' | 'project-home-builder';
|
|
@@ -491,7 +491,7 @@ export interface OtelSetConfigResult {
|
|
|
491
491
|
}
|
|
492
492
|
|
|
493
493
|
// Customer feedback — client submissions + owner inbox. Shapes mirror
|
|
494
|
-
// src/main/lib/customerFeedbackClient.cjs and customerFeedbackInbox.cjs.
|
|
494
|
+
// src/main/lib/feedback-remote/customerFeedbackClient.cjs and customerFeedbackInbox.cjs.
|
|
495
495
|
export type CustomerFeedbackTag = 'bug' | 'feature' | 'discussion';
|
|
496
496
|
export type CustomerFeedbackStatus = 'open' | 'in_progress' | 'resolved' | 'wontfix';
|
|
497
497
|
|
|
@@ -610,7 +610,7 @@ export interface ScheduleConfig {
|
|
|
610
610
|
schemaVersion: 1;
|
|
611
611
|
}
|
|
612
612
|
|
|
613
|
-
/** Mirrors JOB_STATUSES (src/main/lib/scheduleJobSchema.cjs) — the single
|
|
613
|
+
/** Mirrors JOB_STATUSES (src/main/lib/scheduler/scheduleJobSchema.cjs) — the single
|
|
614
614
|
* source of truth asserted at read time by queueStore.cjs's shapeJobs. This
|
|
615
615
|
* file can't require that .cjs module (types-only, erased at build time),
|
|
616
616
|
* so this union is a manually-kept copy; drift from JOB_STATUSES (and from
|
|
@@ -868,7 +868,7 @@ export interface ScheduleJobHold {
|
|
|
868
868
|
reason?: string | null;
|
|
869
869
|
}
|
|
870
870
|
|
|
871
|
-
/** Why a headless run never got a model turn (lib/launchFailure.cjs, issue #11). */
|
|
871
|
+
/** Why a headless run never got a model turn (lib/scheduler/launchFailure.cjs, issue #11). */
|
|
872
872
|
export type ScheduleLaunchFailureKind =
|
|
873
873
|
| 'model_config_rejected'
|
|
874
874
|
| 'bad_request'
|
|
@@ -1495,6 +1495,8 @@ export interface ChatRunPayload {
|
|
|
1495
1495
|
/** Originating PromptTicket.id (PRD 748) when dequeued from a tab's
|
|
1496
1496
|
* prompt queue — absent for a fresh manual send. */
|
|
1497
1497
|
promptId?: string;
|
|
1498
|
+
/** Who wrote the prompt: a local human, an injected external source, or an Epic proposal from another project. */
|
|
1499
|
+
origin?: 'human' | 'external' | 'inbound-proposal';
|
|
1498
1500
|
}
|
|
1499
1501
|
|
|
1500
1502
|
export interface ChatCreatePrdPayload {
|
|
@@ -1649,6 +1651,8 @@ export interface WebRemoteStatus {
|
|
|
1649
1651
|
enabled: boolean;
|
|
1650
1652
|
remoteControlEnabled: boolean;
|
|
1651
1653
|
connected: boolean;
|
|
1654
|
+
/** 'repair-needed' once the relay rejected the device token; the device must be re-paired. */
|
|
1655
|
+
linkState?: 'ok' | 'repair-needed';
|
|
1652
1656
|
e2eActive: boolean;
|
|
1653
1657
|
/** True once the user has confirmed the SAS on the desktop. */
|
|
1654
1658
|
e2eAuthenticated: boolean;
|
|
@@ -2260,28 +2264,30 @@ export interface SessionManagerAPI {
|
|
|
2260
2264
|
}) => Promise<Exchange[]>;
|
|
2261
2265
|
};
|
|
2262
2266
|
promptSessions: {
|
|
2267
|
+
/** Main requests approve-and-start of a verified inbound proposal. */
|
|
2268
|
+
onInboundAutoApprove: (handler: (e: { cwd: string; epicId: string }) => void) => () => void;
|
|
2263
2269
|
/** Fires when the main process appends an event to a PromptSession's
|
|
2264
2270
|
* chain on disk (currently only the scheduler's response-event append
|
|
2265
2271
|
* from notifyOriginatingTab) — lets an already-hydrated Epic pick it up
|
|
2266
2272
|
* live instead of waiting for a restart. */
|
|
2267
2273
|
onEventAppended: (handler: (e: PromptSessionEventAppendedPayload) => void) => () => void;
|
|
2268
2274
|
/** Main-side read-merge-write of a cwd's active-index.json
|
|
2269
|
-
* (lib/activeIndexMerge.cjs) — persistActiveIndex sends only its own
|
|
2275
|
+
* (lib/epic/activeIndexMerge.cjs) — persistActiveIndex sends only its own
|
|
2270
2276
|
* in-memory contribution for the cwd; disk stays main's truth, merged
|
|
2271
2277
|
* inside the same lock epicMint.cjs's ensureEpic serializes through. */
|
|
2272
2278
|
mergeActiveIndex: (payload: PromptSessionsMergeActiveIndexPayload) => Promise<PromptSessionsMergeActiveIndexResult>;
|
|
2273
2279
|
/** Mints a brand-new 'proposed' Epic through main's own ensureEpic()
|
|
2274
|
-
* (lib/promptSessionsCreateEpic.cjs) instead of the renderer
|
|
2280
|
+
* (lib/epic/promptSessionsCreateEpic.cjs) instead of the renderer
|
|
2275
2281
|
* hand-constructing the PromptSession record itself. Unused today —
|
|
2276
2282
|
* additive step 1 of a two-PRD chain; a later PRD routes
|
|
2277
2283
|
* createPromptSession through this. */
|
|
2278
2284
|
create: (payload: PromptSessionsCreateEpicPayload) => Promise<PromptSessionsCreateEpicResult>;
|
|
2279
2285
|
/** Creates this Epic's isolated `git worktree` checkout
|
|
2280
|
-
* (lib/epicWorktreeMint.cjs) — resolves to the `worktree` field shape on
|
|
2286
|
+
* (lib/epic/epicWorktreeMint.cjs) — resolves to the `worktree` field shape on
|
|
2281
2287
|
* success, or null on any failure (never rejects). */
|
|
2282
2288
|
createWorktree: (payload: PromptSessionsCreateWorktreePayload) => Promise<PromptSessionsCreateWorktreeResult | null>;
|
|
2283
2289
|
/** Folds an Epic's isolated git worktree branch back into its owning
|
|
2284
|
-
* project's main tree (lib/epicWorktreeMerge.cjs) — the ONLY point
|
|
2290
|
+
* project's main tree (lib/epic/epicWorktreeMerge.cjs) — the ONLY point
|
|
2285
2291
|
* where PRD 1033's per-Epic isolation resolves back into the shared
|
|
2286
2292
|
* tree. Never rejects. */
|
|
2287
2293
|
mergeToMain: (payload: PromptSessionsMergeToMainPayload) => Promise<PromptSessionsMergeToMainResult>;
|
package/src/preload/index.cjs
CHANGED
|
@@ -543,6 +543,12 @@ contextBridge.exposeInMainWorld('api', {
|
|
|
543
543
|
list: (payload) => ipcRenderer.invoke('exchanges:list', payload),
|
|
544
544
|
},
|
|
545
545
|
promptSessions: {
|
|
546
|
+
/** Main asks the renderer to approve-and-start a verified inbound proposal. */
|
|
547
|
+
onInboundAutoApprove: (handler) => {
|
|
548
|
+
const listener = (_e, payload) => handler(payload);
|
|
549
|
+
ipcRenderer.on('promptSessions:inbound-auto-approve', listener);
|
|
550
|
+
return () => ipcRenderer.removeListener('promptSessions:inbound-auto-approve', listener);
|
|
551
|
+
},
|
|
546
552
|
/** Fires when the main process (currently only the scheduler's
|
|
547
553
|
* response-event append) appends an event to a PromptSession's chain on
|
|
548
554
|
* disk — lets an already-hydrated Epic pick it up live instead of
|
|
@@ -553,12 +559,12 @@ contextBridge.exposeInMainWorld('api', {
|
|
|
553
559
|
return () => ipcRenderer.removeListener('promptSession:event-appended', listener);
|
|
554
560
|
},
|
|
555
561
|
/** Main-side read-merge-write of a cwd's active-index.json
|
|
556
|
-
* (lib/activeIndexMerge.cjs) — replaces persistActiveIndex's old
|
|
562
|
+
* (lib/epic/activeIndexMerge.cjs) — replaces persistActiveIndex's old
|
|
557
563
|
* renderer-side read-merge-write. Payload carries only this renderer's
|
|
558
564
|
* own in-memory contribution for the cwd; disk stays main's truth. */
|
|
559
565
|
mergeActiveIndex: (payload) => ipcRenderer.invoke('promptSessions:merge-active-index', payload),
|
|
560
566
|
/** Mints a brand-new 'proposed' Epic through main's own ensureEpic()
|
|
561
|
-
* (lib/promptSessionsCreateEpic.cjs) instead of the renderer
|
|
567
|
+
* (lib/epic/promptSessionsCreateEpic.cjs) instead of the renderer
|
|
562
568
|
* hand-constructing the PromptSession record itself. Unused today —
|
|
563
569
|
* additive step 1 of a two-PRD chain; a later PRD routes
|
|
564
570
|
* createPromptSession through this. */
|
|
@@ -571,7 +577,7 @@ contextBridge.exposeInMainWorld('api', {
|
|
|
571
577
|
createWorktree: (payload) => ipcRenderer.invoke('promptSessions:create-worktree', payload),
|
|
572
578
|
/** Folds an Epic's isolated git worktree branch back into its owning
|
|
573
579
|
* project's main tree (main-side gitWorktree.cjs's integrateEpicBranch,
|
|
574
|
-
* via lib/epicWorktreeMerge.cjs) — the ONLY point where PRD 1033's
|
|
580
|
+
* via lib/epic/epicWorktreeMerge.cjs) — the ONLY point where PRD 1033's
|
|
575
581
|
* per-Epic isolation resolves back into the shared tree. Never rejects:
|
|
576
582
|
* resolves `{ ok: true, status: 'merged', integrated }` on a clean
|
|
577
583
|
* merge (worktree cleaned up), or `{ ok: false, status:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a3 as P,b1 as G,aD as x,an as i,Z as R,B as T,a as _}from"./index-CPieAFsl.js";import{a as E,C as B,c as L,d as S,b as I}from"./Library-CeF4qh9d.js";const O=e=>`${e}/.claude/session-manager/provenance.json`;function D(e){if(!e||typeof e!="object")return{};const t={};for(const[n,o]of Object.entries(e))(o==="anthropic"||o==="community"||o==="local")&&(t[n]=o);return t}const K=P((e,t)=>({overrides:{},loaded:!1,loading:!1,home:null,load:async n=>{const o=t();if(!(o.home===n&&(o.loaded||o.loading))){e({home:n,loading:!0});try{const r=await window.api.config.readJson(O(n)),d=r.exists?D(r.data):{};e(h=>({overrides:{...d,...h.overrides},loaded:!0,loading:!1}))}catch{e({loaded:!0,loading:!1})}}},setOverride:async(n,o)=>{const r={...t().overrides};o===null?delete r[n]:r[n]=o,e({overrides:r});const d=t().home;if(d)try{await window.api.config.writeJson(O(d),r)}catch{}}})),a=e=>(e??"").toLowerCase().trim(),j=new Set,$=new Set;for(const e of I){const t=e.official?j:$;t.add(a(e.id)),t.add(a(e.name))}const H=new Set(S.filter(e=>e.official).flatMap(e=>[a(e.id),a(e.name)])),J=new Set(S.filter(e=>!e.official).flatMap(e=>[a(e.id),a(e.name)])),U=new Set(L.filter(e=>e.official).flatMap(e=>[a(e.id),a(e.name)])),V=new Set(L.filter(e=>!e.official).flatMap(e=>[a(e.id),a(e.name)])),z=new Set(B.flatMap(e=>[a(e.id),a(e.name)])),Z=new Set(E.flatMap(e=>[a(e.id),a(e.name)])),q=new Set(E.map(e=>e.command.trim())),F=new Set(["security-review","pr-comments","release-notes","add-dir","code-review","simplify"]),Q=/(@anthropic-ai\/|anthropic\.com|github\.com\/anthropics)/i,W=/(^|\s)(npx|uvx|pipx|bunx|mcp-remote|deno\s+run|docker\s+run)(\s|$)/i;function X(e){return[e.command,...e.args??[],e.url,e.repository,e.homepage].filter(Boolean).join(" ").toLowerCase()}const l=e=>({provenance:"anthropic",reason:e}),y=e=>({provenance:"community",reason:e});function Y(e,t,n){switch(e){case"mcp":return j.has(t)?l("official MCP server (catalog)"):$.has(t)?y("third-party server (catalog)"):null;case"skill":case"command":return H.has(t)?l("official Anthropic skill (catalog)"):J.has(t)?y("third-party skill (catalog)"):null;case"plugin":return U.has(t)?l("official Anthropic plugin (catalog)"):V.has(t)?y("third-party plugin (catalog)"):null;case"subagent":return z.has(t)?l("bundled Anthropic subagent (catalog)"):null;case"hook":return Z.has(t)||n&&q.has(n.trim())?l("bundled hook (catalog)"):null}}function ee(e,t){return e.repository?"has a source repository":e.homepage?"has a homepage":e.url?"remote endpoint":W.test(t)?"installed from a package registry":null}function te(e){const t=a(e.name),n=X(e),o=Y(e.type,t,e.command);if(o)return o;if((e.type==="command"||e.type==="skill")&&F.has(t))return l("built-in Claude Code command");if(Q.test(n))return l("Anthropic package or repo");const r=ee(e,n);return r?y(r):{provenance:"local",reason:"no external source — assumed self-created"}}function ne(e,t,n){return`${e}:${t??"-"}:${n}`}const c={anthropic:"Anthropic",community:"Community",local:"Local"},N={anthropic:"accent",community:"warn",local:"dim"},oe=["anthropic","community","local"];function se({input:e,scope:t,interactive:n=!0,className:o=""}){const r=G(),{overrides:d,load:h,setOverride:k}=K(),[b,m]=x.useState(!1),v=x.useRef(null);x.useEffect(()=>{r&&h(r)},[r,h]),x.useEffect(()=>{if(!b)return;const s=C=>{v.current&&!v.current.contains(C.target)&&m(!1)},g=C=>{C.key==="Escape"&&m(!1)};return window.addEventListener("mousedown",s),window.addEventListener("keydown",g),()=>{window.removeEventListener("mousedown",s),window.removeEventListener("keydown",g)}},[b]);const w=ne(e.type,t??null,e.name),f=te(e),p=d[w],u=p??f.provenance,M=p?`Origin manually set to ${c[u]} — auto-detected ${c[f.provenance]} (${f.reason})`:`Auto-detected ${c[u]}: ${f.reason}`,A=i.jsxs(_,{tone:N[u],title:M,className:`${n?"cursor-pointer hover:brightness-125":""} ${o}`,children:[c[u],p&&i.jsx("span",{className:"w-1 h-1 rounded-full bg-current opacity-70","aria-hidden":!0})]});return n?i.jsxs("span",{ref:v,className:"relative inline-flex",children:[i.jsx("button",{type:"button",onClick:s=>{s.stopPropagation(),m(g=>!g)},className:"inline-flex","aria-label":`Origin: ${c[u]}. Click to change.`,children:A}),b&&i.jsxs("span",{className:`absolute ${R.dialog} top-full right-0 mt-1 min-w-[7.5rem] rounded-md border border-line bg-bg-elev shadow-lg py-1 text-left`,onClick:s=>s.stopPropagation(),children:[i.jsx("span",{className:"block px-2 pb-1 text-[10px] uppercase tracking-wide text-fg-faint",children:"Mark origin as"}),oe.map(s=>i.jsxs("button",{type:"button",onClick:()=>{k(w,s),m(!1)},className:`flex w-full items-center gap-2 px-2 py-1 text-[12px] hover:bg-bg-hi/60 ${u===s?"text-fg":"text-fg-dim"}`,children:[i.jsx("span",{className:`w-2 h-2 rounded-full border ${T[N[s]]}`,"aria-hidden":!0}),c[s],p===s&&i.jsx("span",{className:"ml-auto text-[10px] text-fg-faint",children:"set"})]},s)),i.jsx("div",{className:"my-1 border-t border-line"}),i.jsxs("button",{type:"button",onClick:()=>{k(w,null),m(!1)},disabled:!p,className:"flex w-full items-center gap-2 px-2 py-1 text-[12px] text-fg-dim hover:bg-bg-hi/60 disabled:opacity-40 disabled:hover:bg-transparent",title:`Revert to auto-detection (${c[f.provenance]})`,children:["Auto-detect",i.jsx("span",{className:"ml-auto text-[10px] text-fg-faint",children:c[f.provenance]})]})]})]}):A}export{se as P};
|