@quantiya/codevibe-codex-plugin 1.0.7 → 1.0.9
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.
- package/dist/server.js +22 -1051
- package/package.json +5 -7
- package/dist/approval-detector.js +0 -174
- package/dist/appsync-client.js +0 -937
- package/dist/auth-cli.js +0 -241
- package/dist/config.js +0 -116
- package/dist/crypto-service.js +0 -278
- package/dist/event-mapper.js +0 -302
- package/dist/key-manager.js +0 -287
- package/dist/logger.js +0 -18
- package/dist/prompt-parser.js +0 -8
- package/dist/prompt-responder.js +0 -78
- package/dist/session-id-cache.js +0 -90
- package/dist/session-log-watcher.js +0 -372
- package/dist/tmux-pane-observer.js +0 -255
- package/dist/token-storage.js +0 -169
- package/dist/types.js +0 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quantiya/codevibe-codex-plugin",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Control OpenAI Codex CLI from your iPhone and Android — real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",
|
|
5
5
|
"main": "dist/server.js",
|
|
6
6
|
"bin": {
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
".env.example"
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
|
-
"
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"build": "rm -rf dist && npm run typecheck && esbuild src/server.ts --bundle --platform=node --target=node18 --minify --packages=external --outfile=dist/server.js",
|
|
18
19
|
"prepack": "node scripts/prepare-publish.js && npm run build",
|
|
19
20
|
"postpack": "node scripts/restore-dev.js",
|
|
20
21
|
"dev": "ts-node src/server.ts",
|
|
21
22
|
"start": "node dist/server.js",
|
|
22
|
-
"watch": "tsc --watch",
|
|
23
23
|
"test": "jest --config jest.config.js"
|
|
24
24
|
},
|
|
25
25
|
"keywords": [
|
|
@@ -46,11 +46,8 @@
|
|
|
46
46
|
"engines": {
|
|
47
47
|
"node": ">=18.0.0"
|
|
48
48
|
},
|
|
49
|
-
"os": [
|
|
50
|
-
"darwin"
|
|
51
|
-
],
|
|
52
49
|
"dependencies": {
|
|
53
|
-
"@quantiya/codevibe-core": "^1.0.
|
|
50
|
+
"@quantiya/codevibe-core": "^1.0.7",
|
|
54
51
|
"chokidar": "^4.0.0",
|
|
55
52
|
"dotenv": "^16.6.1",
|
|
56
53
|
"express": "^5.1.0",
|
|
@@ -64,6 +61,7 @@
|
|
|
64
61
|
"@types/node": "^24.10.1",
|
|
65
62
|
"@types/uuid": "^10.0.0",
|
|
66
63
|
"@types/ws": "^8.18.1",
|
|
64
|
+
"esbuild": "^0.28.0",
|
|
67
65
|
"jest": "^30.3.0",
|
|
68
66
|
"ts-jest": "^29.4.9",
|
|
69
67
|
"ts-node": "^10.9.2",
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ApprovalDetector = void 0;
|
|
4
|
-
const events_1 = require("events");
|
|
5
|
-
const codevibe_core_1 = require("@quantiya/codevibe-core");
|
|
6
|
-
const logger_1 = require("./logger");
|
|
7
|
-
/**
|
|
8
|
-
* Detects when Codex might be waiting for approval using timeout heuristic.
|
|
9
|
-
* Emits an event with contextual metadata (file path, diff, parsed input) so the
|
|
10
|
-
* mobile client can show an interactive prompt with details.
|
|
11
|
-
*/
|
|
12
|
-
class ApprovalDetector extends events_1.EventEmitter {
|
|
13
|
-
constructor() {
|
|
14
|
-
super();
|
|
15
|
-
this.pendingCalls = new Map();
|
|
16
|
-
this.timers = new Map();
|
|
17
|
-
this.timeoutMs = (0, codevibe_core_1.getConfig)().codex.approvalTimeoutMs;
|
|
18
|
-
logger_1.logger.info('Approval detector initialized', { timeoutMs: this.timeoutMs });
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Called when a tool call starts.
|
|
22
|
-
*/
|
|
23
|
-
onToolCallStart(callId, name, input) {
|
|
24
|
-
logger_1.logger.debug('Tool call started', { callId, name });
|
|
25
|
-
// Parse input for extra context (file path, diff, parsed JSON)
|
|
26
|
-
const parsedInput = this.parseInput(input);
|
|
27
|
-
const filePath = this.extractFilePath(name, input, parsedInput);
|
|
28
|
-
const diff = this.extractDiff(name, input, parsedInput);
|
|
29
|
-
const pending = {
|
|
30
|
-
callId,
|
|
31
|
-
name,
|
|
32
|
-
input,
|
|
33
|
-
filePath,
|
|
34
|
-
diff,
|
|
35
|
-
parsedInput,
|
|
36
|
-
timestamp: Date.now(),
|
|
37
|
-
notificationSent: false,
|
|
38
|
-
};
|
|
39
|
-
this.pendingCalls.set(callId, pending);
|
|
40
|
-
const timer = setTimeout(() => {
|
|
41
|
-
this.checkPendingCall(callId);
|
|
42
|
-
}, this.timeoutMs);
|
|
43
|
-
this.timers.set(callId, timer);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Called when a tool call completes (output received).
|
|
47
|
-
*/
|
|
48
|
-
onToolCallComplete(callId) {
|
|
49
|
-
logger_1.logger.debug('Tool call completed', { callId });
|
|
50
|
-
this.pendingCalls.delete(callId);
|
|
51
|
-
const timer = this.timers.get(callId);
|
|
52
|
-
if (timer) {
|
|
53
|
-
clearTimeout(timer);
|
|
54
|
-
this.timers.delete(callId);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Check if a call is still pending after timeout.
|
|
59
|
-
*/
|
|
60
|
-
checkPendingCall(callId) {
|
|
61
|
-
const pending = this.pendingCalls.get(callId);
|
|
62
|
-
if (!pending)
|
|
63
|
-
return;
|
|
64
|
-
if (pending.notificationSent)
|
|
65
|
-
return;
|
|
66
|
-
const elapsed = Date.now() - pending.timestamp;
|
|
67
|
-
logger_1.logger.info('Tool call still pending after timeout', {
|
|
68
|
-
callId,
|
|
69
|
-
name: pending.name,
|
|
70
|
-
elapsedMs: elapsed,
|
|
71
|
-
});
|
|
72
|
-
pending.notificationSent = true;
|
|
73
|
-
this.pendingCalls.set(callId, pending);
|
|
74
|
-
this.emit('approval-pending', {
|
|
75
|
-
callId,
|
|
76
|
-
toolName: pending.name,
|
|
77
|
-
hint: this.extractHint(pending.name, pending.input, pending.filePath),
|
|
78
|
-
filePath: pending.filePath,
|
|
79
|
-
diff: pending.diff,
|
|
80
|
-
toolInput: pending.parsedInput,
|
|
81
|
-
rawInput: pending.input,
|
|
82
|
-
elapsedMs: elapsed,
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Extract a user-facing hint for the pending approval.
|
|
87
|
-
*/
|
|
88
|
-
extractHint(name, input, filePath) {
|
|
89
|
-
if (filePath) {
|
|
90
|
-
return `File: ${filePath}`;
|
|
91
|
-
}
|
|
92
|
-
if (name === 'apply_patch' && input) {
|
|
93
|
-
const match = input.match(/\*\*\* (?:Update|Add|Delete) File: (.+)/);
|
|
94
|
-
if (match) {
|
|
95
|
-
return `File: ${match[1].trim()}`;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (name === 'shell_command' || name === 'shell') {
|
|
99
|
-
try {
|
|
100
|
-
const args = JSON.parse(input);
|
|
101
|
-
if (args.command) {
|
|
102
|
-
const cmd = args.command.substring(0, 50);
|
|
103
|
-
return `Command: ${cmd}${args.command.length > 50 ? '...' : ''}`;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
// Ignore parse errors
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return `Tool: ${this.mapToolName(name)}`;
|
|
111
|
-
}
|
|
112
|
-
mapToolName(name) {
|
|
113
|
-
const mapping = {
|
|
114
|
-
shell_command: 'Bash',
|
|
115
|
-
shell: 'Bash',
|
|
116
|
-
apply_patch: 'File Edit',
|
|
117
|
-
write_file: 'Write File',
|
|
118
|
-
read_file: 'Read File',
|
|
119
|
-
};
|
|
120
|
-
return mapping[name] || name;
|
|
121
|
-
}
|
|
122
|
-
parseInput(input) {
|
|
123
|
-
if (!input)
|
|
124
|
-
return undefined;
|
|
125
|
-
try {
|
|
126
|
-
return JSON.parse(input);
|
|
127
|
-
}
|
|
128
|
-
catch {
|
|
129
|
-
return undefined;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
extractFilePath(name, rawInput, parsedInput) {
|
|
133
|
-
if (name === 'apply_patch' && rawInput) {
|
|
134
|
-
const match = rawInput.match(/\*\*\* (?:Update|Add|Delete) File: (.+)/);
|
|
135
|
-
if (match)
|
|
136
|
-
return match[1].trim();
|
|
137
|
-
}
|
|
138
|
-
const candidate = parsedInput?.file_path || parsedInput?.path || parsedInput?.filePath;
|
|
139
|
-
if (candidate && typeof candidate === 'string') {
|
|
140
|
-
return candidate;
|
|
141
|
-
}
|
|
142
|
-
return undefined;
|
|
143
|
-
}
|
|
144
|
-
extractDiff(name, rawInput, parsedInput) {
|
|
145
|
-
if (name === 'apply_patch' && rawInput) {
|
|
146
|
-
return rawInput;
|
|
147
|
-
}
|
|
148
|
-
if (parsedInput?.diff && typeof parsedInput.diff === 'string') {
|
|
149
|
-
return parsedInput.diff;
|
|
150
|
-
}
|
|
151
|
-
return undefined;
|
|
152
|
-
}
|
|
153
|
-
getPendingCalls() {
|
|
154
|
-
return Array.from(this.pendingCalls.values());
|
|
155
|
-
}
|
|
156
|
-
hasPendingCalls() {
|
|
157
|
-
return this.pendingCalls.size > 0;
|
|
158
|
-
}
|
|
159
|
-
clear() {
|
|
160
|
-
for (const timer of this.timers.values()) {
|
|
161
|
-
clearTimeout(timer);
|
|
162
|
-
}
|
|
163
|
-
this.timers.clear();
|
|
164
|
-
this.pendingCalls.clear();
|
|
165
|
-
logger_1.logger.debug('Approval detector cleared');
|
|
166
|
-
}
|
|
167
|
-
shutdown() {
|
|
168
|
-
this.clear();
|
|
169
|
-
this.removeAllListeners();
|
|
170
|
-
logger_1.logger.info('Approval detector shutdown');
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
exports.ApprovalDetector = ApprovalDetector;
|
|
174
|
-
//# sourceMappingURL=approval-detector.js.map
|