super-dsh 0.1.9 → 0.1.10-e

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.
Files changed (178) hide show
  1. package/README.md +25 -3
  2. package/agent-agy/cordis.patch.yml +7 -4
  3. package/agent-agy/dist/agent.d.ts +12 -11
  4. package/agent-agy/dist/agy-auth-gateway.d.ts +124 -0
  5. package/agent-agy/dist/agy-auth-gateway.js +233 -0
  6. package/agent-agy/dist/agy-auth.d.ts +153 -0
  7. package/agent-agy/dist/agy-auth.js +179 -0
  8. package/agent-agy/dist/agy-cli-client.d.ts +39 -9
  9. package/agent-agy/dist/agy-cli-client.js +82 -18
  10. package/agent-agy/dist/agy-store.d.ts +8 -0
  11. package/agent-agy/dist/index.d.ts +46 -16
  12. package/agent-agy/dist/index.js +82 -56
  13. package/agent-agy/dist/models.d.ts +70 -0
  14. package/agent-agy/dist/models.js +102 -3
  15. package/agent-agy/package.json +7 -5
  16. package/agent-agy-sdk/cordis.patch.yml +58 -0
  17. package/agent-agy-sdk/dist/adapter.d.ts +15 -0
  18. package/agent-agy-sdk/dist/adapter.js +42 -0
  19. package/agent-agy-sdk/dist/agent-preset-agy.d.ts +27 -0
  20. package/agent-agy-sdk/dist/agent-preset-agy.js +32 -0
  21. package/agent-agy-sdk/dist/agent.d.ts +138 -0
  22. package/agent-agy-sdk/dist/agent.js +494 -0
  23. package/{agent-agy → agent-agy-sdk}/dist/agy-client.d.ts +26 -6
  24. package/{agent-agy → agent-agy-sdk}/dist/agy-client.js +43 -25
  25. package/agent-agy-sdk/dist/agy-sessions.d.ts +25 -0
  26. package/agent-agy-sdk/dist/agy-sessions.js +107 -0
  27. package/agent-agy-sdk/dist/agy-store.d.ts +39 -0
  28. package/agent-agy-sdk/dist/agy-store.js +83 -0
  29. package/agent-agy-sdk/dist/inbox.d.ts +26 -0
  30. package/agent-agy-sdk/dist/inbox.js +53 -0
  31. package/agent-agy-sdk/dist/index.d.ts +93 -0
  32. package/agent-agy-sdk/dist/index.js +476 -0
  33. package/agent-agy-sdk/dist/models.d.ts +41 -0
  34. package/agent-agy-sdk/dist/models.js +74 -0
  35. package/agent-agy-sdk/dist/sdk-venv.d.ts +76 -0
  36. package/agent-agy-sdk/dist/sdk-venv.js +173 -0
  37. package/agent-agy-sdk/dist/world-plugin.d.ts +10 -0
  38. package/agent-agy-sdk/dist/world-plugin.js +82 -0
  39. package/agent-agy-sdk/package.json +64 -0
  40. package/agent-claude/dist/adapter.js +106 -31
  41. package/agent-claude/dist/agent.js +154 -17
  42. package/agent-claude/dist/claude-client.js +84 -43
  43. package/agent-claude/dist/claude-launch.js +101 -0
  44. package/agent-claude/dist/claude-native-config.js +169 -0
  45. package/agent-claude/dist/claude-provider-gateway.js +340 -0
  46. package/agent-claude/dist/claude-providers.js +391 -0
  47. package/agent-claude/dist/claude-route.js +152 -0
  48. package/agent-claude/dist/index.js +214 -37
  49. package/agent-claude/dist/models.js +14 -0
  50. package/agent-claude/dist/sdk-runtime.js +320 -0
  51. package/agent-claude/package.json +6 -4
  52. package/agent-codex/README.md +141 -36
  53. package/agent-codex/cordis.patch.yml +14 -10
  54. package/agent-codex/dist/adapter.js +64 -28
  55. package/agent-codex/dist/agent.js +255 -81
  56. package/agent-codex/dist/app-server-approvals.js +165 -0
  57. package/agent-codex/dist/app-server-client.js +723 -0
  58. package/agent-codex/dist/app-server-events.js +432 -0
  59. package/agent-codex/dist/app-server-protocol.js +95 -0
  60. package/agent-codex/dist/app-server-wire.js +299 -0
  61. package/agent-codex/dist/codex-launch.js +78 -0
  62. package/agent-codex/dist/codex-native-config.js +392 -0
  63. package/agent-codex/dist/codex-provider-gateway.js +402 -0
  64. package/agent-codex/dist/codex-providers.js +376 -0
  65. package/agent-codex/dist/codex-route.js +86 -0
  66. package/agent-codex/dist/index.js +256 -115
  67. package/agent-codex/dist/permission.js +75 -1
  68. package/agent-codex/package.json +1 -2
  69. package/agent-codex-sdk/README.md +79 -0
  70. package/agent-codex-sdk/cordis.patch.yml +81 -0
  71. package/agent-codex-sdk/dist/adapter.js +91 -0
  72. package/agent-codex-sdk/dist/agent-preset-codex.js +32 -0
  73. package/agent-codex-sdk/dist/agent.js +1085 -0
  74. package/agent-codex-sdk/dist/codex-native-config.js +392 -0
  75. package/agent-codex-sdk/dist/codex-provider-gateway.js +402 -0
  76. package/agent-codex-sdk/dist/codex-providers.js +376 -0
  77. package/agent-codex-sdk/dist/codex-route.js +86 -0
  78. package/{agent-codex/dist/codex-client.js → agent-codex-sdk/dist/codex-sdk-client.js} +253 -32
  79. package/agent-codex-sdk/dist/codex-sdk-launch.js +92 -0
  80. package/agent-codex-sdk/dist/codex-store.js +180 -0
  81. package/agent-codex-sdk/dist/inbox.js +53 -0
  82. package/agent-codex-sdk/dist/index.js +739 -0
  83. package/agent-codex-sdk/dist/permission.js +71 -0
  84. package/agent-codex-sdk/dist/sdk-runtime.js +307 -0
  85. package/agent-codex-sdk/dist/session-map.js +167 -0
  86. package/agent-codex-sdk/dist/world-plugin.js +93 -0
  87. package/agent-codex-sdk/package.json +79 -0
  88. package/agent-codex-sdk/scripts/fetch-sdk-runtime.mjs +57 -0
  89. package/agent-omp/README.md +72 -55
  90. package/agent-omp/dist/agent.js +36 -11
  91. package/agent-omp/dist/index.js +92 -52
  92. package/agent-omp/dist/lazy-rpc.js +11 -4
  93. package/agent-omp/dist/omp-cli.js +114 -97
  94. package/agent-omp/dist/omp-store.js +12 -4
  95. package/agent-omp/dist/permission.js +70 -5
  96. package/agent-omp/dist/rpc-client.js +409 -0
  97. package/agent-omp/dist/world-plugin.js +36 -3
  98. package/agent-omp/package.json +2 -6
  99. package/agent-omp-sdk/README.md +103 -0
  100. package/agent-omp-sdk/cordis.patch.yml +108 -0
  101. package/agent-omp-sdk/dist/adapter.d.ts +21 -0
  102. package/agent-omp-sdk/dist/adapter.js +36 -0
  103. package/agent-omp-sdk/dist/agent-preset-omp.d.ts +31 -0
  104. package/agent-omp-sdk/dist/agent-preset-omp.js +32 -0
  105. package/agent-omp-sdk/dist/agent.d.ts +64 -0
  106. package/agent-omp-sdk/dist/agent.js +1178 -0
  107. package/agent-omp-sdk/dist/discovery.d.ts +57 -0
  108. package/agent-omp-sdk/dist/discovery.js +116 -0
  109. package/agent-omp-sdk/dist/inbox.d.ts +28 -0
  110. package/agent-omp-sdk/dist/inbox.js +53 -0
  111. package/agent-omp-sdk/dist/index.d.ts +60 -0
  112. package/agent-omp-sdk/dist/index.js +632 -0
  113. package/agent-omp-sdk/dist/knobs.d.ts +34 -0
  114. package/agent-omp-sdk/dist/knobs.js +50 -0
  115. package/agent-omp-sdk/dist/lazy-rpc.d.ts +98 -0
  116. package/agent-omp-sdk/dist/lazy-rpc.js +178 -0
  117. package/agent-omp-sdk/dist/mobile/zoom-guard.d.ts +187 -0
  118. package/agent-omp-sdk/dist/mobile/zoom-guard.js +294 -0
  119. package/agent-omp-sdk/dist/mobile-boot.d.ts +49 -0
  120. package/agent-omp-sdk/dist/mobile-boot.js +38 -0
  121. package/agent-omp-sdk/dist/models.d.ts +39 -0
  122. package/agent-omp-sdk/dist/models.js +299 -0
  123. package/agent-omp-sdk/dist/omp-cli.d.ts +67 -0
  124. package/agent-omp-sdk/dist/omp-cli.js +164 -0
  125. package/agent-omp-sdk/dist/omp-disk-discovery.d.ts +27 -0
  126. package/agent-omp-sdk/dist/omp-disk-discovery.js +178 -0
  127. package/agent-omp-sdk/dist/omp-executable.d.ts +2 -0
  128. package/agent-omp-sdk/dist/omp-executable.js +30 -0
  129. package/agent-omp-sdk/dist/omp-store.d.ts +134 -0
  130. package/agent-omp-sdk/dist/omp-store.js +526 -0
  131. package/agent-omp-sdk/dist/pairing.d.ts +7 -0
  132. package/agent-omp-sdk/dist/pairing.js +45 -0
  133. package/agent-omp-sdk/dist/permission.d.ts +138 -0
  134. package/agent-omp-sdk/dist/permission.js +161 -0
  135. package/agent-omp-sdk/dist/protocol.d.ts +189 -0
  136. package/agent-omp-sdk/dist/rpc-types.d.ts +77 -0
  137. package/agent-omp-sdk/dist/rpc-types.js +1 -0
  138. package/agent-omp-sdk/dist/sdk-client.d.ts +160 -0
  139. package/{agent-omp → agent-omp-sdk}/dist/sdk-client.js +108 -56
  140. package/agent-omp-sdk/dist/sdk-runtime.d.ts +211 -0
  141. package/agent-omp-sdk/dist/sdk-runtime.js +418 -0
  142. package/agent-omp-sdk/dist/sidecar-client.d.ts +87 -0
  143. package/agent-omp-sdk/dist/sidecar-client.js +197 -0
  144. package/agent-omp-sdk/dist/store/adapter.d.ts +17 -0
  145. package/agent-omp-sdk/dist/store/adapter.js +47 -0
  146. package/agent-omp-sdk/dist/store/db.d.ts +70 -0
  147. package/agent-omp-sdk/dist/store/db.js +210 -0
  148. package/agent-omp-sdk/dist/store/index.d.ts +23 -0
  149. package/agent-omp-sdk/dist/store/index.js +59 -0
  150. package/agent-omp-sdk/dist/store/reconcile.d.ts +15 -0
  151. package/agent-omp-sdk/dist/store/reconcile.js +51 -0
  152. package/agent-omp-sdk/dist/store/schema.d.ts +8 -0
  153. package/agent-omp-sdk/dist/store/schema.js +40 -0
  154. package/agent-omp-sdk/dist/transport.d.ts +49 -0
  155. package/agent-omp-sdk/dist/transport.js +35 -0
  156. package/agent-omp-sdk/dist/world-home.d.ts +4 -0
  157. package/agent-omp-sdk/dist/world-home.js +23 -0
  158. package/agent-omp-sdk/dist/world-plugin.d.ts +10 -0
  159. package/agent-omp-sdk/dist/world-plugin.js +137 -0
  160. package/agent-omp-sdk/package.json +87 -0
  161. package/client/index.js +1204 -93
  162. package/cordis.patch.yml +64 -0
  163. package/package.json +17 -8
  164. package/superd-hub/dist/client/agent-settings.d.ts +210 -0
  165. package/superd-hub/dist/client/agent-settings.js +300 -0
  166. package/superd-hub/dist/client/roster.js +6 -0
  167. package/superd-hub/dist/client/runtime-settings-api.d.ts +76 -0
  168. package/superd-hub/dist/client/runtime-settings-api.js +137 -0
  169. package/superd-hub/dist/client/switch.d.ts +165 -0
  170. package/superd-hub/dist/client/switch.js +295 -0
  171. package/superd-hub/lib/client/index.js +1204 -93
  172. package/agent-codex/dist/models.js +0 -152
  173. package/agent-omp/dist/sidecar-client.js +0 -195
  174. /package/{agent-agy → agent-agy-sdk}/bridge/agy_bridge.py +0 -0
  175. /package/{agent-agy → agent-agy-sdk}/bridge/gemini_openai_server.mjs +0 -0
  176. /package/{agent-codex/dist/codex-events.js → agent-codex-sdk/dist/codex-sdk-events.js} +0 -0
  177. /package/{agent-omp → agent-omp-sdk}/dist/protocol.js +0 -0
  178. /package/{agent-omp → agent-omp-sdk}/sidecar/main.ts +0 -0
package/README.md CHANGED
@@ -18,21 +18,43 @@ dsh plugin --profile <name> add super-dsh@0.1.0
18
18
  ```
19
19
 
20
20
  That single package composes the whole line (`@pgmi-builds/superd-hub` plus the
21
- six `@pgmi-builds/agent-*` packages). Restart the profile and the
22
- sidebar gains the runtime selector; each world provisions its own nested DSH
21
+ six primary `@pgmi-builds/agent-*` packages and three OPTIONAL SDK halves).
22
+ Restart the profile and the
23
23
  home under `<DSH_HOME>/agents/<label>/` on first boot.
24
24
 
25
25
  ## Runtimes
26
26
 
27
27
  | Label | Runtime | Integration |
28
28
  |---|---|---|
29
- | OMP | OMP (`~/.omp`) | in-process SDK sidecar, lazy per session |
29
+ | OMP | OMP (`~/.omp`) | host `omp` binary over RPC (`omp --mode rpc`, NDJSON v1), lazy per session |
30
30
  | Codex | Codex CLI (`~/.codex`) | adapter world plugin |
31
31
  | Claude | Claude Code (`~/.claude`) | standalone adapter, joined by the hub |
32
32
  | Pi | pi coding agent (`~/.pi`) | in-process SDK |
33
33
  | Hermes | Hermes (`~/.hermes`) | gateway child |
34
34
  | Antigravity | agy SDK | Python bridge (`bridge/agy_bridge.py`) |
35
35
 
36
+ ### Opt-in SDK halves
37
+
38
+ Three runtimes also ship a preserved in-process SDK transport beside the primary
39
+ line: `agent-omp-sdk`, `agent-agy-sdk` and `agent-codex-sdk`. Each is a complete
40
+ standalone copy of its adapter with an injectable transport, and each
41
+
42
+ - is **`disabled: true`** in this package's composite patch — turning the row on
43
+ IS the switch (`plugin-presence IS the roster`), and it runs under its own
44
+ world key (`omp-sdk` / `agy-sdk` / `codex-sdk`) so it can sit beside the
45
+ primary row without a duplicate-key error;
46
+ - declares **no dependency at all** — not a dependency, not an optional, not a
47
+ peer — so `dsh plugin add super-dsh` installs and downloads nothing for it,
48
+ and ships no postinstall;
49
+ - supports the same multi-provider surface as its primary line (the Codex halves
50
+ share one provider store implementation, one native-config reader, one route
51
+ resolver and one `codexProviders` panel; only the launch encoding differs —
52
+ argv for the app-server child, a config object for the SDK);
53
+ - fetches its own durable runtime into `<DSH_HOME>/agents/<key>/` on the FIRST
54
+ real prompt (bun + the coding-agent tree for OMP, a Python venv for agy, the
55
+ `@openai/codex-sdk` tree for Codex), where it survives restarts and upgrades.
56
+ Pre-warm with `npm run fetch-sdk-runtime` in the package.
57
+
36
58
  ## Design
37
59
 
38
60
  - **S1** selector handoff is one hop; the dispatcher never addresses sessions.
@@ -1,11 +1,14 @@
1
- # @pgmi-builds/agent-agy bundle patch (AW-G SDK line, pi/hermes form).
1
+ # @pgmi-builds/agent-agy bundle patch (pi/hermes form).
2
2
  # The `dsh.bundle.patch` layer of the adapter package: mounts the agy provider
3
3
  # and disables the native components it replaces. Port/webserver posture is
4
4
  # NOT here (worldMountPatches owns it); the world profile patch pins the home.
5
5
  #
6
- # Auth (2026-09-18 consumer-first ruling, dev-rules §16a): Gemini API key in
7
- # adapter world-home state (or GEMINI_API_KEY env), else ADC — the SDK consumes
8
- # either transparently. The agy CLI is never invoked.
6
+ # Auth (2026-10-02 ruling 「拥抱用户自己的使用环境」): the adapter drives the
7
+ # user's OWN Antigravity CLI and shares their real native configuration —
8
+ # settings.json, ADC, keyring. Ladder: Gemini API key → OAuth (placeholder) →
9
+ # ADC. The opt-in Python SDK transport is the sibling package
10
+ # @pgmi-builds/agent-agy-sdk (its own bundle, delivered disabled).
11
+
9
12
 
10
13
  - insert:
11
14
  - id: agy-provider
@@ -1,26 +1,27 @@
1
1
  /**
2
- * AgyAgent — the Dash `Agent` shim over one `AgyBridgeClient` (the Python SDK
3
- * bridge child; localharness materializes inside it on the first prompt).
2
+ * AgyAgent — the Dash `Agent` shim over one `AgyCliClient` (the user's own
3
+ * Antigravity CLI in headless stream-json mode; the child spawns lazily on the
4
+ * first real prompt).
4
5
  *
5
- * Projection (bridge → Dash session events):
6
+ * Projection (CLI stream → Dash session events):
6
7
  * (prompt delivery) → turn/start + user/message
7
8
  * chunk (streamed) → assistant stream frames (v2 protocol) accumulated
8
9
  * as durable records; the FULL text commits once as
9
10
  * assistant/message at `done`
10
- * tool → (V1: bridge supplies name only — omitted from the
11
+ * tool → (V1: CLI supplies name only — omitted from the
11
12
  * log rather than fabricated; event-stream honesty)
12
13
  * done → assistant/message + step/end + turn/end {completed}
13
14
  * error → turn/end {error} with a stable code
14
15
  *
15
- * Bridge gaps registered explicitly (never fabricated):
16
- * - token usage: the bridge `done` event carries none → no usage field.
16
+ * CLI-stream gaps registered explicitly (never fabricated):
17
+ * - token usage: the CLI `done` event carries none → no usage field.
17
18
  * - tool fidelity: only a tool name arrives (no call id / args / result) → no
18
19
  * tool/call or tool/result events in V1.
19
- * - steer/cancel: the bridge has no in-turn interrupt; `steer` degrades to a
20
+ * - steer/cancel: the CLI has no in-turn interrupt; `steer` degrades to a
20
21
  * parked follow-up, `cancel` records the cause (applied at the terminal).
21
22
  *
22
23
  * Onboarding (§17 minimal, consumer-first): when no Gemini API key is known,
23
- * the first user turn never touches the bridge — the turn is answered locally
24
+ * the first user turn never touches the CLI — the turn is answered locally
24
25
  * with a system/message asking for the key; a pasted key is persisted through
25
26
  * `onApiKey` (adapter state, world home only) and confirmed in the same turn.
26
27
  */
@@ -29,10 +30,10 @@ import type { Agent, AgentOptions, AgentStatus, CancelOptions, InboxTarget } fro
29
30
  import { Inbox } from "./inbox.js";
30
31
  import type { AgentCancelCause, Session, SessionId, UserMessage } from "@deepseek-ai/dsh-session";
31
32
  import type { TokenUsage } from "@deepseek-ai/dsh-llm";
32
- import type { AgyBridgeClient } from "./agy-client.js";
33
+ import type { AgyCliClient } from "./agy-cli-client.js";
33
34
  import { type WithSystemHead } from "../../superd-hub/dist/index.js";
34
- /** Structural union of the two live transports (SDK bridge | CLI stream). */
35
- export type LiveAgyClient = Pick<AgyBridgeClient, "conversationId" | "lastUsage" | "onThinkingDelta" | "onToolEvent" | "setApprovalHandler" | "turn" | "close"> & {
35
+ /** The CLI stream transport the agent drives (SDK bridge moved to agent-agy-sdk). */
36
+ export type LiveAgyClient = Pick<AgyCliClient, "conversationId" | "lastUsage" | "onThinkingDelta" | "onToolEvent" | "setApprovalHandler" | "turn" | "close"> & {
36
37
  setSystemMessageHandler?(handler: (text: string) => void): void;
37
38
  };
38
39
  /** Classify a bridge turn failure into the stable {message, code} UI chip. */
@@ -0,0 +1,124 @@
1
+ /**
2
+ * agy-auth-gateway.ts — the adapter-owned Remote behind the Hub's Antigravity
3
+ * settings panel (P3, 2026-10-02 user ruling).
4
+ *
5
+ * Why a Remote and not a hub route: the auth ladder, the probe results and the
6
+ * native-settings mutation are ADAPTER config (agent-adapter-dev-rules §12), so
7
+ * the adapter owns them and the hub only forwards. `TypertRemoteService` +
8
+ * `@Remote` is the whole mechanism — standard (TC39) method decorators recorded
9
+ * on the class prototype, read back at dispatch time by the gateway's
10
+ * source-claim scan. There is NO codegen step and no compiler-injected
11
+ * metadata, which is why a plain `tsc` adapter build can ship one.
12
+ *
13
+ * Wire contract (both halves are pinned by tests):
14
+ * request POST /hub/api?agent=agy
15
+ * { type:'client-request', rpcId, method:'agyAuth/get'|'agyAuth/set',
16
+ * payload: { args: { request?: AgyAuthSetRequest } } }
17
+ * response { type:'server-response', rpcId, result:{ ok:true, value:<view> } }
18
+ *
19
+ * The endpoint namespace is `agyAuth`; the hub's carrier forwards
20
+ * `envelope.method` verbatim to this world's `typertGateway`.
21
+ *
22
+ * Side effects are deliberate and bounded (the 2026-10-02 ruling
23
+ * 「拥抱用户自己的使用环境」): choosing a form rewrites the USER's real
24
+ * `~/.gemini/antigravity-cli/settings.json` immediately, so their own TUI
25
+ * behaves the same way afterwards. The SELECTION itself lives in the world home
26
+ * (`agy-adapter.json`) — adapter state never leaks into the native home.
27
+ *
28
+ * @module agent-agy/agy-auth-gateway
29
+ */
30
+ import type { Context } from "@deepseek-ai/cordis";
31
+ import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
32
+ import { type AgyAuthAvailability, type AgyAuthMode } from "./agy-auth.js";
33
+ /** One auth option as the Hub panel renders it (`client/agent-settings.ts` parses this). */
34
+ export interface AgyAuthOptionView {
35
+ /** Stable id the panel round-trips (`apiKey` | `oauth` | `adc`). */
36
+ readonly key: AgyAuthMode;
37
+ readonly label: string;
38
+ /** Detected on THIS machine right now. */
39
+ readonly available: boolean;
40
+ /** Rendered but never selectable this round (OAuth). */
41
+ readonly placeholder: boolean;
42
+ readonly hint: string;
43
+ }
44
+ /** The panel's full state: the options, the choice, and what would actually run. */
45
+ export interface AgyAuthView {
46
+ readonly methods: readonly AgyAuthOptionView[];
47
+ /** The user's persisted choice; `null` when they have not made one. */
48
+ readonly selected: AgyAuthMode | null;
49
+ /** What a new session would use right now (ladder applied); `null` when nothing is available. */
50
+ readonly effective: AgyAuthMode | null;
51
+ /** The native file a selection rewrites — shown so the effect is never a surprise. */
52
+ readonly settingsPath: string;
53
+ /** Populated only when something needs explaining (stale choice, absent ADC). */
54
+ readonly note?: string;
55
+ }
56
+ /** `agyAuth/set` payload (the gateway's single wire argument). */
57
+ export interface AgyAuthSetRequest {
58
+ /**
59
+ * The form to adopt. `null` clears the explicit choice and hands the decision
60
+ * back to the ladder. Unknown values are rejected, never coerced.
61
+ */
62
+ readonly mode?: AgyAuthMode | null;
63
+ }
64
+ /**
65
+ * The adapter's auth-form Remote. One instance per world context.
66
+ */
67
+ export declare class AgyAuthGateway extends TypertRemoteService {
68
+ private readonly home;
69
+ private readonly realHome;
70
+ private readonly availability;
71
+ /**
72
+ * @param ctx - the world context this service registers on (namespace `agyAuth`).
73
+ * @param home - the world home holding adapter state (`agy-adapter.json`).
74
+ * @param realHome - the USER's real home (native settings live there).
75
+ * @param availability - probe of the current machine.
76
+ */
77
+ constructor(ctx: Context, home: string, realHome: () => string, availability: () => AgyAuthAvailability);
78
+ /**
79
+ * Read the panel state. Pure read: no probe beyond what the caller injected,
80
+ * no write, safe to call on every expand.
81
+ * @returns the options, the persisted choice, and the effective form.
82
+ */
83
+ get(): Promise<AgyAuthView>;
84
+ /**
85
+ * Adopt one form (or clear the choice), persist it to the world home, and
86
+ * apply the matching mutation to the user's native settings.json right away.
87
+ *
88
+ * Applying immediately is the point of the 2026-10-02 ruling: leaving a
89
+ * previously selected key mode pinned would strand the user's own TUI on
90
+ * "Gemini API key" with no key exported.
91
+ * @param request - the requested form.
92
+ * @returns the panel state after the change.
93
+ * @throws {TypeError} when `mode` is neither a known form nor null/absent.
94
+ */
95
+ set(request?: AgyAuthSetRequest | null): Promise<AgyAuthView>;
96
+ /** Project the current probe + persisted choice into the panel's view model. */
97
+ private view;
98
+ }
99
+ /**
100
+ * The panel's view model. Pure: the probe result, the persisted choice and the
101
+ * settings path are all injected, which is what makes the ladder and the
102
+ * annotation rules pinnable under `node --test` with no Cordis context and no
103
+ * real home.
104
+ *
105
+ * @param input - probe, persisted selection (raw; unknown values are ignored), settings path.
106
+ * @returns the options, the choice, and the form that would actually run.
107
+ */
108
+ export declare function buildAuthView(input: {
109
+ availability: AgyAuthAvailability;
110
+ selected?: unknown;
111
+ settingsPath: string;
112
+ }): AgyAuthView;
113
+ /**
114
+ * Validate one `agyAuth/set` request into the mode to adopt.
115
+ *
116
+ * `null` means "clear the explicit choice and let the ladder decide" — a real
117
+ * instruction, not a missing value, which is why an absent field and an
118
+ * explicit `null` agree while an unknown string is rejected.
119
+ *
120
+ * @param request - the wire payload's `request` argument.
121
+ * @returns the mode to persist, or `null` to clear the choice.
122
+ * @throws {TypeError} on an unknown mode.
123
+ */
124
+ export declare function normalizeSetRequest(request?: AgyAuthSetRequest | null): AgyAuthMode | null;
@@ -0,0 +1,233 @@
1
+ /**
2
+ * agy-auth-gateway.ts — the adapter-owned Remote behind the Hub's Antigravity
3
+ * settings panel (P3, 2026-10-02 user ruling).
4
+ *
5
+ * Why a Remote and not a hub route: the auth ladder, the probe results and the
6
+ * native-settings mutation are ADAPTER config (agent-adapter-dev-rules §12), so
7
+ * the adapter owns them and the hub only forwards. `TypertRemoteService` +
8
+ * `@Remote` is the whole mechanism — standard (TC39) method decorators recorded
9
+ * on the class prototype, read back at dispatch time by the gateway's
10
+ * source-claim scan. There is NO codegen step and no compiler-injected
11
+ * metadata, which is why a plain `tsc` adapter build can ship one.
12
+ *
13
+ * Wire contract (both halves are pinned by tests):
14
+ * request POST /hub/api?agent=agy
15
+ * { type:'client-request', rpcId, method:'agyAuth/get'|'agyAuth/set',
16
+ * payload: { args: { request?: AgyAuthSetRequest } } }
17
+ * response { type:'server-response', rpcId, result:{ ok:true, value:<view> } }
18
+ *
19
+ * The endpoint namespace is `agyAuth`; the hub's carrier forwards
20
+ * `envelope.method` verbatim to this world's `typertGateway`.
21
+ *
22
+ * Side effects are deliberate and bounded (the 2026-10-02 ruling
23
+ * 「拥抱用户自己的使用环境」): choosing a form rewrites the USER's real
24
+ * `~/.gemini/antigravity-cli/settings.json` immediately, so their own TUI
25
+ * behaves the same way afterwards. The SELECTION itself lives in the world home
26
+ * (`agy-adapter.json`) — adapter state never leaks into the native home.
27
+ *
28
+ * @module agent-agy/agy-auth-gateway
29
+ */
30
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
31
+ var useValue = arguments.length > 2;
32
+ for (var i = 0; i < initializers.length; i++) {
33
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
34
+ }
35
+ return useValue ? value : void 0;
36
+ };
37
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
38
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
39
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
40
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
41
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
42
+ var _, done = false;
43
+ for (var i = decorators.length - 1; i >= 0; i--) {
44
+ var context = {};
45
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
46
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
47
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
48
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
49
+ if (kind === "accessor") {
50
+ if (result === void 0) continue;
51
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
52
+ if (_ = accept(result.get)) descriptor.get = _;
53
+ if (_ = accept(result.set)) descriptor.set = _;
54
+ if (_ = accept(result.init)) initializers.unshift(_);
55
+ }
56
+ else if (_ = accept(result)) {
57
+ if (kind === "field") initializers.unshift(_);
58
+ else descriptor[key] = _;
59
+ }
60
+ }
61
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
62
+ done = true;
63
+ };
64
+ import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
65
+ import { AGY_AUTH_LABELS, AGY_AUTH_ORDER, authSettingsMutation, nativeSettingsPath, resolveAuthMode, } from "./agy-auth.js";
66
+ import { applyAgySettings } from "./agy-cli-client.js";
67
+ import { readAdapterState, writeAdapterState } from "./agy-store.js";
68
+ /**
69
+ * OAuth is NOT a placeholder any more (measured 2026-10-02): it is the CLI's own
70
+ * Google sign-in (Agent Platform), the plane headless actually runs on, and the
71
+ * one that works on this machine with no key, no ADC and no `modelProvider`.
72
+ * Selecting it means "let the CLI use the account it is already signed in as".
73
+ */
74
+ function isMode(value) {
75
+ return typeof value === "string" && AGY_AUTH_ORDER.includes(value);
76
+ }
77
+ /**
78
+ * The adapter's auth-form Remote. One instance per world context.
79
+ */
80
+ let AgyAuthGateway = (() => {
81
+ let _classSuper = TypertRemoteService;
82
+ let _instanceExtraInitializers = [];
83
+ let _get_decorators;
84
+ let _set_decorators;
85
+ return class AgyAuthGateway extends _classSuper {
86
+ static {
87
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
88
+ _get_decorators = [Remote("get")];
89
+ _set_decorators = [Remote("set")];
90
+ __esDecorate(this, null, _get_decorators, { kind: "method", name: "get", static: false, private: false, access: { has: obj => "get" in obj, get: obj => obj.get }, metadata: _metadata }, null, _instanceExtraInitializers);
91
+ __esDecorate(this, null, _set_decorators, { kind: "method", name: "set", static: false, private: false, access: { has: obj => "set" in obj, get: obj => obj.set }, metadata: _metadata }, null, _instanceExtraInitializers);
92
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
93
+ }
94
+ home = __runInitializers(this, _instanceExtraInitializers);
95
+ realHome;
96
+ availability;
97
+ /**
98
+ * @param ctx - the world context this service registers on (namespace `agyAuth`).
99
+ * @param home - the world home holding adapter state (`agy-adapter.json`).
100
+ * @param realHome - the USER's real home (native settings live there).
101
+ * @param availability - probe of the current machine.
102
+ */
103
+ constructor(ctx, home, realHome, availability) {
104
+ super(ctx, "agyAuth");
105
+ this.home = home;
106
+ this.realHome = realHome;
107
+ this.availability = availability;
108
+ }
109
+ /**
110
+ * Read the panel state. Pure read: no probe beyond what the caller injected,
111
+ * no write, safe to call on every expand.
112
+ * @returns the options, the persisted choice, and the effective form.
113
+ */
114
+ async get() {
115
+ return this.view();
116
+ }
117
+ /**
118
+ * Adopt one form (or clear the choice), persist it to the world home, and
119
+ * apply the matching mutation to the user's native settings.json right away.
120
+ *
121
+ * Applying immediately is the point of the 2026-10-02 ruling: leaving a
122
+ * previously selected key mode pinned would strand the user's own TUI on
123
+ * "Gemini API key" with no key exported.
124
+ * @param request - the requested form.
125
+ * @returns the panel state after the change.
126
+ * @throws {TypeError} when `mode` is neither a known form nor null/absent.
127
+ */
128
+ async set(request) {
129
+ const mode = normalizeSetRequest(request);
130
+ const state = readAdapterState(this.home);
131
+ if (mode === null) {
132
+ const { authMode: _dropped, ...rest } = state;
133
+ writeAdapterState(this.home, rest);
134
+ }
135
+ else {
136
+ writeAdapterState(this.home, { ...state, authMode: mode });
137
+ }
138
+ // The native flip follows the EFFECTIVE form: clearing the choice (or
139
+ // selecting a form that is not present) must still undo a stale key pin
140
+ // rather than leave the user's TUI stuck on it.
141
+ const effective = resolveAuthMode(this.availability(), mode ?? undefined);
142
+ if (effective !== undefined) {
143
+ applyAgySettings(this.realHome(), authSettingsMutation(effective));
144
+ }
145
+ return this.view();
146
+ }
147
+ /** Project the current probe + persisted choice into the panel's view model. */
148
+ view() {
149
+ return buildAuthView({
150
+ availability: this.availability(),
151
+ selected: readAdapterState(this.home).authMode,
152
+ settingsPath: nativeSettingsPath(this.realHome()),
153
+ });
154
+ }
155
+ };
156
+ })();
157
+ export { AgyAuthGateway };
158
+ /**
159
+ * The panel's view model. Pure: the probe result, the persisted choice and the
160
+ * settings path are all injected, which is what makes the ladder and the
161
+ * annotation rules pinnable under `node --test` with no Cordis context and no
162
+ * real home.
163
+ *
164
+ * @param input - probe, persisted selection (raw; unknown values are ignored), settings path.
165
+ * @returns the options, the choice, and the form that would actually run.
166
+ */
167
+ export function buildAuthView(input) {
168
+ const { availability, settingsPath } = input;
169
+ const known = isMode(input.selected) ? input.selected : undefined;
170
+ const effective = resolveAuthMode(availability, known) ?? null;
171
+ const methods = AGY_AUTH_ORDER.map((mode) => ({
172
+ key: mode,
173
+ label: AGY_AUTH_LABELS[mode],
174
+ available: availability[mode],
175
+ placeholder: false,
176
+ hint: hintFor(mode, availability),
177
+ }));
178
+ const note = noteFor(known, effective, availability);
179
+ return {
180
+ methods,
181
+ selected: known ?? null,
182
+ effective,
183
+ settingsPath,
184
+ ...(note === undefined ? {} : { note }),
185
+ };
186
+ }
187
+ /**
188
+ * Validate one `agyAuth/set` request into the mode to adopt.
189
+ *
190
+ * `null` means "clear the explicit choice and let the ladder decide" — a real
191
+ * instruction, not a missing value, which is why an absent field and an
192
+ * explicit `null` agree while an unknown string is rejected.
193
+ *
194
+ * @param request - the wire payload's `request` argument.
195
+ * @returns the mode to persist, or `null` to clear the choice.
196
+ * @throws {TypeError} on an unknown mode.
197
+ */
198
+ export function normalizeSetRequest(request) {
199
+ const requested = request?.mode;
200
+ if (requested === undefined || requested === null)
201
+ return null;
202
+ if (!isMode(requested)) {
203
+ throw new TypeError(`agyAuth/set: unknown auth mode ${JSON.stringify(requested)}`);
204
+ }
205
+ return requested;
206
+ }
207
+ /** One short line per option: what makes it usable, or what is missing. */
208
+ function hintFor(mode, availability) {
209
+ if (mode === "oauth") {
210
+ return availability.oauth
211
+ ? "Uses the CLI's own Google sign-in (Agent Platform) — the default backend."
212
+ : "No Google sign-in found; run `agy` once to sign in.";
213
+ }
214
+ if (mode === "apiKey") {
215
+ return availability.apiKey
216
+ ? "A key is available (saved for this runtime or GEMINI_API_KEY)."
217
+ : "No key yet — save one, or export GEMINI_API_KEY.";
218
+ }
219
+ return availability.adc
220
+ ? "Application Default Credentials found on this machine."
221
+ : "No ADC found — run `gcloud auth application-default login`.";
222
+ }
223
+ /** Explain the one case the panel cannot show on its own: a stale selection. */
224
+ function noteFor(selected, effective, availability) {
225
+ if (selected !== undefined && !availability[selected]) {
226
+ return effective === null
227
+ ? `${AGY_AUTH_LABELS[selected]} is no longer present on this machine, and no other form is available.`
228
+ : `${AGY_AUTH_LABELS[selected]} is no longer present on this machine — falling back to ${AGY_AUTH_LABELS[effective]}.`;
229
+ }
230
+ if (effective === null)
231
+ return "No auth form is available yet; sessions will ask for one.";
232
+ return undefined;
233
+ }
@@ -0,0 +1,153 @@
1
+ /**
2
+ * agy-auth.ts — the CLI adapter's auth-form detection, fallback ladder, and
3
+ * the mutation it applies to the user's LOCAL Antigravity configuration.
4
+ *
5
+ * The Antigravity CLI has four auth channels (dev-rules §16a, re-probed
6
+ * 2026-10-02 against `agy` 1.2.14):
7
+ *
8
+ * 1. account sign-in default, `cloudcode-pa.googleapis.com`; the token
9
+ * lives in the freedesktop Secret Service keyring
10
+ * (`gnome-keyring-daemon`, `org.freedesktop.secrets`,
11
+ * entry `service=gemini username=antigravity`) with a
12
+ * file fallback at `~/.gemini/antigravity-cli/
13
+ * antigravity-oauth-token`;
14
+ * 2. Gemini API key `modelProvider: "gemini"` in the CLI's settings.json
15
+ * + `GEMINI_API_KEY` in the launch environment
16
+ * (+ optional `GOOGLE_GEMINI_BASE_URL`);
17
+ * 3. ADC `AGY_ADC_AUTH=1` — `adc_auth.go` reports
18
+ * "authenticated via adc (effective: adc)". Credentials
19
+ * are `~/.config/gcloud/application_default_credentials
20
+ * .json` (or a GCE metadata server). NOT the keyring;
21
+ * 4. BYO gateway `AGY_LLM_GATEWAY_*` (out of scope; see the spec).
22
+ *
23
+ * user ruling 2026-10-02 (supersedes the dev-rules §5 "never write the native
24
+ * home" default for THIS adapter, under §12 per-adapter discretion):
25
+ *
26
+ * 「拥抱用户自己的使用环境」 — this adapter is deliberately the configuration
27
+ * surface for the user's LOCAL Antigravity. Selecting a form here really does
28
+ * rewrite their `~/.gemini/antigravity-cli/settings.json`, so the TUI they
29
+ * already use keeps working afterwards. Paths are hard-coded relative to the
30
+ * user's home for exactly that reason.
31
+ *
32
+ * Fallback order (same ruling) = Gemini API key → OAuth → ADC. OAuth stays a
33
+ * PLACEHOLDER this round: no eligible account exists to characterise the
34
+ * native fields a real sign-in stores, so nothing reports it present.
35
+ *
36
+ * Pure: every probe result is injected, so `node --test` pins the ladder; the
37
+ * one filesystem-touching helper (`nativeSettingsPath`) is a pure path fold.
38
+ *
39
+ * @module agent-agy/agy-auth
40
+ */
41
+ /** The three forms this adapter arbitrates. */
42
+ export type AgyAuthMode = "apiKey" | "oauth" | "adc";
43
+ /** Which forms are present right now (probe result). */
44
+ export interface AgyAuthAvailability {
45
+ readonly apiKey: boolean;
46
+ readonly oauth: boolean;
47
+ readonly adc: boolean;
48
+ }
49
+ /** Declared fallback order (user ruling 2026-10-02). Exported for the UI. */
50
+ export declare const AGY_AUTH_ORDER: readonly AgyAuthMode[];
51
+ /** Human labels, shared by the Hub settings panel and diagnostics. */
52
+ export declare const AGY_AUTH_LABELS: Readonly<Record<AgyAuthMode, string>>;
53
+ /**
54
+ * The CLI's own app-data directory, hard-coded under the USER's home — the
55
+ * native Antigravity config we deliberately share with the TUI.
56
+ *
57
+ * @param realHome - the user's real `$HOME` (never an isolated override).
58
+ * @returns the absolute app-data directory.
59
+ */
60
+ export declare function nativeCliDir(realHome: string): string;
61
+ /**
62
+ * The CLI's settings file. The binary documents the auth flip here: "To switch
63
+ * back to signing in, remove `modelProvider` from settings.json and restart
64
+ * the CLI."
65
+ *
66
+ * @param realHome - the user's real `$HOME`.
67
+ * @returns the absolute settings.json path.
68
+ */
69
+ export declare function nativeSettingsPath(realHome: string): string;
70
+ /**
71
+ * The credential file the CLI writes when a Google account signs in. This is
72
+ * the **Agent Platform** plane: `auth_method: "gcp"`, a `project_id`, and an
73
+ * access/refresh token pair. It is the backend the interactive TUI uses.
74
+ *
75
+ * @param realHome - the user's real `$HOME`.
76
+ * @returns the absolute path of the CLI's stored sign-in credential.
77
+ */
78
+ export declare function signinTokenPath(realHome: string): string;
79
+ /**
80
+ * Is the CLI's own Google sign-in in place?
81
+ *
82
+ * Measured 2026-10-02 (this machine): headless CLI reads this plane first, and
83
+ * when it is present the transport works with NO Gemini API key, NO
84
+ * `AGY_ADC_AUTH`, and NO `modelProvider` in settings — the run reaches
85
+ * `result.status: SUCCESS`.
86
+ *
87
+ * This is what the auth ladder's middle rung means in practice: not a
88
+ * placeholder, but "let the CLI use the account it is already signed in as".
89
+ * It therefore must be DETECTED rather than assumed absent: treating it as
90
+ * permanently unavailable is what pushed the ladder onto ADC, whose project
91
+ * has `cloudcode-pa` disabled, and the adapter could never start a turn.
92
+ *
93
+ * @param realHome - the user's real `$HOME`.
94
+ * @returns whether a non-empty sign-in credential is on disk.
95
+ */
96
+ export declare function hasSigninCredential(realHome: string): boolean;
97
+ /** A settings.json mutation: keys to set, keys to remove. */
98
+ export interface AgySettingsMutation {
99
+ readonly set: Readonly<Record<string, unknown>>;
100
+ readonly remove: readonly string[];
101
+ }
102
+ /**
103
+ * The settings.json change one form needs.
104
+ *
105
+ * Key mode pins the Gemini provider. ADC and OAuth need the DEFAULT backend, so
106
+ * `modelProvider` must be actively REMOVED — merely not setting it would leave
107
+ * a previously selected key mode in force and the TUI stuck on "Gemini API key"
108
+ * with no key exported.
109
+ *
110
+ * @param mode - the effective form.
111
+ * @returns the mutation to apply.
112
+ */
113
+ export declare function authSettingsMutation(mode: AgyAuthMode): AgySettingsMutation;
114
+ /**
115
+ * Is this mode usable at all right now?
116
+ *
117
+ * @param availability - probe result.
118
+ * @param mode - the form to test.
119
+ * @returns whether the form is present.
120
+ */
121
+ export declare function authAvailable(availability: AgyAuthAvailability, mode: AgyAuthMode): boolean;
122
+ /**
123
+ * Resolve the effective mode: an explicit selection wins when that form is
124
+ * actually present; otherwise the ladder supplies the first available form.
125
+ * Nothing present ⇒ `undefined` (the caller gates into onboarding).
126
+ *
127
+ * A stale selection (user picked API key, key later removed) deliberately
128
+ * falls through to the ladder instead of failing — the adapter must not wedge
129
+ * on config that no longer matches the machine.
130
+ *
131
+ * @param availability - probe result.
132
+ * @param selected - the user's persisted choice, when any.
133
+ * @returns the effective form, or `undefined` when nothing is available.
134
+ */
135
+ export declare function resolveAuthMode(availability: AgyAuthAvailability, selected?: AgyAuthMode | undefined): AgyAuthMode | undefined;
136
+ /**
137
+ * The environment additions the spawned CLI needs for one mode.
138
+ *
139
+ * `AGY_CLI_DISABLE_AUTO_UPDATE=1` rides every mode: the CLI silently
140
+ * self-updated 1.2.12 → 1.2.14 on this machine on 2026-10-02, which makes any
141
+ * acceptance run unreproducible.
142
+ *
143
+ * NOTE there is no HOME handling here at all: the adapter runs the CLI against
144
+ * the user's REAL home in every mode. Isolating HOME (the previous design) both
145
+ * hid the very settings.json we now maintain and silently destroyed ADC
146
+ * (`$HOME/.config/gcloud`) and the keyring — which is how this adapter
147
+ * previously mis-concluded "the CLI cannot use ADC".
148
+ *
149
+ * @param mode - the effective form.
150
+ * @param apiKey - the resolved key (env or adapter state); empty ⇒ omitted.
151
+ * @returns env entries to ADD to the child's environment.
152
+ */
153
+ export declare function authChildEnv(mode: AgyAuthMode, apiKey?: string | undefined): Record<string, string>;