paseo-acp-agy 1.1.2 → 1.1.3

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.
@@ -1,17 +1,33 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { EventEmitter } from "node:events";
3
3
  import fs from "node:fs";
4
+ import os from "node:os";
4
5
  import path from "node:path";
5
6
  import { logger } from "./logger.js";
6
7
  import { getEffectiveEffortForModel, } from "./protocol.js";
7
- import { buildAgyArgs } from "./permissions.js";
8
+ import { buildAgyArgs, resolvePermissionSettings } from "./permissions.js";
8
9
  function resolveDefaultAgyBinary() {
9
10
  if (process.env.AGY_BIN_PATH)
10
11
  return process.env.AGY_BIN_PATH;
11
- if (process.env.HOME) {
12
- const localPath = path.join(process.env.HOME, ".local", "bin", "agy");
13
- if (fs.existsSync(localPath))
14
- return localPath;
12
+ const home = os.homedir();
13
+ if (home) {
14
+ if (process.platform === "win32") {
15
+ const candidates = [
16
+ path.join(home, ".local", "bin", "agy.exe"),
17
+ path.join(home, "AppData", "Local", "Programs", "antigravity", "agy.exe"),
18
+ path.join(home, ".local", "bin", "agy.cmd"),
19
+ path.join(home, ".local", "bin", "agy.bat"),
20
+ ];
21
+ for (const cand of candidates) {
22
+ if (fs.existsSync(cand))
23
+ return cand;
24
+ }
25
+ }
26
+ else {
27
+ const localPath = path.join(home, ".local", "bin", "agy");
28
+ if (fs.existsSync(localPath))
29
+ return localPath;
30
+ }
15
31
  }
16
32
  return "agy";
17
33
  }
@@ -38,7 +54,7 @@ export class AntigravityProcess extends EventEmitter {
38
54
  this.effort = options.effort;
39
55
  this.mode = options.mode;
40
56
  this.conversationId = options.conversationId;
41
- this.permissions = options.permissions || { sandbox: false, dangerouslySkipPermissions: false };
57
+ this.permissions = options.permissions || resolvePermissionSettings();
42
58
  this.env = { ...process.env, ...options.env };
43
59
  // EventEmitter treats "error" specially. Keep a defensive listener for
44
60
  // callers/tests that emit it directly; child failures use process_error.
@@ -212,10 +228,15 @@ export class AntigravityProcess extends EventEmitter {
212
228
  extraArgs.push("--effort", effectiveEffort);
213
229
  if (this.conversationId)
214
230
  extraArgs.push("--conversation", this.conversationId);
231
+ const addDirs = [...(this.permissions.addDirs || [])];
232
+ if (this.cwd && !addDirs.includes(this.cwd)) {
233
+ addDirs.push(this.cwd);
234
+ }
215
235
  const args = buildAgyArgs({
216
236
  sandbox: this.permissions.sandbox,
217
237
  dangerouslySkipPermissions: this.permissions.dangerouslySkipPermissions,
218
238
  mode: this.mode,
239
+ addDirs,
219
240
  }, extraArgs);
220
241
  logger.info("Spawning agy process", {
221
242
  binary: this.binaryPath,
@@ -14,7 +14,9 @@ function getAttachmentsDir() {
14
14
  const attachmentsDir = path.join(getStateRoot(), "attachments");
15
15
  try {
16
16
  fs.mkdirSync(attachmentsDir, { recursive: true, mode: 0o700 });
17
- fs.chmodSync(attachmentsDir, 0o700);
17
+ if (process.platform !== "win32") {
18
+ fs.chmodSync(attachmentsDir, 0o700);
19
+ }
18
20
  }
19
21
  catch { }
20
22
  return attachmentsDir;
@@ -88,7 +90,9 @@ export function saveBase64Image(data, mimeType = "image/png") {
88
90
  if (!fs.existsSync(filePath)) {
89
91
  try {
90
92
  fs.writeFileSync(filePath, buffer, { mode: 0o600, flag: "wx" });
91
- fs.chmodSync(filePath, 0o600);
93
+ if (process.platform !== "win32") {
94
+ fs.chmodSync(filePath, 0o600);
95
+ }
92
96
  logger.info("Saved attached image for session", { filePath, sizeBytes: buffer.length });
93
97
  }
94
98
  catch (err) {
@@ -2,10 +2,12 @@ export interface PermissionSettings {
2
2
  sandbox: boolean;
3
3
  dangerouslySkipPermissions: boolean;
4
4
  mode?: string;
5
+ addDirs?: string[];
5
6
  }
6
7
  export declare function resolvePermissionSettings(options?: {
7
8
  sandbox?: boolean;
8
9
  dangerouslySkipPermissions?: boolean;
9
10
  mode?: string;
11
+ addDirs?: string[];
10
12
  }): PermissionSettings;
11
13
  export declare function buildAgyArgs(settings: PermissionSettings, extraArgs?: string[]): string[];
@@ -3,12 +3,17 @@ export function resolvePermissionSettings(options) {
3
3
  const envSandbox = process.env.AGY_ACP_SANDBOX;
4
4
  const envSkipPerms = process.env.AGY_ACP_DANGEROUSLY_SKIP_PERMISSIONS;
5
5
  const sandbox = options?.sandbox ?? (envSandbox === "true" || envSandbox === "1");
6
- // Never default to skip permissions; must be explicit
7
- const dangerouslySkipPermissions = options?.dangerouslySkipPermissions ?? (envSkipPerms === "true" || envSkipPerms === "1");
6
+ // In ACP mode, permissions and tool approvals are governed by the host application (e.g. Paseo).
7
+ // Because agy runs non-interactively over stream-json pipes without an interactive TTY, agy's
8
+ // internal terminal prompts cannot query the user and will fail with "user denied permission".
9
+ // Therefore, dangerouslySkipPermissions defaults to true unless explicitly disabled.
10
+ const dangerouslySkipPermissions = options?.dangerouslySkipPermissions ??
11
+ (envSkipPerms !== undefined ? envSkipPerms === "true" || envSkipPerms === "1" : true);
8
12
  return {
9
13
  sandbox,
10
14
  dangerouslySkipPermissions,
11
15
  mode: options?.mode,
16
+ addDirs: options?.addDirs,
12
17
  };
13
18
  }
14
19
  export function buildAgyArgs(settings, extraArgs) {
@@ -22,6 +27,13 @@ export function buildAgyArgs(settings, extraArgs) {
22
27
  if (settings.mode && settings.mode !== "default") {
23
28
  args.push("--mode", settings.mode);
24
29
  }
30
+ if (settings.addDirs && settings.addDirs.length > 0) {
31
+ for (const dir of settings.addDirs) {
32
+ if (dir) {
33
+ args.push("--add-dir", dir);
34
+ }
35
+ }
36
+ }
25
37
  if (extraArgs && extraArgs.length > 0) {
26
38
  args.push(...extraArgs);
27
39
  }
@@ -19,7 +19,9 @@ export class SessionStore {
19
19
  this.dir = dir || path.join(getStateRoot(), "sessions");
20
20
  try {
21
21
  fs.mkdirSync(this.dir, { recursive: true, mode: 0o700 });
22
- fs.chmodSync(this.dir, 0o700);
22
+ if (process.platform !== "win32") {
23
+ fs.chmodSync(this.dir, 0o700);
24
+ }
23
25
  }
24
26
  catch { }
25
27
  }
@@ -56,8 +58,13 @@ export class SessionStore {
56
58
  mode: 0o600,
57
59
  flag: "wx",
58
60
  });
61
+ if (process.platform === "win32" && fs.existsSync(filePath)) {
62
+ fs.unlinkSync(filePath);
63
+ }
59
64
  fs.renameSync(tempPath, filePath);
60
- fs.chmodSync(filePath, 0o600);
65
+ if (process.platform !== "win32") {
66
+ fs.chmodSync(filePath, 0o600);
67
+ }
61
68
  }
62
69
  catch (err) {
63
70
  try {
package/dist/version.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import fs from "node:fs";
3
+ import os from "node:os";
3
4
  import path from "node:path";
4
5
  import { fileURLToPath } from "node:url";
5
6
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -31,16 +32,35 @@ function resolveAgyInfo() {
31
32
  let binaryPath = process.env.AGY_BIN_PATH;
32
33
  if (!binaryPath) {
33
34
  try {
34
- binaryPath = execSync("which agy 2>/dev/null || command -v agy 2>/dev/null", { encoding: "utf8" }).trim();
35
+ const lookupCmd = process.platform === "win32"
36
+ ? "where.exe agy"
37
+ : "which agy 2>/dev/null || command -v agy 2>/dev/null";
38
+ const output = execSync(lookupCmd, { encoding: "utf8" }).trim();
39
+ if (output) {
40
+ binaryPath = output.split(/\r?\n/)[0].trim();
41
+ }
35
42
  }
36
43
  catch {
37
44
  // ignore
38
45
  }
39
46
  }
40
- if (!binaryPath && process.env.HOME) {
41
- const defaultLocalPath = path.join(process.env.HOME, ".local", "bin", "agy");
42
- if (fs.existsSync(defaultLocalPath)) {
43
- binaryPath = defaultLocalPath;
47
+ if (!binaryPath) {
48
+ const homeDir = os.homedir();
49
+ if (homeDir) {
50
+ const candidates = process.platform === "win32"
51
+ ? [
52
+ path.join(homeDir, ".local", "bin", "agy.exe"),
53
+ path.join(homeDir, "AppData", "Local", "Programs", "antigravity", "agy.exe"),
54
+ path.join(homeDir, ".local", "bin", "agy.cmd"),
55
+ path.join(homeDir, ".local", "bin", "agy.bat"),
56
+ ]
57
+ : [path.join(homeDir, ".local", "bin", "agy")];
58
+ for (const cand of candidates) {
59
+ if (fs.existsSync(cand)) {
60
+ binaryPath = cand;
61
+ break;
62
+ }
63
+ }
44
64
  }
45
65
  }
46
66
  if (!binaryPath)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paseo-acp-agy",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "ACP (Agent Client Protocol) provider for Google Antigravity in Paseo and Zed",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",