@kodrunhq/opencode-autopilot 1.17.0 → 1.19.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.
Files changed (118) hide show
  1. package/README.md +95 -13
  2. package/assets/commands/oc-doctor.md +17 -0
  3. package/assets/commands/oc-update-docs.md +1 -1
  4. package/bin/configure-tui.ts +1 -1
  5. package/package.json +1 -1
  6. package/src/agents/index.ts +0 -12
  7. package/src/agents/pipeline/index.ts +0 -4
  8. package/src/autonomy/completion.ts +52 -0
  9. package/src/autonomy/controller.ts +144 -0
  10. package/src/autonomy/index.ts +25 -0
  11. package/src/autonomy/injector.ts +49 -0
  12. package/src/autonomy/state.ts +91 -0
  13. package/src/autonomy/types.ts +30 -0
  14. package/src/autonomy/verification.ts +86 -0
  15. package/src/background/database.ts +170 -0
  16. package/src/background/executor.ts +174 -0
  17. package/src/background/index.ts +8 -0
  18. package/src/background/manager.ts +232 -0
  19. package/src/background/repository.ts +174 -0
  20. package/src/background/schema.ts +24 -0
  21. package/src/background/sdk-runner.ts +40 -0
  22. package/src/background/slot-manager.ts +41 -0
  23. package/src/background/state-machine.ts +19 -0
  24. package/src/config/v7.ts +3 -3
  25. package/src/config.ts +105 -21
  26. package/src/context/budget.ts +45 -0
  27. package/src/context/compaction-handler.ts +58 -0
  28. package/src/context/discovery.ts +94 -0
  29. package/src/context/index.ts +14 -0
  30. package/src/context/injector.ts +119 -0
  31. package/src/context/types.ts +24 -0
  32. package/src/health/checks.ts +214 -3
  33. package/src/health/index.ts +7 -1
  34. package/src/health/runner.ts +14 -2
  35. package/src/index.ts +113 -6
  36. package/src/installer.ts +13 -0
  37. package/src/kernel/index.ts +6 -0
  38. package/src/kernel/migrations.ts +50 -0
  39. package/src/kernel/retry.ts +49 -0
  40. package/src/kernel/schema.ts +9 -1
  41. package/src/kernel/transaction.ts +40 -12
  42. package/src/logging/forensic-writer.ts +6 -2
  43. package/src/logging/index.ts +2 -0
  44. package/src/mcp/index.ts +34 -0
  45. package/src/mcp/manager.ts +206 -0
  46. package/src/mcp/scope-filter.ts +44 -0
  47. package/src/mcp/types.ts +38 -0
  48. package/src/orchestrator/arena.ts +7 -1
  49. package/src/orchestrator/fallback/event-handler.ts +12 -1
  50. package/src/orchestrator/handlers/challenge.ts +8 -1
  51. package/src/orchestrator/handlers/plan.ts +8 -1
  52. package/src/orchestrator/handlers/recon.ts +8 -1
  53. package/src/orchestrator/handlers/types.ts +2 -2
  54. package/src/orchestrator/lesson-memory.ts +6 -1
  55. package/src/orchestrator/orchestration-logger.ts +15 -3
  56. package/src/orchestrator/skill-injection.ts +7 -1
  57. package/src/orchestrator/state.ts +6 -1
  58. package/src/recovery/classifier.ts +127 -0
  59. package/src/recovery/event-handler.ts +263 -0
  60. package/src/recovery/index.ts +20 -0
  61. package/src/recovery/orchestrator.ts +180 -0
  62. package/src/recovery/persistence.ts +87 -0
  63. package/src/recovery/strategies.ts +107 -0
  64. package/src/recovery/types.ts +31 -0
  65. package/src/registry/model-groups.ts +2 -19
  66. package/src/registry/resolver.ts +38 -9
  67. package/src/review/agent-catalog.ts +83 -251
  68. package/src/review/agents/architecture-verifier.ts +41 -0
  69. package/src/review/agents/code-hygiene-auditor.ts +40 -0
  70. package/src/review/agents/correctness-auditor.ts +41 -0
  71. package/src/review/agents/frontend-auditor.ts +39 -0
  72. package/src/review/agents/index.ts +15 -42
  73. package/src/review/agents/language-idioms-auditor.ts +39 -0
  74. package/src/review/agents/security-auditor.ts +12 -8
  75. package/src/review/stack-gate.ts +2 -6
  76. package/src/routing/categories.ts +111 -0
  77. package/src/routing/classifier.ts +152 -0
  78. package/src/routing/engine.ts +89 -0
  79. package/src/routing/index.ts +4 -0
  80. package/src/routing/types.ts +14 -0
  81. package/src/skills/adaptive-injector.ts +34 -3
  82. package/src/skills/loader.ts +4 -0
  83. package/src/tools/background.ts +196 -0
  84. package/src/tools/configure.ts +1 -1
  85. package/src/tools/delegate.ts +205 -0
  86. package/src/tools/loop.ts +94 -0
  87. package/src/tools/recover.ts +172 -0
  88. package/src/types/background.ts +51 -0
  89. package/src/types/mcp.ts +27 -0
  90. package/src/types/recovery.ts +49 -0
  91. package/src/types/routing.ts +39 -0
  92. package/src/ux/context-warnings.ts +81 -0
  93. package/src/ux/error-hints.ts +38 -0
  94. package/src/ux/index.ts +7 -0
  95. package/src/ux/notifications.ts +67 -0
  96. package/src/ux/progress.ts +77 -0
  97. package/src/ux/session-summary.ts +67 -0
  98. package/src/ux/task-status.ts +109 -0
  99. package/src/ux/types.ts +24 -0
  100. package/src/agents/db-specialist.ts +0 -295
  101. package/src/agents/devops.ts +0 -352
  102. package/src/agents/documenter.ts +0 -44
  103. package/src/agents/frontend-engineer.ts +0 -541
  104. package/src/agents/pipeline/oc-explorer.ts +0 -46
  105. package/src/agents/pipeline/oc-retrospector.ts +0 -42
  106. package/src/review/agents/auth-flow-verifier.ts +0 -47
  107. package/src/review/agents/concurrency-checker.ts +0 -47
  108. package/src/review/agents/dead-code-scanner.ts +0 -47
  109. package/src/review/agents/go-idioms-auditor.ts +0 -46
  110. package/src/review/agents/python-django-auditor.ts +0 -46
  111. package/src/review/agents/react-patterns-auditor.ts +0 -46
  112. package/src/review/agents/rust-safety-auditor.ts +0 -46
  113. package/src/review/agents/scope-intent-verifier.ts +0 -45
  114. package/src/review/agents/silent-failure-hunter.ts +0 -45
  115. package/src/review/agents/spec-checker.ts +0 -45
  116. package/src/review/agents/state-mgmt-auditor.ts +0 -46
  117. package/src/review/agents/type-soundness.ts +0 -46
  118. package/src/review/agents/wiring-inspector.ts +0 -46
@@ -0,0 +1,107 @@
1
+ import type { ErrorCategory, RecoveryAction } from "../types/recovery";
2
+ import type { RecoveryState } from "./types";
3
+
4
+ export type RecoveryStrategyResolver = (context: RecoveryState) => RecoveryAction;
5
+
6
+ function createAction(
7
+ strategy: RecoveryAction["strategy"],
8
+ errorCategory: ErrorCategory,
9
+ maxAttempts: number,
10
+ backoffMs: number,
11
+ metadata: Record<string, unknown> = {},
12
+ ): RecoveryAction {
13
+ return Object.freeze({
14
+ strategy,
15
+ errorCategory,
16
+ maxAttempts,
17
+ backoffMs,
18
+ metadata,
19
+ });
20
+ }
21
+
22
+ function getAttemptIndex(context: RecoveryState): number {
23
+ return context.attempts.length;
24
+ }
25
+
26
+ function retryWithBackoff(category: ErrorCategory): RecoveryStrategyResolver {
27
+ return (context) => {
28
+ const attemptIndex = getAttemptIndex(context);
29
+ return createAction("retry", category, context.maxAttempts, 1000 * 2 ** attemptIndex, {
30
+ retryMode: "backoff",
31
+ });
32
+ };
33
+ }
34
+
35
+ function fallbackModel(category: ErrorCategory): RecoveryStrategyResolver {
36
+ return (context) =>
37
+ createAction("fallback_model", category, context.maxAttempts, 0, {
38
+ switchModel: true,
39
+ });
40
+ }
41
+
42
+ function compactAndRetry(category: ErrorCategory): RecoveryStrategyResolver {
43
+ return (context) =>
44
+ createAction("compact_and_retry", category, context.maxAttempts, 500, {
45
+ compactContext: true,
46
+ });
47
+ }
48
+
49
+ function restartSession(category: ErrorCategory): RecoveryStrategyResolver {
50
+ return (context) =>
51
+ createAction("restart_session", category, context.maxAttempts, 0, {
52
+ restartSession: true,
53
+ });
54
+ }
55
+
56
+ function reduceContext(category: ErrorCategory): RecoveryStrategyResolver {
57
+ return (context) =>
58
+ createAction("reduce_context", category, context.maxAttempts, 250, {
59
+ trimContext: true,
60
+ });
61
+ }
62
+
63
+ function skipAndContinue(category: ErrorCategory): RecoveryStrategyResolver {
64
+ return (context) =>
65
+ createAction("skip_and_continue", category, context.maxAttempts, 0, {
66
+ skipCurrentStep: true,
67
+ });
68
+ }
69
+
70
+ function userPrompt(category: ErrorCategory): RecoveryStrategyResolver {
71
+ return (context) => createAction("user_prompt", category, context.maxAttempts, 0);
72
+ }
73
+
74
+ function abort(category: ErrorCategory): RecoveryStrategyResolver {
75
+ return (context) => createAction("abort", category, context.maxAttempts, 0);
76
+ }
77
+
78
+ export function getStrategy(category: ErrorCategory): RecoveryStrategyResolver {
79
+ switch (category) {
80
+ case "rate_limit":
81
+ case "timeout":
82
+ case "network":
83
+ case "service_unavailable":
84
+ return retryWithBackoff(category);
85
+ case "quota_exceeded":
86
+ case "empty_content":
87
+ case "thinking_block_error":
88
+ return fallbackModel(category);
89
+ case "tool_result_overflow":
90
+ return compactAndRetry(category);
91
+ case "context_window_exceeded":
92
+ return (context) =>
93
+ getAttemptIndex(context) > 0
94
+ ? reduceContext(category)(context)
95
+ : compactAndRetry(category)(context);
96
+ case "session_corruption":
97
+ return restartSession(category);
98
+ case "agent_loop_stuck":
99
+ return skipAndContinue(category);
100
+ case "validation":
101
+ return userPrompt(category);
102
+ case "auth_failure":
103
+ return abort(category);
104
+ default:
105
+ return retryWithBackoff(category);
106
+ }
107
+ }
@@ -0,0 +1,31 @@
1
+ import type { ErrorCategory, RecoveryAction, RecoveryStrategy } from "../types/recovery";
2
+
3
+ export interface ClassificationResult {
4
+ readonly category: ErrorCategory;
5
+ readonly confidence: number;
6
+ readonly reasoning: string;
7
+ readonly isRecoverable: boolean;
8
+ }
9
+
10
+ export interface RecoveryAttempt {
11
+ readonly attemptNumber: number;
12
+ readonly strategy: RecoveryStrategy;
13
+ readonly errorCategory: ErrorCategory;
14
+ readonly timestamp: string;
15
+ readonly success: boolean;
16
+ readonly error?: string;
17
+ }
18
+
19
+ export interface RecoveryState {
20
+ readonly sessionId: string;
21
+ readonly attempts: readonly RecoveryAttempt[];
22
+ readonly currentStrategy: RecoveryStrategy | null;
23
+ readonly maxAttempts: number;
24
+ readonly isRecovering: boolean;
25
+ readonly lastError: string | null;
26
+ }
27
+
28
+ export interface RecoveryActionEnvelope {
29
+ readonly action: RecoveryAction;
30
+ readonly state: RecoveryState;
31
+ }
@@ -11,56 +11,39 @@ function deepFreeze<T extends object>(obj: T): Readonly<T> {
11
11
 
12
12
  export const AGENT_REGISTRY: Readonly<Record<string, AgentEntry>> = deepFreeze({
13
13
  // ── Architects ─────────────────────────────────────────────
14
- // Deep reasoning: system design, task decomposition, orchestration
15
14
  "oc-architect": { group: "architects" },
16
15
  "oc-planner": { group: "architects" },
17
16
  autopilot: { group: "architects" },
18
17
  planner: { group: "architects" },
19
18
 
20
19
  // ── Challengers ────────────────────────────────────────────
21
- // Adversarial to Architects: critique proposals, enhance ideas
22
20
  "oc-critic": { group: "challengers" },
23
21
  "oc-challenger": { group: "challengers" },
24
22
 
25
23
  // ── Builders ───────────────────────────────────────────────
26
- // Code generation and debugging
27
24
  "oc-implementer": { group: "builders" },
25
+ coder: { group: "builders" },
28
26
  debugger: { group: "builders" },
29
27
 
30
28
  // ── Reviewers ──────────────────────────────────────────────
31
- // Code analysis, adversarial to Builders
32
- // NOTE: The 21 internal ReviewAgent objects (logic-auditor, security-auditor,
33
- // etc.) are NOT in this registry. They use the ReviewAgent type from
34
- // src/review/types.ts, not AgentConfig. The review pipeline resolves their
35
- // model via resolveModelForGroup("reviewers") directly.
36
29
  "oc-reviewer": { group: "reviewers" },
37
30
  reviewer: { group: "reviewers" },
38
31
 
39
32
  // ── Red Team ───────────────────────────────────────────────
40
- // Final adversarial pass
41
- // NOTE: red-team and product-thinker are ALSO internal ReviewAgent objects
42
- // in STAGE3_AGENTS (src/review/agents/index.ts). They appear here so the
43
- // review pipeline can resolve their model via resolveModelForGroup("red-team")
44
- // separately from the "reviewers" group.
45
33
  "red-team": { group: "red-team" },
46
34
  "product-thinker": { group: "red-team" },
47
35
 
48
36
  // ── Researchers ────────────────────────────────────────────
49
- // Domain research, feasibility analysis
50
37
  "oc-researcher": { group: "researchers" },
51
38
  researcher: { group: "researchers" },
52
39
 
53
40
  // ── Communicators ──────────────────────────────────────────
54
- // Docs, changelogs, lesson extraction
55
41
  "oc-shipper": { group: "communicators" },
56
- documenter: { group: "communicators" },
57
- "oc-retrospector": { group: "communicators" },
58
42
 
59
43
  // ── Utilities ──────────────────────────────────────────────
60
- // Fast lookups, prompt tuning, PR scanning
61
- "oc-explorer": { group: "utilities" },
62
44
  metaprompter: { group: "utilities" },
63
45
  "pr-reviewer": { group: "utilities" },
46
+ "security-auditor": { group: "reviewers" },
64
47
  });
65
48
 
66
49
  export const GROUP_DEFINITIONS: Readonly<Record<GroupId, GroupDefinition>> = deepFreeze({
@@ -1,6 +1,15 @@
1
1
  import { AGENT_REGISTRY } from "./model-groups";
2
2
  import type { AgentOverride, GroupId, GroupModelAssignment, ResolvedModel } from "./types";
3
3
 
4
+ const DEPRECATED_AGENT_REMAP: Readonly<Record<string, string>> = Object.freeze({
5
+ documenter: "coder",
6
+ devops: "coder",
7
+ "frontend-engineer": "coder",
8
+ "db-specialist": "coder",
9
+ "oc-explorer": "oc-researcher",
10
+ "oc-retrospector": "oc-shipper",
11
+ });
12
+
4
13
  /**
5
14
  * Extract model family (provider) from a model string.
6
15
  * "anthropic/claude-opus-4-6" → "anthropic"
@@ -17,15 +26,15 @@ export function extractFamily(model: string): string {
17
26
  *
18
27
  * Resolution order:
19
28
  * 1. Per-agent override in overrides[agentName]
20
- * 2. Agent's group in AGENT_REGISTRY groups[groupId]
21
- * 3. null (agent uses OpenCode's default model)
29
+ * 2. Deprecated agent remapresolve via new agent name
30
+ * 3. Agent's group in AGENT_REGISTRY groups[groupId]
31
+ * 4. null (agent uses OpenCode's default model)
22
32
  */
23
33
  export function resolveModelForAgent(
24
34
  agentName: string,
25
35
  groups: Readonly<Record<string, GroupModelAssignment>>,
26
36
  overrides: Readonly<Record<string, AgentOverride>>,
27
37
  ): ResolvedModel | null {
28
- // Tier 1: per-agent override
29
38
  const override = overrides[agentName];
30
39
  if (override) {
31
40
  return {
@@ -35,7 +44,30 @@ export function resolveModelForAgent(
35
44
  };
36
45
  }
37
46
 
38
- // Tier 2: group assignment
47
+ const remappedName = DEPRECATED_AGENT_REMAP[agentName];
48
+ if (remappedName) {
49
+ const remappedOverride = overrides[remappedName];
50
+ if (remappedOverride) {
51
+ return {
52
+ primary: remappedOverride.primary,
53
+ fallbacks: remappedOverride.fallbacks ?? [],
54
+ source: "override",
55
+ };
56
+ }
57
+
58
+ const remappedEntry = AGENT_REGISTRY[remappedName];
59
+ if (remappedEntry) {
60
+ const remappedGroup = groups[remappedEntry.group];
61
+ if (remappedGroup) {
62
+ return {
63
+ primary: remappedGroup.primary,
64
+ fallbacks: remappedGroup.fallbacks,
65
+ source: "group",
66
+ };
67
+ }
68
+ }
69
+ }
70
+
39
71
  const entry = AGENT_REGISTRY[agentName];
40
72
  if (entry) {
41
73
  const group = groups[entry.group];
@@ -48,17 +80,12 @@ export function resolveModelForAgent(
48
80
  }
49
81
  }
50
82
 
51
- // Tier 3: no assignment
52
83
  return null;
53
84
  }
54
85
 
55
86
  /**
56
87
  * Resolve model for a group directly (used by review pipeline for
57
88
  * internal ReviewAgent objects that are not in AGENT_REGISTRY).
58
- *
59
- * Used by:
60
- * - Review pipeline for the 19 universal+specialized agents → "reviewers"
61
- * - Review pipeline for red-team + product-thinker → "red-team"
62
89
  */
63
90
  export function resolveModelForGroup(
64
91
  groupId: GroupId,
@@ -72,3 +99,5 @@ export function resolveModelForGroup(
72
99
  source: "group",
73
100
  };
74
101
  }
102
+
103
+ export { DEPRECATED_AGENT_REMAP };