@codyswann/lisa 4.84.11 → 4.86.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/dist/cli/doctor-session-manager-pending.d.ts +17 -0
- package/dist/cli/doctor-session-manager-pending.d.ts.map +1 -0
- package/dist/cli/doctor-session-manager-pending.js +130 -0
- package/dist/cli/doctor-session-manager-pending.js.map +1 -0
- package/dist/cli/doctor-session-manager-token.d.ts +69 -0
- package/dist/cli/doctor-session-manager-token.d.ts.map +1 -0
- package/dist/cli/doctor-session-manager-token.js +264 -0
- package/dist/cli/doctor-session-manager-token.js.map +1 -0
- package/dist/cli/doctor-session-manager.d.ts +3 -1
- package/dist/cli/doctor-session-manager.d.ts.map +1 -1
- package/dist/cli/doctor-session-manager.js +168 -146
- package/dist/cli/doctor-session-manager.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +34 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/nightly-e2e-guard-behavior-certificate.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +172 -23
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/SKILL.md +5 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/SKILL.md +197 -54
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/references/runbook-template.md +23 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/config.mjs +39 -11
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/launch.mjs +69 -60
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token.mjs +39 -120
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-session-manager/SKILL.md +82 -19
- package/plugins/lisa/commands/session-manager.md +1 -1
- package/plugins/lisa/commands/setup/session-manager.md +1 -1
- package/plugins/lisa/rules/reference/config-resolution.md +39 -7
- package/plugins/lisa/skills/lisa-secrets-access/SKILL.md +5 -3
- package/plugins/lisa/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
- package/plugins/lisa/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
- package/plugins/lisa/skills/lisa-session-manager/SKILL.md +197 -54
- package/plugins/lisa/skills/lisa-session-manager/references/runbook-template.md +23 -10
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
- package/plugins/lisa/skills/lisa-session-manager/scripts/config.mjs +39 -11
- package/plugins/lisa/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/launch.mjs +69 -60
- package/plugins/lisa/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
- package/plugins/lisa/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
- package/plugins/lisa/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/token.mjs +39 -120
- package/plugins/lisa/skills/lisa-setup-session-manager/SKILL.md +82 -19
- package/plugins/lisa-agy/commands/lisa/session-manager.md +1 -1
- package/plugins/lisa-agy/commands/lisa/setup/session-manager.md +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-secrets-access/SKILL.md +5 -3
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
- package/plugins/lisa-agy/skills/lisa-session-manager/SKILL.md +197 -54
- package/plugins/lisa-agy/skills/lisa-session-manager/references/runbook-template.md +23 -10
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/config.mjs +39 -11
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/launch.mjs +69 -60
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token.mjs +39 -120
- package/plugins/lisa-agy/skills/lisa-setup-session-manager/SKILL.md +82 -19
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/commands/lisa/session-manager.md +1 -1
- package/plugins/lisa-copilot/commands/lisa/setup/session-manager.md +1 -1
- package/plugins/lisa-copilot/rules/reference/config-resolution.md +39 -7
- package/plugins/lisa-copilot/skills/lisa-secrets-access/SKILL.md +5 -3
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
- package/plugins/lisa-copilot/skills/lisa-session-manager/SKILL.md +197 -54
- package/plugins/lisa-copilot/skills/lisa-session-manager/references/runbook-template.md +23 -10
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/config.mjs +39 -11
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/launch.mjs +69 -60
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token.mjs +39 -120
- package/plugins/lisa-copilot/skills/lisa-setup-session-manager/SKILL.md +82 -19
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/commands/lisa/session-manager.md +1 -1
- package/plugins/lisa-cursor/commands/lisa/setup/session-manager.md +1 -1
- package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +39 -7
- package/plugins/lisa-cursor/skills/lisa-secrets-access/SKILL.md +5 -3
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
- package/plugins/lisa-cursor/skills/lisa-session-manager/SKILL.md +197 -54
- package/plugins/lisa-cursor/skills/lisa-session-manager/references/runbook-template.md +23 -10
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/config.mjs +39 -11
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/launch.mjs +69 -60
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token.mjs +39 -120
- package/plugins/lisa-cursor/skills/lisa-setup-session-manager/SKILL.md +82 -19
- package/plugins/lisa-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-devin/rules/reference/config-resolution.md +39 -7
- package/plugins/lisa-devin/skills/lisa-secrets-access/SKILL.md +5 -3
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
- package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
- package/plugins/lisa-devin/skills/lisa-session-manager/SKILL.md +197 -54
- package/plugins/lisa-devin/skills/lisa-session-manager/references/runbook-template.md +23 -10
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/config.mjs +39 -11
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/launch.mjs +69 -60
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token.mjs +39 -120
- package/plugins/lisa-devin/skills/lisa-setup-session-manager/SKILL.md +82 -19
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/src/base/commands/session-manager.md +1 -1
- package/plugins/src/base/commands/setup/session-manager.md +1 -1
- package/plugins/src/base/rules/reference/config-resolution.md +39 -7
- package/plugins/src/base/skills/lisa-secrets-access/SKILL.md +5 -3
- package/plugins/src/base/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
- package/plugins/src/base/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
- package/plugins/src/base/skills/lisa-session-manager/SKILL.md +197 -54
- package/plugins/src/base/skills/lisa-session-manager/references/runbook-template.md +23 -10
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
- package/plugins/src/base/skills/lisa-session-manager/scripts/config.mjs +39 -11
- package/plugins/src/base/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/launch.mjs +69 -60
- package/plugins/src/base/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
- package/plugins/src/base/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
- package/plugins/src/base/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/token.mjs +39 -120
- package/plugins/src/base/skills/lisa-setup-session-manager/SKILL.md +82 -19
- package/rails/copy-overwrite/scripts/lisa-rspec-shards.mjs +747 -0
- package/rails/copy-overwrite/scripts/lisa_rspec_shard_recorder.rb +143 -0
- package/rails/copy-overwrite/scripts/lisa_simplecov_collate.rb +51 -0
- package/rails/create-only/.github/workflows/ci.yml +4 -0
- package/scripts/two-channel-couplings.json +89 -7
- package/typescript/copy-overwrite/.prettierignore +1 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Telegram bot token held in the project's secrets provider (#4555).
|
|
3
|
+
*
|
|
4
|
+
* Before this, `store-token` wrote the token in plaintext to
|
|
5
|
+
* `<notify.stateDir>/.env`: the only Lisa-managed secret outside the secrets
|
|
6
|
+
* contract. When the project declares a secrets provider (`secrets.provider`
|
|
7
|
+
* set and not `env`), the token instead lives in that provider under one
|
|
8
|
+
* per-project name ({@link telegramSecretName}), and nothing is written to
|
|
9
|
+
* disk:
|
|
10
|
+
* - `store-token` stores it there: from a leftover plaintext file (migration)
|
|
11
|
+
* or from the operator's prompt or clipboard. It reads the secret back and
|
|
12
|
+
* compares hashes, and only then deletes the file.
|
|
13
|
+
* - `start` resolves it once and hands it to tmux on stdin, never argv. A
|
|
14
|
+
* plaintext file left behind stops `start` with the exact command that
|
|
15
|
+
* migrates it. An unreachable, rate-limited or slow provider is a failure
|
|
16
|
+
* (exit 1) with retry guidance, never a fallback to a stale file.
|
|
17
|
+
* With no provider configured the old `.env` path in token.mjs is unchanged.
|
|
18
|
+
*
|
|
19
|
+
* Every provider call goes through `lisa-secrets-access` (`surfaces.mjs` for
|
|
20
|
+
* the config, `providers.mjs` for reads and writes), behind an injectable
|
|
21
|
+
* adapter so tests run against a fake vault. The token is never returned to
|
|
22
|
+
* the CLI, put in a message, or logged: errors carry fixed reason text, never
|
|
23
|
+
* a provider's raw error, since a failed write's error can quote its argv.
|
|
24
|
+
*
|
|
25
|
+
* The adapter and provider-error handling live in token-provider.mjs and the
|
|
26
|
+
* plaintext-file migration helpers in token-migrate.mjs; this module keeps
|
|
27
|
+
* the two flows and re-exports what the CLI imports.
|
|
28
|
+
* @module session-manager/token-store
|
|
29
|
+
*/
|
|
30
|
+
import * as nodeFs from "node:fs";
|
|
31
|
+
|
|
32
|
+
import {
|
|
33
|
+
TOKEN_VAR,
|
|
34
|
+
TokenStoreError,
|
|
35
|
+
assertMigratable,
|
|
36
|
+
digest,
|
|
37
|
+
holdsToken,
|
|
38
|
+
keepExisting,
|
|
39
|
+
readEnvFile,
|
|
40
|
+
removeAfterVerify,
|
|
41
|
+
setupError,
|
|
42
|
+
} from "./token-migrate.mjs";
|
|
43
|
+
import { guarded } from "./token-provider.mjs";
|
|
44
|
+
import { validateBotToken } from "./token.mjs";
|
|
45
|
+
|
|
46
|
+
export { TokenStoreError } from "./token-migrate.mjs";
|
|
47
|
+
export {
|
|
48
|
+
classifyProviderFailure,
|
|
49
|
+
defaultSecretsAdapter,
|
|
50
|
+
loadTokenSecrets,
|
|
51
|
+
} from "./token-provider.mjs";
|
|
52
|
+
|
|
53
|
+
/** Providers whose secrets live in a project that a create must name. */
|
|
54
|
+
const PROJECT_SCOPED = new Set(["bitwarden"]);
|
|
55
|
+
|
|
56
|
+
/** The usage note stored with the secret (format: note-format.mjs). */
|
|
57
|
+
const NOTE = [
|
|
58
|
+
"Telegram bot token for a Lisa session manager, stored by its store-token command and read only by its start command.",
|
|
59
|
+
"scope: one Telegram bot - whoever holds it can read and send that bot's messages",
|
|
60
|
+
"owner: lisa-session-manager",
|
|
61
|
+
].join("\n");
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The provider secret name for one manager: `TELEGRAM_BOT_TOKEN_<NAME>`, with
|
|
65
|
+
* the manager name upper-snaked. The `TELEGRAM_` prefix keeps
|
|
66
|
+
* `scrubWorkerEnv` stripping it from every worker's environment.
|
|
67
|
+
* @param {string} managerName - `sessionManager.name`, e.g. `lisa-1a2b-manager`
|
|
68
|
+
* @returns {string} e.g. `TELEGRAM_BOT_TOKEN_LISA_1A2B_MANAGER`
|
|
69
|
+
*/
|
|
70
|
+
export function telegramSecretName(managerName) {
|
|
71
|
+
const suffix = String(managerName)
|
|
72
|
+
.toUpperCase()
|
|
73
|
+
.replaceAll(/[^A-Z0-9]+/g, "_");
|
|
74
|
+
return `${TOKEN_VAR}_${suffix}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Refuse a name the project's `secrets.require` allowlist does not declare:
|
|
79
|
+
* the provider would never hand it to this project.
|
|
80
|
+
* @param {{ require?: string[] | null }} cfg - Secrets config
|
|
81
|
+
* @param {string} name - Secret name
|
|
82
|
+
*/
|
|
83
|
+
function assertDeclared(cfg, name) {
|
|
84
|
+
if (Array.isArray(cfg.require) && !cfg.require.includes(name)) {
|
|
85
|
+
throw setupError(
|
|
86
|
+
`${name} is not declared in secrets.require in .lisa.config.json, so ` +
|
|
87
|
+
`this project may not read it. Add "${name}" to secrets.require, ` +
|
|
88
|
+
`then run this again.`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The provider project a new secret goes in: `--vault-project`, else the one
|
|
95
|
+
* project `secrets.narrow.projectIds` names, else the one project every
|
|
96
|
+
* visible secret lives in. Exit 2 rather than guess.
|
|
97
|
+
* @param {object} cfg - Secrets config
|
|
98
|
+
* @param {Array<{ projectId: string | null }>} rows - Visible secrets
|
|
99
|
+
* @param {{ name: string, vaultProject?: string }} input - Secret and flag
|
|
100
|
+
* @returns {string | undefined} Project id (undefined: provider has none)
|
|
101
|
+
*/
|
|
102
|
+
function chooseProject(cfg, rows, { name, vaultProject }) {
|
|
103
|
+
if (!PROJECT_SCOPED.has(cfg.provider)) return undefined;
|
|
104
|
+
const narrowed = cfg.narrow?.projectIds ?? [];
|
|
105
|
+
if (vaultProject) {
|
|
106
|
+
if (narrowed.length > 0 && !narrowed.includes(vaultProject)) {
|
|
107
|
+
throw setupError(
|
|
108
|
+
`--vault-project ${vaultProject} is not in secrets.narrow.projectIds, ` +
|
|
109
|
+
`so ${name} would be stored where this project cannot read it.`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
return vaultProject;
|
|
113
|
+
}
|
|
114
|
+
if (narrowed.length === 1) return narrowed[0];
|
|
115
|
+
const seen = [...new Set(rows.map(row => row.projectId).filter(Boolean))];
|
|
116
|
+
if (seen.length === 1) return seen[0];
|
|
117
|
+
throw setupError(
|
|
118
|
+
`Cannot tell which ${cfg.provider} project to store ${name} in ` +
|
|
119
|
+
`(${seen.length} projects are visible). Run store-token again with ` +
|
|
120
|
+
`--vault-project <project id>.`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Store the bot token in the secrets provider: look it up, take it from the
|
|
126
|
+
* plaintext file (migration) or `readToken` (prompt or clipboard), create or
|
|
127
|
+
* replace it, read it back and compare hashes, and only then delete the
|
|
128
|
+
* file. An existing secret is kept unless `replace`.
|
|
129
|
+
* @param {{ cfg: object, adapter: object, name: string, stateDir: string,
|
|
130
|
+
* replace?: boolean, vaultProject?: string,
|
|
131
|
+
* readToken: () => Promise<{ token?: string, clear?: () => boolean,
|
|
132
|
+
* stored?: boolean, reason?: string, message?: string }>,
|
|
133
|
+
* fs?: object }} input - Config, adapter, secret
|
|
134
|
+
* name, resolved state dir, flags, the token reader and an fs seam
|
|
135
|
+
* @returns {Promise<object>} `{stored:true,storage:"provider",...}`, or the
|
|
136
|
+
* reader's `{stored:false,...}` outcome
|
|
137
|
+
*/
|
|
138
|
+
export async function storeTokenInProvider(input) {
|
|
139
|
+
const { cfg, adapter, name, replace = false, fs = nodeFs } = input;
|
|
140
|
+
const where = {
|
|
141
|
+
provider: cfg.provider,
|
|
142
|
+
name,
|
|
143
|
+
retry:
|
|
144
|
+
`Could not store the Telegram bot token in ${cfg.provider}: <reason>. ` +
|
|
145
|
+
`Nothing was stored and any plaintext token file was kept. Wait a ` +
|
|
146
|
+
`minute and run store-token again.`,
|
|
147
|
+
};
|
|
148
|
+
assertDeclared(cfg, name);
|
|
149
|
+
const file = readEnvFile(input.stateDir, fs);
|
|
150
|
+
assertMigratable(file);
|
|
151
|
+
await guarded(() => adapter.preflight(cfg), where);
|
|
152
|
+
const rows = await guarded(() => adapter.list(cfg), where);
|
|
153
|
+
const existing = rows.find(row => row.key === name);
|
|
154
|
+
if (existing && !replace) {
|
|
155
|
+
return keepExisting(existing, file, { cfg, name, fs });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const read = holdsToken(file)
|
|
159
|
+
? { token: file.token }
|
|
160
|
+
: await input.readToken();
|
|
161
|
+
if (read.token === undefined) return read;
|
|
162
|
+
const projectId = existing ? undefined : chooseProject(cfg, rows, input);
|
|
163
|
+
await guarded(
|
|
164
|
+
() =>
|
|
165
|
+
existing
|
|
166
|
+
? adapter.replace(cfg, { id: existing.id, value: read.token })
|
|
167
|
+
: adapter.create(cfg, {
|
|
168
|
+
name,
|
|
169
|
+
value: read.token,
|
|
170
|
+
projectId,
|
|
171
|
+
note: NOTE,
|
|
172
|
+
}),
|
|
173
|
+
where
|
|
174
|
+
);
|
|
175
|
+
const after = (await guarded(() => adapter.list(cfg), where)).find(
|
|
176
|
+
row => row.key === name
|
|
177
|
+
);
|
|
178
|
+
if (after === undefined || digest(after.value) !== digest(read.token)) {
|
|
179
|
+
throw new TokenStoreError(
|
|
180
|
+
`Reading ${name} back from ${cfg.provider} did not return what was ` +
|
|
181
|
+
`written, so the token is not proven stored. Any plaintext token ` +
|
|
182
|
+
`file was kept. Run store-token again.`,
|
|
183
|
+
1
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
stored: true,
|
|
188
|
+
storage: "provider",
|
|
189
|
+
provider: cfg.provider,
|
|
190
|
+
secret: name,
|
|
191
|
+
verified: true,
|
|
192
|
+
...removeAfterVerify(file, fs),
|
|
193
|
+
...(read.clear ? { clipboardCleared: read.clear() } : {}),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Resolve the bot token for `start`, once, from the provider. Refuses (exit
|
|
199
|
+
* 2) a leftover plaintext file that holds a token line, naming `fixCommand`
|
|
200
|
+
* (the `store-token` call that migrates it; an empty or comment-only file
|
|
201
|
+
* holds nothing to migrate and does not stop `start`), an undeclared or
|
|
202
|
+
* missing secret, and a value that is not
|
|
203
|
+
* bot-token shaped; fails (exit 1) when the provider is unreachable,
|
|
204
|
+
* rate-limited or slow, saying nothing was started.
|
|
205
|
+
* @param {{ cfg: object, adapter: object, name: string, stateDir: string,
|
|
206
|
+
* fixCommand: string, fs?: object }} input - Config, adapter, secret name,
|
|
207
|
+
* resolved state dir, the migrating command and an fs seam
|
|
208
|
+
* @returns {Promise<string>} The token, for the tmux stdin line only
|
|
209
|
+
*/
|
|
210
|
+
export async function resolveTelegramToken(input) {
|
|
211
|
+
const { cfg, adapter, name, fixCommand, fs = nodeFs } = input;
|
|
212
|
+
assertDeclared(cfg, name);
|
|
213
|
+
const file = readEnvFile(input.stateDir, fs);
|
|
214
|
+
if (holdsToken(file)) {
|
|
215
|
+
throw setupError(
|
|
216
|
+
`A plaintext Telegram bot token file is still at ${file.path}. With a ` +
|
|
217
|
+
`secrets provider configured the token must live in ` +
|
|
218
|
+
`${cfg.provider} only. Nothing was started. Move it there (this ` +
|
|
219
|
+
`stores the token, verifies it and deletes the file), then run start ` +
|
|
220
|
+
`again:\n ${fixCommand}`
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
const where = {
|
|
224
|
+
provider: cfg.provider,
|
|
225
|
+
name,
|
|
226
|
+
retry:
|
|
227
|
+
`Could not read the Telegram bot token from ${cfg.provider}: ` +
|
|
228
|
+
`<reason>. Nothing was started. Wait a minute and run start again; if ` +
|
|
229
|
+
`it keeps failing, check ${cfg.provider}'s status and this machine's ` +
|
|
230
|
+
`network.`,
|
|
231
|
+
};
|
|
232
|
+
await guarded(() => adapter.preflight(cfg), where);
|
|
233
|
+
const rows = await guarded(() => adapter.list(cfg), where);
|
|
234
|
+
const hit = rows.find(row => row.key === name);
|
|
235
|
+
if (!hit?.value) {
|
|
236
|
+
throw setupError(
|
|
237
|
+
`${cfg.provider} has no secret named ${name}, so the manager has no ` +
|
|
238
|
+
`bot token. Nothing was started. Store it with:\n ${fixCommand}`
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
if (!validateBotToken(hit.value)) {
|
|
242
|
+
throw setupError(
|
|
243
|
+
`${name} in ${cfg.provider} does not look like a Telegram bot token. ` +
|
|
244
|
+
`Nothing was started. Run store-token --replace to store the right one.`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
return hit.value;
|
|
248
|
+
}
|
|
@@ -5,30 +5,40 @@
|
|
|
5
5
|
* reachable), and never put in argv, a return value, an error message or a
|
|
6
6
|
* log line. An existing token is replaced only on request. Split out of
|
|
7
7
|
* launch.mjs, which re-exports everything here.
|
|
8
|
+
*
|
|
9
|
+
* The `.env` file is the storage only when the project has no secrets
|
|
10
|
+
* provider; with one, token-store.mjs stores the token there instead and
|
|
11
|
+
* reuses the prompt and clipboard readers (#4555).
|
|
12
|
+
*
|
|
13
|
+
* Validation, the prompt and clipboard readers and the printed `store-token`
|
|
14
|
+
* command live in token-read.mjs, re-exported here, to keep this module under
|
|
15
|
+
* the line budget.
|
|
8
16
|
* @module token
|
|
9
17
|
*/
|
|
10
18
|
import { randomUUID } from "node:crypto";
|
|
11
19
|
import * as nodeFs from "node:fs";
|
|
12
20
|
import path from "node:path";
|
|
13
21
|
|
|
14
|
-
import { readClipboard } from "./clipboard.mjs";
|
|
15
22
|
import { LaunchError, resolveStateDir } from "./state-dir.mjs";
|
|
23
|
+
import {
|
|
24
|
+
readTokenFromClipboard,
|
|
25
|
+
readTokenFromPrompt,
|
|
26
|
+
shellQuote,
|
|
27
|
+
validateBotToken,
|
|
28
|
+
} from "./token-read.mjs";
|
|
16
29
|
|
|
17
|
-
|
|
18
|
-
|
|
30
|
+
export {
|
|
31
|
+
buildStoreTokenCommand,
|
|
32
|
+
loadPromptSecret,
|
|
33
|
+
readTokenFromClipboard,
|
|
34
|
+
readTokenFromPrompt,
|
|
35
|
+
shellQuote,
|
|
36
|
+
validateBotToken,
|
|
37
|
+
} from "./token-read.mjs";
|
|
19
38
|
|
|
20
39
|
/** The plugin reads its token from this file in the state dir. */
|
|
21
40
|
const TOKEN_FILE_NAME = ".env";
|
|
22
41
|
|
|
23
|
-
/**
|
|
24
|
-
* Whether `token` looks like a BotFather bot token.
|
|
25
|
-
* @param {unknown} token - Candidate
|
|
26
|
-
* @returns {boolean} True for `<digits>:<30+ of [A-Za-z0-9_-]>`
|
|
27
|
-
*/
|
|
28
|
-
export function validateBotToken(token) {
|
|
29
|
-
return typeof token === "string" && BOT_TOKEN_PATTERN.test(token);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
42
|
/**
|
|
33
43
|
* Write `<stateDir>/.env` as `TELEGRAM_BOT_TOKEN=<token>`.
|
|
34
44
|
*
|
|
@@ -64,65 +74,6 @@ export function writeTokenFile(stateDir, token, seams = {}) {
|
|
|
64
74
|
return { path: target };
|
|
65
75
|
}
|
|
66
76
|
|
|
67
|
-
/**
|
|
68
|
-
* Load `promptSecret`/`canPrompt` from the secrets-access skill, by path
|
|
69
|
-
* relative to this file, the same way other skills reach it. Lazy so the
|
|
70
|
-
* argv builders never pay for it.
|
|
71
|
-
* @returns {Promise<{ promptSecret: Function, canPrompt: Function }>} Module
|
|
72
|
-
*/
|
|
73
|
-
export function loadPromptSecret() {
|
|
74
|
-
return import(
|
|
75
|
-
new URL(
|
|
76
|
-
"../../lisa-secrets-access/scripts/prompt-secret.mjs",
|
|
77
|
-
import.meta.url
|
|
78
|
-
).href
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Quote one word for a POSIX shell.
|
|
84
|
-
* @param {string} word - Word to quote
|
|
85
|
-
* @returns {string} Single-quoted word
|
|
86
|
-
*/
|
|
87
|
-
function shellQuote(word) {
|
|
88
|
-
const escaped = String(word).replaceAll("'", String.raw`'\''`);
|
|
89
|
-
return `'${escaped}'`;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* The command an operator pastes into their own terminal to store the token,
|
|
94
|
-
* for when the caller (an agent's Bash) has no TTY to prompt on.
|
|
95
|
-
* @param {{ scriptsDir: string, projectRoot: string, replace?: boolean }}
|
|
96
|
-
* input - Script and project locations, and whether to carry `--replace`
|
|
97
|
-
* @returns {string} One shell line
|
|
98
|
-
*/
|
|
99
|
-
export function buildStoreTokenCommand({
|
|
100
|
-
scriptsDir,
|
|
101
|
-
projectRoot,
|
|
102
|
-
replace,
|
|
103
|
-
fromClipboard = false,
|
|
104
|
-
}) {
|
|
105
|
-
const script = shellQuote(path.join(scriptsDir, "session-manager.mjs"));
|
|
106
|
-
const flags =
|
|
107
|
-
(replace ? " --replace" : "") + (fromClipboard ? " --from-clipboard" : "");
|
|
108
|
-
return `node ${script} store-token${flags} --project-root ${shellQuote(projectRoot)}`;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/** Why `store-token` cannot prompt here, and the two ways forward. */
|
|
112
|
-
const NO_TTY_HINT =
|
|
113
|
-
"No terminal to prompt on, and Claude Code's ! prefix has no TTY either. " +
|
|
114
|
-
"Run `command` in a separate terminal app, or copy the token from " +
|
|
115
|
-
"BotFather and run `clipboardCommand`.";
|
|
116
|
-
|
|
117
|
-
/** The `invalid` outcome; names the expected shape, never the input. */
|
|
118
|
-
const INVALID = Object.freeze({
|
|
119
|
-
stored: false,
|
|
120
|
-
reason: "invalid",
|
|
121
|
-
message:
|
|
122
|
-
"That does not look like a Telegram bot token " +
|
|
123
|
-
"(expected <digits>:<30 or more letters, digits, _ or ->).",
|
|
124
|
-
});
|
|
125
|
-
|
|
126
77
|
/**
|
|
127
78
|
* Refuse to overwrite an existing token unless `replace` was asked for: a
|
|
128
79
|
* second project that shares this state dir by mistake would otherwise
|
|
@@ -161,31 +112,17 @@ export function storeTokenFromClipboard(input) {
|
|
|
161
112
|
const { replace = false, io = {} } = input;
|
|
162
113
|
const stateDir = resolveStateDir(input.stateDir, input);
|
|
163
114
|
assertReplaceable(stateDir, replace, io);
|
|
164
|
-
const
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
const token = clip.text.trim();
|
|
169
|
-
if (!token) {
|
|
170
|
-
return {
|
|
171
|
-
stored: false,
|
|
172
|
-
reason: "empty",
|
|
173
|
-
message: "The clipboard is empty.",
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
if (!validateBotToken(token)) return { ...INVALID };
|
|
177
|
-
const written = writeTokenFile(stateDir, token, io);
|
|
178
|
-
return { stored: true, ...written, clipboardCleared: clip.clear() };
|
|
115
|
+
const read = readTokenFromClipboard(io);
|
|
116
|
+
if (read.token === undefined) return read;
|
|
117
|
+
const written = writeTokenFile(stateDir, read.token, io);
|
|
118
|
+
return { stored: true, ...written, clipboardCleared: read.clear() };
|
|
179
119
|
}
|
|
180
120
|
|
|
181
121
|
/**
|
|
182
|
-
* Prompt for the bot token on the operator's terminal and store it
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* operator to run in a separate terminal app, and the `--from-clipboard` form
|
|
187
|
-
* of it, because an agent's Bash (and Claude Code's `!` prefix) can never
|
|
188
|
-
* answer a prompt and a hung setup looks like a slow one.
|
|
122
|
+
* Prompt for the bot token on the operator's terminal and store it in
|
|
123
|
+
* `<stateDir>/.env`. An existing token is never overwritten without
|
|
124
|
+
* `replace`; with no TTY it returns the commands that work instead (see
|
|
125
|
+
* {@link readTokenFromPrompt}).
|
|
189
126
|
* @param {{ stateDir: string, scriptsDir: string, projectRoot: string,
|
|
190
127
|
* replace?: boolean, env?: Record<string, string | undefined>,
|
|
191
128
|
* homedir?: string, io?: { canPrompt?: () => boolean,
|
|
@@ -200,33 +137,15 @@ export async function storeToken(input) {
|
|
|
200
137
|
const { scriptsDir, projectRoot, replace = false, io = {} } = input;
|
|
201
138
|
const stateDir = resolveStateDir(input.stateDir, input);
|
|
202
139
|
assertReplaceable(stateDir, replace, io);
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
message: NO_TTY_HINT,
|
|
213
|
-
command: buildStoreTokenCommand({ scriptsDir, projectRoot, replace }),
|
|
214
|
-
clipboardCommand: buildStoreTokenCommand({
|
|
215
|
-
scriptsDir,
|
|
216
|
-
projectRoot,
|
|
217
|
-
replace,
|
|
218
|
-
fromClipboard: true,
|
|
219
|
-
}),
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
const typed = promptSecret(
|
|
223
|
-
`Paste the Telegram bot token for ${stateDir} (input is hidden): `
|
|
224
|
-
);
|
|
225
|
-
if (!typed) {
|
|
226
|
-
return { stored: false, reason: "empty", message: "Nothing entered." };
|
|
227
|
-
}
|
|
228
|
-
if (!validateBotToken(typed)) return { ...INVALID };
|
|
229
|
-
return { stored: true, ...writeTokenFile(stateDir, typed, io) };
|
|
140
|
+
const read = await readTokenFromPrompt({
|
|
141
|
+
label: stateDir,
|
|
142
|
+
scriptsDir,
|
|
143
|
+
projectRoot,
|
|
144
|
+
replace,
|
|
145
|
+
io,
|
|
146
|
+
});
|
|
147
|
+
if (read.token === undefined) return read;
|
|
148
|
+
return { stored: true, ...writeTokenFile(stateDir, read.token, io) };
|
|
230
149
|
}
|
|
231
150
|
|
|
232
151
|
/**
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lisa-setup-session-manager
|
|
3
|
-
description: "Set up the local session manager for this project: writes the non-secret `sessionManager` block to `.lisa.config.json` (detecting a multi-repo layout: repos under `projects/`, or directly under the project root),
|
|
3
|
+
description: "Set up the local session manager for this project: writes the non-secret `sessionManager` block to `.lisa.config.json` (detecting a multi-repo layout: repos under `projects/`, or directly under the project root), optionally sets up a Telegram notification channel (the project's own bot token stored in its secrets provider, or outside the repo when none is configured, with a leftover plaintext token file migrated into the provider, the Telegram plugin installed but not enabled at user scope, pairing; skipped entirely with no channel, the default), keeps the manager's state out of git, seeds the checked-in runbook, starts the manager in tmux, and finishes with doctor's session-manager check. Idempotent."
|
|
4
4
|
allowed-tools: ["Bash", "Read", "Write", "Skill", "AskUserQuestion"]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Setup session manager
|
|
8
8
|
|
|
9
|
-
After this skill the project has a `sessionManager` block, a
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
After this skill the project has a `sessionManager` block, a runbook at
|
|
10
|
+
`.lisa/automations/session-manager.runbook.md`, and a running manager. Telegram is optional: with it,
|
|
11
|
+
the project also has its own bot token (in the project's secrets provider when one is configured,
|
|
12
|
+
else in its own state directory) and a manager paired with the operator's
|
|
13
|
+
Telegram chat; with no channel (the default), Steps 3 and 4 and the pairing in Step 9 are skipped,
|
|
14
|
+
and questions wait in the manager's ledger, where `status` shows them, and on the item itself,
|
|
15
|
+
which the manager marks human-needed while it keeps dispatching other work. Re-running is safe: every
|
|
16
|
+
step keeps what is already there.
|
|
12
17
|
|
|
13
18
|
The manager itself always runs on Claude Code (see `lisa-session-manager` "Runtime parity"). Setup
|
|
14
19
|
can run from any agent that can reach the scripts; `start` launches the Claude Code manager.
|
|
@@ -40,15 +45,23 @@ writes `$SM`, and pass `--project-root "$ROOT"` (the absolute project root) on e
|
|
|
40
45
|
|
|
41
46
|
## Step 2: Write the config block
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
0. Ask the operator whether they want Telegram notifications: worker questions and status on their
|
|
49
|
+
phone, through a bot they create for this project. Say plainly that it is optional: without it
|
|
50
|
+
the manager runs normally, and questions wait in its ledger (shown by `status`) instead of
|
|
51
|
+
reaching a phone. Their answer is `<notify>`: `telegram` or `none` (the default).
|
|
52
|
+
1. Preview: `node "$SM/session-manager.mjs" init-config --notify <notify> --project-root "$ROOT"`.
|
|
53
|
+
It detects
|
|
44
54
|
`projects/*/.lisa.config.json`, or, when `projects/` holds none, the root's own children that
|
|
45
55
|
have a `.lisa.config.json` and their own `.git` (written as `repos.root: "."`). It proposes
|
|
46
|
-
`name`, `interval`, `repos`, `capacity`, `stall` and
|
|
56
|
+
`name`, `interval`, `repos`, `capacity`, `stall` and `notify`: `{"provider":"none"}`, or with
|
|
57
|
+
`--notify telegram` the telegram provider and a per-project `notify.stateDir`. Repo
|
|
47
58
|
detection leaves out linked worktrees and keeps one checkout per remote, so ticket worktrees and
|
|
48
59
|
second clones are not proposed. Show the block to the operator and ask whether any repo is
|
|
49
60
|
missing or should not be routed.
|
|
50
61
|
2. Write it: the same command with `--write`. It adds only non-secret fields and never overwrites an
|
|
51
|
-
existing block (`reason: "exists"` means keep it).
|
|
62
|
+
existing block (`reason: "exists"` means keep it). To add Telegram to an existing block later,
|
|
63
|
+
set `notify` to `{"provider":"telegram","stateDir":"~/.claude/channels/telegram-<project>"}`
|
|
64
|
+
(the `<project>` part as `init-config --notify telegram` would derive it) and re-run this skill.
|
|
52
65
|
3. Each repo's `hints` are a draft: its name plus one per well-known dependency (`NestJS`, `Expo`,
|
|
53
66
|
`AWS CDK`, ...). Ask the operator to correct them and add the areas that identify the repo
|
|
54
67
|
(e.g. `api`: `["NestJS","migrations"]`, `web`: `["Expo","screens"]`), and whether to
|
|
@@ -68,6 +81,12 @@ writes `$SM`, and pass `--project-root "$ROOT"` (the absolute project root) on e
|
|
|
68
81
|
"me", spelled as the tracker API returns it: the GitHub **login** (`gh api users/<login> --jq
|
|
69
82
|
.login`), the Jira `accountId`, or the Linear user id (the operator's entry in the team's member
|
|
70
83
|
list, or `viewer.id` only when the operator runs the lookup with their own credential).
|
|
84
|
+
**Recommend setting it in every setup**, even a single-user one: it is also who may answer a
|
|
85
|
+
human-needed question by replying on the item. With neither `operatorIds` nor
|
|
86
|
+
`trustedAuthorIds` set, the manager reads no answer off the item at all, because the tracker
|
|
87
|
+
credential's identity is the one the workers and the manager post as, so its comments cannot be
|
|
88
|
+
told apart from a human's answer. The operator then answers only at the terminal, with the
|
|
89
|
+
`answerCommand` that `status` lists. Say so plainly.
|
|
71
90
|
5. Ask whether to set `sessionManager.backlogPickup` to `true` (default off). When the Ready queue
|
|
72
91
|
is exhausted and a worker slot is still free, the manager then looks at backlog items (open
|
|
73
92
|
leaves in no lifecycle role) that nobody else is assigned to, that are not human-held and have
|
|
@@ -79,12 +98,45 @@ writes `$SM`, and pass `--project-root "$ROOT"` (the absolute project root) on e
|
|
|
79
98
|
|
|
80
99
|
## Step 3: Store the bot token
|
|
81
100
|
|
|
101
|
+
Only when `sessionManager.notify.provider` is `telegram`. With no channel (`none`, or no `notify`
|
|
102
|
+
block) there is no token: skip Steps 3 and 4 and go to Step 5.
|
|
103
|
+
|
|
82
104
|
The operator creates a bot with @BotFather, one per project. Then run
|
|
83
105
|
`node "$SM/session-manager.mjs" store-token --project-root "$ROOT"`.
|
|
84
106
|
|
|
107
|
+
Where the token goes depends on the project's secrets provider (`secrets.provider` in
|
|
108
|
+
`.lisa.config.json`, read through `lisa-secrets-access`):
|
|
109
|
+
|
|
110
|
+
- **A provider is configured** (`secrets.provider` set and not `env`): the token is stored in it as
|
|
111
|
+
`TELEGRAM_BOT_TOKEN_<NAME>` (the manager name upper-snaked, e.g. `lisa-1a2b-manager` →
|
|
112
|
+
`TELEGRAM_BOT_TOKEN_LISA_1A2B_MANAGER`) and nothing is written to disk. `start` resolves it from
|
|
113
|
+
there each time. If `secrets.require` is declared, add that name to it first, or `store-token`
|
|
114
|
+
exits 2 saying so.
|
|
115
|
+
- **Migration.** If an older setup left a plaintext `<notify.stateDir>/.env`, `store-token`
|
|
116
|
+
moves it: it stores the token, reads it back and compares, and only then deletes the file. It
|
|
117
|
+
needs no prompt. Report it as "moved the bot token from `<path>` into `<provider>` and deleted
|
|
118
|
+
the file" (the `migratedFrom` and `deleted` fields), never with the value.
|
|
119
|
+
- `alreadyStored: true`: the provider already holds it; nothing to do. A matching leftover file
|
|
120
|
+
is deleted too.
|
|
121
|
+
- Exit 2 naming `--vault-project`: the provider project is ambiguous. Ask the operator which
|
|
122
|
+
project, then re-run with `--vault-project <id>`.
|
|
123
|
+
- Exit 2 because the file holds a different token or other keys: say what `message` reports and
|
|
124
|
+
let the operator decide (`--replace` makes the file's token the stored one).
|
|
125
|
+
- Exit 1 (provider unreachable or rate-limited): nothing was stored and the file was kept. Wait a
|
|
126
|
+
minute and run it again.
|
|
127
|
+
- A provider Lisa cannot write to (anything but Bitwarden today): the message asks the operator
|
|
128
|
+
to create `TELEGRAM_BOT_TOKEN_<NAME>` in the provider themselves; then re-run `store-token`,
|
|
129
|
+
which verifies it and deletes any plaintext copy.
|
|
130
|
+
- **No provider configured**: the token is written to `<notify.stateDir>/.env` (mode 0600) as
|
|
131
|
+
before. Tell the operator that this is a plaintext file, that doctor will warn about it, and that
|
|
132
|
+
configuring a secrets provider and re-running `store-token` moves it there.
|
|
133
|
+
|
|
134
|
+
Outcomes either way:
|
|
135
|
+
|
|
85
136
|
- `stored: true`: done.
|
|
86
|
-
-
|
|
87
|
-
says the stored token is wrong or belongs to another project, re-run with
|
|
137
|
+
- With no provider, exit 2 because a token already exists: keep it (re-running setup is safe). Only
|
|
138
|
+
when the operator says the stored token is wrong or belongs to another project, re-run with
|
|
139
|
+
`store-token --replace`.
|
|
88
140
|
- `reason: "no-tty"` (an agent's Bash has no terminal): offer the operator both routes, and say
|
|
89
141
|
plainly that Claude Code's `!` prefix has no terminal either, so it fails the same way:
|
|
90
142
|
- **Clipboard (simplest):** they copy the token from the BotFather chat and tell you; then run
|
|
@@ -96,11 +148,13 @@ The operator creates a bot with @BotFather, one per project. Then run
|
|
|
96
148
|
- `empty` / `invalid`: say what was wrong and ask again.
|
|
97
149
|
|
|
98
150
|
Never ask for the token in chat, never echo, log or commit it, and never put it in
|
|
99
|
-
`.lisa.config.json`. It lives only in `<notify.stateDir>/.env
|
|
151
|
+
`.lisa.config.json`. It lives only in the secrets provider, or in `<notify.stateDir>/.env` when
|
|
152
|
+
no provider is configured. Never read it back from either to check it: `store-token` already
|
|
153
|
+
verified the stored copy.
|
|
100
154
|
|
|
101
155
|
## Step 4: Telegram plugin scope
|
|
102
156
|
|
|
103
|
-
Read `claude plugin list --json` and look at the `telegram@claude-plugins-official` entries.
|
|
157
|
+
Only when `notify.provider` is `telegram`. Read `claude plugin list --json` and look at the `telegram@claude-plugins-official` entries.
|
|
104
158
|
|
|
105
159
|
- **Not installed:** ask the operator to install it with
|
|
106
160
|
`claude plugin install telegram@claude-plugins-official -s user`, then re-check.
|
|
@@ -173,11 +227,17 @@ project), on every machine that runs the manager:
|
|
|
173
227
|
bypass-permissions worker runs. Ask the operator for the IDs, add them, re-run `validate`, then
|
|
174
228
|
continue. `lisa doctor` fails on the same condition.
|
|
175
229
|
1. `node "$SM/session-manager.mjs" start --project-root "$ROOT"`. `started` and `already-running`
|
|
176
|
-
are both fine.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
230
|
+
are both fine. With no channel it needs no token, plugin or pairing and launches without
|
|
231
|
+
`--channels`. Exit 2 names what is missing (with Telegram, usually the token from Step 3, or a
|
|
232
|
+
plaintext `.env` left over beside a secrets provider: run the `store-token` command the message
|
|
233
|
+
names, which migrates it, then `start` again), or that a tmux session of the same name belongs
|
|
234
|
+
to another project root, or that the manager exited right after starting. For the last, ask the
|
|
235
|
+
operator to run the printed foreground command in their own terminal: claude prints its own
|
|
236
|
+
error there (with a provider, the line fetches the token itself; it never holds the value). Fix
|
|
237
|
+
it, then run `start` again. Exit 1 saying "Nothing was started" means the secrets provider could
|
|
238
|
+
not be reached or rate-limited the read: wait a minute and run `start` again.
|
|
239
|
+
2. Only with Telegram (`notify` is `telegram` in the `start` output); with no channel there is no
|
|
240
|
+
pairing, so skip to Step 10. Walk the operator through pairing, in their own terminal:
|
|
181
241
|
1. `tmux attach -t <name>` (the `attach` value from the output).
|
|
182
242
|
2. Send any message to the bot in a private chat. The bot replies with a pairing code.
|
|
183
243
|
3. In the attached manager session: `/telegram:access pair <code>`.
|
|
@@ -191,10 +251,13 @@ Telegram message asked for it. Every allowlisted sender effectively has shell ac
|
|
|
191
251
|
## Step 10: Verify
|
|
192
252
|
|
|
193
253
|
Run `lisa doctor` (or `npx @codyswann/lisa doctor` when the `lisa` CLI is not on the PATH) and
|
|
194
|
-
confirm the "Session manager
|
|
254
|
+
confirm the "Session manager notifications?" check is green. With no channel its detail is
|
|
255
|
+
`notifications: none`, and it skips every Telegram check. Fix every warning it names, then
|
|
195
256
|
`node "$SM/session-manager.mjs" status --project-root "$ROOT"` should show the manager running.
|
|
196
257
|
|
|
197
|
-
Report: the config block written (or kept),
|
|
198
|
-
|
|
258
|
+
Report: the config block written (or kept), the notification channel (`telegram` or `none`), and
|
|
259
|
+
with Telegram where the token lives (the provider and secret name, or the file path; never the
|
|
260
|
+
value), whether a plaintext `.env` was migrated and deleted, and the plugin scope result, the
|
|
261
|
+
runbook path, which repo dirs were already trusted and which the operator
|
|
199
262
|
accepted trust in, what the competing-loop check found, the manager's tmux session name, and the
|
|
200
263
|
doctor result.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Run the local session manager: one dispatch-and-relay cycle (the /loop prompt), or start, stop or show the tmux-hosted manager. Dispatches Ready work items to fresh background worker sessions and relays their questions over the project's Telegram bot. Claude Code only; configure it with /lisa:setup:session-manager."
|
|
2
|
+
description: "Run the local session manager: one dispatch-and-relay cycle (the /loop prompt), or start, stop or show the tmux-hosted manager. Dispatches Ready work items to fresh background worker sessions and relays their questions over the project's Telegram bot when one is configured (Telegram is optional). Claude Code only; configure it with /lisa:setup:session-manager."
|
|
3
3
|
allowed-tools: ["Skill"]
|
|
4
4
|
argument-hint: "[cycle|start|stop|status]"
|
|
5
5
|
---
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Set up the local session manager for this project: write the sessionManager config block, store the project's own
|
|
2
|
+
description: "Set up the local session manager for this project: write the sessionManager config block, optionally set up Telegram notifications (store the project's own bot token in its secrets provider, migrating any plaintext token file, check the plugin scope, walk through pairing; skipped with no channel, the default), seed the runbook, start the manager in tmux, and run doctor's session-manager check."
|
|
3
3
|
allowed-tools: ["Skill"]
|
|
4
4
|
---
|
|
5
5
|
|