@thegitai/cli 1.0.0-preview.50 → 1.0.0-preview.51

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.
@@ -138,12 +138,25 @@ export async function browserTabs(context, args) {
138
138
  return bridgeFailure(error);
139
139
  }
140
140
  }
141
- export async function browserTabNew(context) {
141
+ export async function browserTabNew(context, args = {}) {
142
142
  const guard = await notConnected(context);
143
143
  if (guard.ok === false)
144
144
  return guard;
145
+ const url = String(args.url ?? '').trim();
145
146
  try {
146
- const result = await call(context, 'tab.create', {});
147
+ if (url) {
148
+ const denied = await ensureSiteAllowed(context, {
149
+ url,
150
+ tool: 'browser_tab_new',
151
+ summary: `Open ${url} in a new tab in TheGitAI's tab group.`,
152
+ });
153
+ if (denied)
154
+ return denied;
155
+ }
156
+ const created = await call(context, 'tab.create', {});
157
+ if (!url)
158
+ return attachEvents({ ok: true, ...created });
159
+ const result = await call(context, 'navigate', { tabId: Number(created.tabId), url }, NAVIGATE_TIMEOUT_MS);
147
160
  return attachEvents({ ok: true, ...result });
148
161
  }
149
162
  catch (error) {
@@ -174,14 +187,6 @@ export async function browserNavigate(context, args) {
174
187
  return missing('url', 'browser_navigate');
175
188
  let tabId = Number(args.tabId ?? args.tab_id);
176
189
  try {
177
- if (!Number.isInteger(tabId)) {
178
- const context_ = await call(context, 'context');
179
- tabId = Number(context_?.tabs?.find((tab) => tab.inSession && tab.available)?.tabId);
180
- if (!Number.isInteger(tabId)) {
181
- const created = await call(context, 'tab.create', {});
182
- tabId = Number(created.tabId);
183
- }
184
- }
185
190
  if (url !== 'back' && url !== 'forward') {
186
191
  const denied = await ensureSiteAllowed(context, {
187
192
  url,
@@ -191,6 +196,14 @@ export async function browserNavigate(context, args) {
191
196
  if (denied)
192
197
  return denied;
193
198
  }
199
+ if (!Number.isInteger(tabId)) {
200
+ const context_ = await call(context, 'context');
201
+ tabId = Number(context_?.tabs?.find((tab) => tab.inSession && tab.available)?.tabId);
202
+ if (!Number.isInteger(tabId)) {
203
+ const created = await call(context, 'tab.create', {});
204
+ tabId = Number(created.tabId);
205
+ }
206
+ }
194
207
  const result = await call(context, 'navigate', { tabId, url }, NAVIGATE_TIMEOUT_MS);
195
208
  return attachEvents({ ok: true, ...result });
196
209
  }
@@ -46,7 +46,7 @@ export const TOOL_MAP = {
46
46
  analyze_image: (context, args) => readImageFile(context, args),
47
47
  browser: (context) => browserGateway(context),
48
48
  browser_tabs: browserTabs,
49
- browser_tab_new: (context) => browserTabNew(context),
49
+ browser_tab_new: (context, args) => browserTabNew(context, args),
50
50
  browser_tab_close: browserTabClose,
51
51
  browser_navigate: browserNavigate,
52
52
  browser_read_page: browserReadPage,
@@ -7,6 +7,8 @@ import { isWithinSessionScratchDir } from '../scratch-dir.js';
7
7
  import { repairFilePath } from './path-suggest.js';
8
8
  import { dotenvFitsRedactionBudget, getCurrentFileHash, recordReadCoverage, redactContentWithStableTokens, redactDotenvWithStableTokens, } from '../session-safety.js';
9
9
  import { readFileRange, truncate } from '../utils.js';
10
+ import { IMAGE_MIME_BY_EXT } from '../core/image-limits.js';
11
+ import { readImageFile } from './read-image-file.js';
10
12
  const MAX_FILE_READ_CHARS = 12000;
11
13
  const DOCUMENT_EXTENSIONS = new Set(['.pdf', '.xlsx', '.docx']);
12
14
  export async function readFile(context, args) {
@@ -38,6 +40,9 @@ export async function readFile(context, args) {
38
40
  failureCategory: 'invalid_argument',
39
41
  };
40
42
  }
43
+ if (IMAGE_MIME_BY_EXT[documentExt] && typeof context !== 'string') {
44
+ return readImageFile(context, { path: filePath });
45
+ }
41
46
  let content;
42
47
  if (projectPath || scratchPath) {
43
48
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thegitai/cli",
3
- "version": "1.0.0-preview.50",
3
+ "version": "1.0.0-preview.51",
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",
@@ -45,11 +45,11 @@
45
45
  "@lydell/node-pty-linux-x64": "1.1.0",
46
46
  "@lydell/node-pty-win32-arm64": "1.1.0",
47
47
  "@lydell/node-pty-win32-x64": "1.1.0",
48
- "@thegitai/tui-darwin-arm64": "1.0.0-preview.50",
49
- "@thegitai/tui-darwin-x64": "1.0.0-preview.50",
50
- "@thegitai/tui-linux-arm64": "1.0.0-preview.50",
51
- "@thegitai/tui-linux-x64": "1.0.0-preview.50",
52
- "@thegitai/tui-win32-x64": "1.0.0-preview.50",
48
+ "@thegitai/tui-darwin-arm64": "1.0.0-preview.51",
49
+ "@thegitai/tui-darwin-x64": "1.0.0-preview.51",
50
+ "@thegitai/tui-linux-arm64": "1.0.0-preview.51",
51
+ "@thegitai/tui-linux-x64": "1.0.0-preview.51",
52
+ "@thegitai/tui-win32-x64": "1.0.0-preview.51",
53
53
  "@vscode/ripgrep": "1.18.0"
54
54
  },
55
55
  "repository": {