@thegitai/cli 1.0.0-preview.47 → 1.0.0-preview.48
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.
|
@@ -91,13 +91,12 @@ export function browserAvailability(options) {
|
|
|
91
91
|
selected: status.selected,
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
|
-
const hint =
|
|
95
|
-
|
|
96
|
-
: status.everConnected
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
: 'Chrome does not appear to be running. Open Chrome with the TheGitAI extension installed.';
|
|
94
|
+
const hint = connectionHint({
|
|
95
|
+
registrationError: status.registrationErrors[0] ?? null,
|
|
96
|
+
everConnected: status.everConnected,
|
|
97
|
+
chromeRunning: () => chromiumProcessRunning(),
|
|
98
|
+
extensionSeen: () => browserExtensionSeen(options.env),
|
|
99
|
+
});
|
|
101
100
|
return {
|
|
102
101
|
connected: false,
|
|
103
102
|
everConnected: status.everConnected,
|
|
@@ -106,6 +105,21 @@ export function browserAvailability(options) {
|
|
|
106
105
|
hint,
|
|
107
106
|
};
|
|
108
107
|
}
|
|
108
|
+
export function connectionHint(state) {
|
|
109
|
+
if (state.registrationError) {
|
|
110
|
+
return `TheGitAI could not register its browser bridge with Chrome: ${state.registrationError}`;
|
|
111
|
+
}
|
|
112
|
+
if (state.everConnected) {
|
|
113
|
+
return 'The browser was connected to this session but is disconnected now. Check Chrome and the connection status shown by the TheGitAI extension.';
|
|
114
|
+
}
|
|
115
|
+
if (!state.chromeRunning()) {
|
|
116
|
+
return 'Chrome does not appear to be running. Open Chrome with the TheGitAI extension enabled and check its connection status.';
|
|
117
|
+
}
|
|
118
|
+
if (state.extensionSeen()) {
|
|
119
|
+
return 'The TheGitAI extension has connected on this machine before, but has not connected to this session yet. Check the connection status shown by the extension.';
|
|
120
|
+
}
|
|
121
|
+
return 'Chrome is running, but no browser connection reached this session. Check that the TheGitAI extension is installed and enabled, and inspect its connection status.';
|
|
122
|
+
}
|
|
109
123
|
export function resyncBrowserBridge(options) {
|
|
110
124
|
try {
|
|
111
125
|
return ensureBrowserBridge(options).resync();
|
|
@@ -8,8 +8,7 @@ import { ensurePermission, originForUrl } from '../permissions.js';
|
|
|
8
8
|
const READ_TIMEOUT_MS = 20000;
|
|
9
9
|
const NAVIGATE_TIMEOUT_MS = 45000;
|
|
10
10
|
const MAX_UPLOAD_BYTES = 10 * 1024 * 1024;
|
|
11
|
-
const
|
|
12
|
-
const SCAN_GRACE_MS = 1200;
|
|
11
|
+
const DISCOVERY_TIMEOUT_MS = 2500;
|
|
13
12
|
export const READ_ONLY_BROWSER_TOOLS = new Set([
|
|
14
13
|
'browser',
|
|
15
14
|
'browser_tabs',
|
|
@@ -35,38 +34,31 @@ function missing(argument, tool) {
|
|
|
35
34
|
}
|
|
36
35
|
async function waitForBrowser(options, timeoutMs) {
|
|
37
36
|
const deadline = Date.now() + timeoutMs;
|
|
38
|
-
|
|
39
|
-
while (!
|
|
37
|
+
const bridge = ensureBrowserBridge(options);
|
|
38
|
+
while (!bridge.status().connected && Date.now() < deadline) {
|
|
40
39
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
41
|
-
availability = browserAvailability(options);
|
|
42
40
|
}
|
|
43
|
-
return
|
|
41
|
+
return browserAvailability(options);
|
|
44
42
|
}
|
|
45
43
|
async function notConnected(context) {
|
|
46
44
|
const options = { cwd: context.rootDir, env: context.env };
|
|
47
|
-
|
|
45
|
+
const status = ensureBrowserBridge(options).status();
|
|
46
|
+
if (status.connected)
|
|
47
|
+
return { ok: true };
|
|
48
|
+
if (status.everConnected)
|
|
49
|
+
resyncBrowserBridge(options);
|
|
50
|
+
const availability = await waitForBrowser(options, DISCOVERY_TIMEOUT_MS);
|
|
48
51
|
if (availability.connected)
|
|
49
52
|
return { ok: true };
|
|
50
|
-
if (availability.everConnected) {
|
|
51
|
-
const grace = resyncBrowserBridge(options) ? RECONNECT_GRACE_MS : SCAN_GRACE_MS;
|
|
52
|
-
availability = await waitForBrowser(options, grace);
|
|
53
|
-
if (availability.connected)
|
|
54
|
-
return { ok: true };
|
|
55
|
-
}
|
|
56
53
|
return {
|
|
57
54
|
ok: false,
|
|
55
|
+
connected: false,
|
|
56
|
+
browserErrorCode: 'not_connected',
|
|
58
57
|
error: `TheGitAI is not connected to a browser. ${availability.hint ?? ''}`.trim(),
|
|
59
58
|
failureCategory: 'external_service',
|
|
60
|
-
failureDetails: {
|
|
61
|
-
category: 'external_service',
|
|
62
|
-
tool: 'browser',
|
|
63
|
-
action: availability.everConnected
|
|
64
|
-
? 'The link to a browser that was working dropped and did not come back. Nothing is missing and nothing needs installing, so do not send the user to reinstall anything. Say what happened, and that reopening the TheGitAI icon in Chrome restores it. Do not retry in a loop.'
|
|
65
|
-
: 'Report the connection instructions. The extension is a separate installation. Do not retry in a loop or invent a download URL.',
|
|
66
|
-
},
|
|
67
59
|
};
|
|
68
60
|
}
|
|
69
|
-
function bridgeFailure(error
|
|
61
|
+
function bridgeFailure(error) {
|
|
70
62
|
const code = error instanceof BrowserBridgeError ? error.code : 'browser_error';
|
|
71
63
|
const message = String(error?.message ?? error);
|
|
72
64
|
return {
|
|
@@ -74,15 +66,6 @@ function bridgeFailure(error, tool) {
|
|
|
74
66
|
error: message,
|
|
75
67
|
failureCategory: code === 'not_connected' ? 'external_service' : 'tool_exception',
|
|
76
68
|
browserErrorCode: code,
|
|
77
|
-
failureDetails: {
|
|
78
|
-
category: code === 'not_connected' ? 'external_service' : 'tool_exception',
|
|
79
|
-
tool,
|
|
80
|
-
action: code === 'timeout' || code === 'disconnected'
|
|
81
|
-
? 'The outcome is unknown. Read the page before repeating anything that submits, sends, buys, or deletes.'
|
|
82
|
-
: code === 'stale_refs' || code === 'unknown_ref'
|
|
83
|
-
? 'Re-read the page and use the references from that read.'
|
|
84
|
-
: 'Report what failed. Do not retry the same call more than once.',
|
|
85
|
-
},
|
|
86
69
|
};
|
|
87
70
|
}
|
|
88
71
|
async function call(context, op, args = {}, timeoutMs = READ_TIMEOUT_MS) {
|
|
@@ -152,7 +135,7 @@ export async function browserTabs(context, args) {
|
|
|
152
135
|
return attachEvents({ ok: true, ...result });
|
|
153
136
|
}
|
|
154
137
|
catch (error) {
|
|
155
|
-
return bridgeFailure(error
|
|
138
|
+
return bridgeFailure(error);
|
|
156
139
|
}
|
|
157
140
|
}
|
|
158
141
|
export async function browserTabNew(context) {
|
|
@@ -164,7 +147,7 @@ export async function browserTabNew(context) {
|
|
|
164
147
|
return attachEvents({ ok: true, ...result });
|
|
165
148
|
}
|
|
166
149
|
catch (error) {
|
|
167
|
-
return bridgeFailure(error
|
|
150
|
+
return bridgeFailure(error);
|
|
168
151
|
}
|
|
169
152
|
}
|
|
170
153
|
export async function browserTabClose(context, args) {
|
|
@@ -179,7 +162,7 @@ export async function browserTabClose(context, args) {
|
|
|
179
162
|
return attachEvents({ ok: true, ...result });
|
|
180
163
|
}
|
|
181
164
|
catch (error) {
|
|
182
|
-
return bridgeFailure(error
|
|
165
|
+
return bridgeFailure(error);
|
|
183
166
|
}
|
|
184
167
|
}
|
|
185
168
|
export async function browserNavigate(context, args) {
|
|
@@ -212,7 +195,7 @@ export async function browserNavigate(context, args) {
|
|
|
212
195
|
return attachEvents({ ok: true, ...result });
|
|
213
196
|
}
|
|
214
197
|
catch (error) {
|
|
215
|
-
return bridgeFailure(error
|
|
198
|
+
return bridgeFailure(error);
|
|
216
199
|
}
|
|
217
200
|
}
|
|
218
201
|
async function gatedTabCall(context, { tool, op, args, summary, timeoutMs = READ_TIMEOUT_MS, }) {
|
|
@@ -249,7 +232,7 @@ async function gatedTabCall(context, { tool, op, args, summary, timeoutMs = READ
|
|
|
249
232
|
return attachEvents({ ok: true, tabId, url: tab.url, ...result });
|
|
250
233
|
}
|
|
251
234
|
catch (error) {
|
|
252
|
-
return bridgeFailure(error
|
|
235
|
+
return bridgeFailure(error);
|
|
253
236
|
}
|
|
254
237
|
}
|
|
255
238
|
export function browserReadPage(context, args) {
|
|
@@ -557,7 +540,7 @@ export async function browserFileUpload(context, args) {
|
|
|
557
540
|
return attachEvents({ ok: true, ...result, files: files.map((file) => file.name) });
|
|
558
541
|
}
|
|
559
542
|
catch (error) {
|
|
560
|
-
return bridgeFailure(error
|
|
543
|
+
return bridgeFailure(error);
|
|
561
544
|
}
|
|
562
545
|
}
|
|
563
546
|
function guessMimeType(file) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thegitai/cli",
|
|
3
|
-
"version": "1.0.0-preview.
|
|
3
|
+
"version": "1.0.0-preview.48",
|
|
4
4
|
"description": "TheGitAI is an agentic AI coding tool for your terminal. It reads and searches your repository, writes and edits files, runs your tests, and verifies the change before handing it back.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentic-ai",
|
|
@@ -44,11 +44,11 @@
|
|
|
44
44
|
"@lydell/node-pty-linux-x64": "1.1.0",
|
|
45
45
|
"@lydell/node-pty-win32-arm64": "1.1.0",
|
|
46
46
|
"@lydell/node-pty-win32-x64": "1.1.0",
|
|
47
|
-
"@thegitai/tui-darwin-arm64": "1.0.0-preview.
|
|
48
|
-
"@thegitai/tui-darwin-x64": "1.0.0-preview.
|
|
49
|
-
"@thegitai/tui-linux-arm64": "1.0.0-preview.
|
|
50
|
-
"@thegitai/tui-linux-x64": "1.0.0-preview.
|
|
51
|
-
"@thegitai/tui-win32-x64": "1.0.0-preview.
|
|
47
|
+
"@thegitai/tui-darwin-arm64": "1.0.0-preview.48",
|
|
48
|
+
"@thegitai/tui-darwin-x64": "1.0.0-preview.48",
|
|
49
|
+
"@thegitai/tui-linux-arm64": "1.0.0-preview.48",
|
|
50
|
+
"@thegitai/tui-linux-x64": "1.0.0-preview.48",
|
|
51
|
+
"@thegitai/tui-win32-x64": "1.0.0-preview.48",
|
|
52
52
|
"@vscode/ripgrep": "1.18.0"
|
|
53
53
|
},
|
|
54
54
|
"repository": {
|