cli-copilot-worker 0.1.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 (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/bin/cli-copilot-worker.mjs +3 -0
  4. package/dist/src/cli.d.ts +2 -0
  5. package/dist/src/cli.js +682 -0
  6. package/dist/src/cli.js.map +1 -0
  7. package/dist/src/core/copilot.d.ts +13 -0
  8. package/dist/src/core/copilot.js +56 -0
  9. package/dist/src/core/copilot.js.map +1 -0
  10. package/dist/src/core/failure-classifier.d.ts +8 -0
  11. package/dist/src/core/failure-classifier.js +148 -0
  12. package/dist/src/core/failure-classifier.js.map +1 -0
  13. package/dist/src/core/ids.d.ts +1 -0
  14. package/dist/src/core/ids.js +11 -0
  15. package/dist/src/core/ids.js.map +1 -0
  16. package/dist/src/core/markdown.d.ts +5 -0
  17. package/dist/src/core/markdown.js +14 -0
  18. package/dist/src/core/markdown.js.map +1 -0
  19. package/dist/src/core/paths.d.ts +18 -0
  20. package/dist/src/core/paths.js +42 -0
  21. package/dist/src/core/paths.js.map +1 -0
  22. package/dist/src/core/profile-faults.d.ts +15 -0
  23. package/dist/src/core/profile-faults.js +110 -0
  24. package/dist/src/core/profile-faults.js.map +1 -0
  25. package/dist/src/core/profile-manager.d.ts +25 -0
  26. package/dist/src/core/profile-manager.js +162 -0
  27. package/dist/src/core/profile-manager.js.map +1 -0
  28. package/dist/src/core/question-registry.d.ts +25 -0
  29. package/dist/src/core/question-registry.js +154 -0
  30. package/dist/src/core/question-registry.js.map +1 -0
  31. package/dist/src/core/store.d.ts +39 -0
  32. package/dist/src/core/store.js +206 -0
  33. package/dist/src/core/store.js.map +1 -0
  34. package/dist/src/core/types.d.ts +152 -0
  35. package/dist/src/core/types.js +2 -0
  36. package/dist/src/core/types.js.map +1 -0
  37. package/dist/src/daemon/client.d.ts +6 -0
  38. package/dist/src/daemon/client.js +117 -0
  39. package/dist/src/daemon/client.js.map +1 -0
  40. package/dist/src/daemon/server.d.ts +1 -0
  41. package/dist/src/daemon/server.js +149 -0
  42. package/dist/src/daemon/server.js.map +1 -0
  43. package/dist/src/daemon/service.d.ts +69 -0
  44. package/dist/src/daemon/service.js +800 -0
  45. package/dist/src/daemon/service.js.map +1 -0
  46. package/dist/src/doctor.d.ts +1 -0
  47. package/dist/src/doctor.js +74 -0
  48. package/dist/src/doctor.js.map +1 -0
  49. package/dist/src/index.d.ts +3 -0
  50. package/dist/src/index.js +4 -0
  51. package/dist/src/index.js.map +1 -0
  52. package/dist/src/output.d.ts +28 -0
  53. package/dist/src/output.js +307 -0
  54. package/dist/src/output.js.map +1 -0
  55. package/package.json +59 -0
  56. package/src/cli.ts +881 -0
  57. package/src/core/copilot.ts +75 -0
  58. package/src/core/failure-classifier.ts +202 -0
  59. package/src/core/ids.ts +11 -0
  60. package/src/core/markdown.ts +19 -0
  61. package/src/core/paths.ts +56 -0
  62. package/src/core/profile-faults.ts +140 -0
  63. package/src/core/profile-manager.ts +220 -0
  64. package/src/core/question-registry.ts +191 -0
  65. package/src/core/store.ts +273 -0
  66. package/src/core/types.ts +211 -0
  67. package/src/daemon/client.ts +137 -0
  68. package/src/daemon/server.ts +167 -0
  69. package/src/daemon/service.ts +968 -0
  70. package/src/doctor.ts +82 -0
  71. package/src/index.ts +3 -0
  72. package/src/output.ts +391 -0
@@ -0,0 +1,152 @@
1
+ export type ConversationStatus = 'idle' | 'running' | 'waiting_answer' | 'failed' | 'cancelled';
2
+ export type JobStatus = 'running' | 'waiting_answer' | 'completed' | 'failed' | 'cancelled';
3
+ export type JobKind = 'run' | 'send' | 'answer';
4
+ export type TranscriptRole = 'user' | 'assistant' | 'tool_use' | 'tool_result' | 'question' | 'answer' | 'status' | 'error';
5
+ export type CopilotFailureCategory = 'auth' | 'rate_limit' | 'connection' | 'transient' | 'fatal';
6
+ export interface CopilotFailureInfo {
7
+ category: CopilotFailureCategory;
8
+ retryable: boolean;
9
+ message: string;
10
+ sessionErrorType?: string | undefined;
11
+ sessionStatusCode?: number | undefined;
12
+ }
13
+ export interface JobAttemptRecord {
14
+ profileId: string;
15
+ profileConfigDir: string;
16
+ startedAt: string;
17
+ endedAt?: string | undefined;
18
+ outcome: 'running' | 'completed' | 'failed';
19
+ failureCategory?: CopilotFailureCategory | undefined;
20
+ failureMessage?: string | undefined;
21
+ sessionErrorType?: string | undefined;
22
+ sessionStatusCode?: number | undefined;
23
+ }
24
+ export interface PendingQuestion {
25
+ question: string;
26
+ choices?: string[] | undefined;
27
+ allowFreeform: boolean;
28
+ askedAt: string;
29
+ sessionId: string;
30
+ }
31
+ export interface ConversationRecord {
32
+ id: string;
33
+ sessionId: string;
34
+ workspaceId: string;
35
+ cwd: string;
36
+ model: string;
37
+ status: ConversationStatus;
38
+ createdAt: string;
39
+ updatedAt: string;
40
+ hasStarted: boolean;
41
+ nextEntryIndex: number;
42
+ lastJobId?: string | undefined;
43
+ pendingQuestion?: PendingQuestion | undefined;
44
+ profileId?: string | undefined;
45
+ profileConfigDir?: string | undefined;
46
+ lastError?: string | undefined;
47
+ }
48
+ export interface JobRecord {
49
+ id: string;
50
+ conversationId: string;
51
+ kind: JobKind;
52
+ status: JobStatus;
53
+ inputFilePath: string;
54
+ createdAt: string;
55
+ startedAt: string;
56
+ endedAt?: string | undefined;
57
+ error?: string | undefined;
58
+ pid?: number | undefined;
59
+ turnIndex: number;
60
+ startEntryIndex: number;
61
+ endEntryIndex?: number | undefined;
62
+ attempts: JobAttemptRecord[];
63
+ }
64
+ export interface TranscriptEntry {
65
+ index: number;
66
+ conversationId: string;
67
+ jobId?: string | undefined;
68
+ role: TranscriptRole;
69
+ content: string;
70
+ timestamp: string;
71
+ data?: Record<string, unknown> | undefined;
72
+ }
73
+ export interface PersistedProfileState {
74
+ id: string;
75
+ configDir: string;
76
+ cooldownUntil?: number | undefined;
77
+ failureCount: number;
78
+ lastFailureReason?: string | undefined;
79
+ lastFailureCategory?: CopilotFailureCategory | undefined;
80
+ lastFailureAt?: string | undefined;
81
+ lastSuccessAt?: string | undefined;
82
+ }
83
+ export interface StateFile {
84
+ version: 1;
85
+ conversations: ConversationRecord[];
86
+ jobs: JobRecord[];
87
+ profiles: PersistedProfileState[];
88
+ }
89
+ export interface CopilotProfile {
90
+ id: string;
91
+ configDir: string;
92
+ cooldownUntil?: number | undefined;
93
+ failureCount: number;
94
+ lastFailureReason?: string | undefined;
95
+ lastFailureCategory?: CopilotFailureCategory | undefined;
96
+ lastFailureAt?: string | undefined;
97
+ lastSuccessAt?: string | undefined;
98
+ }
99
+ export interface DaemonMeta {
100
+ pid: number;
101
+ socketPath: string;
102
+ token: string;
103
+ startedAt: string;
104
+ }
105
+ export interface RunRequest {
106
+ inputFilePath: string;
107
+ content: string;
108
+ cwd: string;
109
+ model?: string | undefined;
110
+ timeoutMs?: number | undefined;
111
+ async?: boolean | undefined;
112
+ }
113
+ export interface SendRequest {
114
+ conversationId: string;
115
+ inputFilePath: string;
116
+ content: string;
117
+ timeoutMs?: number | undefined;
118
+ async?: boolean | undefined;
119
+ }
120
+ export interface AnswerRequest {
121
+ conversationId: string;
122
+ inputFilePath: string;
123
+ content: string;
124
+ }
125
+ export interface ReadRequest {
126
+ conversationId: string;
127
+ from?: number | undefined;
128
+ to?: number | undefined;
129
+ after?: number | undefined;
130
+ before?: number | undefined;
131
+ tokens?: number | undefined;
132
+ detail?: 'standard' | 'verbose' | 'full' | 'meta' | undefined;
133
+ }
134
+ export interface JobWaitRequest {
135
+ jobId: string;
136
+ timeoutSeconds?: number | undefined;
137
+ intervalSeconds?: number | undefined;
138
+ }
139
+ export type DaemonCommand = 'ping' | 'run' | 'send' | 'answer' | 'read' | 'list' | 'info' | 'job.list' | 'job.status' | 'job.wait' | 'job.read' | 'job.cancel' | 'daemon.stop' | 'daemon.status';
140
+ export interface DaemonRequestEnvelope {
141
+ id: string;
142
+ token: string;
143
+ command: DaemonCommand;
144
+ args?: Record<string, unknown> | undefined;
145
+ }
146
+ export interface DaemonResponseEnvelope {
147
+ id: string;
148
+ type: 'event' | 'result' | 'error';
149
+ event?: string | undefined;
150
+ data?: Record<string, unknown> | undefined;
151
+ error?: string | undefined;
152
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import type { DaemonMeta, DaemonRequestEnvelope } from '../core/types.js';
2
+ export declare function ensureDaemonMeta(): Promise<DaemonMeta>;
3
+ export declare function sendDaemonRequest(command: DaemonRequestEnvelope['command'], args?: Record<string, unknown>, options?: {
4
+ onEvent?: ((event: string, data: Record<string, unknown>) => void) | undefined;
5
+ }): Promise<Record<string, unknown>>;
6
+ export declare function daemonIsRunning(): Promise<boolean>;
@@ -0,0 +1,117 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import net from 'node:net';
4
+ import { spawn } from 'node:child_process';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { buildDaemonToken, ensureStateRoot } from '../core/paths.js';
7
+ function delay(ms) {
8
+ return new Promise((resolve) => setTimeout(resolve, ms));
9
+ }
10
+ function cliLaunchSpec() {
11
+ const compiledCliPath = fileURLToPath(new URL('../cli.js', import.meta.url));
12
+ if (existsSync(compiledCliPath)) {
13
+ return {
14
+ command: process.execPath,
15
+ args: ['--import', 'tsx', compiledCliPath, 'daemon-run'],
16
+ };
17
+ }
18
+ const sourceCliPath = fileURLToPath(new URL('../cli.ts', import.meta.url));
19
+ return {
20
+ command: process.execPath,
21
+ args: ['--import', 'tsx', sourceCliPath, 'daemon-run'],
22
+ };
23
+ }
24
+ async function readDaemonMeta() {
25
+ const { daemonMetaPath } = ensureStateRoot();
26
+ if (!existsSync(daemonMetaPath)) {
27
+ return null;
28
+ }
29
+ try {
30
+ const raw = await readFile(daemonMetaPath, 'utf8');
31
+ return JSON.parse(raw);
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ async function canConnect(socketPath) {
38
+ return await new Promise((resolve) => {
39
+ const socket = net.createConnection(socketPath, () => {
40
+ socket.end();
41
+ resolve(true);
42
+ });
43
+ socket.on('error', () => resolve(false));
44
+ });
45
+ }
46
+ export async function ensureDaemonMeta() {
47
+ const existing = await readDaemonMeta();
48
+ if (existing && await canConnect(existing.socketPath)) {
49
+ return existing;
50
+ }
51
+ const { socketPath } = ensureStateRoot();
52
+ const token = buildDaemonToken();
53
+ const launchSpec = cliLaunchSpec();
54
+ const child = spawn(launchSpec.command, launchSpec.args, {
55
+ detached: true,
56
+ stdio: 'ignore',
57
+ env: {
58
+ ...process.env,
59
+ CLI_COPILOT_WORKER_DAEMON_SOCKET: socketPath,
60
+ CLI_COPILOT_WORKER_DAEMON_TOKEN: token,
61
+ },
62
+ });
63
+ child.unref();
64
+ for (let attempt = 0; attempt < 50; attempt += 1) {
65
+ const current = await readDaemonMeta();
66
+ if (current && await canConnect(current.socketPath)) {
67
+ return current;
68
+ }
69
+ await delay(100);
70
+ }
71
+ throw new Error('Timed out waiting for cli-copilot-worker daemon to start');
72
+ }
73
+ export async function sendDaemonRequest(command, args, options) {
74
+ const meta = await ensureDaemonMeta();
75
+ const request = {
76
+ id: `${Date.now()}`,
77
+ token: meta.token,
78
+ command,
79
+ args,
80
+ };
81
+ return await new Promise((resolve, reject) => {
82
+ let buffer = '';
83
+ const socket = net.createConnection(meta.socketPath);
84
+ socket.on('connect', () => {
85
+ socket.write(`${JSON.stringify(request)}\n`);
86
+ });
87
+ socket.on('data', (chunk) => {
88
+ buffer += chunk.toString('utf8');
89
+ let newlineIndex = buffer.indexOf('\n');
90
+ while (newlineIndex >= 0) {
91
+ const line = buffer.slice(0, newlineIndex).trim();
92
+ buffer = buffer.slice(newlineIndex + 1);
93
+ if (line) {
94
+ const envelope = JSON.parse(line);
95
+ if (envelope.type === 'event') {
96
+ options?.onEvent?.(envelope.event ?? 'event', envelope.data ?? {});
97
+ }
98
+ else if (envelope.type === 'result') {
99
+ socket.end();
100
+ resolve(envelope.data ?? {});
101
+ }
102
+ else {
103
+ socket.end();
104
+ reject(new Error(envelope.error ?? 'Unknown daemon error'));
105
+ }
106
+ }
107
+ newlineIndex = buffer.indexOf('\n');
108
+ }
109
+ });
110
+ socket.on('error', reject);
111
+ });
112
+ }
113
+ export async function daemonIsRunning() {
114
+ const meta = await readDaemonMeta();
115
+ return Boolean(meta && await canConnect(meta.socketPath));
116
+ }
117
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/daemon/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function runDaemonServer(): Promise<void>;
@@ -0,0 +1,149 @@
1
+ import net from 'node:net';
2
+ import { existsSync } from 'node:fs';
3
+ import { unlink } from 'node:fs/promises';
4
+ import { ensureStateRoot } from '../core/paths.js';
5
+ import { CliCopilotWorkerService } from './service.js';
6
+ function writeEnvelope(socket, envelope) {
7
+ socket.write(`${JSON.stringify(envelope)}\n`);
8
+ }
9
+ export async function runDaemonServer() {
10
+ const socketPath = process.env.CLI_COPILOT_WORKER_DAEMON_SOCKET ?? ensureStateRoot().socketPath;
11
+ const token = process.env.CLI_COPILOT_WORKER_DAEMON_TOKEN;
12
+ if (!token) {
13
+ throw new Error('Missing CLI_COPILOT_WORKER_DAEMON_TOKEN');
14
+ }
15
+ if (existsSync(socketPath)) {
16
+ await unlink(socketPath).catch(() => { });
17
+ }
18
+ const service = new CliCopilotWorkerService();
19
+ await service.initialize();
20
+ await service.writeDaemonMeta(socketPath, token);
21
+ const shutdown = async () => {
22
+ await service.shutdown().catch(() => { });
23
+ server.close();
24
+ process.exit(0);
25
+ };
26
+ const server = net.createServer((socket) => {
27
+ let buffer = '';
28
+ socket.on('data', (chunk) => {
29
+ buffer += chunk.toString('utf8');
30
+ let newlineIndex = buffer.indexOf('\n');
31
+ while (newlineIndex >= 0) {
32
+ const line = buffer.slice(0, newlineIndex).trim();
33
+ buffer = buffer.slice(newlineIndex + 1);
34
+ if (line) {
35
+ void handleRequest(line, socket, token, service, shutdown);
36
+ }
37
+ newlineIndex = buffer.indexOf('\n');
38
+ }
39
+ });
40
+ });
41
+ await new Promise((resolve, reject) => {
42
+ server.once('error', reject);
43
+ server.listen(socketPath, () => resolve());
44
+ });
45
+ process.on('SIGINT', () => void shutdown());
46
+ process.on('SIGTERM', () => void shutdown());
47
+ }
48
+ async function handleRequest(line, socket, token, service, shutdown) {
49
+ let envelope;
50
+ try {
51
+ envelope = JSON.parse(line);
52
+ }
53
+ catch {
54
+ writeEnvelope(socket, {
55
+ id: 'unknown',
56
+ type: 'error',
57
+ error: 'Invalid JSON request',
58
+ });
59
+ return;
60
+ }
61
+ if (envelope.token !== token) {
62
+ writeEnvelope(socket, {
63
+ id: envelope.id,
64
+ type: 'error',
65
+ error: 'Unauthorized',
66
+ });
67
+ return;
68
+ }
69
+ const writer = {
70
+ event(name, data) {
71
+ writeEnvelope(socket, {
72
+ id: envelope.id,
73
+ type: 'event',
74
+ event: name,
75
+ data,
76
+ });
77
+ },
78
+ };
79
+ try {
80
+ let result;
81
+ let shouldShutdown = false;
82
+ switch (envelope.command) {
83
+ case 'ping':
84
+ result = await service.ping();
85
+ break;
86
+ case 'run':
87
+ result = await service.run(envelope.args, writer);
88
+ break;
89
+ case 'send':
90
+ result = await service.send(envelope.args, writer);
91
+ break;
92
+ case 'answer':
93
+ result = await service.answer(envelope.args);
94
+ break;
95
+ case 'read':
96
+ result = await service.read(envelope.args);
97
+ break;
98
+ case 'list':
99
+ result = await service.list();
100
+ break;
101
+ case 'info':
102
+ result = await service.info(String((envelope.args ?? {}).conversationId));
103
+ break;
104
+ case 'job.list':
105
+ result = await service.jobList();
106
+ break;
107
+ case 'job.status':
108
+ result = await service.jobStatus(String((envelope.args ?? {}).jobId));
109
+ break;
110
+ case 'job.wait':
111
+ result = await service.jobWait(envelope.args);
112
+ break;
113
+ case 'job.read':
114
+ result = await service.jobRead(String((envelope.args ?? {}).jobId));
115
+ break;
116
+ case 'job.cancel':
117
+ result = await service.jobCancel(String((envelope.args ?? {}).jobId));
118
+ break;
119
+ case 'daemon.status':
120
+ result = await service.daemonStatus();
121
+ break;
122
+ case 'daemon.stop':
123
+ result = await service.shutdown();
124
+ shouldShutdown = true;
125
+ break;
126
+ default:
127
+ throw new Error(`Unknown command: ${envelope.command}`);
128
+ }
129
+ writeEnvelope(socket, {
130
+ id: envelope.id,
131
+ type: 'result',
132
+ data: result,
133
+ });
134
+ if (shouldShutdown) {
135
+ socket.end();
136
+ setTimeout(() => {
137
+ void shutdown();
138
+ }, 10).unref();
139
+ }
140
+ }
141
+ catch (error) {
142
+ writeEnvelope(socket, {
143
+ id: envelope.id,
144
+ type: 'error',
145
+ error: error instanceof Error ? error.message : String(error),
146
+ });
147
+ }
148
+ }
149
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/daemon/server.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,SAAS,aAAa,CAAC,MAAkB,EAAE,QAAgC;IACzE,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,gCAAgC,IAAI,eAAe,EAAE,CAAC,UAAU,CAAC;IAChG,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC;IAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,uBAAuB,EAAE,CAAC;IAC9C,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;IAC3B,MAAM,OAAO,CAAC,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAEjD,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QAC1B,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,EAAE;QACzC,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjC,IAAI,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACxC,OAAO,YAAY,IAAI,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;gBAClD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;gBACxC,IAAI,IAAI,EAAE,CAAC;oBACT,KAAK,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;gBAC7D,CAAC;gBACD,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACtC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,IAAY,EACZ,MAAkB,EAClB,KAAa,EACb,OAAgC,EAChC,QAA6B;IAE7B,IAAI,QAA+B,CAAC;IACpC,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA0B,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,aAAa,CAAC,MAAM,EAAE;YACpB,EAAE,EAAE,SAAS;YACb,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,sBAAsB;SAC9B,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QAC7B,aAAa,CAAC,MAAM,EAAE;YACpB,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,cAAc;SACtB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG;QACb,KAAK,CAAC,IAAY,EAAE,IAA6B;YAC/C,aAAa,CAAC,MAAM,EAAE;gBACpB,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,IAAI;gBACX,IAAI;aACL,CAAC,CAAC;QACL,CAAC;KACF,CAAC;IAEF,IAAI,CAAC;QACH,IAAI,MAA+B,CAAC;QACpC,IAAI,cAAc,GAAG,KAAK,CAAC;QAC3B,QAAQ,QAAQ,CAAC,OAAO,EAAE,CAAC;YACzB,KAAK,MAAM;gBACT,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC9B,MAAM;YACR,KAAK,KAAK;gBACR,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAa,EAAE,MAAM,CAAC,CAAC;gBAC3D,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAa,EAAE,MAAM,CAAC,CAAC;gBAC5D,MAAM;YACR,KAAK,QAAQ;gBACX,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAa,CAAC,CAAC;gBACtD,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAa,CAAC,CAAC;gBACpD,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC9B,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;gBAC1E,MAAM;YACR,KAAK,UAAU;gBACb,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;gBACjC,MAAM;YACR,KAAK,YAAY;gBACf,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtE,MAAM;YACR,KAAK,UAAU;gBACb,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAa,CAAC,CAAC;gBACvD,MAAM;YACR,KAAK,UAAU;gBACb,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACpE,MAAM;YACR,KAAK,YAAY;gBACf,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtE,MAAM;YACR,KAAK,eAAe;gBAClB,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;gBACtC,MAAM;YACR,KAAK,aAAa;gBAChB,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;gBAClC,cAAc,GAAG,IAAI,CAAC;gBACtB,MAAM;YACR;gBACE,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,aAAa,CAAC,MAAM,EAAE;YACpB,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QACH,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,EAAE,CAAC;YACb,UAAU,CAAC,GAAG,EAAE;gBACd,KAAK,QAAQ,EAAE,CAAC;YAClB,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,aAAa,CAAC,MAAM,EAAE;YACpB,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { type CopilotClient, type CopilotSession } from '@github/copilot-sdk';
2
+ import { buildAuthenticatedClient } from '../core/copilot.js';
3
+ import { ProfileFaultPlanner } from '../core/profile-faults.js';
4
+ import { ProfileManager } from '../core/profile-manager.js';
5
+ import { QuestionRegistry } from '../core/question-registry.js';
6
+ import { PersistentStore } from '../core/store.js';
7
+ import type { AnswerRequest, CopilotProfile, ConversationRecord, JobAttemptRecord, JobRecord, ReadRequest, RunRequest, SendRequest } from '../core/types.js';
8
+ type EventWriter = {
9
+ event: (name: string, data: Record<string, unknown>) => void;
10
+ };
11
+ interface ActiveExecution {
12
+ conversationId: string;
13
+ jobId: string;
14
+ attempt: JobAttemptRecord;
15
+ profile: CopilotProfile;
16
+ session: CopilotSession;
17
+ client: CopilotClient;
18
+ writer?: EventWriter | undefined;
19
+ resolveDone: (value: {
20
+ status: 'completed' | 'waiting_answer';
21
+ job: JobRecord;
22
+ conversation: ConversationRecord;
23
+ }) => void;
24
+ rejectDone: (error: Error) => void;
25
+ signalWaitingAnswer?: (() => void) | undefined;
26
+ }
27
+ export declare class CliCopilotWorkerService {
28
+ readonly store: PersistentStore;
29
+ readonly activeExecutions: Map<string, ActiveExecution>;
30
+ readonly clients: Map<string, CopilotClient>;
31
+ profileManager: ProfileManager;
32
+ faultPlanner: ProfileFaultPlanner;
33
+ createAuthenticatedClient: typeof buildAuthenticatedClient;
34
+ readonly questionRegistry: QuestionRegistry;
35
+ initialize(): Promise<void>;
36
+ ping(): Promise<Record<string, unknown>>;
37
+ daemonStatus(): Promise<Record<string, unknown>>;
38
+ shutdown(): Promise<Record<string, unknown>>;
39
+ run(args: RunRequest, writer?: EventWriter): Promise<Record<string, unknown>>;
40
+ send(args: SendRequest, writer?: EventWriter): Promise<Record<string, unknown>>;
41
+ answer(args: AnswerRequest): Promise<Record<string, unknown>>;
42
+ read(args: ReadRequest): Promise<Record<string, unknown>>;
43
+ list(): Promise<Record<string, unknown>>;
44
+ info(conversationId: string): Promise<Record<string, unknown>>;
45
+ jobList(): Promise<Record<string, unknown>>;
46
+ jobStatus(jobId: string): Promise<Record<string, unknown>>;
47
+ jobRead(jobId: string): Promise<Record<string, unknown>>;
48
+ jobWait(args: {
49
+ jobId: string;
50
+ timeoutSeconds?: number | undefined;
51
+ intervalSeconds?: number | undefined;
52
+ }): Promise<Record<string, unknown>>;
53
+ jobCancel(jobId: string): Promise<Record<string, unknown>>;
54
+ private executeJob;
55
+ private startExecution;
56
+ private executeInBackground;
57
+ private startProfileAttempt;
58
+ private planProfiles;
59
+ private getOrCreateClient;
60
+ private disposeClient;
61
+ private recordAttemptFailure;
62
+ private finalizeJobFailure;
63
+ private buildConversationActions;
64
+ private buildJobActions;
65
+ writeDaemonMeta(socketPath: string, token: string): Promise<void>;
66
+ private persistState;
67
+ private resolveProfile;
68
+ }
69
+ export {};