charness 3.6.0 → 3.7.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/CHANGELOG.md +274 -0
- package/DEVELOPMENT.md +31 -5
- package/MIGRATION_RENAME_TO_CHARNESS.md +3 -2
- package/README.md +84 -782
- package/SETUP.md +37 -10
- package/agent-plugin/.claude-plugin/plugin.json +7 -0
- package/agent-plugin/README.md +35 -0
- package/agent-plugin/skills/charness-delegate-claude/SKILL.md +85 -0
- package/agent-plugin/skills/charness-delegate-claude/summarize-events.py +90 -0
- package/agent-plugin/skills/charness-delegate-opencode/SKILL.md +68 -0
- package/agent-plugin/skills/charness-manager/SKILL.md +152 -0
- package/dist/adapters/adapterNames.d.ts +6 -0
- package/dist/adapters/adapterNames.d.ts.map +1 -1
- package/dist/adapters/adapterNames.js +8 -2
- package/dist/adapters/adapterNames.js.map +1 -1
- package/dist/adapters/claudeCliAdapter.d.ts +8 -0
- package/dist/adapters/claudeCliAdapter.d.ts.map +1 -1
- package/dist/adapters/claudeCliAdapter.js +42 -5
- package/dist/adapters/claudeCliAdapter.js.map +1 -1
- package/dist/adapters/claudeJsonStreamAdapter.d.ts +10 -9
- package/dist/adapters/claudeJsonStreamAdapter.d.ts.map +1 -1
- package/dist/adapters/claudeJsonStreamAdapter.js +53 -55
- package/dist/adapters/claudeJsonStreamAdapter.js.map +1 -1
- package/dist/adapters/createAdapter.d.ts +8 -0
- package/dist/adapters/createAdapter.d.ts.map +1 -1
- package/dist/adapters/createAdapter.js +14 -2
- package/dist/adapters/createAdapter.js.map +1 -1
- package/dist/adapters/openCodeAdapter.d.ts +43 -6
- package/dist/adapters/openCodeAdapter.d.ts.map +1 -1
- package/dist/adapters/openCodeAdapter.js +95 -6
- package/dist/adapters/openCodeAdapter.js.map +1 -1
- package/dist/agentLogin/agentLogin.d.ts +1 -1
- package/dist/agentLogin/agentLogin.d.ts.map +1 -1
- package/dist/apiRetryKick.d.ts +4 -3
- package/dist/apiRetryKick.d.ts.map +1 -1
- package/dist/apiRetryKick.js +16 -9
- package/dist/apiRetryKick.js.map +1 -1
- package/dist/bot.d.ts.map +1 -1
- package/dist/bot.js +1313 -381
- package/dist/bot.js.map +1 -1
- package/dist/cli/claudeProfiles.d.ts +11 -6
- package/dist/cli/claudeProfiles.d.ts.map +1 -1
- package/dist/cli/claudeProfiles.js +50 -22
- package/dist/cli/claudeProfiles.js.map +1 -1
- package/dist/cli/hot.d.ts +5 -0
- package/dist/cli/hot.d.ts.map +1 -1
- package/dist/cli/hot.js +71 -25
- package/dist/cli/hot.js.map +1 -1
- package/dist/cli/tscWatchGuard.d.ts +95 -0
- package/dist/cli/tscWatchGuard.d.ts.map +1 -0
- package/dist/cli/tscWatchGuard.js +295 -0
- package/dist/cli/tscWatchGuard.js.map +1 -0
- package/dist/cli.js +12 -1
- package/dist/cli.js.map +1 -1
- package/dist/connectors/jira/answerSink.d.ts +10 -0
- package/dist/connectors/jira/answerSink.d.ts.map +1 -1
- package/dist/connectors/jira/answerSink.js +13 -0
- package/dist/connectors/jira/answerSink.js.map +1 -1
- package/dist/connectors/jira/config.d.ts +2 -0
- package/dist/connectors/jira/config.d.ts.map +1 -1
- package/dist/connectors/jira/config.js +9 -1
- package/dist/connectors/jira/config.js.map +1 -1
- package/dist/connectors/jira/connector.d.ts +11 -1
- package/dist/connectors/jira/connector.d.ts.map +1 -1
- package/dist/connectors/jira/connector.js +13 -1
- package/dist/connectors/jira/connector.js.map +1 -1
- package/dist/connectors/jira/inbound.d.ts +29 -4
- package/dist/connectors/jira/inbound.d.ts.map +1 -1
- package/dist/connectors/jira/inbound.js +71 -8
- package/dist/connectors/jira/inbound.js.map +1 -1
- package/dist/connectors/jira/issueBlocks.d.ts +5 -0
- package/dist/connectors/jira/issueBlocks.d.ts.map +1 -1
- package/dist/connectors/jira/issueBlocks.js +11 -0
- package/dist/connectors/jira/issueBlocks.js.map +1 -1
- package/dist/connectors/jira/prompt.d.ts +4 -0
- package/dist/connectors/jira/prompt.d.ts.map +1 -1
- package/dist/connectors/jira/prompt.js +11 -2
- package/dist/connectors/jira/prompt.js.map +1 -1
- package/dist/connectors/telegram/bindPicker.d.ts +5 -0
- package/dist/connectors/telegram/bindPicker.d.ts.map +1 -1
- package/dist/connectors/telegram/bindPicker.js +18 -1
- package/dist/connectors/telegram/bindPicker.js.map +1 -1
- package/dist/connectors/telegram/bindPickerClaims.d.ts +46 -0
- package/dist/connectors/telegram/bindPickerClaims.d.ts.map +1 -0
- package/dist/connectors/telegram/bindPickerClaims.js +83 -0
- package/dist/connectors/telegram/bindPickerClaims.js.map +1 -0
- package/dist/connectors/telegram/bindSweep.d.ts +32 -0
- package/dist/connectors/telegram/bindSweep.d.ts.map +1 -0
- package/dist/connectors/telegram/bindSweep.js +47 -0
- package/dist/connectors/telegram/bindSweep.js.map +1 -0
- package/dist/connectors/telegram/bindingWelcome.d.ts +23 -0
- package/dist/connectors/telegram/bindingWelcome.d.ts.map +1 -0
- package/dist/connectors/telegram/bindingWelcome.js +26 -0
- package/dist/connectors/telegram/bindingWelcome.js.map +1 -0
- package/dist/connectors/telegram/botApiConnection.d.ts +74 -0
- package/dist/connectors/telegram/botApiConnection.d.ts.map +1 -0
- package/dist/connectors/telegram/botApiConnection.js +201 -0
- package/dist/connectors/telegram/botApiConnection.js.map +1 -0
- package/dist/connectors/telegram/commands/botCore.d.ts +8 -2
- package/dist/connectors/telegram/commands/botCore.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/botSkills.d.ts +21 -0
- package/dist/connectors/telegram/commands/botSkills.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/botSkills.js +133 -0
- package/dist/connectors/telegram/commands/botSkills.js.map +1 -0
- package/dist/connectors/telegram/commands/callbackMessage.d.ts +5 -0
- package/dist/connectors/telegram/commands/callbackMessage.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/callbackMessage.js +9 -0
- package/dist/connectors/telegram/commands/callbackMessage.js.map +1 -1
- package/dist/connectors/telegram/commands/compaction.d.ts +65 -3
- package/dist/connectors/telegram/commands/compaction.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/compaction.js +512 -94
- package/dist/connectors/telegram/commands/compaction.js.map +1 -1
- package/dist/connectors/telegram/commands/displayModes.d.ts +1 -1
- package/dist/connectors/telegram/commands/displayModes.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/displayModes.js +6 -18
- package/dist/connectors/telegram/commands/displayModes.js.map +1 -1
- package/dist/connectors/telegram/commands/fallbackChain.js +5 -5
- package/dist/connectors/telegram/commands/fallbackChain.js.map +1 -1
- package/dist/connectors/telegram/commands/reminders.d.ts +1 -1
- package/dist/connectors/telegram/commands/reminders.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/reminders.js +4 -15
- package/dist/connectors/telegram/commands/reminders.js.map +1 -1
- package/dist/connectors/telegram/commands/selfUpdate.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/selfUpdate.js +1 -11
- package/dist/connectors/telegram/commands/selfUpdate.js.map +1 -1
- package/dist/connectors/telegram/commands/taskAgents.d.ts +22 -0
- package/dist/connectors/telegram/commands/taskAgents.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/taskAgents.js +104 -0
- package/dist/connectors/telegram/commands/taskAgents.js.map +1 -0
- package/dist/connectors/telegram/commands/todo.d.ts +82 -0
- package/dist/connectors/telegram/commands/todo.d.ts.map +1 -0
- package/dist/connectors/telegram/commands/todo.js +384 -0
- package/dist/connectors/telegram/commands/todo.js.map +1 -0
- package/dist/connectors/telegram/commands/topicCommand.d.ts +6 -2
- package/dist/connectors/telegram/commands/topicCommand.d.ts.map +1 -1
- package/dist/connectors/telegram/commands/topicCommand.js +6 -9
- package/dist/connectors/telegram/commands/topicCommand.js.map +1 -1
- package/dist/connectors/telegram/openBindMessages.d.ts +45 -0
- package/dist/connectors/telegram/openBindMessages.d.ts.map +1 -0
- package/dist/connectors/telegram/openBindMessages.js +67 -0
- package/dist/connectors/telegram/openBindMessages.js.map +1 -0
- package/dist/connectors/telegram/outputFlushPlan.d.ts +49 -0
- package/dist/connectors/telegram/outputFlushPlan.d.ts.map +1 -1
- package/dist/connectors/telegram/outputFlushPlan.js +46 -0
- package/dist/connectors/telegram/outputFlushPlan.js.map +1 -1
- package/dist/connectors/telegram/pendingTopicName.d.ts +26 -0
- package/dist/connectors/telegram/pendingTopicName.d.ts.map +1 -0
- package/dist/connectors/telegram/pendingTopicName.js +27 -0
- package/dist/connectors/telegram/pendingTopicName.js.map +1 -0
- package/dist/connectors/test/connector.d.ts.map +1 -1
- package/dist/connectors/test/connector.js +6 -1
- package/dist/connectors/test/connector.js.map +1 -1
- package/dist/i18n/de.d.ts.map +1 -1
- package/dist/i18n/de.js +90 -7
- package/dist/i18n/de.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +90 -7
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/i18n/es.js +90 -7
- package/dist/i18n/es.js.map +1 -1
- package/dist/i18n/fr.d.ts.map +1 -1
- package/dist/i18n/fr.js +90 -7
- package/dist/i18n/fr.js.map +1 -1
- package/dist/i18n/hi.d.ts.map +1 -1
- package/dist/i18n/hi.js +90 -7
- package/dist/i18n/hi.js.map +1 -1
- package/dist/i18n/ja.d.ts.map +1 -1
- package/dist/i18n/ja.js +90 -7
- package/dist/i18n/ja.js.map +1 -1
- package/dist/i18n/ka.d.ts.map +1 -1
- package/dist/i18n/ka.js +90 -7
- package/dist/i18n/ka.js.map +1 -1
- package/dist/i18n/pt.d.ts.map +1 -1
- package/dist/i18n/pt.js +90 -7
- package/dist/i18n/pt.js.map +1 -1
- package/dist/i18n/ru.d.ts.map +1 -1
- package/dist/i18n/ru.js +90 -7
- package/dist/i18n/ru.js.map +1 -1
- package/dist/i18n/uk.d.ts.map +1 -1
- package/dist/i18n/uk.js +90 -7
- package/dist/i18n/uk.js.map +1 -1
- package/dist/i18n/uz.d.ts.map +1 -1
- package/dist/i18n/uz.js +90 -7
- package/dist/i18n/uz.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +90 -7
- package/dist/i18n/zh.js.map +1 -1
- package/dist/i18n.d.ts +1 -1
- package/dist/i18n.js +1 -1
- package/dist/installManager.d.ts +13 -0
- package/dist/installManager.d.ts.map +1 -1
- package/dist/installManager.js +38 -4
- package/dist/installManager.js.map +1 -1
- package/dist/instanceSettings.d.ts +40 -1
- package/dist/instanceSettings.d.ts.map +1 -1
- package/dist/instanceSettings.js +105 -26
- package/dist/instanceSettings.js.map +1 -1
- package/dist/openCodeQuestionFlow.d.ts +30 -0
- package/dist/openCodeQuestionFlow.d.ts.map +1 -1
- package/dist/openCodeQuestionFlow.js +43 -0
- package/dist/openCodeQuestionFlow.js.map +1 -1
- package/dist/postToSession.d.ts +20 -5
- package/dist/postToSession.d.ts.map +1 -1
- package/dist/postToSession.js +38 -7
- package/dist/postToSession.js.map +1 -1
- package/dist/remoteRun/cliArgs.d.ts +73 -0
- package/dist/remoteRun/cliArgs.d.ts.map +1 -0
- package/dist/remoteRun/cliArgs.js +197 -0
- package/dist/remoteRun/cliArgs.js.map +1 -0
- package/dist/remoteRun/commands.d.ts +56 -0
- package/dist/remoteRun/commands.d.ts.map +1 -0
- package/dist/remoteRun/commands.js +306 -0
- package/dist/remoteRun/commands.js.map +1 -0
- package/dist/remoteRun/depsPlan.d.ts +16 -0
- package/dist/remoteRun/depsPlan.d.ts.map +1 -0
- package/dist/remoteRun/depsPlan.js +82 -0
- package/dist/remoteRun/depsPlan.js.map +1 -0
- package/dist/remoteRun/exitCodes.d.ts +34 -0
- package/dist/remoteRun/exitCodes.d.ts.map +1 -0
- package/dist/remoteRun/exitCodes.js +38 -0
- package/dist/remoteRun/exitCodes.js.map +1 -0
- package/dist/remoteRun/foreground.d.ts +29 -0
- package/dist/remoteRun/foreground.d.ts.map +1 -0
- package/dist/remoteRun/foreground.js +159 -0
- package/dist/remoteRun/foreground.js.map +1 -0
- package/dist/remoteRun/interrupts.d.ts +17 -0
- package/dist/remoteRun/interrupts.d.ts.map +1 -0
- package/dist/remoteRun/interrupts.js +41 -0
- package/dist/remoteRun/interrupts.js.map +1 -0
- package/dist/remoteRun/jobFiles.d.ts +31 -0
- package/dist/remoteRun/jobFiles.d.ts.map +1 -0
- package/dist/remoteRun/jobFiles.js +84 -0
- package/dist/remoteRun/jobFiles.js.map +1 -0
- package/dist/remoteRun/jobFormat.d.ts +16 -0
- package/dist/remoteRun/jobFormat.d.ts.map +1 -0
- package/dist/remoteRun/jobFormat.js +130 -0
- package/dist/remoteRun/jobFormat.js.map +1 -0
- package/dist/remoteRun/jobId.d.ts +15 -0
- package/dist/remoteRun/jobId.d.ts.map +1 -0
- package/dist/remoteRun/jobId.js +85 -0
- package/dist/remoteRun/jobId.js.map +1 -0
- package/dist/remoteRun/jobMeta.d.ts +18 -0
- package/dist/remoteRun/jobMeta.d.ts.map +1 -0
- package/dist/remoteRun/jobMeta.js +33 -0
- package/dist/remoteRun/jobMeta.js.map +1 -0
- package/dist/remoteRun/jobQuery.d.ts +12 -0
- package/dist/remoteRun/jobQuery.d.ts.map +1 -0
- package/dist/remoteRun/jobQuery.js +22 -0
- package/dist/remoteRun/jobQuery.js.map +1 -0
- package/dist/remoteRun/jobRecords.d.ts +22 -0
- package/dist/remoteRun/jobRecords.d.ts.map +1 -0
- package/dist/remoteRun/jobRecords.js +145 -0
- package/dist/remoteRun/jobRecords.js.map +1 -0
- package/dist/remoteRun/jobState.d.ts +62 -0
- package/dist/remoteRun/jobState.d.ts.map +1 -0
- package/dist/remoteRun/jobState.js +132 -0
- package/dist/remoteRun/jobState.js.map +1 -0
- package/dist/remoteRun/leaseTiming.d.ts +18 -0
- package/dist/remoteRun/leaseTiming.d.ts.map +1 -0
- package/dist/remoteRun/leaseTiming.js +43 -0
- package/dist/remoteRun/leaseTiming.js.map +1 -0
- package/dist/remoteRun/output.d.ts +35 -0
- package/dist/remoteRun/output.d.ts.map +1 -0
- package/dist/remoteRun/output.js +82 -0
- package/dist/remoteRun/output.js.map +1 -0
- package/dist/remoteRun/pathPatterns.d.ts +33 -0
- package/dist/remoteRun/pathPatterns.d.ts.map +1 -0
- package/dist/remoteRun/pathPatterns.js +115 -0
- package/dist/remoteRun/pathPatterns.js.map +1 -0
- package/dist/remoteRun/probe.d.ts +56 -0
- package/dist/remoteRun/probe.d.ts.map +1 -0
- package/dist/remoteRun/probe.js +123 -0
- package/dist/remoteRun/probe.js.map +1 -0
- package/dist/remoteRun/project.d.ts +26 -0
- package/dist/remoteRun/project.d.ts.map +1 -0
- package/dist/remoteRun/project.js +159 -0
- package/dist/remoteRun/project.js.map +1 -0
- package/dist/remoteRun/projectConfig.d.ts +38 -0
- package/dist/remoteRun/projectConfig.d.ts.map +1 -0
- package/dist/remoteRun/projectConfig.js +87 -0
- package/dist/remoteRun/projectConfig.js.map +1 -0
- package/dist/remoteRun/remoteRunCli.d.ts +15 -0
- package/dist/remoteRun/remoteRunCli.d.ts.map +1 -0
- package/dist/remoteRun/remoteRunCli.js +144 -0
- package/dist/remoteRun/remoteRunCli.js.map +1 -0
- package/dist/remoteRun/remoteRunError.d.ts +14 -0
- package/dist/remoteRun/remoteRunError.d.ts.map +1 -0
- package/dist/remoteRun/remoteRunError.js +28 -0
- package/dist/remoteRun/remoteRunError.js.map +1 -0
- package/dist/remoteRun/rsync.d.ts +17 -0
- package/dist/remoteRun/rsync.d.ts.map +1 -0
- package/dist/remoteRun/rsync.js +39 -0
- package/dist/remoteRun/rsync.js.map +1 -0
- package/dist/remoteRun/runnerClient.d.ts +50 -0
- package/dist/remoteRun/runnerClient.d.ts.map +1 -0
- package/dist/remoteRun/runnerClient.js +139 -0
- package/dist/remoteRun/runnerClient.js.map +1 -0
- package/dist/remoteRun/runners.d.ts +57 -0
- package/dist/remoteRun/runners.d.ts.map +1 -0
- package/dist/remoteRun/runners.js +181 -0
- package/dist/remoteRun/runners.js.map +1 -0
- package/dist/remoteRun/runnersConfig.d.ts +44 -0
- package/dist/remoteRun/runnersConfig.d.ts.map +1 -0
- package/dist/remoteRun/runnersConfig.js +107 -0
- package/dist/remoteRun/runnersConfig.js.map +1 -0
- package/dist/remoteRun/safeCopy.d.ts +31 -0
- package/dist/remoteRun/safeCopy.d.ts.map +1 -0
- package/dist/remoteRun/safeCopy.js +137 -0
- package/dist/remoteRun/safeCopy.js.map +1 -0
- package/dist/remoteRun/sendPlan.d.ts +67 -0
- package/dist/remoteRun/sendPlan.d.ts.map +1 -0
- package/dist/remoteRun/sendPlan.js +139 -0
- package/dist/remoteRun/sendPlan.js.map +1 -0
- package/dist/remoteRun/ssh.d.ts +62 -0
- package/dist/remoteRun/ssh.d.ts.map +1 -0
- package/dist/remoteRun/ssh.js +202 -0
- package/dist/remoteRun/ssh.js.map +1 -0
- package/dist/remoteRun/submit.d.ts +29 -0
- package/dist/remoteRun/submit.d.ts.map +1 -0
- package/dist/remoteRun/submit.js +142 -0
- package/dist/remoteRun/submit.js.map +1 -0
- package/dist/requests/answerRequest.d.ts +5 -0
- package/dist/requests/answerRequest.d.ts.map +1 -1
- package/dist/requests/answerRequest.js +16 -1
- package/dist/requests/answerRequest.js.map +1 -1
- package/dist/requests/requestLedger.d.ts +13 -0
- package/dist/requests/requestLedger.d.ts.map +1 -1
- package/dist/requests/requestLedger.js +9 -0
- package/dist/requests/requestLedger.js.map +1 -1
- package/dist/requests/topicRequestSettle.d.ts +30 -0
- package/dist/requests/topicRequestSettle.d.ts.map +1 -0
- package/dist/requests/topicRequestSettle.js +23 -0
- package/dist/requests/topicRequestSettle.js.map +1 -0
- package/dist/requests/wakeUpEngine.d.ts +4 -0
- package/dist/requests/wakeUpEngine.d.ts.map +1 -1
- package/dist/requests/wakeUpEngine.js +5 -1
- package/dist/requests/wakeUpEngine.js.map +1 -1
- package/dist/scheduler/delivery.d.ts +2 -0
- package/dist/scheduler/delivery.d.ts.map +1 -1
- package/dist/scheduler/delivery.js +8 -4
- package/dist/scheduler/delivery.js.map +1 -1
- package/dist/scheduler/mcpSurface.d.ts +59 -10
- package/dist/scheduler/mcpSurface.d.ts.map +1 -1
- package/dist/scheduler/mcpSurface.js +276 -79
- package/dist/scheduler/mcpSurface.js.map +1 -1
- package/dist/scheduler/recurrence.d.ts +5 -0
- package/dist/scheduler/recurrence.d.ts.map +1 -1
- package/dist/scheduler/recurrence.js +12 -2
- package/dist/scheduler/recurrence.js.map +1 -1
- package/dist/scheduler/strictToolInput.d.ts +45 -0
- package/dist/scheduler/strictToolInput.d.ts.map +1 -0
- package/dist/scheduler/strictToolInput.js +155 -0
- package/dist/scheduler/strictToolInput.js.map +1 -0
- package/dist/scheduler/types.d.ts +5 -0
- package/dist/scheduler/types.d.ts.map +1 -1
- package/dist/scheduler/workerWatch.d.ts +23 -0
- package/dist/scheduler/workerWatch.d.ts.map +1 -0
- package/dist/scheduler/workerWatch.js +26 -0
- package/dist/scheduler/workerWatch.js.map +1 -0
- package/dist/selfUpdate/emittedSource.d.ts +11 -0
- package/dist/selfUpdate/emittedSource.d.ts.map +1 -0
- package/dist/selfUpdate/emittedSource.js +24 -0
- package/dist/selfUpdate/emittedSource.js.map +1 -0
- package/dist/selfUpdate/gitSource.d.ts +0 -6
- package/dist/selfUpdate/gitSource.d.ts.map +1 -1
- package/dist/selfUpdate/gitSource.js +2 -18
- package/dist/selfUpdate/gitSource.js.map +1 -1
- package/dist/selfUpdate/updatePending.d.ts +1 -1
- package/dist/sendErrorClassifier.d.ts +10 -0
- package/dist/sendErrorClassifier.d.ts.map +1 -1
- package/dist/sendErrorClassifier.js +22 -0
- package/dist/sendErrorClassifier.js.map +1 -1
- package/dist/state.d.ts +78 -7
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +125 -8
- package/dist/state.js.map +1 -1
- package/dist/stateFile.d.ts +9 -0
- package/dist/stateFile.d.ts.map +1 -0
- package/dist/stateFile.js +57 -0
- package/dist/stateFile.js.map +1 -0
- package/dist/stt/sttInstall.d.ts +7 -3
- package/dist/stt/sttInstall.d.ts.map +1 -1
- package/dist/stt/sttInstall.js +8 -4
- package/dist/stt/sttInstall.js.map +1 -1
- package/dist/stt/sttSettings.d.ts +2 -1
- package/dist/stt/sttSettings.d.ts.map +1 -1
- package/dist/stt/sttSettings.js +3 -2
- package/dist/stt/sttSettings.js.map +1 -1
- package/dist/stt/transcribeChain.js +2 -0
- package/dist/stt/transcribeChain.js.map +1 -1
- package/dist/testTimings.d.ts +13 -3
- package/dist/testTimings.d.ts.map +1 -1
- package/dist/testTimings.js +26 -2
- package/dist/testTimings.js.map +1 -1
- package/dist/todos/board.d.ts +83 -0
- package/dist/todos/board.d.ts.map +1 -0
- package/dist/todos/board.js +227 -0
- package/dist/todos/board.js.map +1 -0
- package/dist/todos/format.d.ts +33 -0
- package/dist/todos/format.d.ts.map +1 -0
- package/dist/todos/format.js +90 -0
- package/dist/todos/format.js.map +1 -0
- package/dist/todos/merge.d.ts +46 -0
- package/dist/todos/merge.d.ts.map +1 -0
- package/dist/todos/merge.js +137 -0
- package/dist/todos/merge.js.map +1 -0
- package/dist/todos/midTurn.d.ts +75 -0
- package/dist/todos/midTurn.d.ts.map +1 -0
- package/dist/todos/midTurn.js +214 -0
- package/dist/todos/midTurn.js.map +1 -0
- package/dist/todos/nag.d.ts +85 -0
- package/dist/todos/nag.d.ts.map +1 -0
- package/dist/todos/nag.js +103 -0
- package/dist/todos/nag.js.map +1 -0
- package/dist/todos/order.d.ts +25 -0
- package/dist/todos/order.d.ts.map +1 -0
- package/dist/todos/order.js +61 -0
- package/dist/todos/order.js.map +1 -0
- package/dist/todos/projects.d.ts +102 -0
- package/dist/todos/projects.d.ts.map +1 -0
- package/dist/todos/projects.js +342 -0
- package/dist/todos/projects.js.map +1 -0
- package/dist/todos/registry.d.ts +64 -0
- package/dist/todos/registry.d.ts.map +1 -0
- package/dist/todos/registry.js +116 -0
- package/dist/todos/registry.js.map +1 -0
- package/dist/todos/reminderEngine.d.ts +78 -0
- package/dist/todos/reminderEngine.d.ts.map +1 -0
- package/dist/todos/reminderEngine.js +162 -0
- package/dist/todos/reminderEngine.js.map +1 -0
- package/dist/todos/store.d.ts +34 -0
- package/dist/todos/store.d.ts.map +1 -0
- package/dist/todos/store.js +208 -0
- package/dist/todos/store.js.map +1 -0
- package/dist/todos/tools.d.ts +26 -0
- package/dist/todos/tools.d.ts.map +1 -0
- package/dist/todos/tools.js +25 -0
- package/dist/todos/tools.js.map +1 -0
- package/dist/todos/types.d.ts +85 -0
- package/dist/todos/types.d.ts.map +1 -0
- package/dist/todos/types.js +30 -0
- package/dist/todos/types.js.map +1 -0
- package/dist/trackers/taskAgentLimit.d.ts +58 -0
- package/dist/trackers/taskAgentLimit.d.ts.map +1 -0
- package/dist/trackers/taskAgentLimit.js +62 -0
- package/dist/trackers/taskAgentLimit.js.map +1 -0
- package/dist/trackers/taskAgentSlots.d.ts +109 -0
- package/dist/trackers/taskAgentSlots.d.ts.map +1 -0
- package/dist/trackers/taskAgentSlots.js +227 -0
- package/dist/trackers/taskAgentSlots.js.map +1 -0
- package/dist/trackers/types.d.ts +14 -0
- package/dist/trackers/types.d.ts.map +1 -0
- package/dist/trackers/types.js +3 -0
- package/dist/trackers/types.js.map +1 -0
- package/dist/types.d.ts +80 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/adoptReplayGate.d.ts +16 -0
- package/dist/utils/adoptReplayGate.d.ts.map +1 -0
- package/dist/utils/adoptReplayGate.js +35 -0
- package/dist/utils/adoptReplayGate.js.map +1 -0
- package/dist/utils/agentPlugin.d.ts +113 -0
- package/dist/utils/agentPlugin.d.ts.map +1 -0
- package/dist/utils/agentPlugin.js +192 -0
- package/dist/utils/agentPlugin.js.map +1 -0
- package/dist/utils/autoContinueOnLimit.d.ts +7 -4
- package/dist/utils/autoContinueOnLimit.d.ts.map +1 -1
- package/dist/utils/autoContinueOnLimit.js +8 -5
- package/dist/utils/autoContinueOnLimit.js.map +1 -1
- package/dist/utils/botSkills.d.ts +62 -0
- package/dist/utils/botSkills.d.ts.map +1 -0
- package/dist/utils/botSkills.js +53 -0
- package/dist/utils/botSkills.js.map +1 -0
- package/dist/utils/botSkillsSetting.d.ts +7 -0
- package/dist/utils/botSkillsSetting.d.ts.map +1 -0
- package/dist/utils/botSkillsSetting.js +9 -0
- package/dist/utils/botSkillsSetting.js.map +1 -0
- package/dist/utils/claudeCodeVersion.d.ts +7 -0
- package/dist/utils/claudeCodeVersion.d.ts.map +1 -1
- package/dist/utils/claudeCodeVersion.js +14 -1
- package/dist/utils/claudeCodeVersion.js.map +1 -1
- package/dist/utils/claudeCompactHook.d.ts +33 -15
- package/dist/utils/claudeCompactHook.d.ts.map +1 -1
- package/dist/utils/claudeCompactHook.js +36 -17
- package/dist/utils/claudeCompactHook.js.map +1 -1
- package/dist/utils/claudeCompactSummary.d.ts +15 -0
- package/dist/utils/claudeCompactSummary.d.ts.map +1 -0
- package/dist/utils/claudeCompactSummary.js +96 -0
- package/dist/utils/claudeCompactSummary.js.map +1 -0
- package/dist/utils/claudeLimitSwitch.d.ts +11 -9
- package/dist/utils/claudeLimitSwitch.d.ts.map +1 -1
- package/dist/utils/claudeLimitSwitch.js +18 -16
- package/dist/utils/claudeLimitSwitch.js.map +1 -1
- package/dist/utils/claudeProfiles.d.ts +5 -0
- package/dist/utils/claudeProfiles.d.ts.map +1 -1
- package/dist/utils/claudeProfiles.js +14 -0
- package/dist/utils/claudeProfiles.js.map +1 -1
- package/dist/utils/claudeSessionTitle.d.ts +2 -1
- package/dist/utils/claudeSessionTitle.d.ts.map +1 -1
- package/dist/utils/claudeSessionTitle.js +14 -14
- package/dist/utils/claudeSessionTitle.js.map +1 -1
- package/dist/utils/claudeUsage.d.ts +95 -15
- package/dist/utils/claudeUsage.d.ts.map +1 -1
- package/dist/utils/claudeUsage.js +241 -41
- package/dist/utils/claudeUsage.js.map +1 -1
- package/dist/utils/claudeUsageRefresher.d.ts +10 -0
- package/dist/utils/claudeUsageRefresher.d.ts.map +1 -1
- package/dist/utils/claudeUsageRefresher.js +11 -0
- package/dist/utils/claudeUsageRefresher.js.map +1 -1
- package/dist/utils/claudeUserEntry.d.ts +50 -0
- package/dist/utils/claudeUserEntry.d.ts.map +1 -0
- package/dist/utils/claudeUserEntry.js +120 -0
- package/dist/utils/claudeUserEntry.js.map +1 -0
- package/dist/utils/clearThreadOutputQueues.d.ts +4 -3
- package/dist/utils/clearThreadOutputQueues.d.ts.map +1 -1
- package/dist/utils/clearThreadOutputQueues.js +1 -1
- package/dist/utils/clearThreadOutputQueues.js.map +1 -1
- package/dist/utils/compactOnIdle.d.ts +33 -13
- package/dist/utils/compactOnIdle.d.ts.map +1 -1
- package/dist/utils/compactOnIdle.js +35 -15
- package/dist/utils/compactOnIdle.js.map +1 -1
- package/dist/utils/fallbackBridge.d.ts +5 -0
- package/dist/utils/fallbackBridge.d.ts.map +1 -1
- package/dist/utils/fallbackBridge.js +19 -3
- package/dist/utils/fallbackBridge.js.map +1 -1
- package/dist/utils/fallbackChain.d.ts +9 -3
- package/dist/utils/fallbackChain.d.ts.map +1 -1
- package/dist/utils/fallbackChain.js +21 -3
- package/dist/utils/fallbackChain.js.map +1 -1
- package/dist/utils/fileSendPlan.d.ts +6 -0
- package/dist/utils/fileSendPlan.d.ts.map +1 -1
- package/dist/utils/fileSendPlan.js +11 -0
- package/dist/utils/fileSendPlan.js.map +1 -1
- package/dist/utils/fileSendService.d.ts +7 -1
- package/dist/utils/fileSendService.d.ts.map +1 -1
- package/dist/utils/fileSendService.js +6 -2
- package/dist/utils/fileSendService.js.map +1 -1
- package/dist/utils/groupFinalizePlan.d.ts +8 -10
- package/dist/utils/groupFinalizePlan.d.ts.map +1 -1
- package/dist/utils/groupFinalizePlan.js +8 -12
- package/dist/utils/groupFinalizePlan.js.map +1 -1
- package/dist/utils/jsonStreamHost.d.ts +13 -0
- package/dist/utils/jsonStreamHost.d.ts.map +1 -1
- package/dist/utils/jsonStreamHost.js +13 -0
- package/dist/utils/jsonStreamHost.js.map +1 -1
- package/dist/utils/messageSendService.d.ts +5 -3
- package/dist/utils/messageSendService.d.ts.map +1 -1
- package/dist/utils/messageSendService.js +12 -5
- package/dist/utils/messageSendService.js.map +1 -1
- package/dist/utils/openCodeCompactPlugin.d.ts +39 -14
- package/dist/utils/openCodeCompactPlugin.d.ts.map +1 -1
- package/dist/utils/openCodeCompactPlugin.js +106 -38
- package/dist/utils/openCodeCompactPlugin.js.map +1 -1
- package/dist/utils/promptDelivery.d.ts +29 -12
- package/dist/utils/promptDelivery.d.ts.map +1 -1
- package/dist/utils/promptDelivery.js +13 -5
- package/dist/utils/promptDelivery.js.map +1 -1
- package/dist/utils/sentKindsSummary.d.ts +10 -0
- package/dist/utils/sentKindsSummary.d.ts.map +1 -0
- package/dist/utils/sentKindsSummary.js +18 -0
- package/dist/utils/sentKindsSummary.js.map +1 -0
- package/dist/utils/telegramError.d.ts +6 -0
- package/dist/utils/telegramError.d.ts.map +1 -1
- package/dist/utils/telegramError.js +12 -0
- package/dist/utils/telegramError.js.map +1 -1
- package/dist/utils/topicView.d.ts +1 -1
- package/dist/utils/topicView.js +1 -1
- package/dist/utils/transcribeAudio.d.ts +10 -0
- package/dist/utils/transcribeAudio.d.ts.map +1 -1
- package/dist/utils/transcribeAudio.js +22 -3
- package/dist/utils/transcribeAudio.js.map +1 -1
- package/dist/utils/transcriptErrorTime.d.ts +8 -0
- package/dist/utils/transcriptErrorTime.d.ts.map +1 -0
- package/dist/utils/transcriptErrorTime.js +56 -0
- package/dist/utils/transcriptErrorTime.js.map +1 -0
- package/dist/utils/wedgeRecovery.d.ts +2 -0
- package/dist/utils/wedgeRecovery.d.ts.map +1 -1
- package/dist/utils/wedgeRecovery.js +1 -1
- package/dist/utils/wedgeRecovery.js.map +1 -1
- package/package.json +11 -3
- package/remoteRun/runner.sh +1242 -0
- package/stt/gigaam_sidecar.py +555 -50
|
@@ -12,6 +12,7 @@ exports.verifySchedulerMcpToken = verifySchedulerMcpToken;
|
|
|
12
12
|
exports.extractBearerToken = extractBearerToken;
|
|
13
13
|
exports.buildBotMcpToolDigest = buildBotMcpToolDigest;
|
|
14
14
|
exports.getBotMcpToolDigest = getBotMcpToolDigest;
|
|
15
|
+
exports.getBotMcpToolDefinitions = getBotMcpToolDefinitions;
|
|
15
16
|
exports.resolveTargetThreadKey = resolveTargetThreadKey;
|
|
16
17
|
exports.buildSpecFromCreateArgs = buildSpecFromCreateArgs;
|
|
17
18
|
exports.checkIsConversationInScope = checkIsConversationInScope;
|
|
@@ -23,17 +24,25 @@ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
|
23
24
|
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
24
25
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
25
26
|
const zod_1 = require("zod");
|
|
27
|
+
const adapterNames_1 = require("../adapters/adapterNames");
|
|
26
28
|
const sessionKey_1 = require("../sessionKey");
|
|
29
|
+
const botSkills_1 = require("../utils/botSkills");
|
|
30
|
+
const claudeProfiles_1 = require("../utils/claudeProfiles");
|
|
31
|
+
const claudeUsage_1 = require("../utils/claudeUsage");
|
|
27
32
|
const isoTimestamp_1 = require("../utils/isoTimestamp");
|
|
28
33
|
const messageSendService_1 = require("../utils/messageSendService");
|
|
29
34
|
const utils_1 = require("../utils");
|
|
30
35
|
const checkRun_1 = require("./checkRun");
|
|
31
36
|
const deliveryKind_1 = require("./deliveryKind");
|
|
37
|
+
const workerWatch_1 = require("./workerWatch");
|
|
32
38
|
const recurrence_1 = require("./recurrence");
|
|
39
|
+
const strictToolInput_1 = require("./strictToolInput");
|
|
33
40
|
const store_1 = require("./store");
|
|
34
41
|
const legacyNames_1 = require("../legacyNames");
|
|
35
42
|
const answerRequest_1 = require("../requests/answerRequest");
|
|
36
43
|
const answerStyle_1 = require("../requests/answerStyle");
|
|
44
|
+
const registry_1 = require("../todos/registry");
|
|
45
|
+
const types_1 = require("../todos/types");
|
|
37
46
|
/**
|
|
38
47
|
* @description The bot-owned MCP server exposes the agent-facing tools —
|
|
39
48
|
* `schedule_create`, `schedule_list`, `schedule_cancel`, `send_file_to_user`,
|
|
@@ -106,28 +115,61 @@ const schedulerMcpClientIdPattern = /^[A-Za-z0-9._:-]+$/;
|
|
|
106
115
|
/** Server identity reported in the MCP `initialize` handshake. */
|
|
107
116
|
const mcpServerName = 'telegram-bot-scheduler';
|
|
108
117
|
const mcpServerVersion = '1.0.0';
|
|
118
|
+
/** The skill an orchestrating agent loads in a bot session, as each CLI names it. */
|
|
119
|
+
const managerSkillInstruction = 'load the `charness-manager` skill (Claude Code lists it as `charness:charness-manager`) and follow it instead of any other manager skill';
|
|
109
120
|
/** The instruction bullets that hold on every platform (the two platform-neutral tools). */
|
|
110
121
|
const compactConversationInstruction = '• The user EXPLICITLY asks to compact/shrink/summarize this conversation\'s context → compact_conversation. Only on an explicit request, never on your own judgement.';
|
|
111
122
|
const answerRequestInstruction = '• A message carries a "[Request <id> · from: …]" header → answer it through answer_request with that id: kind "final" with the full result at the end of your turn, "question" when you need the requester before you can go on (their reply arrives as a new request), "progress" for an interim note. You may call it several times; only question/final close the request. ' +
|
|
112
123
|
answerStyle_1.answerStyleInstruction;
|
|
113
|
-
|
|
114
|
-
const
|
|
124
|
+
/** The shared todo registry's bullet (D7) — Telegram topics and Jira issues publish alike. */
|
|
125
|
+
const todoInstruction = '• BEFORE you start any task (fixes you found yourself included: a failing test, a leak) → todo_update adds it as inWork, naming the area concretely (files, tests). Check the returned board for overlap with other agents. Take the queue top-down; mark items done / dropped at once. A ticket you create in a tracker gets an item with its key in `ref`.';
|
|
126
|
+
/** The `charness remote-run` bullet — present only while `runners.json` lists a runner, for Telegram topics and tracker issues alike. */
|
|
127
|
+
const remoteRunInstruction = '• Heavy work (a test suite, a build, an e2e run) can run on a runner machine instead of this one → `charness remote-run runners` shows which runners are online with their CPU, RAM, disk, load and what each can do (android, ios, docker, playwright); then `charness remote-run [--needs <capability>] <command>` runs the command in a copy of this git project there and gives you its output, exit code and declared result files as if it ran here (edit files only here; an interrupt or tool timeout kills the remote job). Longer than your tool timeout: `charness remote-run --bg <command>` prints a job id, then run `charness remote-run wait <id>` in the background (it blocks until the job ends and exits with its code); `ls`, `status <id>`, `logs <id> -f`, `kill <id>` manage jobs.';
|
|
128
|
+
const orchestrationInstructionHead = '• You orchestrate detached workers (a `claude -p` / `opencode run` builder, reviewer, researcher) →';
|
|
129
|
+
/** What the worker-watch recipe says once a tool is named: shared by both wordings of the Telegram bullet. */
|
|
130
|
+
const workerWatchRecipeText = `its description has the recipe (checkCommand, cron, \`${workerWatch_1.workerWatchPinArgument}\`); never \`kill -0\` alone: it never fires on a hung worker.`;
|
|
131
|
+
/**
|
|
132
|
+
* The orchestration bullet of a conversation on a tracker, which has no scheduling tools: only the manager-skill hint, so
|
|
133
|
+
* with the bot's skills off (`/bot_skills`) there is nothing left of it and `null` drops it.
|
|
134
|
+
*/
|
|
135
|
+
function buildTrackerOrchestrationInstruction(isBotSkillsEnabled) {
|
|
136
|
+
return isBotSkillsEnabled ? `${orchestrationInstructionHead} ${managerSkillInstruction}.` : null;
|
|
137
|
+
}
|
|
138
|
+
/** The orchestration bullet of a Telegram topic: the manager-skill hint (dropped with the skills off) and the worker-watch recipe, which is a tool fact and stays. */
|
|
139
|
+
function buildTelegramOrchestrationInstruction(isBotSkillsEnabled) {
|
|
140
|
+
return isBotSkillsEnabled
|
|
141
|
+
? `${orchestrationInstructionHead} ${managerSkillInstruction}. Watch EACH worker with schedule_create — ${workerWatchRecipeText}`
|
|
142
|
+
: `${orchestrationInstructionHead} schedule_create to watch EACH worker — ${workerWatchRecipeText}`;
|
|
143
|
+
}
|
|
144
|
+
const claudeProfilesInstruction = '• Before you start or resume a child `claude` process (a detached worker, reviewer, planner) → claude_profiles with the model you will launch: it lists the signed-in Claude accounts with their usage windows and names the one to run on (`recommended`: the account whose weekly limit resets soonest is spent first). A new child: no `currentProfile`; a resumed one: the profile it last ran on, plus `isStoppedByLimit: true` when it broke off on a usage limit. Launch the child with `CLAUDE_CONFIG_DIR=<its configDir>` in its environment (nothing when configDir is null); without it the child inherits YOUR account and drains the same limits. `recommended: null` → nothing is usable now: schedule one resume at `nextAvailable.at` (null too: tell the user, retry once in about 30 minutes).';
|
|
145
|
+
/** @description Which optional tools `deps` offers. */
|
|
146
|
+
function getOptionalBotTools(deps) {
|
|
147
|
+
return {
|
|
148
|
+
isJiraAttachmentToolOffered: deps.fetchJiraAttachment !== undefined,
|
|
149
|
+
isTodoToolOffered: deps.todos !== undefined,
|
|
150
|
+
isRemoteRunOffered: deps.isRemoteRunOffered?.() ?? false,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function buildTelegramInstructions(isTodoToolOffered, isRemoteRunOffered, isBotSkillsEnabled) {
|
|
154
|
+
return `This MCP lets the agent act on its own Telegram topic.
|
|
115
155
|
|
|
116
156
|
When to use it:
|
|
117
157
|
• The user asks to run/finish a plan or task LATER ("in 2h", "tomorrow 9am", "every weekday") → schedule_create. Put the work in \`prompt\`; the future run is a fresh session with no memory of this chat. Not CronCreate / ScheduleWakeup for anything that must happen: they live only in your process, which the bot stops after a long idle stretch, and die with it.
|
|
118
158
|
• You produced a file/chart/screenshot/video to deliver → send_file_to_user. Videos MUST be H.264 .mp4 sent as video (never as_file/document, never .webm/.mov — those render as GIFs or don't play); transcode first if needed (the tool description has the ffmpeg recipe).
|
|
119
159
|
• You want to deliver SEVERAL discrete messages (each as its own Telegram message, e.g. a per-item news digest) → send_messages_to_user. Each item can optionally attach ONE file/photo/video (text becomes its caption).
|
|
120
160
|
${compactConversationInstruction}
|
|
121
|
-
• You need to review or remove scheduled jobs → schedule_list / schedule_cancel.
|
|
161
|
+
${isTodoToolOffered ? `${todoInstruction}\n` : ''}• You need to review or remove scheduled jobs → schedule_list / schedule_cancel.
|
|
122
162
|
• You need a watchdog — keep an eye on a service, process, build, deploy, disk, URL… → schedule_create with \`checkCommand\` (cron). The bot runs the command in this folder on schedule, stays silent while it exits 0, and on the first failure pins an alert and wakes you with \`prompt\` + the exit code and output tail. Checks survive bot restarts and crashes. NEVER build your own watcher (a background loop, nohup, a sleep loop, a tmux pane, a shell crontab): it dies with your session or a restart and then fails silently.
|
|
163
|
+
${buildTelegramOrchestrationInstruction(isBotSkillsEnabled)}
|
|
123
164
|
${answerRequestInstruction} The requester may not see your plain text, so anything they must read goes through answer_request. Your plain text is relayed into the topic too, so after answer_request end the turn WITHOUT a plain-text recap of what you answered — it would show up twice.
|
|
124
|
-
${claudeProfilesInstruction}
|
|
165
|
+
${claudeProfilesInstruction}${isRemoteRunOffered ? `\n${remoteRunInstruction}` : ''}
|
|
125
166
|
|
|
126
167
|
Each tool's own description has the exact argument recipe (one-shot vs cron vs N-times, checks).`;
|
|
168
|
+
}
|
|
127
169
|
/** What a Jira session's instructions add: the tool that reaches the issue's original files (C10). */
|
|
128
170
|
const jiraAttachmentInstruction = '• The issue lists a file (an attachment id in the attachments list, or in a placeholder such as "[image: shot.png — attachment 10234]") you need to look at → jira_get_attachment with that id; it saves the original file and returns its path.';
|
|
129
171
|
/** For a conversation on a tracker: the requester sees nothing but the answers; `extraInstructions` name the platform's own tools. */
|
|
130
|
-
function buildTrackerInstructions(extraInstructions) {
|
|
172
|
+
function buildTrackerInstructions(extraInstructions, isBotSkillsEnabled) {
|
|
131
173
|
return `This MCP connects the agent to the conversation that asked for its work.
|
|
132
174
|
|
|
133
175
|
When to use it:
|
|
@@ -136,12 +178,11 @@ ${[
|
|
|
136
178
|
...extraInstructions,
|
|
137
179
|
compactConversationInstruction,
|
|
138
180
|
claudeProfilesInstruction,
|
|
139
|
-
|
|
181
|
+
buildTrackerOrchestrationInstruction(isBotSkillsEnabled),
|
|
182
|
+
].filter((instruction) => instruction !== null).join('\n')}
|
|
140
183
|
|
|
141
184
|
Each tool's own description has the exact argument recipe.`;
|
|
142
185
|
}
|
|
143
|
-
const neutralInstructions = buildTrackerInstructions([]);
|
|
144
|
-
const jiraInstructions = buildTrackerInstructions([jiraAttachmentInstruction]);
|
|
145
186
|
/**
|
|
146
187
|
* Connect-time `instructions` returned in the MCP `initialize` handshake — a
|
|
147
188
|
* short, high-level pointer the client surfaces to the agent BEFORE any call.
|
|
@@ -151,12 +192,21 @@ const jiraInstructions = buildTrackerInstructions([jiraAttachmentInstruction]);
|
|
|
151
192
|
*
|
|
152
193
|
* @description The connect-time instructions for a session of `platform`: only
|
|
153
194
|
* a Telegram session has the scheduling and send-to-topic tools, so only its
|
|
154
|
-
* instructions name them (Jira connector plan J2, D18)
|
|
195
|
+
* instructions name them (Jira connector plan J2, D18); an optional tool is named
|
|
196
|
+
* only where it is offered. With the bot's skills off for the session
|
|
197
|
+
* (`isBotSkillsEnabled`, `/bot_skills`) the orchestration bullet no longer tells it to load `charness-manager`.
|
|
155
198
|
*/
|
|
156
|
-
function buildMcpServerInstructions(platform,
|
|
199
|
+
function buildMcpServerInstructions(platform, offered, isBotSkillsEnabled) {
|
|
157
200
|
if (platform === 'telegram')
|
|
158
|
-
return
|
|
159
|
-
|
|
201
|
+
return buildTelegramInstructions(offered.isTodoToolOffered, offered.isRemoteRunOffered, isBotSkillsEnabled);
|
|
202
|
+
const remoteRunInstructions = offered.isRemoteRunOffered ? [remoteRunInstruction] : [];
|
|
203
|
+
if (platform !== 'jira')
|
|
204
|
+
return buildTrackerInstructions(remoteRunInstructions, isBotSkillsEnabled);
|
|
205
|
+
return buildTrackerInstructions([
|
|
206
|
+
...(offered.isJiraAttachmentToolOffered ? [jiraAttachmentInstruction] : []),
|
|
207
|
+
...(offered.isTodoToolOffered ? [todoInstruction] : []),
|
|
208
|
+
...remoteRunInstructions,
|
|
209
|
+
], isBotSkillsEnabled);
|
|
160
210
|
}
|
|
161
211
|
/** Max characters of a free-text job name / prompt accepted by a tool (defensive bound). */
|
|
162
212
|
const maxNameLength = 200;
|
|
@@ -298,15 +348,22 @@ const digestScope = { kind: 'dir', directory: '' };
|
|
|
298
348
|
* a tool added, renamed, re-described or re-shaped changes it and nothing else
|
|
299
349
|
* has to be kept in step by hand.
|
|
300
350
|
*/
|
|
301
|
-
function getBotMcpToolDigest(deps, platform) {
|
|
351
|
+
function getBotMcpToolDigest(deps, platform, isBotSkillsEnabled) {
|
|
352
|
+
return buildBotMcpToolDigest(buildMcpServerInstructions(platform, getOptionalBotTools(deps), isBotSkillsEnabled), getBotMcpToolDefinitions(deps, platform));
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* @description The tool definitions a session of `platform` gets, recorded from the SAME registration the request
|
|
356
|
+
* path runs (never a handler): what the digest hashes, and what a test reads the tools' names and descriptions from.
|
|
357
|
+
*/
|
|
358
|
+
function getBotMcpToolDefinitions(deps, platform) {
|
|
302
359
|
const definitions = [];
|
|
303
360
|
const recorder = {
|
|
304
361
|
registerTool: (name, config) => {
|
|
305
|
-
definitions.push({ name, title: config.title, description: config.description, inputKeys: Object.keys(config.inputSchema
|
|
362
|
+
definitions.push({ name, title: config.title, description: config.description, inputKeys: Object.keys(config.inputSchema.shape).sort() });
|
|
306
363
|
},
|
|
307
364
|
};
|
|
308
365
|
registerBotTools(recorder, deps, digestScope, platform, undefined);
|
|
309
|
-
return
|
|
366
|
+
return definitions;
|
|
310
367
|
}
|
|
311
368
|
/**
|
|
312
369
|
* @description Resolve the single thread a tool call targets, from its scope and
|
|
@@ -356,6 +413,11 @@ function resolveTargetThreadKey(scope, suppliedThreadKey, getThreadsForDirectory
|
|
|
356
413
|
return { ok: true, threadKey: suppliedThreadKey };
|
|
357
414
|
}
|
|
358
415
|
// ─── tool input schemas + spec building ──────────────────────────────
|
|
416
|
+
/** The optional target thread every topic-scoped tool takes (a `dir:` scope with several bound threads needs it). */
|
|
417
|
+
const threadKeyArgSchema = zod_1.z
|
|
418
|
+
.string()
|
|
419
|
+
.optional()
|
|
420
|
+
.describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.');
|
|
359
421
|
const scheduleCreateShape = {
|
|
360
422
|
name: zod_1.z.string().min(1).max(maxNameLength).describe('Short human name for the job (shown in announcements/lists).'),
|
|
361
423
|
cron: zod_1.z
|
|
@@ -396,7 +458,7 @@ const scheduleCreateShape = {
|
|
|
396
458
|
'non-zero exit or timeout pins an alert in the topic and wakes you with `prompt` plus the exit ' +
|
|
397
459
|
'code and output tail; later failures stay silent until a run passes again (the topic is told). ' +
|
|
398
460
|
'Keep it a quick probe, e.g. `systemctl --user is-active myapp`, `curl -fsS -m 10 http://127.0.0.1:8080/health`, ' +
|
|
399
|
-
'`test $(df --output=pcent / | tail -1 | tr -dc 0-9) -lt 90
|
|
461
|
+
'`test $(df --output=pcent / | tail -1 | tr -dc 0-9) -lt 90`; a detached worker: the recipe in the tool description.'),
|
|
400
462
|
checkTimeoutSeconds: zod_1.z
|
|
401
463
|
.number()
|
|
402
464
|
.int()
|
|
@@ -409,24 +471,18 @@ const scheduleCreateShape = {
|
|
|
409
471
|
.boolean()
|
|
410
472
|
.optional()
|
|
411
473
|
.describe('Pin the fire announcement silently (no member notification). Default false = notify all.'),
|
|
412
|
-
threadKey:
|
|
413
|
-
.string()
|
|
414
|
-
.optional()
|
|
415
|
-
.describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.'),
|
|
474
|
+
threadKey: threadKeyArgSchema,
|
|
416
475
|
};
|
|
476
|
+
const scheduleCreateInput = (0, strictToolInput_1.createStrictToolInput)(scheduleCreateShape);
|
|
417
477
|
const scheduleListShape = {
|
|
418
|
-
threadKey:
|
|
419
|
-
.string()
|
|
420
|
-
.optional()
|
|
421
|
-
.describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.'),
|
|
478
|
+
threadKey: threadKeyArgSchema,
|
|
422
479
|
};
|
|
480
|
+
const scheduleListInput = (0, strictToolInput_1.createStrictToolInput)(scheduleListShape);
|
|
423
481
|
const scheduleCancelShape = {
|
|
424
482
|
id: zod_1.z.string().min(1).describe('The schedule id to cancel (from schedule_list).'),
|
|
425
|
-
threadKey:
|
|
426
|
-
.string()
|
|
427
|
-
.optional()
|
|
428
|
-
.describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.'),
|
|
483
|
+
threadKey: threadKeyArgSchema,
|
|
429
484
|
};
|
|
485
|
+
const scheduleCancelInput = (0, strictToolInput_1.createStrictToolInput)(scheduleCancelShape);
|
|
430
486
|
/**
|
|
431
487
|
* Coerces an ARRAY tool argument into an actual array before validation. Some
|
|
432
488
|
* MCP bridges (observed: Claude-agent harnesses AND OpenCode) serialize an array
|
|
@@ -466,19 +522,18 @@ const sendFileShape = {
|
|
|
466
522
|
.boolean()
|
|
467
523
|
.optional()
|
|
468
524
|
.describe('Explicitly force sendDocument (original quality, no inline preview), including for MP4s that use sendVideo by default.'),
|
|
469
|
-
threadKey:
|
|
470
|
-
.string()
|
|
471
|
-
.optional()
|
|
472
|
-
.describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.'),
|
|
525
|
+
threadKey: threadKeyArgSchema,
|
|
473
526
|
};
|
|
527
|
+
const sendFileInput = (0, strictToolInput_1.createStrictToolInput)(sendFileShape);
|
|
474
528
|
/**
|
|
475
529
|
* One batch item: EITHER a plain non-empty string (text-only message,
|
|
476
530
|
* backward-compatible with the original string-array tool) OR an object that may
|
|
477
|
-
* carry a text body, an attachment `path`, or both. The
|
|
478
|
-
*
|
|
531
|
+
* carry a text body, an attachment `path`, or both. The object is CLOSED: an
|
|
532
|
+
* agent that writes `filePath` for `path` must be told, not silently sent as a
|
|
533
|
+
* text-only message. The `.refine` rejects an all-empty object so a stray `{}`
|
|
534
|
+
* never posts nothing.
|
|
479
535
|
*/
|
|
480
|
-
const sendMessageItemObjectSchema =
|
|
481
|
-
.object({
|
|
536
|
+
const sendMessageItemObjectSchema = (0, strictToolInput_1.createStrictToolInput)({
|
|
482
537
|
text: zod_1.z
|
|
483
538
|
.string()
|
|
484
539
|
.optional()
|
|
@@ -494,12 +549,11 @@ const sendMessageItemObjectSchema = zod_1.z
|
|
|
494
549
|
.boolean()
|
|
495
550
|
.optional()
|
|
496
551
|
.describe('Force sendDocument for THIS attachment (original quality, no inline preview), including for MP4s.'),
|
|
497
|
-
})
|
|
498
|
-
.refine((item) => (item.text?.trim().length ?? 0) > 0 || (item.path?.trim().length ?? 0) > 0, { message: 'each message object must set a non-empty text or path' });
|
|
552
|
+
}).refine((item) => (item.text?.trim().length ?? 0) > 0 || (item.path?.trim().length ?? 0) > 0, { message: 'each message object must set a non-empty text or path' });
|
|
499
553
|
const sendMessageShape = {
|
|
500
554
|
messages: zod_1.z
|
|
501
555
|
.preprocess(coerceJsonArrayArg, zod_1.z
|
|
502
|
-
.array(zod_1.z.union([zod_1.z.string().min(1), sendMessageItemObjectSchema]))
|
|
556
|
+
.array(zod_1.z.union([zod_1.z.string().min(1), sendMessageItemObjectSchema], { error: strictToolInput_1.getUnknownKeysMessageOfUnion }))
|
|
503
557
|
.min(1)
|
|
504
558
|
.max(messageSendService_1.maxDiscreteMessages))
|
|
505
559
|
.describe(`1..${messageSendService_1.maxDiscreteMessages} items; EACH item is posted as its OWN separate Telegram message, in order (never ` +
|
|
@@ -512,11 +566,9 @@ const sendMessageShape = {
|
|
|
512
566
|
'Use this when you deliberately want several distinct messages (e.g. a per-item news digest: one message ' +
|
|
513
567
|
'per headline). Do NOT also print the same content as your normal reply, or it posts twice. Text supports ' +
|
|
514
568
|
'the usual markdown (links, bold); an over-long text item is split automatically.'),
|
|
515
|
-
threadKey:
|
|
516
|
-
.string()
|
|
517
|
-
.optional()
|
|
518
|
-
.describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.'),
|
|
569
|
+
threadKey: threadKeyArgSchema,
|
|
519
570
|
};
|
|
571
|
+
const sendMessageInput = (0, strictToolInput_1.createStrictToolInput)(sendMessageShape);
|
|
520
572
|
/**
|
|
521
573
|
* The three valid call shapes, appended to structural errors so a bad first call
|
|
522
574
|
* teaches the corrected next call (the model spirals when an error says only what
|
|
@@ -629,8 +681,13 @@ function registerSchedulerTools(server, deps, scope) {
|
|
|
629
681
|
'with a cron — the bot runs it in this folder and wakes you only when it starts failing. This is ' +
|
|
630
682
|
'the ONLY reliable watcher: it survives bot restarts and crashes. Never build your own (a ' +
|
|
631
683
|
'background loop, nohup, a sleep loop, a tmux pane, a shell crontab) — it dies with your session ' +
|
|
632
|
-
'or a restart and then fails silently
|
|
633
|
-
|
|
684
|
+
'or a restart and then fails silently.\n\n' +
|
|
685
|
+
`A DETACHED WORKER you launched (a \`claude -p\` / \`opencode run\` process): cron \`${workerWatch_1.workerWatchCheckCron}\`, ` +
|
|
686
|
+
`\`${workerWatch_1.workerWatchPinArgument}\`, checkCommand \`${workerWatch_1.workerWatchCheckCommand}\` with its PID and run dir — it fails when ` +
|
|
687
|
+
'the worker exits OR nothing in its run dir changed for 45 min, so the first failure is also the "worker finished" ' +
|
|
688
|
+
'signal (hence the silent pin: a normal finish must not notify the user). Never `kill -0` alone: it stays green ' +
|
|
689
|
+
'while a worker hangs. One check per worker run; schedule_cancel it once its wake is handled.',
|
|
690
|
+
inputSchema: scheduleCreateInput,
|
|
634
691
|
}, async (args) => {
|
|
635
692
|
const resolved = resolveTargetThreadKey(scope, args.threadKey, deps.getThreadsForDirectory);
|
|
636
693
|
if (!resolved.ok)
|
|
@@ -678,7 +735,7 @@ function registerSchedulerTools(server, deps, scope) {
|
|
|
678
735
|
server.registerTool('schedule_list', {
|
|
679
736
|
title: 'List scheduled prompts',
|
|
680
737
|
description: 'List the scheduled prompts for this topic (id, name, schedule, next run, paused flag).',
|
|
681
|
-
inputSchema:
|
|
738
|
+
inputSchema: scheduleListInput,
|
|
682
739
|
}, async (args) => {
|
|
683
740
|
const resolved = resolveTargetThreadKey(scope, args.threadKey, deps.getThreadsForDirectory);
|
|
684
741
|
if (!resolved.ok)
|
|
@@ -706,8 +763,10 @@ function registerSchedulerTools(server, deps, scope) {
|
|
|
706
763
|
});
|
|
707
764
|
server.registerTool('schedule_cancel', {
|
|
708
765
|
title: 'Cancel a scheduled prompt',
|
|
709
|
-
description: 'Cancel (delete) a scheduled prompt by its id. Only schedules owned by this topic can be cancelled.'
|
|
710
|
-
|
|
766
|
+
description: 'Cancel (delete) a scheduled prompt by its id. Only schedules owned by this topic can be cancelled. Cancelling a ' +
|
|
767
|
+
'watchdog check also unpins the alerts it pinned — cancel a worker watch once its wake is handled, so a finished ' +
|
|
768
|
+
'worker leaves no pinned alert behind.',
|
|
769
|
+
inputSchema: scheduleCancelInput,
|
|
711
770
|
}, async (args) => {
|
|
712
771
|
const resolved = resolveTargetThreadKey(scope, args.threadKey, deps.getThreadsForDirectory);
|
|
713
772
|
if (!resolved.ok)
|
|
@@ -723,7 +782,11 @@ function registerSchedulerTools(server, deps, scope) {
|
|
|
723
782
|
}
|
|
724
783
|
await deps.store.removeSchedule(args.id);
|
|
725
784
|
deps.disarmJob(args.id);
|
|
726
|
-
|
|
785
|
+
const alertPins = record.alertPinMessageIds ?? [];
|
|
786
|
+
if (alertPins.length === 0)
|
|
787
|
+
return textResult(`Cancelled "${record.name}" (id: ${record.id}).`);
|
|
788
|
+
await deps.unpinMessages(record.threadKey, alertPins);
|
|
789
|
+
return textResult(`Cancelled "${record.name}" (id: ${record.id}); its ${alertPins.length} pinned alert(s) unpinned.`);
|
|
727
790
|
});
|
|
728
791
|
}
|
|
729
792
|
/**
|
|
@@ -750,7 +813,7 @@ function registerFileSendTool(server, deps, scope, requestSignal) {
|
|
|
750
813
|
'the whole album documents — which turns its MP4s into GIFs, so send videos in their own call. ' +
|
|
751
814
|
'If a send fails, say so and give the file\'s path in your reply, then go on with the work — never stop over it. ' +
|
|
752
815
|
'Caption is optional (trimmed to 1024 chars; on the first album item).',
|
|
753
|
-
inputSchema:
|
|
816
|
+
inputSchema: sendFileInput,
|
|
754
817
|
}, async (args, extra) => {
|
|
755
818
|
const signal = requestSignal
|
|
756
819
|
? AbortSignal.any([extra.signal, requestSignal])
|
|
@@ -797,7 +860,7 @@ function registerMessageSendTool(server, deps, scope, requestSignal) {
|
|
|
797
860
|
'items; an over-long text item is split automatically. Note: this does NOT replace your normal single ' +
|
|
798
861
|
'reply — only reach for it when multiple discrete messages are wanted, and do not also print the same ' +
|
|
799
862
|
'content as your reply text (that would post it twice).',
|
|
800
|
-
inputSchema:
|
|
863
|
+
inputSchema: sendMessageInput,
|
|
801
864
|
}, async (args, extra) => {
|
|
802
865
|
const signal = requestSignal
|
|
803
866
|
? AbortSignal.any([extra.signal, requestSignal])
|
|
@@ -843,12 +906,12 @@ function registerCompactConversationTool(server, deps, scope) {
|
|
|
843
906
|
'never to "clean up". It does NOT compact mid-turn: it arms compaction and returns immediately; the ' +
|
|
844
907
|
'bot runs the real compaction the moment this turn finishes. There is nothing for you to do ' +
|
|
845
908
|
'afterwards — do not call it again for the same request.',
|
|
846
|
-
inputSchema: {
|
|
909
|
+
inputSchema: (0, strictToolInput_1.createStrictToolInput)({
|
|
847
910
|
reason: zod_1.z
|
|
848
911
|
.string()
|
|
849
912
|
.optional()
|
|
850
913
|
.describe('Optional short note on why the user asked to compact (for the bot log only).'),
|
|
851
|
-
},
|
|
914
|
+
}),
|
|
852
915
|
}, async (args) => {
|
|
853
916
|
// A surviving session may call this before boot re-attached it.
|
|
854
917
|
await deps.whenSessionsRestored();
|
|
@@ -861,6 +924,95 @@ function registerCompactConversationTool(server, deps, scope) {
|
|
|
861
924
|
return outcome.ok ? textResult(outcome.message) : errorResult(outcome.message);
|
|
862
925
|
});
|
|
863
926
|
}
|
|
927
|
+
/** The most items one `todo_update` call may name, and the longest `order` — a stand-up list is a few items (D1). */
|
|
928
|
+
const todoUpdateMaxItems = 30;
|
|
929
|
+
const todoOrderMaxIds = 100;
|
|
930
|
+
const todoItemPatchSchema = (0, strictToolInput_1.createStrictToolInput)({
|
|
931
|
+
id: zod_1.z
|
|
932
|
+
.string()
|
|
933
|
+
.trim()
|
|
934
|
+
.regex(/^t\d+$/)
|
|
935
|
+
.optional()
|
|
936
|
+
.describe('The item to change ("t3", from your list). Leave it out to ADD a new item.'),
|
|
937
|
+
title: zod_1.z
|
|
938
|
+
.string()
|
|
939
|
+
.max(types_1.todoTitleMaxLength)
|
|
940
|
+
.optional()
|
|
941
|
+
.describe('Task-sized and concrete: name the area (files, tests). Required for a new item.'),
|
|
942
|
+
status: zod_1.z
|
|
943
|
+
.enum(types_1.todoStatuses)
|
|
944
|
+
.optional()
|
|
945
|
+
.describe('queued (default for a new item) · inWork (you are on it) · done · dropped (will not be done — the way to remove an item).'),
|
|
946
|
+
note: zod_1.z.string().max(types_1.todoNoteMaxLength).optional().describe('A short note other agents should know (what is left, a blocker). An empty note removes it.'),
|
|
947
|
+
ref: zod_1.z
|
|
948
|
+
.string()
|
|
949
|
+
.max(types_1.todoRefMaxLength)
|
|
950
|
+
.optional()
|
|
951
|
+
.describe('A tracker key / id / link the item stands for, e.g. the bug ticket you just created. An empty ref removes it.'),
|
|
952
|
+
position: zod_1.z.enum(types_1.todoPositions).optional().describe('Put the item first or last among the open ones (a new item goes last by default).'),
|
|
953
|
+
});
|
|
954
|
+
const todoUpdateShape = {
|
|
955
|
+
items: zod_1.z
|
|
956
|
+
.preprocess(coerceJsonArrayArg, zod_1.z.array(todoItemPatchSchema).max(todoUpdateMaxItems))
|
|
957
|
+
.optional()
|
|
958
|
+
.describe('Items to add (no id) or change (id + only the fields that change). Nothing disappears by omission: set status dropped to remove one.'),
|
|
959
|
+
order: zod_1.z
|
|
960
|
+
.preprocess(coerceJsonArrayArg, zod_1.z.array(zod_1.z.string().trim().min(1)).max(todoOrderMaxIds))
|
|
961
|
+
.optional()
|
|
962
|
+
.describe('Open item ids in the wanted queue order; the ones left out keep their relative order after them.'),
|
|
963
|
+
threadKey: threadKeyArgSchema,
|
|
964
|
+
};
|
|
965
|
+
const todoUpdateInput = (0, strictToolInput_1.createStrictToolInput)(todoUpdateShape);
|
|
966
|
+
const todoReadShape = {
|
|
967
|
+
scope: zod_1.z
|
|
968
|
+
.enum(registry_1.todoReadScopes)
|
|
969
|
+
.optional()
|
|
970
|
+
.describe('own (default): your list · project: the whole board of the project\'s other topics (what they work on now).'),
|
|
971
|
+
includeHistory: zod_1.z.boolean().optional().describe(`With scope own: also list older closed items (done / dropped), up to ${registry_1.todoHistoryMaxItems}.`),
|
|
972
|
+
threadKey: threadKeyArgSchema,
|
|
973
|
+
};
|
|
974
|
+
const todoReadInput = (0, strictToolInput_1.createStrictToolInput)(todoReadShape);
|
|
975
|
+
/**
|
|
976
|
+
* @description Register `todo_update` / `todo_read` (shared todo registry D3–D5): the published list of the
|
|
977
|
+
* conversation the token names — never another one; the rules live in `todos/registry.ts`.
|
|
978
|
+
*/
|
|
979
|
+
function registerTodoTools(server, deps, todos, scope) {
|
|
980
|
+
server.registerTool('todo_update', {
|
|
981
|
+
title: 'Update your published todo list',
|
|
982
|
+
description: 'Publish what you are doing so the agents in the project\'s other topics see it and never fix the same thing ' +
|
|
983
|
+
'unknowingly (and you see theirs). Stand-up level: a few task-sized items, never micro-steps (those stay in ' +
|
|
984
|
+
'your own todo tool). Add an item as inWork BEFORE you start any task, self-found fixes included (a failing ' +
|
|
985
|
+
'test, a leak), naming the area concretely; mark it done / dropped as soon as it is. An UPSERT: an item ' +
|
|
986
|
+
'without id is new; with an id only the fields given change. A call with no items and no order confirms the ' +
|
|
987
|
+
'list is still accurate. The result is your list and what changed in the project\'s other topics since you last saw them.',
|
|
988
|
+
inputSchema: todoUpdateInput,
|
|
989
|
+
}, async (args) => {
|
|
990
|
+
const resolved = resolveTargetThreadKey(scope, args.threadKey, deps.getThreadsForDirectory);
|
|
991
|
+
if (!resolved.ok)
|
|
992
|
+
return errorResult(resolved.error);
|
|
993
|
+
const outcome = await todos.update(resolved.threadKey, {
|
|
994
|
+
...(args.items === undefined ? {} : { items: args.items }),
|
|
995
|
+
...(args.order === undefined ? {} : { order: args.order }),
|
|
996
|
+
});
|
|
997
|
+
return outcome.ok ? textResult(outcome.message) : errorResult(outcome.error);
|
|
998
|
+
});
|
|
999
|
+
server.registerTool('todo_read', {
|
|
1000
|
+
title: 'Read your published todo list',
|
|
1001
|
+
description: 'Your published todo list (in work, the queue in order, recently done) and what changed in the project\'s other ' +
|
|
1002
|
+
'topics since you last saw them; with includeHistory also your older closed items; with scope project the whole board ' +
|
|
1003
|
+
'of the other topics.',
|
|
1004
|
+
inputSchema: todoReadInput,
|
|
1005
|
+
}, async (args) => {
|
|
1006
|
+
const resolved = resolveTargetThreadKey(scope, args.threadKey, deps.getThreadsForDirectory);
|
|
1007
|
+
if (!resolved.ok)
|
|
1008
|
+
return errorResult(resolved.error);
|
|
1009
|
+
const outcome = await todos.read(resolved.threadKey, {
|
|
1010
|
+
...(args.scope === undefined ? {} : { scope: args.scope }),
|
|
1011
|
+
...(args.includeHistory === undefined ? {} : { includeHistory: args.includeHistory }),
|
|
1012
|
+
});
|
|
1013
|
+
return outcome.ok ? textResult(outcome.message) : errorResult(outcome.error);
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
864
1016
|
/**
|
|
865
1017
|
* `jira_get_attachment`: the issue is the conversation this session's token names — never an argument —
|
|
866
1018
|
* so a file of any other issue cannot be asked for, however the id got into the agent's head.
|
|
@@ -873,9 +1025,9 @@ function registerJiraAttachmentTool(server, deps, fetchJiraAttachment, scope) {
|
|
|
873
1025
|
'"[image: shot.png — attachment 10234]". There is no size limit. What you do with the file is up to ' +
|
|
874
1026
|
'you: view an image with your file-reading tool, take frames or the audio of a video with ffmpeg ' +
|
|
875
1027
|
'(when it is on your PATH). Only this issue\'s own attachments can be fetched.',
|
|
876
|
-
inputSchema: {
|
|
1028
|
+
inputSchema: (0, strictToolInput_1.createStrictToolInput)({
|
|
877
1029
|
attachmentId: zod_1.z.string().min(1).describe('The attachment id, e.g. "10234" from "[image: shot.png — attachment 10234]".'),
|
|
878
|
-
},
|
|
1030
|
+
}),
|
|
879
1031
|
}, async (args) => {
|
|
880
1032
|
await deps.whenSessionsRestored();
|
|
881
1033
|
const resolved = resolveTargetThreadKey(scope, undefined, deps.getThreadsForDirectory);
|
|
@@ -917,6 +1069,7 @@ const answerRequestShape = {
|
|
|
917
1069
|
.max(answerRequest_1.answerBodyMaxLength)
|
|
918
1070
|
.describe(`The answer itself, in Markdown. The requester does not see your other output. ${answerStyle_1.answerStyleInstruction}`),
|
|
919
1071
|
};
|
|
1072
|
+
const answerRequestInput = (0, strictToolInput_1.createStrictToolInput)(answerRequestShape);
|
|
920
1073
|
/** `answer_request` in a Jira session: the same, and the comments the answer replies to. */
|
|
921
1074
|
const jiraAnswerRequestShape = {
|
|
922
1075
|
...answerRequestShape,
|
|
@@ -927,6 +1080,7 @@ const jiraAnswerRequestShape = {
|
|
|
927
1080
|
.describe('Ids of the issue\'s comments this answer replies to, e.g. ["10240"]. The bot mentions each comment\'s ' +
|
|
928
1081
|
'author at the top of your answer so they are notified. Only comments you were shown in this conversation count.'),
|
|
929
1082
|
};
|
|
1083
|
+
const jiraAnswerRequestInput = (0, strictToolInput_1.createStrictToolInput)(jiraAnswerRequestShape);
|
|
930
1084
|
/**
|
|
931
1085
|
* @description Register `answer_request` (request/answer core S3): the agent's
|
|
932
1086
|
* answer to a request, delivered to the surface the request came from. The
|
|
@@ -956,9 +1110,9 @@ function registerAnswerRequestTool(server, deps, scope, platform) {
|
|
|
956
1110
|
};
|
|
957
1111
|
// The reply field names a tracker's comments: only a Jira session is offered it.
|
|
958
1112
|
if (platform === 'jira')
|
|
959
|
-
server.registerTool('answer_request', { ...definition, inputSchema:
|
|
1113
|
+
server.registerTool('answer_request', { ...definition, inputSchema: jiraAnswerRequestInput }, handle);
|
|
960
1114
|
else
|
|
961
|
-
server.registerTool('answer_request', { ...definition, inputSchema:
|
|
1115
|
+
server.registerTool('answer_request', { ...definition, inputSchema: answerRequestInput }, handle);
|
|
962
1116
|
}
|
|
963
1117
|
/**
|
|
964
1118
|
* @description Correlate stateless MCP requests with cancellation notifications.
|
|
@@ -1058,6 +1212,20 @@ function createSchedulerMcpCancellationLifecycle(options = {}) {
|
|
|
1058
1212
|
}
|
|
1059
1213
|
return { registerRequest, cancelRequest };
|
|
1060
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* @description Whether the bot's skills are on for the conversations a scope reaches (`utils/botSkills.ts`). A `thread:`
|
|
1217
|
+
* scope is one conversation. A `dir:` scope is the OpenCode registration of a folder — ONE per folder and server run, read
|
|
1218
|
+
* at connect — so it serves the folder's OpenCode topics alone (a Claude topic bound to the same folder has its own
|
|
1219
|
+
* `thread:` scope) and keeps the manager hint while any of them has the skills on; a folder with no OpenCode topic gets the
|
|
1220
|
+
* instance value.
|
|
1221
|
+
*/
|
|
1222
|
+
function checkIsBotSkillsEnabledForScope(deps, scope) {
|
|
1223
|
+
const threadKeys = scope.kind === 'thread'
|
|
1224
|
+
? [scope.threadKey]
|
|
1225
|
+
: deps.getThreadsForDirectory(scope.directory).filter((threadKey) => deps.getThreadAdapterName(threadKey) === adapterNames_1.openCodeAdapterName);
|
|
1226
|
+
const keys = threadKeys.map(sessionKey_1.tryKeyFromString).filter((key) => key !== null);
|
|
1227
|
+
return keys.length === 0 ? (0, botSkills_1.checkIsBotSkillsEnabled)(null) : keys.some((key) => (0, botSkills_1.checkIsBotSkillsEnabled)(key));
|
|
1228
|
+
}
|
|
1061
1229
|
/**
|
|
1062
1230
|
* @description Build a fresh {@link McpServer} for one request, registering the
|
|
1063
1231
|
* scope-bound scheduler tools plus the `send_file_to_user` tool. The SDK binds one server
|
|
@@ -1066,7 +1234,7 @@ function createSchedulerMcpCancellationLifecycle(options = {}) {
|
|
|
1066
1234
|
*/
|
|
1067
1235
|
function buildRequestServer(deps, scope, requestSignal) {
|
|
1068
1236
|
const platform = getSchedulerScopePlatform(scope);
|
|
1069
|
-
const server = new mcp_js_1.McpServer({ name: mcpServerName, version: mcpServerVersion }, { instructions: buildMcpServerInstructions(platform, deps
|
|
1237
|
+
const server = new mcp_js_1.McpServer({ name: mcpServerName, version: mcpServerVersion }, { instructions: buildMcpServerInstructions(platform, getOptionalBotTools(deps), checkIsBotSkillsEnabledForScope(deps, scope)) });
|
|
1070
1238
|
registerBotTools(server, deps, scope, platform, requestSignal);
|
|
1071
1239
|
return server;
|
|
1072
1240
|
}
|
|
@@ -1082,10 +1250,22 @@ function registerBotTools(server, deps, scope, platform, requestSignal) {
|
|
|
1082
1250
|
if (platform === 'jira' && deps.fetchJiraAttachment)
|
|
1083
1251
|
registerJiraAttachmentTool(server, deps, deps.fetchJiraAttachment, scope);
|
|
1084
1252
|
registerCompactConversationTool(server, deps, scope);
|
|
1253
|
+
// A published list belongs to a conversation of a platform that has one (D54): a topic or a Jira issue.
|
|
1254
|
+
if (deps.todos && (platform === 'telegram' || platform === 'jira'))
|
|
1255
|
+
registerTodoTools(server, deps, deps.todos, scope);
|
|
1085
1256
|
registerAnswerRequestTool(server, deps, scope, platform);
|
|
1086
1257
|
if (deps.listClaudeProfiles)
|
|
1087
1258
|
registerClaudeProfilesTool(server, deps.listClaudeProfiles);
|
|
1088
1259
|
}
|
|
1260
|
+
/** The first line of the `claude_profiles` answer: the pick with how to launch it and why, or that nothing is usable and when something is. */
|
|
1261
|
+
function buildClaudeProfilesVerdict(report, currentProfile) {
|
|
1262
|
+
const outcome = (0, claudeUsage_1.describeClaudeLaunchOutcome)(report, currentProfile);
|
|
1263
|
+
if (report.recommended === null)
|
|
1264
|
+
return outcome;
|
|
1265
|
+
const dir = report.profiles.find((profile) => profile.name === report.recommended)?.configDir ?? null;
|
|
1266
|
+
const launch = dir === null ? 'default profile, set no CLAUDE_CONFIG_DIR' : `CLAUDE_CONFIG_DIR=${dir}`;
|
|
1267
|
+
return `recommended: ${report.recommended} → ${launch} (${outcome})`;
|
|
1268
|
+
}
|
|
1089
1269
|
/**
|
|
1090
1270
|
* `claude_profiles`: which Claude account a child process should run on. Reads the bot's per-profile usage
|
|
1091
1271
|
* cache (refreshed on demand by the port); touches no conversation, so it needs no scope resolution. The
|
|
@@ -1095,31 +1275,43 @@ function registerClaudeProfilesTool(server, listClaudeProfiles) {
|
|
|
1095
1275
|
server.registerTool('claude_profiles', {
|
|
1096
1276
|
title: 'Claude accounts and their usage',
|
|
1097
1277
|
description: 'The Claude account profiles signed in on this host, each with its usage windows — session (5 h), weekly ' +
|
|
1098
|
-
'(all models) and weekly Fable — as percent used + reset instant, and `recommended`: the
|
|
1099
|
-
'
|
|
1100
|
-
'
|
|
1101
|
-
'
|
|
1102
|
-
'
|
|
1103
|
-
'
|
|
1104
|
-
'
|
|
1105
|
-
'
|
|
1106
|
-
|
|
1278
|
+
'(all models) and weekly Fable — as percent used + reset instant, and `recommended`: the account a process of ' +
|
|
1279
|
+
'the model you pass should run on. A NEW agent (omit `currentProfile`) goes to the usable account whose weekly ' +
|
|
1280
|
+
'limit resets SOONEST — what burns soonest is spent first; an account whose five-hour window is at 90 % or more ' +
|
|
1281
|
+
'is skipped until it resets. A session you RESUME (pass `currentProfile`, the profile it last ran on) stays on ' +
|
|
1282
|
+
'it unless that account is signed out, limited or at 100 % on a window the model drains; when it broke off on a ' +
|
|
1283
|
+
'usage limit pass `isStoppedByLimit: true` and resume the SAME session at once on the answer. The session ' +
|
|
1284
|
+
'window and the shared weekly window bound every model, Fable included; Fable also drains its own weekly ' +
|
|
1285
|
+
'window; signed-out, limited and operator-switched-off accounts are skipped. An account with `billing: "api"` ' +
|
|
1286
|
+
'pays per request from a Claude Console balance: it has no windows and is NEVER picked for a new agent — do ' +
|
|
1287
|
+
'not launch a child on it unless the operator asked you to. `recommended: null` means nothing is usable now: ' +
|
|
1288
|
+
'`nextAvailable` names the account and instant that frees up first — schedule ONE resume at that time instead ' +
|
|
1289
|
+
'of retrying; when `nextAvailable` is null too, tell the user and retry once in about 30 minutes. Call it BEFORE launching or resuming a child `claude` and start the child with ' +
|
|
1290
|
+
'CLAUDE_CONFIG_DIR=<configDir> in its environment — configDir null means the default profile: set nothing. ' +
|
|
1291
|
+
'Without the variable the child inherits the account of this very session.',
|
|
1292
|
+
inputSchema: (0, strictToolInput_1.createStrictToolInput)({
|
|
1107
1293
|
model: zod_1.z
|
|
1108
1294
|
.string()
|
|
1109
1295
|
.max(64)
|
|
1110
1296
|
.optional()
|
|
1111
1297
|
.describe('The model the child will run (e.g. "fable", "opus", "sonnet"); decides whether the Fable weekly window counts besides the shared ones. Omit for the shared windows.'),
|
|
1112
|
-
|
|
1298
|
+
currentProfile: zod_1.z
|
|
1299
|
+
.string()
|
|
1300
|
+
.max(claudeProfiles_1.claudeProfileNameMaxLength)
|
|
1301
|
+
.optional()
|
|
1302
|
+
.describe('The profile the session you RESUME last ran on (the `name` you recorded at its launch); omit for a new agent.'),
|
|
1303
|
+
isStoppedByLimit: zod_1.z
|
|
1304
|
+
.boolean()
|
|
1305
|
+
.optional()
|
|
1306
|
+
.describe('The resumed session broke off on a usage limit of `currentProfile`: that account is left out of this answer. Needs `currentProfile`.'),
|
|
1307
|
+
}),
|
|
1113
1308
|
}, async (args) => {
|
|
1114
|
-
const
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
return `recommended: ${report.recommended} → ${dir === null ? 'default profile, set no CLAUDE_CONFIG_DIR' : `CLAUDE_CONFIG_DIR=${dir}`}`;
|
|
1121
|
-
})();
|
|
1122
|
-
return textResult(`${verdict}\n${JSON.stringify(report, null, 1)}`);
|
|
1309
|
+
const currentProfile = args.currentProfile?.trim() || null;
|
|
1310
|
+
if (args.isStoppedByLimit === true && currentProfile === null) {
|
|
1311
|
+
return errorResult('isStoppedByLimit needs currentProfile — the profile the session that hit the limit last ran on.');
|
|
1312
|
+
}
|
|
1313
|
+
const report = await listClaudeProfiles({ model: args.model?.trim() || null, currentProfile, isStoppedByLimit: args.isStoppedByLimit === true });
|
|
1314
|
+
return textResult(`${buildClaudeProfilesVerdict(report, currentProfile)}\n${JSON.stringify(report, null, 1)}`);
|
|
1123
1315
|
});
|
|
1124
1316
|
}
|
|
1125
1317
|
/** Read the whole request body into a string (the SDK wants the parsed JSON body). */
|
|
@@ -1229,7 +1421,12 @@ function createSchedulerMcpServer(deps) {
|
|
|
1229
1421
|
void server.close();
|
|
1230
1422
|
});
|
|
1231
1423
|
await server.connect(transport);
|
|
1232
|
-
|
|
1424
|
+
// The SDK refuses a call's input before any tool code runs, so the refusal is reported from inside the handling.
|
|
1425
|
+
const toolCall = types_js_1.CallToolRequestSchema.safeParse(parsedBody);
|
|
1426
|
+
const handleRequest = () => transport.handleRequest(req, res, parsedBody);
|
|
1427
|
+
await (toolCall.success && deps.logDiagnostic
|
|
1428
|
+
? (0, strictToolInput_1.runWithRefusalLogging)({ toolName: toolCall.data.params.name, log: deps.logDiagnostic }, handleRequest)
|
|
1429
|
+
: handleRequest());
|
|
1233
1430
|
}
|
|
1234
1431
|
function start() {
|
|
1235
1432
|
return new Promise((resolve, reject) => {
|
|
@@ -1323,7 +1520,7 @@ function createSchedulerMcpServer(deps) {
|
|
|
1323
1520
|
return {
|
|
1324
1521
|
start,
|
|
1325
1522
|
stop,
|
|
1326
|
-
getToolDigest: (platform) => getBotMcpToolDigest(deps, platform),
|
|
1523
|
+
getToolDigest: (platform, isBotSkillsEnabled) => getBotMcpToolDigest(deps, platform, isBotSkillsEnabled),
|
|
1327
1524
|
get port() {
|
|
1328
1525
|
return boundPort;
|
|
1329
1526
|
},
|