super-dsh 0.1.0 → 0.1.1
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.
- package/agent-agy/bridge/agy_bridge.py +250 -0
- package/agent-agy/bridge/gemini_openai_server.mjs +98 -0
- package/agent-agy/cordis.patch.yml +49 -0
- package/agent-agy/dist/adapter.d.ts +15 -0
- package/agent-agy/dist/adapter.js +42 -0
- package/agent-agy/dist/agent-preset-agy.d.ts +47 -0
- package/agent-agy/dist/agent-preset-agy.js +169 -0
- package/agent-agy/dist/agent-preset-projection.d.ts +31 -0
- package/agent-agy/dist/agent-preset-projection.js +33 -0
- package/agent-agy/dist/agent.d.ts +137 -0
- package/agent-agy/dist/agent.js +493 -0
- package/agent-agy/dist/agy-cli-client.d.ts +137 -0
- package/agent-agy/dist/agy-cli-client.js +301 -0
- package/agent-agy/dist/agy-client.d.ts +160 -0
- package/agent-agy/dist/agy-client.js +252 -0
- package/agent-agy/dist/agy-sessions.d.ts +24 -0
- package/agent-agy/dist/agy-sessions.js +116 -0
- package/agent-agy/dist/agy-store.d.ts +39 -0
- package/agent-agy/dist/agy-store.js +83 -0
- package/agent-agy/dist/inbox.d.ts +26 -0
- package/agent-agy/dist/inbox.js +53 -0
- package/agent-agy/dist/index.d.ts +80 -0
- package/agent-agy/dist/index.js +505 -0
- package/agent-agy/dist/models.d.ts +41 -0
- package/agent-agy/dist/models.js +74 -0
- package/agent-agy/dist/world-plugin.d.ts +9 -0
- package/agent-agy/dist/world-plugin.js +88 -0
- package/agent-agy/package.json +64 -0
- package/agent-claude/cordis.patch.yml +42 -0
- package/agent-claude/dist/adapter.js +62 -0
- package/agent-claude/dist/agent-preset-claude.js +169 -0
- package/agent-claude/dist/agent-preset-projection.js +30 -0
- package/agent-claude/dist/agent.js +1271 -0
- package/agent-claude/dist/claude-client.js +357 -0
- package/agent-claude/dist/claude-events.js +223 -0
- package/agent-claude/dist/claude-home.js +29 -0
- package/agent-claude/dist/commands.js +182 -0
- package/agent-claude/dist/content.js +134 -0
- package/agent-claude/dist/inbox.js +53 -0
- package/agent-claude/dist/index.js +555 -0
- package/agent-claude/dist/input-queue.js +64 -0
- package/agent-claude/dist/interaction.js +271 -0
- package/agent-claude/dist/models.js +158 -0
- package/agent-claude/dist/permission.js +120 -0
- package/agent-claude/dist/session-id.js +20 -0
- package/agent-claude/dist/session-map.js +165 -0
- package/agent-claude/dist/world-plugin.js +14 -0
- package/agent-claude/package.json +74 -0
- package/agent-codex/README.md +74 -0
- package/agent-codex/cordis.patch.yml +77 -0
- package/agent-codex/dist/adapter.js +55 -0
- package/agent-codex/dist/agent-preset-codex.js +171 -0
- package/agent-codex/dist/agent-preset-projection.js +37 -0
- package/agent-codex/dist/agent.js +1056 -0
- package/agent-codex/dist/app-home.js +65 -0
- package/agent-codex/dist/codex-client.js +469 -0
- package/agent-codex/dist/codex-events.js +297 -0
- package/agent-codex/dist/codex-store.js +190 -0
- package/agent-codex/dist/inbox.js +53 -0
- package/agent-codex/dist/index.js +605 -0
- package/agent-codex/dist/models.js +152 -0
- package/agent-codex/dist/permission.js +71 -0
- package/agent-codex/dist/session-map.js +170 -0
- package/agent-codex/dist/spike.js +46 -0
- package/agent-codex/dist/world-plugin.js +87 -0
- package/agent-codex/package.json +78 -0
- package/agent-hermes/README.md +144 -0
- package/agent-hermes/cordis.patch.yml +83 -0
- package/agent-hermes/dist/adapter.js +83 -0
- package/agent-hermes/dist/agent-preset-hermes.js +171 -0
- package/agent-hermes/dist/agent-preset-projection.js +34 -0
- package/agent-hermes/dist/agent.js +1068 -0
- package/agent-hermes/dist/hermes-client.js +953 -0
- package/agent-hermes/dist/hermes-events.js +289 -0
- package/agent-hermes/dist/hermes-store.js +158 -0
- package/agent-hermes/dist/inbox.js +53 -0
- package/agent-hermes/dist/index.js +541 -0
- package/agent-hermes/dist/models.js +324 -0
- package/agent-hermes/dist/permission.js +60 -0
- package/agent-hermes/dist/world-plugin.js +92 -0
- package/agent-hermes/package.json +76 -0
- package/agent-hub/cordis.patch.yml +12 -0
- package/agent-hub/dist/agent-roster.d.ts +34 -0
- package/agent-hub/dist/agent-roster.js +27 -0
- package/agent-hub/dist/carrier.d.ts +43 -0
- package/agent-hub/dist/carrier.js +241 -0
- package/agent-hub/dist/client-shim.d.ts +28 -0
- package/agent-hub/dist/client-shim.js +251 -0
- package/agent-hub/dist/envelope.d.ts +54 -0
- package/agent-hub/dist/envelope.js +92 -0
- package/agent-hub/dist/gateway.d.ts +28 -0
- package/agent-hub/dist/gateway.js +18 -0
- package/agent-hub/dist/index-pass.d.ts +22 -0
- package/agent-hub/dist/index-pass.js +47 -0
- package/agent-hub/dist/index.d.ts +29 -0
- package/agent-hub/dist/index.js +29 -0
- package/agent-hub/dist/labels.d.ts +45 -0
- package/agent-hub/dist/labels.js +83 -0
- package/agent-hub/dist/ownership.d.ts +37 -0
- package/agent-hub/dist/ownership.js +54 -0
- package/agent-hub/dist/roster.d.ts +28 -0
- package/agent-hub/dist/roster.js +38 -0
- package/agent-hub/dist/rpc.d.ts +38 -0
- package/agent-hub/dist/rpc.js +52 -0
- package/agent-hub/dist/spawn-world.d.ts +46 -0
- package/agent-hub/dist/spawn-world.js +72 -0
- package/agent-hub/dist/targets.d.ts +33 -0
- package/agent-hub/dist/targets.js +30 -0
- package/agent-hub/dist/world-entry.d.ts +31 -0
- package/agent-hub/dist/world-entry.js +51 -0
- package/agent-hub/dist/world-host.d.ts +69 -0
- package/agent-hub/dist/world-host.js +44 -0
- package/agent-hub/dist/world-join.d.ts +16 -0
- package/agent-hub/dist/world-join.js +113 -0
- package/agent-hub/dist/world-mount.d.ts +52 -0
- package/agent-hub/dist/world-mount.js +52 -0
- package/agent-hub/dist/world-mux.d.ts +72 -0
- package/agent-hub/dist/world-mux.js +224 -0
- package/agent-hub/dist/world-provision.d.ts +16 -0
- package/agent-hub/dist/world-provision.js +109 -0
- package/agent-hub/dist/world-web-server.d.ts +162 -0
- package/agent-hub/dist/world-web-server.js +248 -0
- package/agent-hub/lib/client/index.js +242 -0
- package/agent-hub/package.json +65 -0
- package/agent-omp/README.md +77 -0
- package/agent-omp/cordis.patch.yml +92 -0
- package/agent-omp/dist/adapter.js +36 -0
- package/agent-omp/dist/agent-preset-omp.js +171 -0
- package/agent-omp/dist/agent-preset-projection.js +36 -0
- package/agent-omp/dist/agent.js +1145 -0
- package/agent-omp/dist/app-home.js +86 -0
- package/agent-omp/dist/discovery.js +116 -0
- package/agent-omp/dist/inbox.js +53 -0
- package/agent-omp/dist/index.js +574 -0
- package/agent-omp/dist/knobs.js +50 -0
- package/agent-omp/dist/lazy-rpc.js +161 -0
- package/agent-omp/dist/mobile/gesture.js +148 -0
- package/agent-omp/dist/mobile/zoom-guard.js +294 -0
- package/agent-omp/dist/mobile-boot.js +38 -0
- package/agent-omp/dist/models.js +299 -0
- package/agent-omp/dist/omp-cli.js +147 -0
- package/agent-omp/dist/omp-disk-discovery.js +178 -0
- package/agent-omp/dist/omp-store.js +518 -0
- package/agent-omp/dist/pairing.js +45 -0
- package/agent-omp/dist/permission.js +96 -0
- package/agent-omp/dist/protocol.js +13 -0
- package/agent-omp/dist/rpc-types.js +1 -0
- package/agent-omp/dist/sdk-client.js +378 -0
- package/agent-omp/dist/sidecar-client.js +195 -0
- package/agent-omp/dist/store/adapter.js +47 -0
- package/agent-omp/dist/store/db.js +210 -0
- package/agent-omp/dist/store/index.js +59 -0
- package/agent-omp/dist/store/reconcile.js +51 -0
- package/agent-omp/dist/store/schema.js +40 -0
- package/agent-omp/dist/world-plugin.js +87 -0
- package/agent-omp/package.json +97 -0
- package/agent-omp/sidecar/main.ts +481 -0
- package/agent-pi/README.md +67 -0
- package/agent-pi/cordis.patch.yml +80 -0
- package/agent-pi/dist/adapter.js +53 -0
- package/agent-pi/dist/agent-preset-pi.js +169 -0
- package/agent-pi/dist/agent-preset-projection.js +29 -0
- package/agent-pi/dist/agent.js +949 -0
- package/agent-pi/dist/inbox.js +53 -0
- package/agent-pi/dist/index.js +595 -0
- package/agent-pi/dist/knobs.js +24 -0
- package/agent-pi/dist/models.js +200 -0
- package/agent-pi/dist/permission.js +66 -0
- package/agent-pi/dist/pi-client.js +224 -0
- package/agent-pi/dist/pi-events.js +155 -0
- package/agent-pi/dist/pi-home.js +55 -0
- package/agent-pi/dist/safe-json.js +25 -0
- package/agent-pi/dist/session-map.js +119 -0
- package/agent-pi/dist/world-plugin.js +88 -0
- package/agent-pi/package.json +77 -0
- package/cordis.patch.yml +22 -19
- package/package.json +45 -11
- package/client.js +0 -4
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# agy_bridge.py — JSONL-over-stdio bridge hosting the google-antigravity SDK.
|
|
3
|
+
#
|
|
4
|
+
# Contract (one JSON object per line; requests on stdin, events on stdout):
|
|
5
|
+
# -> {"op":"start", "model":str, "thinking_level"?:"minimal|low|medium|high|extra_high",
|
|
6
|
+
# "api_key"?:str, "project"?:str, "location"?:str,
|
|
7
|
+
# "approval_mode"?:"allow"|"ask", # default "allow"
|
|
8
|
+
# "workspaces":[str], "save_dir"?:str}
|
|
9
|
+
# (localharness is NOT spawned here — materializes lazily on first prompt)
|
|
10
|
+
# -> {"op":"prompt", "text":str, "conversation_id"?:str}
|
|
11
|
+
# streams back:
|
|
12
|
+
# <- {"event":"thinking","text":str} # Thought delta (reasoning)
|
|
13
|
+
# <- {"event":"chunk","text":str} # Text delta
|
|
14
|
+
# <- {"event":"tool","name":str} # tool dispatched
|
|
15
|
+
# <- {"event":"approval_request","id":str,"tool":str,"args":str} # ask mode
|
|
16
|
+
# <- {"event":"usage","input_tokens":int,"output_tokens":int,
|
|
17
|
+
# "thinking_tokens":int,"total_tokens":int} # best effort
|
|
18
|
+
# <- {"event":"done","conversation_id":str,"turn_ms":int}
|
|
19
|
+
# <- {"event":"error","error":str,"recoverable":bool}
|
|
20
|
+
# -> {"op":"approval","id":str,"allow":bool} # host reply to approval_request
|
|
21
|
+
# -> {"op":"ping"} -> {"event":"pong"}
|
|
22
|
+
# -> {"op":"close"} -> exits 0
|
|
23
|
+
#
|
|
24
|
+
# Auth is transparent: pass api_key (Gemini API key) or project (+ADC) for the
|
|
25
|
+
# Vertex endpoint. CLI (agy) is never invoked.
|
|
26
|
+
|
|
27
|
+
import asyncio
|
|
28
|
+
import json
|
|
29
|
+
import os
|
|
30
|
+
import sys
|
|
31
|
+
import time
|
|
32
|
+
import uuid
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def emit(obj):
|
|
36
|
+
sys.stdout.write(json.dumps(obj, ensure_ascii=False) + "\n")
|
|
37
|
+
sys.stdout.flush()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Bridge:
|
|
41
|
+
def __init__(self):
|
|
42
|
+
self.config = None
|
|
43
|
+
self.started = False
|
|
44
|
+
self.pending_approvals = {} # id -> asyncio.Event
|
|
45
|
+
self.approval_results = {} # id -> bool
|
|
46
|
+
self.approval_mode = "allow"
|
|
47
|
+
|
|
48
|
+
async def handle_start(self, req):
|
|
49
|
+
import google.antigravity as ga
|
|
50
|
+
|
|
51
|
+
kwargs = {
|
|
52
|
+
"model": req.get("model") or "gemini-3.5-flash",
|
|
53
|
+
"workspaces": req.get("workspaces") or [os.getcwd()],
|
|
54
|
+
}
|
|
55
|
+
if req.get("save_dir"):
|
|
56
|
+
kwargs["save_dir"] = req["save_dir"]
|
|
57
|
+
if req.get("api_key"):
|
|
58
|
+
kwargs["api_key"] = req["api_key"]
|
|
59
|
+
if req.get("project"):
|
|
60
|
+
kwargs["vertex"] = True
|
|
61
|
+
kwargs["project"] = req["project"]
|
|
62
|
+
if req.get("location"):
|
|
63
|
+
kwargs["location"] = req["location"]
|
|
64
|
+
self.approval_mode = req.get("approval_mode") or "allow"
|
|
65
|
+
# ask mode requires the SDK to keep hook objects in-process; the current
|
|
66
|
+
# localharness pickles parts of the config, which fails on runtime
|
|
67
|
+
# references (SimpleQueue). Opt-in via AGY_BRIDGE_ASK=1 until the SDK
|
|
68
|
+
# supports in-process hooks; otherwise degrade to allow with a trace.
|
|
69
|
+
if self.approval_mode == "ask":
|
|
70
|
+
if os.environ.get("AGY_BRIDGE_ASK") == "1":
|
|
71
|
+
kwargs["hooks"] = list(kwargs.get("hooks") or []) + [PreToolApprovalBridge(self)]
|
|
72
|
+
else:
|
|
73
|
+
emit({"event": "error", "error": "approval_mode=ask unavailable (SDK pickles config; set AGY_BRIDGE_ASK=1 to force); degrading to allow", "recoverable": True})
|
|
74
|
+
self.approval_mode = "allow"
|
|
75
|
+
level = req.get("thinking_level")
|
|
76
|
+
if level:
|
|
77
|
+
from google.antigravity.models import (
|
|
78
|
+
GeminiAPIEndpoint, GeminiModelOptions, ModelTarget, VertexEndpoint,
|
|
79
|
+
)
|
|
80
|
+
from google.antigravity.types import ThinkingLevel
|
|
81
|
+
if kwargs.get("vertex"):
|
|
82
|
+
endpoint = VertexEndpoint(project=kwargs.get("project"),
|
|
83
|
+
location=kwargs.get("location"))
|
|
84
|
+
else:
|
|
85
|
+
endpoint = GeminiAPIEndpoint(api_key=kwargs.get("api_key"))
|
|
86
|
+
kwargs["model"] = None
|
|
87
|
+
kwargs["models"] = [ModelTarget(
|
|
88
|
+
name=req["model"],
|
|
89
|
+
endpoint=endpoint,
|
|
90
|
+
options=GeminiModelOptions(thinking_level=ThinkingLevel(level)),
|
|
91
|
+
)]
|
|
92
|
+
self.config = ga.LocalAgentConfig(**kwargs)
|
|
93
|
+
self.started = True
|
|
94
|
+
emit({"event": "started"})
|
|
95
|
+
|
|
96
|
+
async def handle_prompt(self, req):
|
|
97
|
+
if not self.started:
|
|
98
|
+
emit({"event": "error", "error": "not started", "recoverable": False})
|
|
99
|
+
return
|
|
100
|
+
import google.antigravity as ga
|
|
101
|
+
|
|
102
|
+
text = req.get("text") or ""
|
|
103
|
+
cid = req.get("conversation_id")
|
|
104
|
+
t0 = time.time()
|
|
105
|
+
agent = ga.Agent(self.config)
|
|
106
|
+
try:
|
|
107
|
+
await agent.__aenter__()
|
|
108
|
+
resp = await agent.chat(text)
|
|
109
|
+
usage = None
|
|
110
|
+
# resp.__aiter__ yields only Text strings; .chunks carries the full
|
|
111
|
+
# typed stream (Thought / ToolCall / ToolResult).
|
|
112
|
+
async for ch in resp.chunks:
|
|
113
|
+
kind = type(ch).__name__
|
|
114
|
+
if isinstance(ch, str):
|
|
115
|
+
emit({"event": "chunk", "text": ch})
|
|
116
|
+
elif kind == "Thought":
|
|
117
|
+
emit({"event": "thinking", "text": getattr(ch, "text", "")})
|
|
118
|
+
elif kind == "Text":
|
|
119
|
+
emit({"event": "chunk", "text": getattr(ch, "text", "")})
|
|
120
|
+
elif kind == "ToolCall":
|
|
121
|
+
emit({"event": "tool_call", "id": str(getattr(ch, "id", "") or ""),
|
|
122
|
+
"name": str(getattr(ch, "name", "") or "unknown"),
|
|
123
|
+
"args": json.dumps(getattr(ch, "args", ""), ensure_ascii=False, default=str)[:600]})
|
|
124
|
+
elif kind == "ToolResult":
|
|
125
|
+
err = getattr(ch, "error", None)
|
|
126
|
+
emit({"event": "tool_result", "id": str(getattr(ch, "id", "") or ""),
|
|
127
|
+
"name": str(getattr(ch, "name", "") or ""),
|
|
128
|
+
"is_error": err is not None,
|
|
129
|
+
"result": str(getattr(ch, "result", ""))[:600]})
|
|
130
|
+
conv = agent.conversation
|
|
131
|
+
new_cid = (conv.conversation_id if conv else None) or cid or ""
|
|
132
|
+
if conv is not None:
|
|
133
|
+
u = getattr(conv, "last_turn_usage", None)
|
|
134
|
+
if callable(u):
|
|
135
|
+
u = u()
|
|
136
|
+
if u is not None:
|
|
137
|
+
d = u.model_dump() if hasattr(u, "model_dump") else {}
|
|
138
|
+
emit({"event": "usage",
|
|
139
|
+
"input_tokens": int(d.get("prompt_token_count") or 0),
|
|
140
|
+
"output_tokens": int(d.get("candidates_token_count") or 0),
|
|
141
|
+
"thinking_tokens": int(d.get("thoughts_token_count") or 0),
|
|
142
|
+
"total_tokens": int(d.get("total_token_count") or 0)})
|
|
143
|
+
emit({"event": "done", "conversation_id": new_cid,
|
|
144
|
+
"turn_ms": int((time.time() - t0) * 1000)})
|
|
145
|
+
except Exception as e: # noqa: BLE001 — surface everything to the host
|
|
146
|
+
emit({"event": "error", "error": f"{type(e).__name__}: {e}",
|
|
147
|
+
"recoverable": True})
|
|
148
|
+
finally:
|
|
149
|
+
try:
|
|
150
|
+
await agent.__aexit__(None, None, None)
|
|
151
|
+
except Exception:
|
|
152
|
+
pass
|
|
153
|
+
|
|
154
|
+
async def handle_approval(self, req):
|
|
155
|
+
aid = req.get("id")
|
|
156
|
+
if aid in self.pending_approvals:
|
|
157
|
+
self.approval_results[aid] = bool(req.get("allow"))
|
|
158
|
+
self.pending_approvals.pop(aid).set()
|
|
159
|
+
|
|
160
|
+
async def wait_approval(self, aid, timeout=120.0):
|
|
161
|
+
ev = asyncio.Event()
|
|
162
|
+
self.pending_approvals[aid] = ev
|
|
163
|
+
try:
|
|
164
|
+
await asyncio.wait_for(ev.wait(), timeout)
|
|
165
|
+
return self.approval_results.get(aid, False)
|
|
166
|
+
except asyncio.TimeoutError:
|
|
167
|
+
self.pending_approvals.pop(aid, None)
|
|
168
|
+
return False
|
|
169
|
+
|
|
170
|
+
async def main_loop(self):
|
|
171
|
+
loop = asyncio.get_event_loop()
|
|
172
|
+
|
|
173
|
+
async def read_stdin():
|
|
174
|
+
# Dedicated reader: approval ops must arrive WHILE a prompt is
|
|
175
|
+
# in flight (the prompt handler blocks its own coroutine).
|
|
176
|
+
while True:
|
|
177
|
+
line = await loop.run_in_executor(None, sys.stdin.readline)
|
|
178
|
+
if not line:
|
|
179
|
+
self.host_gone = True
|
|
180
|
+
return
|
|
181
|
+
line = line.strip()
|
|
182
|
+
if not line:
|
|
183
|
+
continue
|
|
184
|
+
try:
|
|
185
|
+
req = json.loads(line)
|
|
186
|
+
except json.JSONDecodeError as e:
|
|
187
|
+
emit({"event": "error", "error": f"bad json: {e}", "recoverable": False})
|
|
188
|
+
continue
|
|
189
|
+
op = req.get("op")
|
|
190
|
+
if op == "approval":
|
|
191
|
+
await self.handle_approval(req)
|
|
192
|
+
elif op == "ping":
|
|
193
|
+
emit({"event": "pong"})
|
|
194
|
+
else:
|
|
195
|
+
await self.ops.put(req) # close included: processed in order
|
|
196
|
+
|
|
197
|
+
self.host_gone = False
|
|
198
|
+
self.ops = asyncio.Queue()
|
|
199
|
+
reader = asyncio.ensure_future(read_stdin())
|
|
200
|
+
try:
|
|
201
|
+
while not self.host_gone:
|
|
202
|
+
req = await self.ops.get()
|
|
203
|
+
op = req.get("op")
|
|
204
|
+
if op == "start":
|
|
205
|
+
await self.handle_start(req)
|
|
206
|
+
elif op == "prompt":
|
|
207
|
+
await self.handle_prompt(req)
|
|
208
|
+
elif op == "close":
|
|
209
|
+
emit({"event": "closed"})
|
|
210
|
+
return
|
|
211
|
+
else:
|
|
212
|
+
emit({"event": "error", "error": f"unknown op {op!r}", "recoverable": False})
|
|
213
|
+
finally:
|
|
214
|
+
reader.cancel()
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _sdk_hooks():
|
|
218
|
+
from google.antigravity import hooks as hooks_mod
|
|
219
|
+
return hooks_mod
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
try:
|
|
223
|
+
_HOOKS = _sdk_hooks()
|
|
224
|
+
_DECIDE_BASE = _HOOKS.PreToolCallDecideHook
|
|
225
|
+
except Exception: # pragma: no cover — SDK absent in pure-syntax checks
|
|
226
|
+
_DECIDE_BASE = object
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class PreToolApprovalBridge(_DECIDE_BASE):
|
|
230
|
+
"""Ask the host over the bridge protocol before every tool call (ask mode)."""
|
|
231
|
+
|
|
232
|
+
def __init__(self, bridge: Bridge):
|
|
233
|
+
self.bridge = bridge
|
|
234
|
+
|
|
235
|
+
async def run(self, context, data): # SDK DecideHook protocol
|
|
236
|
+
aid = uuid.uuid4().hex
|
|
237
|
+
emit({"event": "approval_request", "id": aid,
|
|
238
|
+
"tool": str(getattr(data, "name", "unknown")),
|
|
239
|
+
"args": str(getattr(data, "args", "") or "")[:400]})
|
|
240
|
+
allow = await self.bridge.wait_approval(aid)
|
|
241
|
+
return _HOOKS.HookResult(allow=allow, message=None if allow else "denied by user")
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
async def main():
|
|
245
|
+
bridge = Bridge()
|
|
246
|
+
await bridge.main_loop()
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
if __name__ == "__main__":
|
|
250
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* gemini_openai_server.mjs — SPIKE: minimal Gemini-protocol front → OpenAI
|
|
4
|
+
* chat/completions back. Enough surface for the google-antigravity SDK's
|
|
5
|
+
* generateContent path: text messages, system instruction, SSE streaming,
|
|
6
|
+
* usage passthrough. Tools / multimodal are NOT translated (spike scope).
|
|
7
|
+
*
|
|
8
|
+
* Usage: node gemini_openai_server.mjs <listenPort> <openaiBaseUrl> <openaiKey> <openaiModel>
|
|
9
|
+
*/
|
|
10
|
+
import http from "node:http";
|
|
11
|
+
|
|
12
|
+
const [port, oaBase, oaKey, oaModel] = process.argv.slice(2);
|
|
13
|
+
const UP = `${oaBase.replace(/\/$/, "")}/chat/completions`;
|
|
14
|
+
|
|
15
|
+
function g2o(req) {
|
|
16
|
+
const messages = [];
|
|
17
|
+
const sys = req.systemInstruction ?? req.system_instruction;
|
|
18
|
+
const sysText = sys ? partsText(sys.parts ?? sys.parts === undefined ? sys.parts ?? [] : []) : "";
|
|
19
|
+
if (sysText) messages.push({ role: "system", content: sysText });
|
|
20
|
+
for (const c of req.contents ?? []) {
|
|
21
|
+
const t = partsText(c.parts ?? []);
|
|
22
|
+
if (t) messages.push({ role: c.role === "model" ? "assistant" : "user", content: t });
|
|
23
|
+
}
|
|
24
|
+
return { model: oaModel, messages, stream: req.__stream === true };
|
|
25
|
+
}
|
|
26
|
+
function partsText(parts) {
|
|
27
|
+
return (parts ?? []).map((p) => (typeof p === "string" ? p : p.text ?? "")).join("");
|
|
28
|
+
}
|
|
29
|
+
function o2g(oa, model) {
|
|
30
|
+
return {
|
|
31
|
+
candidates: [{
|
|
32
|
+
content: { role: "model", parts: [{ text: oa.choices?.[0]?.message?.content ?? "" }] },
|
|
33
|
+
finishReason: oa.choices?.[0]?.finish_reason === "length" ? "MAX_TOKENS" : "STOP",
|
|
34
|
+
}],
|
|
35
|
+
usageMetadata: oa.usage
|
|
36
|
+
? { promptTokenCount: oa.usage.prompt_tokens, candidatesTokenCount: oa.usage.completion_tokens, totalTokenCount: oa.usage.total_tokens }
|
|
37
|
+
: undefined,
|
|
38
|
+
modelVersion: model,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function callUpstream(body) {
|
|
42
|
+
const r = await fetch(UP, {
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${oaKey}` },
|
|
45
|
+
body: JSON.stringify(body),
|
|
46
|
+
});
|
|
47
|
+
if (!r.ok) throw new Error(`upstream ${r.status}: ${(await r.text()).slice(0, 200)}`);
|
|
48
|
+
return r;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const server = http.createServer(async (req, res) => {
|
|
52
|
+
const url = new URL(req.url, "http://x");
|
|
53
|
+
if (req.method === "GET" && url.pathname.endsWith("/models")) {
|
|
54
|
+
res.setHeader("Content-Type", "application/json");
|
|
55
|
+
res.end(JSON.stringify({ models: [{ name: `models/${oaModel}`, supportedGenerationMethods: ["generateContent", "streamGenerateContent"] }] }));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (req.method !== "POST") { res.writeHead(404).end(); return; }
|
|
59
|
+
let raw = "";
|
|
60
|
+
for await (const c of req) raw += c;
|
|
61
|
+
let g; try { g = JSON.parse(raw); } catch { res.writeHead(400).end(); return; }
|
|
62
|
+
const streaming = url.pathname.includes("streamGenerateContent");
|
|
63
|
+
const body = g2o({ ...g, __stream: streaming });
|
|
64
|
+
try {
|
|
65
|
+
if (!streaming) {
|
|
66
|
+
const oa = await (await callUpstream(body)).json();
|
|
67
|
+
res.setHeader("Content-Type", "application/json");
|
|
68
|
+
res.end(JSON.stringify(o2g(oa, oa.model)));
|
|
69
|
+
} else {
|
|
70
|
+
res.writeHead(200, { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" });
|
|
71
|
+
const up = await callUpstream(body);
|
|
72
|
+
const dec = new TextDecoder();
|
|
73
|
+
let buf = "";
|
|
74
|
+
for await (const chunk of up.body) {
|
|
75
|
+
buf += dec.decode(chunk, { stream: true });
|
|
76
|
+
let i;
|
|
77
|
+
while ((i = buf.indexOf("\n")) >= 0) {
|
|
78
|
+
const line = buf.slice(0, i).trim(); buf = buf.slice(i + 1);
|
|
79
|
+
if (!line.startsWith("data:")) continue;
|
|
80
|
+
const payload = line.slice(5).trim();
|
|
81
|
+
if (payload === "[DONE]") continue;
|
|
82
|
+
const oa = JSON.parse(payload);
|
|
83
|
+
const delta = oa.choices?.[0]?.delta?.content ?? "";
|
|
84
|
+
const ev = {
|
|
85
|
+
candidates: [{ content: { role: "model", parts: [{ text: delta }] } }],
|
|
86
|
+
};
|
|
87
|
+
if (oa.usage) ev.usageMetadata = { promptTokenCount: oa.usage.prompt_tokens, candidatesTokenCount: oa.usage.completion_tokens, totalTokenCount: oa.usage.total_tokens };
|
|
88
|
+
res.write(`data: ${JSON.stringify(ev)}\n\n`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
res.end();
|
|
92
|
+
}
|
|
93
|
+
} catch (e) {
|
|
94
|
+
res.writeHead(502, { "Content-Type": "application/json" });
|
|
95
|
+
res.end(JSON.stringify({ error: { code: 502, message: String(e.message ?? e) } }));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
server.listen(Number(port), "127.0.0.1", () => console.log(`gemini-openai spike on ${port} -> ${oaModel}`));
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @pgmi-builds/agent-adapter-agy bundle patch (AW-G SDK line, pi/hermes form).
|
|
2
|
+
# The `dsh.bundle.patch` layer of the adapter package: mounts the agy provider
|
|
3
|
+
# and disables the native components it replaces. Port/webserver posture is
|
|
4
|
+
# NOT here (worldMountPatches owns it); the world profile patch pins the home.
|
|
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.
|
|
9
|
+
|
|
10
|
+
- insert:
|
|
11
|
+
- id: agy-provider
|
|
12
|
+
name: '@pgmi-builds/agent-adapter-agy'
|
|
13
|
+
|
|
14
|
+
# The SDK bridge owns the live transcript; disable the built-in loop so it
|
|
15
|
+
# does not double-run alongside the bridge session.
|
|
16
|
+
- id: agent-loop
|
|
17
|
+
disabled: true
|
|
18
|
+
|
|
19
|
+
# The agy provider registers the single `agy` route on ctx.llm; leaving the
|
|
20
|
+
# native deepseek row mounted would advertise foreign models in this world.
|
|
21
|
+
- id: llm-deepseek
|
|
22
|
+
disabled: true
|
|
23
|
+
|
|
24
|
+
# Single-preset roster like pi: launch-only permission mapping (headless bridge
|
|
25
|
+
# has no per-action approval channel). Full 3-preset restatement per §4.1.
|
|
26
|
+
- id: agent-presets
|
|
27
|
+
disabled: true
|
|
28
|
+
- id: permission
|
|
29
|
+
config:
|
|
30
|
+
presets:
|
|
31
|
+
read-only:
|
|
32
|
+
sandbox: read-only
|
|
33
|
+
approval: ask
|
|
34
|
+
workspace-write:
|
|
35
|
+
sandbox: workspace-write
|
|
36
|
+
approval: ask
|
|
37
|
+
danger-full-access:
|
|
38
|
+
sandbox: danger-full-access
|
|
39
|
+
approval: never
|
|
40
|
+
defaultPreset: danger-full-access
|
|
41
|
+
|
|
42
|
+
# Directory picker: pin both faces of `browse`, unmount the auto row (§4.1).
|
|
43
|
+
- insert:
|
|
44
|
+
- id: directory-picker-browse
|
|
45
|
+
name: '@deepseek-ai/dsh-host-directory-picker-browse'
|
|
46
|
+
- id: directory-picker-browse-surface
|
|
47
|
+
name: '@deepseek-ai/dsh-client-ui-directory-picker-browse'
|
|
48
|
+
- id: directory-picker
|
|
49
|
+
disabled: true
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antigravity-backed `LlmAdapter` registered on `ctx.llm` by the Agy provider.
|
|
3
|
+
* Catalog is STATIC (models.ts): the SDK has no model-list API and the CLI
|
|
4
|
+
* catalog path is auth-gated (dev-rules §16a), so every surface is synchronous.
|
|
5
|
+
* `stream` is never dispatched — the Antigravity agent owns generation through
|
|
6
|
+
* its bridge child (`AgyAgent`); it throws rather than fabricating a wire route.
|
|
7
|
+
*/
|
|
8
|
+
import { LlmAdapter, type GenerateOptions, type LlmModelInfo, type LlmProviderInfo, type LlmResolvedModelInfo, type StreamChunk } from "@deepseek-ai/dsh-llm";
|
|
9
|
+
export declare const AGY_PROVIDER_ID = "agy";
|
|
10
|
+
export declare class AgyLlmAdapter extends LlmAdapter {
|
|
11
|
+
providerInfo(provider: string): LlmProviderInfo;
|
|
12
|
+
listModels(provider: string): Promise<readonly LlmModelInfo[]>;
|
|
13
|
+
resolveModel(provider: string, model: string): Promise<LlmResolvedModelInfo>;
|
|
14
|
+
stream(_options: GenerateOptions): AsyncIterable<StreamChunk>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antigravity-backed `LlmAdapter` registered on `ctx.llm` by the Agy provider.
|
|
3
|
+
* Catalog is STATIC (models.ts): the SDK has no model-list API and the CLI
|
|
4
|
+
* catalog path is auth-gated (dev-rules §16a), so every surface is synchronous.
|
|
5
|
+
* `stream` is never dispatched — the Antigravity agent owns generation through
|
|
6
|
+
* its bridge child (`AgyAgent`); it throws rather than fabricating a wire route.
|
|
7
|
+
*/
|
|
8
|
+
import { LlmAdapter, LlmError, ReasoningEffortId, } from "@deepseek-ai/dsh-llm";
|
|
9
|
+
import { AGY_MODEL_CATALOG } from "./models.js";
|
|
10
|
+
export const AGY_PROVIDER_ID = "agy";
|
|
11
|
+
export class AgyLlmAdapter extends LlmAdapter {
|
|
12
|
+
providerInfo(provider) {
|
|
13
|
+
return { id: provider, name: provider === AGY_PROVIDER_ID ? "Google" : provider };
|
|
14
|
+
}
|
|
15
|
+
async listModels(provider) {
|
|
16
|
+
return AGY_MODEL_CATALOG.map((model) => ({
|
|
17
|
+
provider,
|
|
18
|
+
id: model.slug,
|
|
19
|
+
name: model.label,
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
async resolveModel(provider, model) {
|
|
23
|
+
const found = AGY_MODEL_CATALOG.find((candidate) => candidate.slug === model);
|
|
24
|
+
if (found === undefined) {
|
|
25
|
+
throw new LlmError(`Agy provider "${provider}" does not serve model "${model}"`, "MODEL_NOT_FOUND");
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
provider,
|
|
29
|
+
id: found.slug,
|
|
30
|
+
name: found.label,
|
|
31
|
+
...(found.efforts === undefined ? {} : {
|
|
32
|
+
reasoning: {
|
|
33
|
+
efforts: found.efforts.map((level) => ({ id: ReasoningEffortId(level), name: level })),
|
|
34
|
+
...(found.defaultEffort === undefined ? {} : { defaultEffort: ReasoningEffortId(found.defaultEffort) }),
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
stream(_options) {
|
|
40
|
+
throw new LlmError("the Agy adapter does not stream: Antigravity owns generation through its bridge agent", "UNSUPPORTED_STREAM");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SingleAgyPresetRoster — the profile's `agentPresets` service.
|
|
3
|
+
*
|
|
4
|
+
* Antigravity is single-mode: the agy CLI/SDK bridge drives its own tools, so
|
|
5
|
+
* no Dash-side preset composition exists to choose from. But the web surfaces
|
|
6
|
+
* (new-session mode dropdown, Settings → Agent Preset) render from the roster
|
|
7
|
+
* RPC, and an absent roster renders "empty" rather than "one mode". This
|
|
8
|
+
* service publishes exactly one non-authorable preset, `Antigravity`, whose
|
|
9
|
+
* composition is deliberately empty — mounting it composes nothing, exactly
|
|
10
|
+
* the rosterless behavior the provider runs on.
|
|
11
|
+
*
|
|
12
|
+
* REGISTRATION LESSON (ported verbatim from the omp bridge via hermes): this
|
|
13
|
+
* service must be constructed on the PROVIDER's own top-level fiber, never
|
|
14
|
+
* under `ctx.plugin(...)` — a child fiber hides its @Remote routes from the
|
|
15
|
+
* API gateway's root-level remote enumeration and every agentPresets/* call
|
|
16
|
+
* 404s.
|
|
17
|
+
*/
|
|
18
|
+
import { type Context } from "@deepseek-ai/cordis";
|
|
19
|
+
import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
20
|
+
import { type Agent } from "@deepseek-ai/dsh-agent";
|
|
21
|
+
import { type AgentPreset, type AgentPresetDocument, type AgentPresetRoster } from "@deepseek-ai/dsh-agent-presets";
|
|
22
|
+
import type { ScopeKey } from "@deepseek-ai/dsh-scope";
|
|
23
|
+
export declare class SingleAgyPresetRoster extends TypertRemoteService {
|
|
24
|
+
constructor(ctx: Context);
|
|
25
|
+
get defaultId(): string;
|
|
26
|
+
get roots(): readonly never[];
|
|
27
|
+
get authorable(): boolean;
|
|
28
|
+
list(): Promise<AgentPreset[]>;
|
|
29
|
+
resolve(id?: string): Promise<AgentPreset>;
|
|
30
|
+
mount(_agentCtx: Context, id?: string): Promise<AgentPreset>;
|
|
31
|
+
recompose(_agentCtx: Context, id: string): Promise<AgentPreset>;
|
|
32
|
+
read(id: string): Promise<string>;
|
|
33
|
+
remoteList(): Promise<AgentPresetRoster>;
|
|
34
|
+
remoteRead(agentPreset: string): Promise<AgentPresetDocument>;
|
|
35
|
+
remoteCopy(from: string, id: string, name?: string): Promise<void>;
|
|
36
|
+
remoteDelete(id: string): Promise<void>;
|
|
37
|
+
/** Fixed roster: one preset, so selecting it is a no-op ack; anything else is unknown. */
|
|
38
|
+
remoteSelect(agent: Agent, agentPreset: string): Promise<string>;
|
|
39
|
+
copy(_from: string, id: string, _name?: string): Promise<void>;
|
|
40
|
+
remove(id: string): Promise<void>;
|
|
41
|
+
serviceFor(_agent: {
|
|
42
|
+
ctx: Context;
|
|
43
|
+
}, _name: string): undefined;
|
|
44
|
+
composeFrom(_agentCtx: Context, _parentCtx: Context): undefined;
|
|
45
|
+
composedPreset(_agentCtx: Context): string | undefined;
|
|
46
|
+
standingKeyFor(id?: string): Promise<ScopeKey>;
|
|
47
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
2
|
+
var useValue = arguments.length > 2;
|
|
3
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
4
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
5
|
+
}
|
|
6
|
+
return useValue ? value : void 0;
|
|
7
|
+
};
|
|
8
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
9
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
10
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
11
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
12
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
13
|
+
var _, done = false;
|
|
14
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
15
|
+
var context = {};
|
|
16
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
17
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
18
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
19
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
20
|
+
if (kind === "accessor") {
|
|
21
|
+
if (result === void 0) continue;
|
|
22
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
23
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
24
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
25
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
26
|
+
}
|
|
27
|
+
else if (_ = accept(result)) {
|
|
28
|
+
if (kind === "field") initializers.unshift(_);
|
|
29
|
+
else descriptor[key] = _;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
33
|
+
done = true;
|
|
34
|
+
};
|
|
35
|
+
import { Remote, RemoteError, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
36
|
+
const AGY_PRESET = Object.freeze({
|
|
37
|
+
id: "agy",
|
|
38
|
+
trust: "system",
|
|
39
|
+
path: "",
|
|
40
|
+
name: "Antigravity",
|
|
41
|
+
description: "Google Antigravity (Gemini) via the agent-agy adapter",
|
|
42
|
+
});
|
|
43
|
+
const COMPOSITION_TEXT = [
|
|
44
|
+
"# Antigravity (fixed roster)",
|
|
45
|
+
"",
|
|
46
|
+
"This deployment runs exactly one agent mode: the Antigravity provider bridges Dash",
|
|
47
|
+
"sessions to the google-antigravity runtime (CLI stream-json primary, SDK bridge",
|
|
48
|
+
"fallback). There is no per-session plugin composition to configure, so this",
|
|
49
|
+
"preset mounts nothing.",
|
|
50
|
+
"",
|
|
51
|
+
"rows: []",
|
|
52
|
+
"",
|
|
53
|
+
].join("\n");
|
|
54
|
+
/** The standing scope key every `agy` session reads presenters through. */
|
|
55
|
+
const STANDING_KEY = {};
|
|
56
|
+
let SingleAgyPresetRoster = (() => {
|
|
57
|
+
let _classSuper = TypertRemoteService;
|
|
58
|
+
let _instanceExtraInitializers = [];
|
|
59
|
+
let _remoteList_decorators;
|
|
60
|
+
let _remoteRead_decorators;
|
|
61
|
+
let _remoteCopy_decorators;
|
|
62
|
+
let _remoteDelete_decorators;
|
|
63
|
+
let _remoteSelect_decorators;
|
|
64
|
+
return class SingleAgyPresetRoster extends _classSuper {
|
|
65
|
+
static {
|
|
66
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
67
|
+
_remoteList_decorators = [Remote("list")];
|
|
68
|
+
_remoteRead_decorators = [Remote("read")];
|
|
69
|
+
_remoteCopy_decorators = [Remote("copy")];
|
|
70
|
+
_remoteDelete_decorators = [Remote("deletePreset")];
|
|
71
|
+
_remoteSelect_decorators = [Remote("select")];
|
|
72
|
+
__esDecorate(this, null, _remoteList_decorators, { kind: "method", name: "remoteList", static: false, private: false, access: { has: obj => "remoteList" in obj, get: obj => obj.remoteList }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
73
|
+
__esDecorate(this, null, _remoteRead_decorators, { kind: "method", name: "remoteRead", static: false, private: false, access: { has: obj => "remoteRead" in obj, get: obj => obj.remoteRead }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
74
|
+
__esDecorate(this, null, _remoteCopy_decorators, { kind: "method", name: "remoteCopy", static: false, private: false, access: { has: obj => "remoteCopy" in obj, get: obj => obj.remoteCopy }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
75
|
+
__esDecorate(this, null, _remoteDelete_decorators, { kind: "method", name: "remoteDelete", static: false, private: false, access: { has: obj => "remoteDelete" in obj, get: obj => obj.remoteDelete }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
76
|
+
__esDecorate(this, null, _remoteSelect_decorators, { kind: "method", name: "remoteSelect", static: false, private: false, access: { has: obj => "remoteSelect" in obj, get: obj => obj.remoteSelect }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
77
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
78
|
+
}
|
|
79
|
+
constructor(ctx) {
|
|
80
|
+
super(ctx, "agentPresets");
|
|
81
|
+
__runInitializers(this, _instanceExtraInitializers);
|
|
82
|
+
}
|
|
83
|
+
get defaultId() {
|
|
84
|
+
return AGY_PRESET.id;
|
|
85
|
+
}
|
|
86
|
+
get roots() {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
get authorable() {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
async list() {
|
|
93
|
+
return [AGY_PRESET];
|
|
94
|
+
}
|
|
95
|
+
async resolve(id) {
|
|
96
|
+
if (id === undefined || id === AGY_PRESET.id)
|
|
97
|
+
return AGY_PRESET;
|
|
98
|
+
throw new RemoteError("agent-preset/not-found", `agent-presets: preset "${id}" not found (available: agy)`, { agentPreset: id, available: [AGY_PRESET.id] });
|
|
99
|
+
}
|
|
100
|
+
async mount(_agentCtx, id) {
|
|
101
|
+
return this.resolve(id);
|
|
102
|
+
}
|
|
103
|
+
async recompose(_agentCtx, id) {
|
|
104
|
+
return this.resolve(id);
|
|
105
|
+
}
|
|
106
|
+
async read(id) {
|
|
107
|
+
await this.resolve(id);
|
|
108
|
+
return COMPOSITION_TEXT;
|
|
109
|
+
}
|
|
110
|
+
// ── Remote RPC surface (alpha: agentPresets routes come from @Remote) ────
|
|
111
|
+
async remoteList() {
|
|
112
|
+
if (process.env.AGY_TRACE === "1")
|
|
113
|
+
process.stderr.write("[agy-roster] remoteList INVOKED\n");
|
|
114
|
+
return {
|
|
115
|
+
presets: [
|
|
116
|
+
{
|
|
117
|
+
id: AGY_PRESET.id,
|
|
118
|
+
trust: AGY_PRESET.trust,
|
|
119
|
+
isDefault: true,
|
|
120
|
+
name: AGY_PRESET.name,
|
|
121
|
+
description: AGY_PRESET.description,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
authorable: this.authorable,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async remoteRead(agentPreset) {
|
|
128
|
+
const preset = await this.resolve(agentPreset);
|
|
129
|
+
return {
|
|
130
|
+
agentPreset: preset.id,
|
|
131
|
+
trust: preset.trust,
|
|
132
|
+
content: await this.read(preset.id),
|
|
133
|
+
name: preset.name,
|
|
134
|
+
description: preset.description,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
async remoteCopy(from, id, name) {
|
|
138
|
+
await this.copy(from, id, name);
|
|
139
|
+
}
|
|
140
|
+
async remoteDelete(id) {
|
|
141
|
+
await this.remove(id);
|
|
142
|
+
}
|
|
143
|
+
/** Fixed roster: one preset, so selecting it is a no-op ack; anything else is unknown. */
|
|
144
|
+
async remoteSelect(agent, agentPreset) {
|
|
145
|
+
const preset = await this.resolve(agentPreset);
|
|
146
|
+
return preset.id;
|
|
147
|
+
}
|
|
148
|
+
async copy(_from, id, _name) {
|
|
149
|
+
throw new RemoteError("agent-preset/read-only", `agent-presets: preset "${id}" cannot be written: the Antigravity roster is fixed and ships exactly one preset`, { agentPreset: id, reason: "the Antigravity roster is fixed and ships exactly one preset" });
|
|
150
|
+
}
|
|
151
|
+
async remove(id) {
|
|
152
|
+
throw new RemoteError("agent-preset/read-only", `agent-presets: preset "${id}" cannot be written: the Antigravity roster is fixed and ships exactly one preset`, { agentPreset: id, reason: "the Antigravity roster is fixed and ships exactly one preset" });
|
|
153
|
+
}
|
|
154
|
+
serviceFor(_agent, _name) {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
composeFrom(_agentCtx, _parentCtx) {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
composedPreset(_agentCtx) {
|
|
161
|
+
return AGY_PRESET.id;
|
|
162
|
+
}
|
|
163
|
+
async standingKeyFor(id) {
|
|
164
|
+
await this.resolve(id);
|
|
165
|
+
return STANDING_KEY;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
})();
|
|
169
|
+
export { SingleAgyPresetRoster };
|