mcp-subagents-opencode 1.0.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 (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +602 -0
  3. package/build/config/timeouts.d.ts +9 -0
  4. package/build/config/timeouts.d.ts.map +1 -0
  5. package/build/config/timeouts.js +18 -0
  6. package/build/config/timeouts.js.map +1 -0
  7. package/build/helpers.d.ts +6 -0
  8. package/build/helpers.d.ts.map +1 -0
  9. package/build/helpers.js +47 -0
  10. package/build/helpers.js.map +1 -0
  11. package/build/index.d.ts +3 -0
  12. package/build/index.d.ts.map +1 -0
  13. package/build/index.js +245 -0
  14. package/build/index.js.map +1 -0
  15. package/build/models.d.ts +32 -0
  16. package/build/models.d.ts.map +1 -0
  17. package/build/models.js +58 -0
  18. package/build/models.js.map +1 -0
  19. package/build/server/register-notifications.d.ts +3 -0
  20. package/build/server/register-notifications.d.ts.map +1 -0
  21. package/build/server/register-notifications.js +77 -0
  22. package/build/server/register-notifications.js.map +1 -0
  23. package/build/server/register-resources.d.ts +3 -0
  24. package/build/server/register-resources.d.ts.map +1 -0
  25. package/build/server/register-resources.js +210 -0
  26. package/build/server/register-resources.js.map +1 -0
  27. package/build/server/register-retry-execution.d.ts +2 -0
  28. package/build/server/register-retry-execution.d.ts.map +1 -0
  29. package/build/server/register-retry-execution.js +28 -0
  30. package/build/server/register-retry-execution.js.map +1 -0
  31. package/build/server/register-tasks.d.ts +3 -0
  32. package/build/server/register-tasks.d.ts.map +1 -0
  33. package/build/server/register-tasks.js +52 -0
  34. package/build/server/register-tasks.js.map +1 -0
  35. package/build/server/register-tools.d.ts +3 -0
  36. package/build/server/register-tools.d.ts.map +1 -0
  37. package/build/server/register-tools.js +32 -0
  38. package/build/server/register-tools.js.map +1 -0
  39. package/build/server/resource-helpers.d.ts +21 -0
  40. package/build/server/resource-helpers.d.ts.map +1 -0
  41. package/build/server/resource-helpers.js +84 -0
  42. package/build/server/resource-helpers.js.map +1 -0
  43. package/build/services/account-manager.d.ts +88 -0
  44. package/build/services/account-manager.d.ts.map +1 -0
  45. package/build/services/account-manager.js +239 -0
  46. package/build/services/account-manager.js.map +1 -0
  47. package/build/services/claude-code-runner.d.ts +15 -0
  48. package/build/services/claude-code-runner.d.ts.map +1 -0
  49. package/build/services/claude-code-runner.js +475 -0
  50. package/build/services/claude-code-runner.js.map +1 -0
  51. package/build/services/client-context.d.ts +31 -0
  52. package/build/services/client-context.d.ts.map +1 -0
  53. package/build/services/client-context.js +44 -0
  54. package/build/services/client-context.js.map +1 -0
  55. package/build/services/exhaustion-fallback.d.ts +27 -0
  56. package/build/services/exhaustion-fallback.d.ts.map +1 -0
  57. package/build/services/exhaustion-fallback.js +30 -0
  58. package/build/services/exhaustion-fallback.js.map +1 -0
  59. package/build/services/fallback-orchestrator.d.ts +16 -0
  60. package/build/services/fallback-orchestrator.d.ts.map +1 -0
  61. package/build/services/fallback-orchestrator.js +48 -0
  62. package/build/services/fallback-orchestrator.js.map +1 -0
  63. package/build/services/opencode-client.d.ts +40 -0
  64. package/build/services/opencode-client.d.ts.map +1 -0
  65. package/build/services/opencode-client.js +147 -0
  66. package/build/services/opencode-client.js.map +1 -0
  67. package/build/services/opencode-spawner.d.ts +56 -0
  68. package/build/services/opencode-spawner.d.ts.map +1 -0
  69. package/build/services/opencode-spawner.js +426 -0
  70. package/build/services/opencode-spawner.js.map +1 -0
  71. package/build/services/output-file.d.ts +24 -0
  72. package/build/services/output-file.d.ts.map +1 -0
  73. package/build/services/output-file.js +90 -0
  74. package/build/services/output-file.js.map +1 -0
  75. package/build/services/progress-registry.d.ts +12 -0
  76. package/build/services/progress-registry.d.ts.map +1 -0
  77. package/build/services/progress-registry.js +97 -0
  78. package/build/services/progress-registry.js.map +1 -0
  79. package/build/services/question-registry.d.ts +79 -0
  80. package/build/services/question-registry.d.ts.map +1 -0
  81. package/build/services/question-registry.js +249 -0
  82. package/build/services/question-registry.js.map +1 -0
  83. package/build/services/retry-queue.d.ts +41 -0
  84. package/build/services/retry-queue.d.ts.map +1 -0
  85. package/build/services/retry-queue.js +195 -0
  86. package/build/services/retry-queue.js.map +1 -0
  87. package/build/services/sdk-client-manager.d.ts +149 -0
  88. package/build/services/sdk-client-manager.d.ts.map +1 -0
  89. package/build/services/sdk-client-manager.js +632 -0
  90. package/build/services/sdk-client-manager.js.map +1 -0
  91. package/build/services/sdk-session-adapter.d.ts +203 -0
  92. package/build/services/sdk-session-adapter.d.ts.map +1 -0
  93. package/build/services/sdk-session-adapter.js +1088 -0
  94. package/build/services/sdk-session-adapter.js.map +1 -0
  95. package/build/services/sdk-spawner.d.ts +42 -0
  96. package/build/services/sdk-spawner.d.ts.map +1 -0
  97. package/build/services/sdk-spawner.js +488 -0
  98. package/build/services/sdk-spawner.js.map +1 -0
  99. package/build/services/session-hooks.d.ts +24 -0
  100. package/build/services/session-hooks.d.ts.map +1 -0
  101. package/build/services/session-hooks.js +130 -0
  102. package/build/services/session-hooks.js.map +1 -0
  103. package/build/services/session-snapshot.d.ts +19 -0
  104. package/build/services/session-snapshot.d.ts.map +1 -0
  105. package/build/services/session-snapshot.js +203 -0
  106. package/build/services/session-snapshot.js.map +1 -0
  107. package/build/services/subscription-registry.d.ts +12 -0
  108. package/build/services/subscription-registry.d.ts.map +1 -0
  109. package/build/services/subscription-registry.js +27 -0
  110. package/build/services/subscription-registry.js.map +1 -0
  111. package/build/services/task-manager.d.ts +150 -0
  112. package/build/services/task-manager.d.ts.map +1 -0
  113. package/build/services/task-manager.js +765 -0
  114. package/build/services/task-manager.js.map +1 -0
  115. package/build/services/task-persistence.d.ts +29 -0
  116. package/build/services/task-persistence.d.ts.map +1 -0
  117. package/build/services/task-persistence.js +159 -0
  118. package/build/services/task-persistence.js.map +1 -0
  119. package/build/services/task-status-mapper.d.ts +21 -0
  120. package/build/services/task-status-mapper.d.ts.map +1 -0
  121. package/build/services/task-status-mapper.js +171 -0
  122. package/build/services/task-status-mapper.js.map +1 -0
  123. package/build/templates/index.d.ts +22 -0
  124. package/build/templates/index.d.ts.map +1 -0
  125. package/build/templates/index.js +147 -0
  126. package/build/templates/index.js.map +1 -0
  127. package/build/templates/overlays/coder-csharp.mdx +58 -0
  128. package/build/templates/overlays/coder-go.mdx +53 -0
  129. package/build/templates/overlays/coder-java.mdx +54 -0
  130. package/build/templates/overlays/coder-kotlin.mdx +56 -0
  131. package/build/templates/overlays/coder-nextjs.mdx +65 -0
  132. package/build/templates/overlays/coder-python.mdx +53 -0
  133. package/build/templates/overlays/coder-react.mdx +55 -0
  134. package/build/templates/overlays/coder-ruby.mdx +59 -0
  135. package/build/templates/overlays/coder-rust.mdx +48 -0
  136. package/build/templates/overlays/coder-supabase.mdx +268 -0
  137. package/build/templates/overlays/coder-supastarter.mdx +313 -0
  138. package/build/templates/overlays/coder-swift.mdx +56 -0
  139. package/build/templates/overlays/coder-tauri.mdx +566 -0
  140. package/build/templates/overlays/coder-triggerdev.mdx +296 -0
  141. package/build/templates/overlays/coder-typescript.mdx +45 -0
  142. package/build/templates/overlays/coder-vue.mdx +62 -0
  143. package/build/templates/overlays/planner-architecture.mdx +78 -0
  144. package/build/templates/overlays/planner-bugfix.mdx +36 -0
  145. package/build/templates/overlays/planner-feature.mdx +38 -0
  146. package/build/templates/overlays/planner-migration.mdx +50 -0
  147. package/build/templates/overlays/planner-refactor.mdx +57 -0
  148. package/build/templates/overlays/researcher-library.mdx +59 -0
  149. package/build/templates/overlays/researcher-performance.mdx +68 -0
  150. package/build/templates/overlays/researcher-security.mdx +86 -0
  151. package/build/templates/overlays/tester-graphql.mdx +191 -0
  152. package/build/templates/overlays/tester-playwright.mdx +621 -0
  153. package/build/templates/overlays/tester-rest.mdx +101 -0
  154. package/build/templates/overlays/tester-suite.mdx +177 -0
  155. package/build/templates/super-coder.mdx +529 -0
  156. package/build/templates/super-planner.mdx +568 -0
  157. package/build/templates/super-researcher.mdx +406 -0
  158. package/build/templates/super-tester.mdx +243 -0
  159. package/build/tools/answer-question.d.ts +30 -0
  160. package/build/tools/answer-question.d.ts.map +1 -0
  161. package/build/tools/answer-question.js +108 -0
  162. package/build/tools/answer-question.js.map +1 -0
  163. package/build/tools/cancel-task.d.ts +44 -0
  164. package/build/tools/cancel-task.d.ts.map +1 -0
  165. package/build/tools/cancel-task.js +144 -0
  166. package/build/tools/cancel-task.js.map +1 -0
  167. package/build/tools/send-message.d.ts +39 -0
  168. package/build/tools/send-message.d.ts.map +1 -0
  169. package/build/tools/send-message.js +124 -0
  170. package/build/tools/send-message.js.map +1 -0
  171. package/build/tools/shared-spawn.d.ts +56 -0
  172. package/build/tools/shared-spawn.d.ts.map +1 -0
  173. package/build/tools/shared-spawn.js +114 -0
  174. package/build/tools/shared-spawn.js.map +1 -0
  175. package/build/tools/spawn-agent.d.ts +85 -0
  176. package/build/tools/spawn-agent.d.ts.map +1 -0
  177. package/build/tools/spawn-agent.js +133 -0
  178. package/build/tools/spawn-agent.js.map +1 -0
  179. package/build/tools/spawn-coder.d.ts +70 -0
  180. package/build/tools/spawn-coder.d.ts.map +1 -0
  181. package/build/tools/spawn-coder.js +71 -0
  182. package/build/tools/spawn-coder.js.map +1 -0
  183. package/build/tools/spawn-planner.d.ts +70 -0
  184. package/build/tools/spawn-planner.d.ts.map +1 -0
  185. package/build/tools/spawn-planner.js +71 -0
  186. package/build/tools/spawn-planner.js.map +1 -0
  187. package/build/tools/spawn-researcher.d.ts +70 -0
  188. package/build/tools/spawn-researcher.d.ts.map +1 -0
  189. package/build/tools/spawn-researcher.js +70 -0
  190. package/build/tools/spawn-researcher.js.map +1 -0
  191. package/build/tools/spawn-task.d.ts +74 -0
  192. package/build/tools/spawn-task.d.ts.map +1 -0
  193. package/build/tools/spawn-task.js +107 -0
  194. package/build/tools/spawn-task.js.map +1 -0
  195. package/build/tools/spawn-tester.d.ts +70 -0
  196. package/build/tools/spawn-tester.d.ts.map +1 -0
  197. package/build/tools/spawn-tester.js +69 -0
  198. package/build/tools/spawn-tester.js.map +1 -0
  199. package/build/types.d.ts +101 -0
  200. package/build/types.d.ts.map +1 -0
  201. package/build/types.js +28 -0
  202. package/build/types.js.map +1 -0
  203. package/build/utils/brief-validator.d.ts +30 -0
  204. package/build/utils/brief-validator.d.ts.map +1 -0
  205. package/build/utils/brief-validator.js +254 -0
  206. package/build/utils/brief-validator.js.map +1 -0
  207. package/build/utils/format.d.ts +34 -0
  208. package/build/utils/format.d.ts.map +1 -0
  209. package/build/utils/format.js +55 -0
  210. package/build/utils/format.js.map +1 -0
  211. package/build/utils/sanitize.d.ts +240 -0
  212. package/build/utils/sanitize.d.ts.map +1 -0
  213. package/build/utils/sanitize.js +89 -0
  214. package/build/utils/sanitize.js.map +1 -0
  215. package/build/utils/task-id-generator.d.ts +10 -0
  216. package/build/utils/task-id-generator.d.ts.map +1 -0
  217. package/build/utils/task-id-generator.js +22 -0
  218. package/build/utils/task-id-generator.js.map +1 -0
  219. package/package.json +62 -0
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Session Hooks Service - Implements SDK SessionHooks for lifecycle control.
3
+ *
4
+ * Provides:
5
+ * - Structured error handling with retry decisions
6
+ * - Session lifecycle monitoring (start, end)
7
+ * - Pre/post tool use hooks for logging and allow/deny decisions
8
+ * - Centralized hook management per task
9
+ *
10
+ * Note: Tool execution metrics are tracked by sdk-session-adapter using
11
+ * toolCallId-based matching, which is more accurate than the toolName-based
12
+ * matching previously done here. This file no longer tracks tool metrics
13
+ * to avoid duplicate/conflicting writes to task.sessionMetrics.toolMetrics.
14
+ *
15
+ * Uses SessionHooks interface from the SDK.
16
+ */
17
+ import type { SessionHooks } from '@github/copilot-sdk';
18
+ /**
19
+ * Create session hooks for a specific task.
20
+ * These hooks integrate SDK lifecycle events with our task management.
21
+ * Returns SessionHooks with single handler functions as expected by the SDK.
22
+ */
23
+ export declare function createSessionHooks(taskId: string): SessionHooks;
24
+ //# sourceMappingURL=session-hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-hooks.d.ts","sourceRoot":"","sources":["../../src/services/session-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,YAAY,EAWb,MAAM,qBAAqB,CAAC;AAI7B;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CA4H/D"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Session Hooks Service - Implements SDK SessionHooks for lifecycle control.
3
+ *
4
+ * Provides:
5
+ * - Structured error handling with retry decisions
6
+ * - Session lifecycle monitoring (start, end)
7
+ * - Pre/post tool use hooks for logging and allow/deny decisions
8
+ * - Centralized hook management per task
9
+ *
10
+ * Note: Tool execution metrics are tracked by sdk-session-adapter using
11
+ * toolCallId-based matching, which is more accurate than the toolName-based
12
+ * matching previously done here. This file no longer tracks tool metrics
13
+ * to avoid duplicate/conflicting writes to task.sessionMetrics.toolMetrics.
14
+ *
15
+ * Uses SessionHooks interface from the SDK.
16
+ */
17
+ import { taskManager } from './task-manager.js';
18
+ /**
19
+ * Create session hooks for a specific task.
20
+ * These hooks integrate SDK lifecycle events with our task management.
21
+ * Returns SessionHooks with single handler functions as expected by the SDK.
22
+ */
23
+ export function createSessionHooks(taskId) {
24
+ return {
25
+ /**
26
+ * Called when a session starts.
27
+ * Logs session start and sets up monitoring.
28
+ */
29
+ onSessionStart: async (input) => {
30
+ console.error(`[session-hooks] Session started for task ${taskId}: source=${input.source}`);
31
+ // Hook lifecycle → file only (internal metadata)
32
+ taskManager.appendOutputFileOnly(taskId, `[hooks] Session ${input.source === 'resume' ? 'resumed' : 'started'}`);
33
+ // Initialize session metrics
34
+ const task = taskManager.getTask(taskId);
35
+ if (task && !task.sessionMetrics) {
36
+ taskManager.updateTask(taskId, {
37
+ sessionMetrics: {
38
+ quotas: {},
39
+ toolMetrics: {},
40
+ activeSubagents: [],
41
+ completedSubagents: [],
42
+ turnCount: 0,
43
+ totalTokens: { input: 0, output: 0 },
44
+ },
45
+ });
46
+ }
47
+ return {
48
+ additionalContext: `Task ID: ${taskId}`,
49
+ };
50
+ },
51
+ /**
52
+ * Called when a session ends.
53
+ * Logs session end and generates summary.
54
+ */
55
+ onSessionEnd: async (input) => {
56
+ console.error(`[session-hooks] Session ended for task ${taskId}: reason=${input.reason}`);
57
+ // Hook lifecycle → file only
58
+ taskManager.appendOutputFileOnly(taskId, `[hooks] Session ended: ${input.reason}`);
59
+ // Generate session summary if available
60
+ if (input.finalMessage) {
61
+ return {
62
+ sessionSummary: input.finalMessage,
63
+ };
64
+ }
65
+ return undefined;
66
+ },
67
+ /**
68
+ * Called when an error occurs.
69
+ * Provides structured error handling with retry decisions.
70
+ */
71
+ onErrorOccurred: async (input) => {
72
+ const errorMsg = String(input.error);
73
+ console.error(`[session-hooks] Error for task ${taskId}: context=${input.errorContext}, recoverable=${input.recoverable}`);
74
+ // Create structured failure context
75
+ const failureContext = {
76
+ errorType: input.errorContext,
77
+ errorContext: input.errorContext,
78
+ recoverable: input.recoverable,
79
+ message: errorMsg,
80
+ };
81
+ // Update task with failure context
82
+ taskManager.updateTask(taskId, { failureContext });
83
+ taskManager.appendOutput(taskId, `[hooks] Error: ${input.errorContext} - ${errorMsg.slice(0, 100)}`);
84
+ // Determine error handling strategy
85
+ if (input.recoverable) {
86
+ // For recoverable errors, suggest retry
87
+ return {
88
+ errorHandling: 'retry',
89
+ retryCount: 3,
90
+ userNotification: `Recoverable error in ${input.errorContext}: ${errorMsg.slice(0, 100)}`,
91
+ };
92
+ }
93
+ // For non-recoverable errors in tool execution, skip the tool
94
+ if (input.errorContext === 'tool_execution') {
95
+ return {
96
+ errorHandling: 'skip',
97
+ userNotification: `Tool execution failed: ${errorMsg.slice(0, 100)}`,
98
+ };
99
+ }
100
+ // For model call errors, abort (let the adapter handle rotation)
101
+ if (input.errorContext === 'model_call') {
102
+ return {
103
+ errorHandling: 'abort',
104
+ userNotification: `Model call failed: ${errorMsg.slice(0, 100)}`,
105
+ };
106
+ }
107
+ return undefined;
108
+ },
109
+ /**
110
+ * Called before a tool is executed.
111
+ * Logs tool start. Metrics are tracked by sdk-session-adapter.
112
+ */
113
+ onPreToolUse: async (input) => {
114
+ console.error(`[session-hooks] Tool starting for task ${taskId}: ${input.toolName}`);
115
+ return {
116
+ permissionDecision: 'allow',
117
+ };
118
+ },
119
+ /**
120
+ * Called after a tool is executed.
121
+ * Logs tool completion. Metrics are tracked by sdk-session-adapter.
122
+ */
123
+ onPostToolUse: async (input) => {
124
+ const isSuccess = input.toolResult?.resultType === 'success';
125
+ console.error(`[session-hooks] Tool completed for task ${taskId}: ${input.toolName} (${isSuccess ? 'success' : 'failure'})`);
126
+ return undefined;
127
+ },
128
+ };
129
+ }
130
+ //# sourceMappingURL=session-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-hooks.js","sourceRoot":"","sources":["../../src/services/session-hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Session Snapshot Builder
3
+ *
4
+ * Extracts bounded context from a Copilot session for handoff to Claude Agent SDK.
5
+ * Provides last N turns with message truncation to prevent excessive context size.
6
+ */
7
+ import type { CopilotSession } from '@github/copilot-sdk';
8
+ import { TaskState } from '../types.js';
9
+ /**
10
+ * Build handoff prompt from session snapshot.
11
+ * Includes original prompt and bounded recent context.
12
+ */
13
+ export declare function buildHandoffPrompt(task: TaskState, maxTurns?: number, reason?: string): string;
14
+ /**
15
+ * Build handoff prompt with structured SDK history when available.
16
+ * Falls back to output-file snapshot if session history is unavailable.
17
+ */
18
+ export declare function buildHandoffPromptFromSession(task: TaskState, session: CopilotSession | undefined, maxTurns?: number, reason?: string): Promise<string>;
19
+ //# sourceMappingURL=session-snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-snapshot.d.ts","sourceRoot":"","sources":["../../src/services/session-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA+HxC;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,GAAE,MAAkB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CA8CzG;AAED;;;GAGG;AACH,wBAAsB,6BAA6B,CACjD,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,cAAc,GAAG,SAAS,EACnC,QAAQ,GAAE,MAAkB,EAC5B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CA2CjB"}
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Session Snapshot Builder
3
+ *
4
+ * Extracts bounded context from a Copilot session for handoff to Claude Agent SDK.
5
+ * Provides last N turns with message truncation to prevent excessive context size.
6
+ */
7
+ import { readFileSync } from 'fs';
8
+ const MAX_TURNS = 5; // Max number of turns to include
9
+ const MAX_MESSAGE_LENGTH = 2000; // Max chars per message
10
+ const MAX_TOTAL_LENGTH = 20000; // Max total snapshot size
11
+ /**
12
+ * Parse output file and extract recent message pairs.
13
+ * Simple heuristic: split on common markers.
14
+ */
15
+ function parseOutputFile(filePath) {
16
+ try {
17
+ const content = readFileSync(filePath, 'utf-8');
18
+ const pairs = [];
19
+ // Split by common output markers
20
+ const lines = content.split('\n');
21
+ let currentAssistant = '';
22
+ let isAssistant = false;
23
+ for (const line of lines) {
24
+ // Detect assistant output (simple heuristic - lines without user markers)
25
+ if (line.startsWith('[') || line.startsWith('>') || line.trim().length === 0) {
26
+ // System/tool output, skip
27
+ continue;
28
+ }
29
+ // Accumulate assistant output
30
+ if (!isAssistant) {
31
+ isAssistant = true;
32
+ currentAssistant = '';
33
+ }
34
+ currentAssistant += line + '\n';
35
+ }
36
+ // If we have any output, treat it as one big assistant turn
37
+ if (currentAssistant.trim()) {
38
+ pairs.push({
39
+ user: '',
40
+ assistant: currentAssistant.trim(),
41
+ });
42
+ }
43
+ return pairs;
44
+ }
45
+ catch (error) {
46
+ console.warn(`[session-snapshot] Failed to read output file: ${error}`);
47
+ return [];
48
+ }
49
+ }
50
+ /**
51
+ * Truncate a message to max length with ellipsis.
52
+ */
53
+ function truncateMessage(msg, maxLength) {
54
+ if (msg.length <= maxLength) {
55
+ return msg;
56
+ }
57
+ return msg.slice(0, maxLength - 3) + '...';
58
+ }
59
+ function pairsFromSessionEvents(events) {
60
+ const pairs = [];
61
+ let pendingUser = '';
62
+ let pendingAssistant = '';
63
+ const flush = () => {
64
+ if (pendingUser.trim() || pendingAssistant.trim()) {
65
+ pairs.push({
66
+ user: pendingUser.trim(),
67
+ assistant: pendingAssistant.trim(),
68
+ });
69
+ }
70
+ pendingUser = '';
71
+ pendingAssistant = '';
72
+ };
73
+ for (const event of events) {
74
+ if (event.type === 'user.message') {
75
+ if (pendingAssistant.trim()) {
76
+ flush();
77
+ }
78
+ const content = event.data.content?.trim();
79
+ if (content) {
80
+ pendingUser = content;
81
+ }
82
+ continue;
83
+ }
84
+ if (event.type === 'assistant.message') {
85
+ const content = event.data.content?.trim();
86
+ if (!content)
87
+ continue;
88
+ if (pendingAssistant.trim()) {
89
+ pendingAssistant += '\n\n' + content;
90
+ }
91
+ else {
92
+ pendingAssistant = content;
93
+ }
94
+ flush();
95
+ }
96
+ }
97
+ flush();
98
+ return pairs;
99
+ }
100
+ function fallbackReasonIntro(reason) {
101
+ switch (reason) {
102
+ case 'copilot_startup_no_accounts':
103
+ return 'No Copilot account is currently available, so you are taking over before initial execution.';
104
+ case 'copilot_accounts_exhausted':
105
+ return 'All Copilot accounts are currently exhausted, so you are taking over.';
106
+ case 'copilot_rate_limited':
107
+ return 'The Copilot session is rate-limited and cannot continue within policy, so you are taking over.';
108
+ case 'copilot_non_rotatable_error':
109
+ return 'The Copilot session hit a non-rotatable error, so you are taking over.';
110
+ case 'copilot_unhandled_error':
111
+ return 'The Copilot path hit an unhandled error, so you are taking over.';
112
+ default:
113
+ return 'The previous Copilot path cannot continue, so you are taking over.';
114
+ }
115
+ }
116
+ /**
117
+ * Build handoff prompt from session snapshot.
118
+ * Includes original prompt and bounded recent context.
119
+ */
120
+ export function buildHandoffPrompt(task, maxTurns = MAX_TURNS, reason) {
121
+ const parts = [];
122
+ // Header explaining the handoff
123
+ parts.push('You are continuing a task that started with GitHub Copilot SDK.');
124
+ parts.push(fallbackReasonIntro(reason));
125
+ parts.push('');
126
+ // Original prompt
127
+ parts.push(`Original task prompt:\n${task.prompt}`);
128
+ parts.push('');
129
+ // Extract recent context if output file exists
130
+ if (task.outputFilePath) {
131
+ const pairs = parseOutputFile(task.outputFilePath);
132
+ const recentPairs = pairs.slice(-maxTurns);
133
+ if (recentPairs.length > 0) {
134
+ parts.push('Recent context from the Copilot session:');
135
+ parts.push('');
136
+ for (const pair of recentPairs) {
137
+ if (pair.user) {
138
+ const truncated = truncateMessage(pair.user, MAX_MESSAGE_LENGTH);
139
+ parts.push(`User: ${truncated}`);
140
+ parts.push('');
141
+ }
142
+ if (pair.assistant) {
143
+ const truncated = truncateMessage(pair.assistant, MAX_MESSAGE_LENGTH);
144
+ parts.push(`Assistant: ${truncated}`);
145
+ parts.push('');
146
+ }
147
+ }
148
+ }
149
+ }
150
+ // Footer with instruction
151
+ parts.push('Please continue working on this task. Pick up where the Copilot session left off.');
152
+ // Join and enforce total length limit
153
+ const snapshot = parts.join('\n');
154
+ if (snapshot.length > MAX_TOTAL_LENGTH) {
155
+ return snapshot.slice(0, MAX_TOTAL_LENGTH - 100) + '\n\n...[context truncated]\n\nPlease continue working on the original task.';
156
+ }
157
+ return snapshot;
158
+ }
159
+ /**
160
+ * Build handoff prompt with structured SDK history when available.
161
+ * Falls back to output-file snapshot if session history is unavailable.
162
+ */
163
+ export async function buildHandoffPromptFromSession(task, session, maxTurns = MAX_TURNS, reason) {
164
+ if (!session) {
165
+ return buildHandoffPrompt(task, maxTurns, reason);
166
+ }
167
+ try {
168
+ const events = await session.getMessages();
169
+ const pairs = pairsFromSessionEvents(events);
170
+ if (pairs.length === 0) {
171
+ return buildHandoffPrompt(task, maxTurns, reason);
172
+ }
173
+ const parts = [];
174
+ parts.push('You are continuing a task that started with GitHub Copilot SDK.');
175
+ parts.push(fallbackReasonIntro(reason));
176
+ parts.push('');
177
+ parts.push(`Original task prompt:\n${task.prompt}`);
178
+ parts.push('');
179
+ parts.push('Recent context from structured Copilot session history:');
180
+ parts.push('');
181
+ for (const pair of pairs.slice(-maxTurns)) {
182
+ if (pair.user) {
183
+ parts.push(`User: ${truncateMessage(pair.user, MAX_MESSAGE_LENGTH)}`);
184
+ parts.push('');
185
+ }
186
+ if (pair.assistant) {
187
+ parts.push(`Assistant: ${truncateMessage(pair.assistant, MAX_MESSAGE_LENGTH)}`);
188
+ parts.push('');
189
+ }
190
+ }
191
+ parts.push('Please continue working on this task. Pick up where the Copilot session left off.');
192
+ const snapshot = parts.join('\n');
193
+ if (snapshot.length > MAX_TOTAL_LENGTH) {
194
+ return snapshot.slice(0, MAX_TOTAL_LENGTH - 100) + '\n\n...[context truncated]\n\nPlease continue working on the original task.';
195
+ }
196
+ return snapshot;
197
+ }
198
+ catch (error) {
199
+ console.warn(`[session-snapshot] Failed to load session history: ${error}`);
200
+ return buildHandoffPrompt(task, maxTurns, reason);
201
+ }
202
+ }
203
+ //# sourceMappingURL=session-snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-snapshot.js","sourceRoot":"","sources":["../../src/services/session-snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ declare class SubscriptionRegistry {
2
+ private subscriptions;
3
+ subscribe(uri: string): void;
4
+ unsubscribe(uri: string): void;
5
+ isSubscribed(uri: string): boolean;
6
+ clear(): void;
7
+ }
8
+ export declare function taskIdToUri(taskId: string): string;
9
+ export declare function uriToTaskId(uri: string): string | null;
10
+ export declare const subscriptionRegistry: SubscriptionRegistry;
11
+ export {};
12
+ //# sourceMappingURL=subscription-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription-registry.d.ts","sourceRoot":"","sources":["../../src/services/subscription-registry.ts"],"names":[],"mappings":"AAEA,cAAM,oBAAoB;IACxB,OAAO,CAAC,aAAa,CAAqB;IAE1C,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI5B,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI9B,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIlC,KAAK,IAAI,IAAI;CAGd;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAItD;AAED,eAAO,MAAM,oBAAoB,sBAA6B,CAAC"}
@@ -0,0 +1,27 @@
1
+ const URI_PREFIX = 'task:///';
2
+ class SubscriptionRegistry {
3
+ subscriptions = new Set();
4
+ subscribe(uri) {
5
+ this.subscriptions.add(uri);
6
+ }
7
+ unsubscribe(uri) {
8
+ this.subscriptions.delete(uri);
9
+ }
10
+ isSubscribed(uri) {
11
+ return this.subscriptions.has(uri);
12
+ }
13
+ clear() {
14
+ this.subscriptions.clear();
15
+ }
16
+ }
17
+ export function taskIdToUri(taskId) {
18
+ return `${URI_PREFIX}${taskId}`;
19
+ }
20
+ export function uriToTaskId(uri) {
21
+ if (!uri.startsWith(URI_PREFIX))
22
+ return null;
23
+ const taskId = uri.slice(URI_PREFIX.length);
24
+ return taskId || null;
25
+ }
26
+ export const subscriptionRegistry = new SubscriptionRegistry();
27
+ //# sourceMappingURL=subscription-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription-registry.js","sourceRoot":"","sources":["../../src/services/subscription-registry.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B,MAAM,oBAAoB;IAChB,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IAE1C,SAAS,CAAC,GAAW;QACnB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,WAAW,CAAC,GAAW;QACrB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,YAAY,CAAC,GAAW;QACtB,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,GAAG,UAAU,GAAG,MAAM,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC5C,OAAO,MAAM,IAAI,IAAI,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,150 @@
1
+ import { TaskState, TaskStatus } from '../types.js';
2
+ export { TERMINAL_STATUSES } from '../types.js';
3
+ /**
4
+ * Check if a session is still active.
5
+ */
6
+ export declare function isSessionActive(task: TaskState): boolean;
7
+ declare class TaskManager {
8
+ private tasks;
9
+ private cleanupInterval;
10
+ private healthCheckInterval;
11
+ private rateLimitTimer;
12
+ private currentCwd;
13
+ private persistTimeout;
14
+ private persistDebounceMs;
15
+ private outputPersistDebounceMs;
16
+ private lastPersistTrigger;
17
+ private retryCallback;
18
+ private executeCallback;
19
+ private statusChangeCallback;
20
+ private outputCallback;
21
+ private taskCreatedCallback;
22
+ private taskDeletedCallback;
23
+ constructor();
24
+ /**
25
+ * Set the current workspace and load persisted tasks
26
+ * Also triggers auto-retry for rate-limited tasks
27
+ */
28
+ setCwd(cwd: string): void;
29
+ /**
30
+ * Register a callback to be called when a rate-limited task should be retried
31
+ * Callback should return the new task ID
32
+ */
33
+ onRetry(callback: (task: TaskState) => Promise<string | undefined>): void;
34
+ /**
35
+ * Register a callback to execute a waiting task when dependencies are satisfied
36
+ */
37
+ onExecute(callback: (task: TaskState) => Promise<void>): void;
38
+ onStatusChange(callback: (task: TaskState, previousStatus: TaskStatus) => void): void;
39
+ onOutput(callback: (taskId: string, line: string) => void): void;
40
+ onTaskCreated(callback: (task: TaskState) => void): void;
41
+ onTaskDeleted(callback: (taskId: string) => void): void;
42
+ /**
43
+ * Process waiting tasks and start those with satisfied dependencies
44
+ */
45
+ private processWaitingTasks;
46
+ /**
47
+ * Validate dependencies for a new task
48
+ * Returns error message if invalid, null if valid
49
+ */
50
+ validateDependencies(dependsOn: string[], newTaskId?: string): string | null;
51
+ /**
52
+ * Get dependency status info for a task
53
+ */
54
+ getDependencyStatus(taskId: string): {
55
+ satisfied: boolean;
56
+ missing: string[];
57
+ failed: string[];
58
+ pending: string[];
59
+ } | null;
60
+ /**
61
+ * Force start a waiting task, bypassing failed/missing dependencies
62
+ */
63
+ forceStartTask(taskId: string): Promise<{
64
+ success: boolean;
65
+ taskId?: string;
66
+ bypassedDeps?: string[];
67
+ error?: string;
68
+ }>;
69
+ /**
70
+ * Process rate-limited tasks and trigger retries for those ready
71
+ */
72
+ private processRateLimitedTasks;
73
+ /**
74
+ * Schedule the next rate-limit retry check based on earliest nextRetryTime.
75
+ */
76
+ private scheduleRateLimitCheck;
77
+ /**
78
+ * Get all rate-limited tasks
79
+ */
80
+ getRateLimitedTasks(): TaskState[];
81
+ /**
82
+ * Expedite all rate-limited tasks by moving their next retry time up.
83
+ * Called after recovery so stalled tasks benefit.
84
+ * Tasks are staggered to avoid thundering herd.
85
+ */
86
+ expediteRateLimitedTasks(baseDelayMs?: number): void;
87
+ /**
88
+ * Clear all tasks from memory (used by clear_tasks tool)
89
+ * Clears all tasks from memory and aborts running sessions.
90
+ */
91
+ clearAllTasks(): Promise<number>;
92
+ /**
93
+ * Manually trigger retry of a rate-limited task
94
+ * Returns the new task ID on success
95
+ */
96
+ triggerManualRetry(taskId: string): Promise<{
97
+ success: boolean;
98
+ newTaskId?: string;
99
+ error?: string;
100
+ }>;
101
+ /**
102
+ * Persist tasks to disk (debounced)
103
+ */
104
+ private schedulePersist;
105
+ /**
106
+ * Persist tasks immediately
107
+ */
108
+ private persistNow;
109
+ private startCleanup;
110
+ /**
111
+ * Start periodic health check for running sessions
112
+ * Monitors for stalled sessions and enforces hard timeouts.
113
+ */
114
+ private startHealthCheck;
115
+ /**
116
+ * Check all RUNNING tasks to verify their sessions are healthy
117
+ * Checks all RUNNING tasks for health: heartbeat, hard timeout, and stalls.
118
+ */
119
+ private checkSessionHealth;
120
+ private cleanup;
121
+ createTask(prompt: string, cwd?: string, model?: string, options?: {
122
+ autonomous?: boolean;
123
+ isResume?: boolean;
124
+ retryInfo?: import('../types.js').RetryInfo;
125
+ dependsOn?: string[];
126
+ labels?: string[];
127
+ provider?: import('../types.js').Provider;
128
+ fallbackAttempted?: boolean;
129
+ switchAttempted?: boolean;
130
+ timeout?: number;
131
+ }): TaskState;
132
+ getTask(id: string): TaskState | null;
133
+ updateTask(id: string, updates: Partial<TaskState>): TaskState | null;
134
+ /**
135
+ * Write to output file only — skips in-memory array and callbacks.
136
+ * Use for verbose debug data (reasoning, internal events) that should be
137
+ * available in the file for debugging but not waste tokens in MCP resources.
138
+ */
139
+ appendOutputFileOnly(id: string, line: string): void;
140
+ appendOutput(id: string, line: string): void;
141
+ getAllTasks(statusFilter?: TaskStatus): TaskState[];
142
+ cancelTask(id: string): {
143
+ success: boolean;
144
+ alreadyDead?: boolean;
145
+ error?: string;
146
+ };
147
+ shutdown(): Promise<void>;
148
+ }
149
+ export declare const taskManager: TaskManager;
150
+ //# sourceMappingURL=task-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-manager.d.ts","sourceRoot":"","sources":["../../src/services/task-manager.ts"],"names":[],"mappings":"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"}