Merge pull request #1879 from code-yeongyu/fix/cli-installer-provider-config-1876
fix: run auth plugins and provider config for all providers, not just gemini
This commit is contained in:
commit
2b7ef43619
@ -129,7 +129,21 @@ Your ONLY valid output locations are \`.sisyphus/plans/*.md\` and \`.sisyphus/dr
|
|||||||
|
|
||||||
Example: \`.sisyphus/plans/auth-refactor.md\`
|
Example: \`.sisyphus/plans/auth-refactor.md\`
|
||||||
|
|
||||||
### 5. SINGLE PLAN MANDATE (CRITICAL)
|
### 5. MAXIMUM PARALLELISM PRINCIPLE (NON-NEGOTIABLE)
|
||||||
|
|
||||||
|
Your plans MUST maximize parallel execution. This is a core planning quality metric.
|
||||||
|
|
||||||
|
**Granularity Rule**: One task = one module/concern = 1-3 files.
|
||||||
|
If a task touches 4+ files or 2+ unrelated concerns, SPLIT IT.
|
||||||
|
|
||||||
|
**Parallelism Target**: Aim for 5-8 tasks per wave.
|
||||||
|
If any wave has fewer than 3 tasks (except the final integration), you under-split.
|
||||||
|
|
||||||
|
**Dependency Minimization**: Structure tasks so shared dependencies
|
||||||
|
(types, interfaces, configs) are extracted as early Wave-1 tasks,
|
||||||
|
unblocking maximum parallelism in subsequent waves.
|
||||||
|
|
||||||
|
### 6. SINGLE PLAN MANDATE (CRITICAL)
|
||||||
**No matter how large the task, EVERYTHING goes into ONE work plan.**
|
**No matter how large the task, EVERYTHING goes into ONE work plan.**
|
||||||
|
|
||||||
**NEVER:**
|
**NEVER:**
|
||||||
@ -152,7 +166,7 @@ Example: \`.sisyphus/plans/auth-refactor.md\`
|
|||||||
|
|
||||||
**The plan can have 50+ TODOs. That's OK. ONE PLAN.**
|
**The plan can have 50+ TODOs. That's OK. ONE PLAN.**
|
||||||
|
|
||||||
### 5.1 SINGLE ATOMIC WRITE (CRITICAL - Prevents Content Loss)
|
### 6.1 SINGLE ATOMIC WRITE (CRITICAL - Prevents Content Loss)
|
||||||
|
|
||||||
<write_protocol>
|
<write_protocol>
|
||||||
**The Write tool OVERWRITES files. It does NOT append.**
|
**The Write tool OVERWRITES files. It does NOT append.**
|
||||||
@ -188,7 +202,7 @@ Example: \`.sisyphus/plans/auth-refactor.md\`
|
|||||||
- [ ] File already exists with my content? → Use Edit to append, NOT Write
|
- [ ] File already exists with my content? → Use Edit to append, NOT Write
|
||||||
</write_protocol>
|
</write_protocol>
|
||||||
|
|
||||||
### 6. DRAFT AS WORKING MEMORY (MANDATORY)
|
### 7. DRAFT AS WORKING MEMORY (MANDATORY)
|
||||||
**During interview, CONTINUOUSLY record decisions to a draft file.**
|
**During interview, CONTINUOUSLY record decisions to a draft file.**
|
||||||
|
|
||||||
**Draft Location**: \`.sisyphus/drafts/{name}.md\`
|
**Draft Location**: \`.sisyphus/drafts/{name}.md\`
|
||||||
|
|||||||
@ -181,42 +181,67 @@ Scenario: [Descriptive name — what user action/flow is being verified]
|
|||||||
|
|
||||||
> Maximize throughput by grouping independent tasks into parallel waves.
|
> Maximize throughput by grouping independent tasks into parallel waves.
|
||||||
> Each wave completes before the next begins.
|
> Each wave completes before the next begins.
|
||||||
|
> Target: 5-8 tasks per wave. Fewer than 3 per wave (except final) = under-splitting.
|
||||||
|
|
||||||
\`\`\`
|
\`\`\`
|
||||||
Wave 1 (Start Immediately):
|
Wave 1 (Start Immediately — foundation + scaffolding):
|
||||||
├── Task 1: [no dependencies]
|
├── Task 1: Project scaffolding + config [quick]
|
||||||
└── Task 5: [no dependencies]
|
├── Task 2: Design system tokens [quick]
|
||||||
|
├── Task 3: Type definitions [quick]
|
||||||
|
├── Task 4: Schema definitions [quick]
|
||||||
|
├── Task 5: Storage interface + in-memory impl [quick]
|
||||||
|
├── Task 6: Auth middleware [quick]
|
||||||
|
└── Task 7: Client module [quick]
|
||||||
|
|
||||||
Wave 2 (After Wave 1):
|
Wave 2 (After Wave 1 — core modules, MAX PARALLEL):
|
||||||
├── Task 2: [depends: 1]
|
├── Task 8: Core business logic (depends: 3, 5, 7) [deep]
|
||||||
├── Task 3: [depends: 1]
|
├── Task 9: API endpoints (depends: 4, 5) [unspecified-high]
|
||||||
└── Task 6: [depends: 5]
|
├── Task 10: Secondary storage impl (depends: 5) [unspecified-high]
|
||||||
|
├── Task 11: Retry/fallback logic (depends: 8) [deep]
|
||||||
|
├── Task 12: UI layout + navigation (depends: 2) [visual-engineering]
|
||||||
|
├── Task 13: API client + hooks (depends: 4) [quick]
|
||||||
|
└── Task 14: Telemetry middleware (depends: 5, 10) [unspecified-high]
|
||||||
|
|
||||||
Wave 3 (After Wave 2):
|
Wave 3 (After Wave 2 — integration + UI):
|
||||||
└── Task 4: [depends: 2, 3]
|
├── Task 15: Main route combining modules (depends: 6, 11, 14) [deep]
|
||||||
|
├── Task 16: UI data visualization (depends: 12, 13) [visual-engineering]
|
||||||
|
├── Task 17: Deployment config A (depends: 15) [quick]
|
||||||
|
├── Task 18: Deployment config B (depends: 15) [quick]
|
||||||
|
├── Task 19: Deployment config C (depends: 15) [quick]
|
||||||
|
└── Task 20: UI request log + build (depends: 16) [visual-engineering]
|
||||||
|
|
||||||
Critical Path: Task 1 → Task 2 → Task 4
|
Wave 4 (After Wave 3 — verification):
|
||||||
Parallel Speedup: ~40% faster than sequential
|
├── Task 21: Integration tests (depends: 15) [deep]
|
||||||
|
├── Task 22: UI QA - Playwright (depends: 20) [unspecified-high]
|
||||||
|
├── Task 23: E2E QA (depends: 21) [deep]
|
||||||
|
└── Task 24: Git cleanup + tagging (depends: 21) [git]
|
||||||
|
|
||||||
|
Critical Path: Task 1 → Task 5 → Task 8 → Task 11 → Task 15 → Task 21
|
||||||
|
Parallel Speedup: ~70% faster than sequential
|
||||||
|
Max Concurrent: 7 (Waves 1 & 2)
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
### Dependency Matrix
|
### Dependency Matrix (abbreviated — show ALL tasks in your generated plan)
|
||||||
|
|
||||||
| Task | Depends On | Blocks | Can Parallelize With |
|
| Task | Depends On | Blocks | Wave |
|
||||||
|------|------------|--------|---------------------|
|
|------|------------|--------|------|
|
||||||
| 1 | None | 2, 3 | 5 |
|
| 1-7 | — | 8-14 | 1 |
|
||||||
| 2 | 1 | 4 | 3, 6 |
|
| 8 | 3, 5, 7 | 11, 15 | 2 |
|
||||||
| 3 | 1 | 4 | 2, 6 |
|
| 11 | 8 | 15 | 2 |
|
||||||
| 4 | 2, 3 | None | None (final) |
|
| 14 | 5, 10 | 15 | 2 |
|
||||||
| 5 | None | 6 | 1 |
|
| 15 | 6, 11, 14 | 17-19, 21 | 3 |
|
||||||
| 6 | 5 | None | 2, 3 |
|
| 21 | 15 | 23, 24 | 4 |
|
||||||
|
|
||||||
|
> This is abbreviated for reference. YOUR generated plan must include the FULL matrix for ALL tasks.
|
||||||
|
|
||||||
### Agent Dispatch Summary
|
### Agent Dispatch Summary
|
||||||
|
|
||||||
| Wave | Tasks | Recommended Agents |
|
| Wave | # Parallel | Tasks → Agent Category |
|
||||||
|------|-------|-------------------|
|
|------|------------|----------------------|
|
||||||
| 1 | 1, 5 | task(category="...", load_skills=[...], run_in_background=false) |
|
| 1 | **7** | T1-T4 → \`quick\`, T5 → \`quick\`, T6 → \`quick\`, T7 → \`quick\` |
|
||||||
| 2 | 2, 3, 6 | dispatch parallel after Wave 1 completes |
|
| 2 | **7** | T8 → \`deep\`, T9 → \`unspecified-high\`, T10 → \`unspecified-high\`, T11 → \`deep\`, T12 → \`visual-engineering\`, T13 → \`quick\`, T14 → \`unspecified-high\` |
|
||||||
| 3 | 4 | final integration task |
|
| 3 | **6** | T15 → \`deep\`, T16 → \`visual-engineering\`, T17-T19 → \`quick\`, T20 → \`visual-engineering\` |
|
||||||
|
| 4 | **4** | T21 → \`deep\`, T22 → \`unspecified-high\`, T23 → \`deep\`, T24 → \`git\` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
83
src/cli/cli-installer.test.ts
Normal file
83
src/cli/cli-installer.test.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import { afterEach, beforeEach, describe, expect, it, mock, spyOn } from "bun:test"
|
||||||
|
import * as configManager from "./config-manager"
|
||||||
|
import { runCliInstaller } from "./cli-installer"
|
||||||
|
import type { InstallArgs } from "./types"
|
||||||
|
|
||||||
|
describe("runCliInstaller", () => {
|
||||||
|
const mockConsoleLog = mock(() => {})
|
||||||
|
const mockConsoleError = mock(() => {})
|
||||||
|
const originalConsoleLog = console.log
|
||||||
|
const originalConsoleError = console.error
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
console.log = mockConsoleLog
|
||||||
|
console.error = mockConsoleError
|
||||||
|
mockConsoleLog.mockClear()
|
||||||
|
mockConsoleError.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
console.log = originalConsoleLog
|
||||||
|
console.error = originalConsoleError
|
||||||
|
})
|
||||||
|
|
||||||
|
it("runs auth and provider setup steps when openai or copilot are enabled without gemini", async () => {
|
||||||
|
//#given
|
||||||
|
const addAuthPluginsSpy = spyOn(configManager, "addAuthPlugins").mockResolvedValue({
|
||||||
|
success: true,
|
||||||
|
configPath: "/tmp/opencode.jsonc",
|
||||||
|
})
|
||||||
|
const addProviderConfigSpy = spyOn(configManager, "addProviderConfig").mockReturnValue({
|
||||||
|
success: true,
|
||||||
|
configPath: "/tmp/opencode.jsonc",
|
||||||
|
})
|
||||||
|
const restoreSpies = [
|
||||||
|
addAuthPluginsSpy,
|
||||||
|
addProviderConfigSpy,
|
||||||
|
spyOn(configManager, "detectCurrentConfig").mockReturnValue({
|
||||||
|
isInstalled: false,
|
||||||
|
hasClaude: false,
|
||||||
|
isMax20: false,
|
||||||
|
hasOpenAI: false,
|
||||||
|
hasGemini: false,
|
||||||
|
hasCopilot: false,
|
||||||
|
hasOpencodeZen: false,
|
||||||
|
hasZaiCodingPlan: false,
|
||||||
|
hasKimiForCoding: false,
|
||||||
|
}),
|
||||||
|
spyOn(configManager, "isOpenCodeInstalled").mockResolvedValue(true),
|
||||||
|
spyOn(configManager, "getOpenCodeVersion").mockResolvedValue("1.0.200"),
|
||||||
|
spyOn(configManager, "addPluginToOpenCodeConfig").mockResolvedValue({
|
||||||
|
success: true,
|
||||||
|
configPath: "/tmp/opencode.jsonc",
|
||||||
|
}),
|
||||||
|
spyOn(configManager, "writeOmoConfig").mockReturnValue({
|
||||||
|
success: true,
|
||||||
|
configPath: "/tmp/oh-my-opencode.jsonc",
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
|
||||||
|
const args: InstallArgs = {
|
||||||
|
tui: false,
|
||||||
|
claude: "no",
|
||||||
|
openai: "yes",
|
||||||
|
gemini: "no",
|
||||||
|
copilot: "yes",
|
||||||
|
opencodeZen: "no",
|
||||||
|
zaiCodingPlan: "no",
|
||||||
|
kimiForCoding: "no",
|
||||||
|
}
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = await runCliInstaller(args, "3.4.0")
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).toBe(0)
|
||||||
|
expect(addAuthPluginsSpy).toHaveBeenCalledTimes(1)
|
||||||
|
expect(addProviderConfigSpy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
for (const spy of restoreSpies) {
|
||||||
|
spy.mockRestore()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -77,7 +77,9 @@ export async function runCliInstaller(args: InstallArgs, version: string): Promi
|
|||||||
`Plugin ${isUpdate ? "verified" : "added"} ${SYMBOLS.arrow} ${color.dim(pluginResult.configPath)}`,
|
`Plugin ${isUpdate ? "verified" : "added"} ${SYMBOLS.arrow} ${color.dim(pluginResult.configPath)}`,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (config.hasGemini) {
|
const needsProviderSetup = config.hasGemini || config.hasOpenAI || config.hasCopilot
|
||||||
|
|
||||||
|
if (needsProviderSetup) {
|
||||||
printStep(step++, totalSteps, "Adding auth plugins...")
|
printStep(step++, totalSteps, "Adding auth plugins...")
|
||||||
const authResult = await addAuthPlugins(config)
|
const authResult = await addAuthPlugins(config)
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user