@yitom/agy-acp-map 0.1.3 → 0.1.6

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.
@@ -60,7 +60,19 @@ export declare function normalizeJsonSchema(v: unknown): string | undefined;
60
60
  */
61
61
  export declare function normalizeSandbox(v: unknown): boolean | undefined;
62
62
  /** Canonical safety tier values (also listed on BRIDGE_CAPABILITIES.safetyTiers). */
63
- export declare const SAFETY_TIERS: readonly ["safe", "autonomous", "autonomous-unsandboxed"];
63
+ export declare const SAFETY_TIERS: readonly ['safe', 'autonomous', 'autonomous-unsandboxed'];
64
+ /** Legacy denominator kept only for unknown models (see modelContextWindow). */
65
+ export declare const DEFAULT_CONTEXT_SIZE = 200000;
66
+ /**
67
+ * Real input context window per model family, used as usage_update.size.
68
+ *
69
+ * Verified 2026-09: gemini-3.x flash = 1,048,576 input tokens;
70
+ * claude sonnet-4-6 / opus-4-6 = 1,000,000; gpt-oss-120b = 131,072.
71
+ * Unknown models fall back to DEFAULT_CONTEXT_SIZE (explicitly pessimistic).
72
+ *
73
+ * Override for any model via AGY_ACP_CONTEXT_SIZE (plain number, e.g. "1000000").
74
+ */
75
+ export declare function modelContextWindow(model: unknown, env?: NodeJS.ProcessEnv): number;
64
76
  /**
65
77
  * Normalize safety mode.
66
78
  * Accepts: safe | autonomous | auto | autonomous-unsandboxed | autonomous_unsandboxed | unsandboxed
@@ -94,14 +106,20 @@ export type SafetyResolveInput = {
94
106
  /**
95
107
  * Central three-tier safety resolution.
96
108
  *
109
+ * Note on `--sandbox`: agy documents it only as "terminal restrictions enabled".
110
+ * It is NOT verified to mean offline. Assumed split:
111
+ * - model API + built-in cloud search tools: unaffected;
112
+ * - terminal network (`curl`, `Invoke-WebRequest`, `git clone`, `npm install`): may be blocked.
113
+ * Use two probes to confirm: built-in search vs `run_command` network.
114
+ *
97
115
  * Tiers:
98
- * safe (default) — no skip-permissions; sandbox only if explicitly true
99
- * autonomous — skip-permissions; default --sandbox unless sandbox:false
116
+ * safe — no skip-permissions; sandbox only if explicitly true
117
+ * autonomous (default) — skip-permissions; default --sandbox unless sandbox:false
100
118
  * autonomous-unsandboxed — skip-permissions; NEVER --sandbox
101
119
  *
102
120
  * Inputs:
103
121
  * session.safety / AGY_ACP_SAFETY
104
- * AGY_ACP_SKIP_PERMISSIONS=1 ≈ autonomous if safety unset; =0 ≈ safe
122
+ * AGY_ACP_SKIP_PERMISSIONS=0 ≈ safe if safety unset; otherwise autonomous
105
123
  * explicit session.skipPermissions overrides the skip flag only
106
124
  * explicit session.sandbox / AGY_ACP_SANDBOX override sandbox except unsandboxed tier
107
125
  */
@@ -144,7 +162,7 @@ export declare function applyConfigOption(session: SessionLaunchFields, configId
144
162
  * they are used as-is. Otherwise resolveSafety(session) fills them from safety tier.
145
163
  *
146
164
  * Defaults:
147
- * - safety: safe → skipPermissions false, sandbox false
165
+ * - safety: autonomous → skipPermissions true, sandbox true
148
166
  * - disableSlashCommands: true
149
167
  * - printTimeout: "0"
150
168
  */
@@ -15,10 +15,16 @@ export declare function parseAgyModelsStdout(stdout: string): string[];
15
15
  * Accepts "id\\tname", "id name", or plain id-per-line.
16
16
  */
17
17
  export declare function parseAgyAgentsStdout(stdout: string): string[];
18
+ /**
19
+ * Official supported Antigravity models (verified 14 models).
20
+ */
21
+ export declare const DEFAULT_AGY_MODELS: string[];
22
+ export declare const FALLBACK_MODELS: string[];
18
23
  export declare function discoverAgyCatalog(opts?: {
19
24
  bin?: string;
20
25
  timeoutMs?: number;
21
26
  force?: boolean;
27
+ dynamic?: boolean;
22
28
  }): Promise<DiscoveryResult>;
23
29
  /** Test helper: clear process-lifetime cache. */
24
30
  export declare function clearDiscoveryCache(): void;
@@ -22,6 +22,30 @@ export interface SpawnAgyOptions extends AgyProcessCallbacks {
22
22
  /** Optional override; manager increments its own generation when omitted. */
23
23
  generation?: number;
24
24
  }
25
+ export interface AgyLaunchTarget {
26
+ bin: string;
27
+ args: string[];
28
+ /** True when a native Windows CREATE_NO_WINDOW shim is being used. */
29
+ headless: boolean;
30
+ }
31
+ /**
32
+ * Resolve the actual process target used for the Google CLI.
33
+ *
34
+ * Bun's Node-compatible spawn(..., {windowsHide: true}) is not sufficient for
35
+ * this CUI executable on every Windows runtime: the OS can still allocate a
36
+ * conhost.exe for agy.exe. The native shim creates agy with CREATE_NO_WINDOW
37
+ * and forwards all three standard streams unchanged.
38
+ */
39
+ export declare function resolveAgyLaunchTarget(bin: string, args: string[]): AgyLaunchTarget;
40
+ /**
41
+ * Generic variant: route ANY Windows console binary through the native
42
+ * headless launcher (CREATE_NO_WINDOW + stdio passthrough). Used for
43
+ * short-lived helpers (discovery, taskkill) that otherwise bypass the
44
+ * agy-specific resolver above. Returns the input unchanged off-Windows,
45
+ * when disabled, when the launcher is missing, or when the target already
46
+ * IS the launcher (recursion guard).
47
+ */
48
+ export declare function resolveHeadlessTarget(bin: string, args: string[]): AgyLaunchTarget;
25
49
  /**
26
50
  * Per-session process supervisor. Tracks generation so late lines from a killed
27
51
  * child are ignored after a respawn.
@@ -30,10 +54,15 @@ export declare class AgyProcessManager {
30
54
  private child;
31
55
  private generation;
32
56
  private killInFlight;
57
+ private callbacks;
33
58
  get currentChild(): ChildProcess | null;
34
59
  get currentGeneration(): number;
35
60
  isAlive(): boolean;
36
61
  isWritable(): boolean;
62
+ /**
63
+ * Dynamically update callbacks for ongoing process (e.g. multi-turn sessions).
64
+ */
65
+ setCallbacks(callbacks: AgyProcessCallbacks): void;
37
66
  /**
38
67
  * Kill any existing child (await exit), then spawn a new one with a fresh generation.
39
68
  */
@@ -0,0 +1,2 @@
1
+ export declare function debugLog(msg: string): void;
2
+ export declare function installFileLogging(): string | null;
@@ -10,6 +10,10 @@ export interface MapperState {
10
10
  agentMessageIds: Map<number, string>;
11
11
  thoughtMessageIds?: Map<number, string>;
12
12
  toolSeen: Set<number>;
13
+ /** Stable per-turn toolCallIds: stepIndex -> id (prevents cross-turn merge in Zed). */
14
+ toolIds: Map<number, string>;
15
+ /** Monotonic turn counter; part of toolCallId so step_index reuse never collides. */
16
+ turnSeq: number;
13
17
  lastStopReason?: string;
14
18
  turnDone?: boolean;
15
19
  emittedImageUris: Set<string>;
@@ -26,15 +30,19 @@ export interface AcpNotification {
26
30
  params: Record<string, unknown>;
27
31
  }
28
32
  export declare function createMapperState(richRoots?: FileToAcpImageOpts): MapperState;
29
- /** Reset per-turn tracking (keep conversationId / tools / richRoots). */
33
+ /** Reset per-turn tracking (keep conversationId / tools / richRoots / turnSeq+1). */
30
34
  export declare function resetTurnState(state: MapperState): MapperState;
31
35
  export declare function guessToolKind(name: unknown): string;
32
- /** Format or downgrade updates according to client ACP protocol version (v1 vs v2). */
33
- export declare function formatUpdateForProtocol(update: Record<string, unknown>, protocolVersion: number): Record<string, unknown>;
36
+ /** Format or adapt updates according to client ACP protocol version (v1 vs v2). */
37
+ export declare function formatUpdateForProtocol(update: Record<string, unknown>, protocolVersion: number): Record<string, unknown> | null;
38
+ export interface MapAgyEventOpts {
39
+ /** Session model id; selects the real context window for usage_update.size. */
40
+ model?: string;
41
+ }
34
42
  /**
35
43
  * Map one agy NDJSON event object into zero or more ACP session/update notifications.
36
44
  */
37
- export declare function mapAgyEvent(sessionId: string, event: unknown, state: MapperState): {
45
+ export declare function mapAgyEvent(sessionId: string, event: unknown, state: MapperState, opts?: MapAgyEventOpts): {
38
46
  notifications: AcpNotification[];
39
47
  state: MapperState;
40
48
  };
@@ -1,5 +1,6 @@
1
1
  export interface NormalizeOpts {
2
2
  cwd: string;
3
+ sessionId?: string;
3
4
  stagingDir?: string;
4
5
  /** Max decoded bytes for a single blob (default 8MB). */
5
6
  maxBlobBytes?: number;
@@ -39,13 +40,27 @@ export declare function cleanupStaging(filesOrDir: string[] | string, opts?: {
39
40
  skipped: boolean;
40
41
  };
41
42
  /**
42
- * Clean `<cwd>/.agy-acp-staging` for a session (all files in that dir).
43
+ * Clean `<cwd>/.agy-acp-staging` for a session.
44
+ * When `sessionId` is provided, cleans exclusively `<cwd>/.agy-acp-staging/<sessionId>`
45
+ * without removing staging files belonging to other sessions under the same cwd.
43
46
  */
44
47
  export declare function cleanupSessionStaging(cwd: string, opts?: {
45
48
  keep?: boolean;
46
49
  stagingDir?: string;
50
+ sessionId?: string;
51
+ files?: string[];
47
52
  }): {
48
53
  removed: string[];
49
54
  skipped: boolean;
50
55
  };
56
+ export interface PromptValidationResult {
57
+ ok: boolean;
58
+ reason?: string;
59
+ }
60
+ /**
61
+ * Synchronous pre-validation for ACP Prompt ContentBlocks.
62
+ * Ensures the prompt is a non-empty array and contains at least one
63
+ * content block with valid, non-empty data (text, resource, resource_link, image, audio).
64
+ */
65
+ export declare function validatePromptBlocks(blocks: unknown): PromptValidationResult;
51
66
  export { STAGING_DIRNAME, };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Small, display-oriented history journal.
3
+ *
4
+ * This is intentionally not a copy of agy's internal conversation database. It
5
+ * only stores the text that an ACP client can display: user prompts and final
6
+ * assistant text. Tool calls, tool output, thoughts, and internal events are
7
+ * deliberately excluded.
8
+ */
9
+ export type SessionHistoryRole = 'user' | 'assistant';
10
+ export type SessionHistoryRecord = {
11
+ version: 1;
12
+ sessionId: string;
13
+ messageId: string;
14
+ role: SessionHistoryRole;
15
+ text: string;
16
+ createdAt: string;
17
+ };
18
+ export declare function resolveHistoryDir(sessionStorePath?: string, env?: NodeJS.ProcessEnv, homedir?: () => string): string;
19
+ export declare class SessionHistoryStore {
20
+ readonly directory: string;
21
+ constructor(directory?: string);
22
+ filePath(sessionId: string): string;
23
+ /**
24
+ * Append one completed turn as two JSONL records.
25
+ *
26
+ * The assistant record is omitted when the turn produced no visible final
27
+ * text. This keeps cancelled/error-only turns from becoming fake answers.
28
+ */
29
+ appendTurn(sessionId: string, userText: string, assistantText?: string): void;
30
+ /** Read valid records and ignore incomplete/corrupt trailing lines. */
31
+ read(sessionId: string): SessionHistoryRecord[];
32
+ delete(sessionId: string): void;
33
+ }
@@ -14,6 +14,7 @@ export type SessionRecord = {
14
14
  jsonSchema?: string;
15
15
  printTimeout?: string;
16
16
  disableSlashCommands?: boolean;
17
+ protocolVersion?: 1 | 2;
17
18
  createdAt: string;
18
19
  updatedAt: string;
19
20
  };
@@ -42,6 +43,7 @@ export declare function sessionToRecord(session: {
42
43
  jsonSchema?: string;
43
44
  printTimeout?: string;
44
45
  disableSlashCommands?: boolean;
46
+ protocolVersion?: 1 | 2;
45
47
  }): SessionRecord;
46
48
  /**
47
49
  * Fields needed to rehydrate an in-memory Session (no child process yet).
@@ -64,13 +66,19 @@ export declare function recordLaunchFields(record: SessionRecord): {
64
66
  jsonSchema?: string;
65
67
  printTimeout?: string;
66
68
  disableSlashCommands?: boolean;
69
+ protocolVersion?: 1 | 2;
67
70
  };
68
71
  export declare class SessionStore {
69
72
  readonly filePath: string;
70
73
  constructor(filePath?: string);
71
- /** Read all records; missing/corrupt file → []. */
74
+ /** Read all records; missing/corrupt file → []; retries on transient locks. */
72
75
  load(): SessionRecord[];
73
- /** Atomic write: temp file in same dir + rename. */
76
+ /**
77
+ * Acquire a cross-process file lock during read-modify-write operations
78
+ * to avoid lost updates between concurrent ACP services or test workers.
79
+ */
80
+ withLock<T>(fn: () => T): T;
81
+ /** Atomic write: temp file in same dir + rename with Windows retry backoff. */
74
82
  save(records: SessionRecord[]): void;
75
83
  upsert(record: SessionRecord): void;
76
84
  get(sessionId: string): SessionRecord | undefined;
@@ -8,6 +8,13 @@
8
8
  * Also accepts explicit key=value fragments: tool=, allow-rule=, path=
9
9
  * And stream-json: tool ERROR with permission/denied wording + result.denied_actions
10
10
  *
11
+ * Sandbox note: `agy --help` documents `--sandbox` only as "terminal restrictions
12
+ * enabled". It does NOT state offline. Convention used here:
13
+ * - model API + built-in search tools: assumed unaffected;
14
+ * - terminal network (`curl`, `Invoke-WebRequest`, ...) may be blocked and is
15
+ * surfaced separately with `source: *-sandbox` so callers can suggest
16
+ * `safety: autonomous-unsandboxed` / `sandbox: false` retry.
17
+ *
11
18
  * v0.1.3: do NOT treat generic tool ERROR as soft-deny (tighten parseSoftDenyFromEvent).
12
19
  */
13
20
  export interface SoftDenyInfo {
@@ -32,5 +39,9 @@ export declare function parseSoftDenyFromEvent(event: unknown): SoftDenyInfo[];
32
39
  export declare function mergeSoftDenies(...lists: (SoftDenyInfo[] | undefined)[]): SoftDenyInfo[];
33
40
  /**
34
41
  * Format soft-denies into a short agent-facing note.
42
+ * Sandbox sources get a separate hint: built-in search is expected to keep
43
+ * working, terminal network (`curl`, `Invoke-WebRequest`, ...) may be blocked —
44
+ * retry the same prompt with `safety: autonomous-unsandboxed` / `sandbox: false`
45
+ * to distinguish the two paths.
35
46
  */
36
47
  export declare function formatSoftDenyMessage(denies: SoftDenyInfo[]): string;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Windows Console Window Self-Hiding Utility.
3
+ *
4
+ * When ACP stdio servers are launched on Windows by a GUI host (Zed, Electron, etc.),
5
+ * Windows kernel automatically allocates a visible conhost console window because
6
+ * Node/Bun are console subsystem binaries.
7
+ *
8
+ * Calling `hideConsoleWindow()` as early as possible in the server entry point
9
+ * immediately hides and detaches the console window via Win32 API, while keeping
10
+ * stdio pipes (pipe handles) 100% intact and functional.
11
+ */
12
+ export declare function hideConsoleWindow(): void;
@@ -0,0 +1,7 @@
1
+ import * as v2 from '@agentclientprotocol/sdk/experimental/v2';
2
+ /**
3
+ * Dual router supporting both ACP v1 and v2 clients automatically.
4
+ * Shares the underlying AgySessionCore so sessions created in v1
5
+ * or v2 share the same runtime store and process supervisors.
6
+ */
7
+ export declare function createDualAcpApp(sharedServiceOrCore?: any): v2.AgentProtocolRouter;
@@ -0,0 +1,17 @@
1
+ import { AgySessionCore } from '../core/session-core.ts';
2
+ export declare class AgyAcpV1Service {
3
+ readonly core: AgySessionCore;
4
+ constructor(core?: AgySessionCore);
5
+ initialize(): Promise<any>;
6
+ newSession(params: any): Promise<any>;
7
+ resumeSession(params: any): Promise<any>;
8
+ loadSession(params: any, notifyClient: (update: any) => Promise<void> | void): Promise<any>;
9
+ setConfigOption(params: any): Promise<any>;
10
+ listSessions(params?: any): Promise<any>;
11
+ closeSession(params: any): Promise<any>;
12
+ deleteSession(params: any): Promise<any>;
13
+ cancelSession(params: any): void;
14
+ promptSession(params: any, notifyClient: (update: any) => Promise<void> | void): Promise<{
15
+ stopReason: string;
16
+ }>;
17
+ }
@@ -0,0 +1,6 @@
1
+ import * as v1 from '@agentclientprotocol/sdk';
2
+ import { AgyAcpV1Service } from './adapter.ts';
3
+ /**
4
+ * Creates an ACP v1 agent app wrapped with official @agentclientprotocol/sdk.
5
+ */
6
+ export declare function createAcpV1App(service?: AgyAcpV1Service | any): v1.AgentApp;
@@ -0,0 +1,8 @@
1
+ import type * as v1 from '@agentclientprotocol/sdk';
2
+ import type { DiscoveryResult } from '../lib/agy-discovery.ts';
3
+ import { type SdkSession } from '../core/types.ts';
4
+ /**
5
+ * Builds standard ACP v1 session configuration options.
6
+ * In ACP v1, the selector ID field is named `id`.
7
+ */
8
+ export declare function buildV1ConfigOptions(discovery: DiscoveryResult, session?: Pick<SdkSession, 'model' | 'agent'>): v1.SessionConfigOption[];
@@ -0,0 +1,4 @@
1
+ export * from './types.ts';
2
+ export * from './config.ts';
3
+ export * from './adapter.ts';
4
+ export * from './app.ts';
@@ -0,0 +1,10 @@
1
+ export declare const V1_AGENT_CAPABILITIES: {
2
+ loadSession: boolean;
3
+ sessionCapabilities: {
4
+ list: {};
5
+ resume: {};
6
+ close: {};
7
+ delete: {};
8
+ additionalDirectories: {};
9
+ };
10
+ };
@@ -0,0 +1,18 @@
1
+ import { AgySessionCore } from '../core/session-core.ts';
2
+ export declare class AgyAcpV2Service {
3
+ readonly core: AgySessionCore;
4
+ constructor(core?: AgySessionCore);
5
+ initialize(): Promise<any>;
6
+ newSession(params: any): Promise<any>;
7
+ resumeSession(params: any, notifyClient?: (update: any) => Promise<void> | void): Promise<any>;
8
+ setConfigOption(params: any): Promise<any>;
9
+ listSessions(params?: any): Promise<any>;
10
+ closeSession(params: any): Promise<any>;
11
+ deleteSession(params: any): Promise<any>;
12
+ cancelSession(params: any): void;
13
+ promptSession(params: any, notifyClient: (update: any) => Promise<void> | void, opts?: {
14
+ isPreLocked?: boolean;
15
+ }): Promise<{
16
+ stopReason: string;
17
+ }>;
18
+ }
@@ -0,0 +1,6 @@
1
+ import * as v2 from '@agentclientprotocol/sdk/experimental/v2';
2
+ import { AgyAcpV2Service } from './adapter.ts';
3
+ /**
4
+ * Creates an ACP v2 agent app wrapped with official @agentclientprotocol/sdk.
5
+ */
6
+ export declare function createAcpV2App(service?: AgyAcpV2Service | any): v2.AgentApp;
@@ -0,0 +1,8 @@
1
+ import type * as v2 from '@agentclientprotocol/sdk/experimental/v2';
2
+ import type { DiscoveryResult } from '../lib/agy-discovery.ts';
3
+ import { type SdkSession } from '../core/types.ts';
4
+ /**
5
+ * Builds experimental ACP v2 session configuration options.
6
+ * In ACP v2, the selector ID field is named `configId`.
7
+ */
8
+ export declare function buildV2ConfigOptions(discovery: DiscoveryResult, session?: Pick<SdkSession, 'model' | 'agent'>): v2.SessionConfigOption[];
@@ -0,0 +1,4 @@
1
+ export * from './types.ts';
2
+ export * from './config.ts';
3
+ export * from './adapter.ts';
4
+ export * from './app.ts';
@@ -0,0 +1,6 @@
1
+ export declare const V2_AGENT_CAPABILITIES: {
2
+ session: {
3
+ additionalDirectories: {};
4
+ delete: {};
5
+ };
6
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yitom/agy-acp-map",
3
- "version": "0.1.3",
3
+ "version": "0.1.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -25,17 +25,25 @@
25
25
  "LICENSE"
26
26
  ],
27
27
  "scripts": {
28
- "build": "bun run build:js && bun run build:types",
28
+ "build": "bun run build:js && bun run build:types && bun run build:headless",
29
+ "build:headless": "bun scripts/build-headless.ts",
29
30
  "build:js": "bun build src/sdk-server.ts --target node --outfile dist/bin.js && bun build src/index.ts --target node --outfile dist/index.js",
31
+ "build:exe": "bun build src/sdk-server.ts --compile --target=bun-windows-x64 --outfile dist/agy-acp-win-x64.exe",
30
32
  "build:types": "bunx tsc -p tsconfig.build.json",
31
- "prepublishOnly": "bun run build && bun test src/lib",
33
+ "release:patch": "bun scripts/release.ts",
34
+ "release:publish": "bun scripts/release.ts --publish",
35
+ "prepublishOnly": "bun run build && bun test --timeout 30000",
32
36
  "start": "bun src/sdk-server.ts",
33
37
  "start:dist": "node dist/bin.js",
34
38
  "start:legacy": "bun archive/legacy-server.ts",
35
39
  "map": "bun src/map.ts",
36
- "test": "bun test src/lib",
40
+ "test": "bun test --timeout 30000",
41
+ "test:unit": "bun test src/lib",
42
+ "test:integration": "bun test tests/protocol-integration.test.ts",
43
+ "test:wire": "bun test tests/protocol-wire-stdio.test.ts",
37
44
  "test:args": "bun tests/test-agy-args.ts",
38
45
  "smoke": "bun tests/smoke/smoke-basic.ts",
46
+ "smoke:v2": "bun tests/smoke/smoke-v2-draft.ts",
39
47
  "smoke:flags": "bun tests/smoke/smoke-flags.ts",
40
48
  "smoke:permissions": "bun tests/smoke/smoke-permissions.ts",
41
49
  "smoke:image-in": "bun tests/smoke/smoke-image-in.ts",