@diggerhq/anyware 0.6.6 → 0.7.1

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 (80) hide show
  1. package/dist/api/auth.d.ts +25 -0
  2. package/dist/api/auth.d.ts.map +1 -0
  3. package/dist/api/auth.js +62 -0
  4. package/dist/api/auth.js.map +1 -0
  5. package/dist/api/session.d.ts +14 -0
  6. package/dist/api/session.d.ts.map +1 -0
  7. package/dist/api/session.js +60 -0
  8. package/dist/api/session.js.map +1 -0
  9. package/dist/api/wsClient.d.ts +40 -0
  10. package/dist/api/wsClient.d.ts.map +1 -0
  11. package/dist/api/wsClient.js +111 -0
  12. package/dist/api/wsClient.js.map +1 -0
  13. package/dist/claude/claudeLocal.d.ts +17 -0
  14. package/dist/claude/claudeLocal.d.ts.map +1 -0
  15. package/dist/claude/claudeLocal.js +170 -0
  16. package/dist/claude/claudeLocal.js.map +1 -0
  17. package/dist/claude/claudeLocalLauncher.d.ts +8 -0
  18. package/dist/claude/claudeLocalLauncher.d.ts.map +1 -0
  19. package/dist/claude/claudeLocalLauncher.js +153 -0
  20. package/dist/claude/claudeLocalLauncher.js.map +1 -0
  21. package/dist/claude/claudeRemote.d.ts +22 -0
  22. package/dist/claude/claudeRemote.d.ts.map +1 -0
  23. package/dist/claude/claudeRemote.js +178 -0
  24. package/dist/claude/claudeRemote.js.map +1 -0
  25. package/dist/claude/claudeRemoteLauncher.d.ts +11 -0
  26. package/dist/claude/claudeRemoteLauncher.d.ts.map +1 -0
  27. package/dist/claude/claudeRemoteLauncher.js +103 -0
  28. package/dist/claude/claudeRemoteLauncher.js.map +1 -0
  29. package/dist/claude/loop.d.ts +21 -0
  30. package/dist/claude/loop.d.ts.map +1 -0
  31. package/dist/claude/loop.js +45 -0
  32. package/dist/claude/loop.js.map +1 -0
  33. package/dist/claude/sdk/query.d.ts +71 -0
  34. package/dist/claude/sdk/query.d.ts.map +1 -0
  35. package/dist/claude/sdk/query.js +353 -0
  36. package/dist/claude/sdk/query.js.map +1 -0
  37. package/dist/claude/sdk/stream.d.ts +28 -0
  38. package/dist/claude/sdk/stream.d.ts.map +1 -0
  39. package/dist/claude/sdk/stream.js +91 -0
  40. package/dist/claude/sdk/stream.js.map +1 -0
  41. package/dist/claude/sdk/types.d.ts +166 -0
  42. package/dist/claude/sdk/types.d.ts.map +1 -0
  43. package/dist/claude/sdk/types.js +13 -0
  44. package/dist/claude/sdk/types.js.map +1 -0
  45. package/dist/claude/session.d.ts +80 -0
  46. package/dist/claude/session.d.ts.map +1 -0
  47. package/dist/claude/session.js +172 -0
  48. package/dist/claude/session.js.map +1 -0
  49. package/dist/claude/sessionScanner.d.ts +100 -0
  50. package/dist/claude/sessionScanner.d.ts.map +1 -0
  51. package/dist/claude/sessionScanner.js +194 -0
  52. package/dist/claude/sessionScanner.js.map +1 -0
  53. package/dist/config/config.d.ts +12 -0
  54. package/dist/config/config.d.ts.map +1 -0
  55. package/dist/config/config.js +40 -0
  56. package/dist/config/config.js.map +1 -0
  57. package/dist/hooks/generateHookSettings.d.ts +20 -0
  58. package/dist/hooks/generateHookSettings.d.ts.map +1 -0
  59. package/dist/hooks/generateHookSettings.js +126 -0
  60. package/dist/hooks/generateHookSettings.js.map +1 -0
  61. package/dist/hooks/hookServer.d.ts +45 -0
  62. package/dist/hooks/hookServer.d.ts.map +1 -0
  63. package/dist/hooks/hookServer.js +83 -0
  64. package/dist/hooks/hookServer.js.map +1 -0
  65. package/dist/main.d.ts +6 -0
  66. package/dist/main.d.ts.map +1 -0
  67. package/dist/main.js +140 -0
  68. package/dist/main.js.map +1 -0
  69. package/dist/utils/messageQueue.d.ts +38 -0
  70. package/dist/utils/messageQueue.d.ts.map +1 -0
  71. package/dist/utils/messageQueue.js +85 -0
  72. package/dist/utils/messageQueue.js.map +1 -0
  73. package/package.json +27 -27
  74. package/scripts/session_hook_forwarder.cjs +51 -0
  75. package/README.md +0 -67
  76. package/bin/anyware +0 -29
  77. package/bin/anyware-darwin-amd64 +0 -0
  78. package/bin/anyware-darwin-arm64 +0 -0
  79. package/bin/anyware-linux-amd64 +0 -0
  80. package/bin/anyware-linux-arm64 +0 -0
@@ -0,0 +1,153 @@
1
+ import { claudeLocal } from './claudeLocal.js';
2
+ import { createSessionScanner } from './sessionScanner.js';
3
+ import { startHookServer } from '../hooks/hookServer.js';
4
+ import { generateHookSettingsFile, cleanupHookSettingsFile } from '../hooks/generateHookSettings.js';
5
+ /**
6
+ * Launch Claude in local mode with session scanning
7
+ * Returns 'switch' if we should switch to remote mode, 'exit' if we should exit
8
+ */
9
+ export async function claudeLocalLauncher(session) {
10
+ // Variable to hold scanner reference (needed in onHookEvent before scanner is created)
11
+ let scanner = null;
12
+ // Start hook server to receive session notifications from Claude
13
+ const hookServer = await startHookServer({
14
+ onSessionHook: (sessionId) => {
15
+ session.setClaudeSessionId(sessionId);
16
+ if (scanner) {
17
+ scanner.onNewSession(sessionId);
18
+ }
19
+ },
20
+ onHookEvent: (eventType, _sessionId, data) => {
21
+ // Forward hook events to the WebSocket as claude_event
22
+ // Transform hook data to the expected format
23
+ const claudeEvent = {
24
+ type: eventType,
25
+ hook_data: {
26
+ tool_name: data.tool_name,
27
+ tool_input: data.tool_input,
28
+ tool_response: data.tool_response,
29
+ prompt: data.prompt,
30
+ stop_reason: data.stop_reason,
31
+ response: data.response,
32
+ cwd: data.cwd,
33
+ },
34
+ session_id: data.session_id,
35
+ };
36
+ session.sendClaudeEvent(claudeEvent);
37
+ },
38
+ });
39
+ // Generate hook settings file for Claude
40
+ const hookSettingsPath = generateHookSettingsFile(hookServer.port);
41
+ // Create scanner to watch session file and forward messages to server
42
+ scanner = await createSessionScanner({
43
+ sessionId: session.claudeSessionId,
44
+ workingDirectory: session.path,
45
+ onMessage: (message) => {
46
+ // Skip summary messages - we generate our own
47
+ if (message.type !== 'summary') {
48
+ session.sendClaudeEvent(message);
49
+ }
50
+ },
51
+ });
52
+ // Register callback for when session ID is discovered (from other sources)
53
+ const scannerSessionCallback = (sessionId) => {
54
+ scanner.onNewSession(sessionId);
55
+ };
56
+ session.addSessionFoundCallback(scannerSessionCallback);
57
+ let exitReason = null;
58
+ const processAbortController = new AbortController();
59
+ // Use a deferred pattern for exit promise
60
+ let exitResolve = () => { };
61
+ const exitPromise = new Promise((resolve) => {
62
+ exitResolve = resolve;
63
+ });
64
+ try {
65
+ // Abort function
66
+ async function abort() {
67
+ if (!processAbortController.signal.aborted) {
68
+ processAbortController.abort();
69
+ }
70
+ await exitPromise;
71
+ }
72
+ // Handle abort request (switch to remote)
73
+ async function doAbort() {
74
+ if (!exitReason) {
75
+ exitReason = 'switch';
76
+ }
77
+ session.queue.reset();
78
+ await abort();
79
+ }
80
+ // Handle switch request
81
+ async function doSwitch() {
82
+ if (!exitReason) {
83
+ exitReason = 'switch';
84
+ }
85
+ await abort();
86
+ }
87
+ // Register handlers for incoming messages
88
+ session.onUserInput(() => {
89
+ // Any user input from web triggers switch to remote mode
90
+ doSwitch();
91
+ });
92
+ session.onSwitch(() => {
93
+ doSwitch();
94
+ });
95
+ // If there are already messages in the queue, switch to remote immediately
96
+ if (session.queue.size() > 0) {
97
+ return 'switch';
98
+ }
99
+ // Handle session start
100
+ const handleSessionStart = (sessionId) => {
101
+ session.setClaudeSessionId(sessionId);
102
+ scanner.onNewSession(sessionId);
103
+ };
104
+ // Run local mode loop
105
+ while (true) {
106
+ if (exitReason) {
107
+ return exitReason;
108
+ }
109
+ try {
110
+ await claudeLocal({
111
+ path: session.path,
112
+ sessionId: session.claudeSessionId,
113
+ onSessionFound: handleSessionStart,
114
+ onThinkingChange: (thinking) => session.sendThinking(thinking),
115
+ abort: processAbortController.signal,
116
+ claudeArgs: session.claudeArgs,
117
+ hookSettingsPath,
118
+ });
119
+ // Consume one-time flags after first spawn
120
+ session.consumeOneTimeFlags();
121
+ // Normal exit
122
+ if (!exitReason) {
123
+ exitReason = 'exit';
124
+ break;
125
+ }
126
+ }
127
+ catch {
128
+ if (!exitReason) {
129
+ // Retry on error
130
+ continue;
131
+ }
132
+ else {
133
+ break;
134
+ }
135
+ }
136
+ }
137
+ }
138
+ finally {
139
+ // Resolve exit promise
140
+ exitResolve();
141
+ // Cleanup handlers
142
+ session.onUserInput(null);
143
+ session.onSwitch(null);
144
+ session.removeSessionFoundCallback(scannerSessionCallback);
145
+ // Cleanup scanner
146
+ await scanner.cleanup();
147
+ // Cleanup hook server and settings file
148
+ hookServer.stop();
149
+ cleanupHookSettingsFile(hookSettingsPath);
150
+ }
151
+ return exitReason || 'exit';
152
+ }
153
+ //# sourceMappingURL=claudeLocalLauncher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeLocalLauncher.js","sourceRoot":"","sources":["../../src/claude/claudeLocalLauncher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Remote mode - runs Claude via SDK with streaming responses
3
+ * Messages come from the web via WebSocket
4
+ */
5
+ import type { SDKMessage } from './sdk/types.js';
6
+ export interface ClaudeRemoteOptions {
7
+ abort: AbortSignal;
8
+ sessionId: string | null;
9
+ path: string;
10
+ onMessage: (message: SDKMessage) => void;
11
+ onSessionFound: (id: string) => void;
12
+ onThinkingChange?: (thinking: boolean) => void;
13
+ nextMessage: () => Promise<{
14
+ message: string;
15
+ } | null>;
16
+ claudeArgs?: string[];
17
+ }
18
+ /**
19
+ * Run Claude in remote mode using the SDK
20
+ */
21
+ export declare function claudeRemote(opts: ClaudeRemoteOptions): Promise<string | null>;
22
+ //# sourceMappingURL=claudeRemote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeRemote.d.ts","sourceRoot":"","sources":["../../src/claude/claudeRemote.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAkC,MAAM,gBAAgB,CAAC;AA0DjF,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,WAAW,EAAE,MAAM,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACvD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAqBD;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqHpF"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Remote mode - runs Claude via SDK with streaming responses
3
+ * Messages come from the web via WebSocket
4
+ */
5
+ import { query } from './sdk/query.js';
6
+ import { join, resolve } from 'node:path';
7
+ import { homedir } from 'node:os';
8
+ import { existsSync } from 'node:fs';
9
+ /**
10
+ * Pushable async iterable for messages
11
+ */
12
+ class PushableAsyncIterable {
13
+ queue = [];
14
+ waitResolve = null;
15
+ ended = false;
16
+ push(value) {
17
+ if (this.ended)
18
+ return;
19
+ if (this.waitResolve) {
20
+ const resolve = this.waitResolve;
21
+ this.waitResolve = null;
22
+ resolve({ done: false, value });
23
+ }
24
+ else {
25
+ this.queue.push(value);
26
+ }
27
+ }
28
+ end() {
29
+ this.ended = true;
30
+ if (this.waitResolve) {
31
+ const resolve = this.waitResolve;
32
+ this.waitResolve = null;
33
+ resolve({ done: true, value: undefined });
34
+ }
35
+ }
36
+ async *[Symbol.asyncIterator]() {
37
+ while (true) {
38
+ if (this.queue.length > 0) {
39
+ yield this.queue.shift();
40
+ continue;
41
+ }
42
+ if (this.ended) {
43
+ return;
44
+ }
45
+ const result = await new Promise((resolve) => {
46
+ this.waitResolve = resolve;
47
+ });
48
+ if (result.done) {
49
+ return;
50
+ }
51
+ yield result.value;
52
+ }
53
+ }
54
+ }
55
+ /**
56
+ * Get project path for Claude sessions
57
+ * Claude uses the resolved path with special chars replaced by dashes
58
+ */
59
+ function getProjectPath(workingDirectory) {
60
+ const projectId = resolve(workingDirectory).replace(/[\\\/.:]/g, '-');
61
+ const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude');
62
+ return join(claudeConfigDir, 'projects', projectId);
63
+ }
64
+ /**
65
+ * Check if Claude session exists
66
+ */
67
+ function claudeCheckSession(sessionId, workingDirectory) {
68
+ const projectDir = getProjectPath(workingDirectory);
69
+ const sessionFile = join(projectDir, `${sessionId}.jsonl`);
70
+ return existsSync(sessionFile);
71
+ }
72
+ /**
73
+ * Run Claude in remote mode using the SDK
74
+ */
75
+ export async function claudeRemote(opts) {
76
+ // Determine session to resume
77
+ let startFrom = opts.sessionId;
78
+ // Extract --resume from claudeArgs if present
79
+ if (!startFrom && opts.claudeArgs) {
80
+ for (let i = 0; i < opts.claudeArgs.length; i++) {
81
+ if (opts.claudeArgs[i] === '--resume') {
82
+ if (i + 1 < opts.claudeArgs.length) {
83
+ const nextArg = opts.claudeArgs[i + 1];
84
+ if (!nextArg.startsWith('-') && nextArg.includes('-')) {
85
+ startFrom = nextArg;
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ // Validate session exists
92
+ if (startFrom && !claudeCheckSession(startFrom, opts.path)) {
93
+ console.log(`Session ${startFrom} not found, starting fresh`);
94
+ startFrom = null;
95
+ }
96
+ if (startFrom) {
97
+ console.log(`Resuming session: ${startFrom}`);
98
+ }
99
+ // Create pushable stream for messages
100
+ const messages = new PushableAsyncIterable();
101
+ // Wait for first message
102
+ const firstMessage = await opts.nextMessage();
103
+ if (!firstMessage) {
104
+ return startFrom;
105
+ }
106
+ // Push first message
107
+ messages.push({
108
+ type: 'user',
109
+ message: { role: 'user', content: firstMessage.message },
110
+ });
111
+ // Thinking state
112
+ let thinking = false;
113
+ const updateThinking = (newThinking) => {
114
+ if (thinking !== newThinking) {
115
+ thinking = newThinking;
116
+ if (opts.onThinkingChange) {
117
+ opts.onThinkingChange(thinking);
118
+ }
119
+ }
120
+ };
121
+ // Build SDK options
122
+ const sdkOptions = {
123
+ cwd: opts.path,
124
+ resume: startFrom ?? undefined,
125
+ abort: opts.abort,
126
+ permissionMode: 'default',
127
+ // Permission callback - allow all tools in remote mode for now
128
+ canCallTool: async (_toolName, input) => {
129
+ return {
130
+ behavior: 'allow',
131
+ updatedInput: input,
132
+ };
133
+ },
134
+ };
135
+ // Start query
136
+ const response = query({
137
+ prompt: messages,
138
+ options: sdkOptions,
139
+ });
140
+ updateThinking(true);
141
+ try {
142
+ for await (const message of response) {
143
+ // Forward message to callback
144
+ opts.onMessage(message);
145
+ if (message.type === 'system' && 'subtype' in message && message.subtype === 'init') {
146
+ updateThinking(true);
147
+ // Extract session ID
148
+ if ('session_id' in message && typeof message.session_id === 'string') {
149
+ opts.onSessionFound(message.session_id);
150
+ }
151
+ }
152
+ if (message.type === 'result') {
153
+ updateThinking(false);
154
+ // Get next message
155
+ const next = await opts.nextMessage();
156
+ if (!next) {
157
+ messages.end();
158
+ return startFrom;
159
+ }
160
+ // Push next message
161
+ messages.push({
162
+ type: 'user',
163
+ message: { role: 'user', content: next.message },
164
+ });
165
+ }
166
+ }
167
+ }
168
+ catch (e) {
169
+ if (!opts.abort.aborted) {
170
+ console.error('[remote] Error:', e);
171
+ }
172
+ }
173
+ finally {
174
+ updateThinking(false);
175
+ }
176
+ return startFrom;
177
+ }
178
+ //# sourceMappingURL=claudeRemote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeRemote.js","sourceRoot":"","sources":["../../src/claude/claudeRemote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Remote launcher - handles remote mode execution with session management
3
+ */
4
+ import type { Session } from './session.js';
5
+ export type RemoteExitReason = 'switch' | 'exit';
6
+ /**
7
+ * Launch Claude in remote mode
8
+ * Returns 'switch' if we should switch to local mode, 'exit' if we should exit
9
+ */
10
+ export declare function claudeRemoteLauncher(session: Session): Promise<RemoteExitReason>;
11
+ //# sourceMappingURL=claudeRemoteLauncher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeRemoteLauncher.d.ts","sourceRoot":"","sources":["../../src/claude/claudeRemoteLauncher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEjD;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuGtF"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Remote launcher - handles remote mode execution with session management
3
+ */
4
+ import { claudeRemote } from './claudeRemote.js';
5
+ import * as readline from 'node:readline';
6
+ /**
7
+ * Launch Claude in remote mode
8
+ * Returns 'switch' if we should switch to local mode, 'exit' if we should exit
9
+ */
10
+ export async function claudeRemoteLauncher(session) {
11
+ let exitReason = null;
12
+ const processAbortController = new AbortController();
13
+ // Setup keyboard listener for switching back to local mode
14
+ const rl = readline.createInterface({
15
+ input: process.stdin,
16
+ output: process.stdout,
17
+ });
18
+ // Listen for any keypress to switch back to local
19
+ readline.emitKeypressEvents(process.stdin);
20
+ if (process.stdin.isTTY) {
21
+ process.stdin.setRawMode(true);
22
+ }
23
+ const keypressHandler = (str, key) => {
24
+ // Switch to local on Enter, Escape, or 'q'
25
+ if (key.name === 'return' || key.name === 'escape' || str === 'q') {
26
+ if (!exitReason) {
27
+ exitReason = 'switch';
28
+ }
29
+ session.queue.reset(); // Unblock waitForMessage
30
+ processAbortController.abort();
31
+ }
32
+ // Ctrl+C to exit completely
33
+ if (key.ctrl && key.name === 'c') {
34
+ if (!exitReason) {
35
+ exitReason = 'exit';
36
+ }
37
+ session.queue.reset(); // Unblock waitForMessage
38
+ processAbortController.abort();
39
+ }
40
+ };
41
+ process.stdin.on('keypress', keypressHandler);
42
+ try {
43
+ // Handle switch request from web (user wants to go back to local mode)
44
+ session.onSwitch(() => {
45
+ if (!exitReason) {
46
+ exitReason = 'switch';
47
+ }
48
+ session.queue.reset(); // Unblock waitForMessage
49
+ processAbortController.abort();
50
+ });
51
+ // Run remote mode
52
+ console.log('Remote mode active. Press Enter/Escape/q to switch to local, Ctrl+C to exit.');
53
+ await claudeRemote({
54
+ path: session.path,
55
+ sessionId: session.claudeSessionId,
56
+ abort: processAbortController.signal,
57
+ claudeArgs: session.claudeArgs,
58
+ onMessage: (message) => {
59
+ // Forward SDK messages to server
60
+ session.sendClaudeEvent(message);
61
+ },
62
+ onSessionFound: (sessionId) => {
63
+ session.setClaudeSessionId(sessionId);
64
+ },
65
+ onThinkingChange: (thinking) => {
66
+ session.sendThinking(thinking);
67
+ },
68
+ nextMessage: async () => {
69
+ // Wait for next message from queue
70
+ const message = await session.queue.waitForMessage();
71
+ if (!message) {
72
+ // Queue was reset or closed
73
+ return null;
74
+ }
75
+ return { message };
76
+ },
77
+ });
78
+ // Consume one-time flags after spawn
79
+ session.consumeOneTimeFlags();
80
+ // Normal exit if no exit reason set
81
+ if (!exitReason) {
82
+ exitReason = 'exit';
83
+ }
84
+ }
85
+ catch (e) {
86
+ console.error('[remote] Error:', e);
87
+ if (!exitReason) {
88
+ exitReason = 'exit';
89
+ }
90
+ }
91
+ finally {
92
+ // Cleanup keyboard listener
93
+ process.stdin.removeListener('keypress', keypressHandler);
94
+ if (process.stdin.isTTY) {
95
+ process.stdin.setRawMode(false);
96
+ }
97
+ rl.close();
98
+ // Cleanup handlers
99
+ session.onSwitch(null);
100
+ }
101
+ return exitReason;
102
+ }
103
+ //# sourceMappingURL=claudeRemoteLauncher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeRemoteLauncher.js","sourceRoot":"","sources":["../../src/claude/claudeRemoteLauncher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAI1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAgB;IACzD,IAAI,UAAU,GAA4B,IAAI,CAAC;IAC/C,MAAM,sBAAsB,GAAG,IAAI,eAAe,EAAE,CAAC;IAErD,2DAA2D;IAC3D,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;QAClC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,kDAAkD;IAClD,QAAQ,CAAC,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,eAAe,GAAG,CAAC,GAAW,EAAE,GAAiB,EAAE,EAAE;QACzD,2CAA2C;QAC3C,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAClE,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,UAAU,GAAG,QAAQ,CAAC;YACxB,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,yBAAyB;YAChD,sBAAsB,CAAC,KAAK,EAAE,CAAC;QACjC,CAAC;QACD,4BAA4B;QAC5B,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;YACjC,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,UAAU,GAAG,MAAM,CAAC;YACtB,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,yBAAyB;YAChD,sBAAsB,CAAC,KAAK,EAAE,CAAC;QACjC,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IAE9C,IAAI,CAAC;QACH,uEAAuE;QACvE,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE;YACpB,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,UAAU,GAAG,QAAQ,CAAC;YACxB,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,yBAAyB;YAChD,sBAAsB,CAAC,KAAK,EAAE,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,kBAAkB;QAClB,OAAO,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAC;QAE5F,MAAM,YAAY,CAAC;YACjB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,SAAS,EAAE,OAAO,CAAC,eAAe;YAClC,KAAK,EAAE,sBAAsB,CAAC,MAAM;YACpC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;gBACrB,iCAAiC;gBACjC,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;YACD,cAAc,EAAE,CAAC,SAAS,EAAE,EAAE;gBAC5B,OAAO,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;YACxC,CAAC;YACD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,EAAE;gBAC7B,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACjC,CAAC;YACD,WAAW,EAAE,KAAK,IAAI,EAAE;gBACtB,mCAAmC;gBACnC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;gBAErD,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,4BAA4B;oBAC5B,OAAO,IAAI,CAAC;gBACd,CAAC;gBAED,OAAO,EAAE,OAAO,EAAE,CAAC;YACrB,CAAC;SACF,CAAC,CAAC;QAEH,qCAAqC;QACrC,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAE9B,oCAAoC;QACpC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,UAAU,GAAG,MAAM,CAAC;QACtB,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,UAAU,GAAG,MAAM,CAAC;QACtB,CAAC;IACH,CAAC;YAAS,CAAC;QACT,4BAA4B;QAC5B,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QAC1D,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC;QACD,EAAE,CAAC,KAAK,EAAE,CAAC;QAEX,mBAAmB;QACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Mode switching loop - alternates between local and remote modes
3
+ */
4
+ import type { Session } from './session.js';
5
+ export interface LoopOptions {
6
+ session: Session;
7
+ startingMode?: 'local' | 'remote';
8
+ onModeChange?: (mode: 'local' | 'remote') => void;
9
+ }
10
+ /**
11
+ * Main loop that switches between local and remote modes
12
+ *
13
+ * - Local mode: User interacts directly with Claude via terminal
14
+ * - Remote mode: Messages come from web via WebSocket, processed via SDK
15
+ *
16
+ * Mode switches happen when:
17
+ * - Local → Remote: When a message arrives from web while in local mode
18
+ * - Remote → Local: When user requests switch (e.g., double-space in web UI)
19
+ */
20
+ export declare function loop(opts: LoopOptions): Promise<void>;
21
+ //# sourceMappingURL=loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/claude/loop.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,KAAK,IAAI,CAAC;CACnD;AAED;;;;;;;;;GASG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC3D"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Mode switching loop - alternates between local and remote modes
3
+ */
4
+ import { claudeLocalLauncher } from './claudeLocalLauncher.js';
5
+ import { claudeRemoteLauncher } from './claudeRemoteLauncher.js';
6
+ /**
7
+ * Main loop that switches between local and remote modes
8
+ *
9
+ * - Local mode: User interacts directly with Claude via terminal
10
+ * - Remote mode: Messages come from web via WebSocket, processed via SDK
11
+ *
12
+ * Mode switches happen when:
13
+ * - Local → Remote: When a message arrives from web while in local mode
14
+ * - Remote → Local: When user requests switch (e.g., double-space in web UI)
15
+ */
16
+ export async function loop(opts) {
17
+ let mode = opts.startingMode ?? 'local';
18
+ while (true) {
19
+ // Notify mode change
20
+ if (opts.onModeChange) {
21
+ opts.onModeChange(mode);
22
+ }
23
+ // Send mode change to server
24
+ opts.session.sendModeChange(mode);
25
+ if (mode === 'local') {
26
+ const reason = await claudeLocalLauncher(opts.session);
27
+ if (reason === 'exit') {
28
+ return;
29
+ }
30
+ // Switch to remote mode
31
+ mode = 'remote';
32
+ continue;
33
+ }
34
+ if (mode === 'remote') {
35
+ const reason = await claudeRemoteLauncher(opts.session);
36
+ if (reason === 'exit') {
37
+ return;
38
+ }
39
+ // Switch to local mode
40
+ mode = 'local';
41
+ continue;
42
+ }
43
+ }
44
+ }
45
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/claude/loop.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AASjE;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAiB;IAC1C,IAAI,IAAI,GAAuB,IAAI,CAAC,YAAY,IAAI,OAAO,CAAC;IAE5D,OAAO,IAAI,EAAE,CAAC;QACZ,qBAAqB;QACrB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAElC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAEvD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,OAAO;YACT,CAAC;YAED,wBAAwB;YACxB,IAAI,GAAG,QAAQ,CAAC;YAChB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAExD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,OAAO;YACT,CAAC;YAED,uBAAuB;YACvB,IAAI,GAAG,OAAO,CAAC;YACf,SAAS;QACX,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Query implementation for Claude Code SDK
3
+ * Handles spawning Claude process and managing message streams
4
+ */
5
+ import type { Writable } from 'node:stream';
6
+ import { type QueryOptions, type QueryPrompt, type SDKMessage, type CanCallToolCallback } from './types.js';
7
+ /**
8
+ * Query class manages Claude Code process interaction
9
+ */
10
+ export declare class Query implements AsyncIterableIterator<SDKMessage> {
11
+ private childStdin;
12
+ private childStdout;
13
+ private processExitPromise;
14
+ private pendingControlResponses;
15
+ private cancelControllers;
16
+ private sdkMessages;
17
+ private inputStream;
18
+ private canCallTool?;
19
+ constructor(childStdin: Writable | null, childStdout: NodeJS.ReadableStream, processExitPromise: Promise<void>, canCallTool?: CanCallToolCallback);
20
+ /**
21
+ * Set an error on the stream
22
+ */
23
+ setError(error: Error): void;
24
+ /**
25
+ * AsyncIterableIterator implementation
26
+ */
27
+ next(): Promise<IteratorResult<SDKMessage>>;
28
+ return(value?: unknown): Promise<IteratorResult<SDKMessage>>;
29
+ throw(e: Error): Promise<IteratorResult<SDKMessage>>;
30
+ [Symbol.asyncIterator](): AsyncIterableIterator<SDKMessage>;
31
+ /**
32
+ * Read messages from Claude process stdout
33
+ */
34
+ private readMessages;
35
+ /**
36
+ * Async generator for SDK messages
37
+ */
38
+ private readSdkMessages;
39
+ /**
40
+ * Send interrupt request to Claude
41
+ */
42
+ interrupt(): Promise<void>;
43
+ /**
44
+ * Send control request to Claude process
45
+ */
46
+ private request;
47
+ /**
48
+ * Handle incoming control requests for tool permissions
49
+ */
50
+ private handleControlRequest;
51
+ /**
52
+ * Handle control cancel requests
53
+ */
54
+ private handleControlCancelRequest;
55
+ /**
56
+ * Process control requests based on subtype
57
+ */
58
+ private processControlRequest;
59
+ /**
60
+ * Cleanup method to abort all pending control requests
61
+ */
62
+ private cleanupControllers;
63
+ }
64
+ /**
65
+ * Main query function to interact with Claude Code
66
+ */
67
+ export declare function query(config: {
68
+ prompt: QueryPrompt;
69
+ options?: QueryOptions;
70
+ }): Query;
71
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/claude/sdk/query.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,UAAU,EAKf,KAAK,mBAAmB,EAMzB,MAAM,YAAY,CAAC;AA0CpB;;GAEG;AACH,qBAAa,KAAM,YAAW,qBAAqB,CAAC,UAAU,CAAC;IAQ3D,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,kBAAkB;IAT5B,OAAO,CAAC,uBAAuB,CAA6C;IAC5E,OAAO,CAAC,iBAAiB,CAAsC;IAC/D,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,WAAW,CAAC,CAAsB;gBAGhC,UAAU,EAAE,QAAQ,GAAG,IAAI,EAC3B,WAAW,EAAE,MAAM,CAAC,cAAc,EAClC,kBAAkB,EAAE,OAAO,CAAC,IAAI,CAAC,EACzC,WAAW,CAAC,EAAE,mBAAmB;IAOnC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAI5B;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAI3C,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAO5D,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAOpD,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,UAAU,CAAC;IAI3D;;OAEG;YACW,YAAY;IAwC1B;;OAEG;YACY,eAAe;IAM9B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAQhC;;OAEG;IACH,OAAO,CAAC,OAAO;IAqBf;;OAEG;YACW,oBAAoB;IAkClC;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAQlC;;OAEG;YACW,qBAAqB;IAcnC;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAM3B;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,OAAO,CAAC,EAAE,YAAY,CAAA;CAAE,GAAG,KAAK,CA4HpF"}