@borgee/agents-host 0.2.1 → 0.2.26
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/README.md +184 -21
- package/dist/agents-host-supervisor.d.ts +7 -5
- package/dist/agents-host-supervisor.js +24 -4
- package/dist/agents-host.d.ts +89 -15
- package/dist/agents-host.js +2099 -142
- package/dist/chat/chat-control-plane.d.ts +14 -3
- package/dist/chat/sdk-chat-control-plane.d.ts +16 -4
- package/dist/chat/sdk-chat-control-plane.js +69 -9
- package/dist/cli-args.d.ts +46 -5
- package/dist/cli-args.js +313 -32
- package/dist/cli.d.ts +9 -0
- package/dist/cli.js +112 -5
- package/dist/compatibility-gates.d.ts +35 -0
- package/dist/compatibility-gates.js +127 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +23 -5
- package/dist/connections-state-store.d.ts +81 -0
- package/dist/connections-state-store.js +228 -0
- package/dist/context/injection.d.ts +109 -0
- package/dist/context/injection.js +350 -0
- package/dist/context/prompt.d.ts +4 -1
- package/dist/context/prompt.js +170 -1
- package/dist/context/turn-preparation.d.ts +9 -0
- package/dist/context/turn-preparation.js +106 -0
- package/dist/debug.d.ts +44 -0
- package/dist/debug.js +135 -0
- package/dist/gateway/localhost-gateway.d.ts +52 -0
- package/dist/gateway/localhost-gateway.js +857 -0
- package/dist/index.js +7 -5
- package/dist/local-config.d.ts +4 -1
- package/dist/local-config.js +24 -7
- package/dist/managed-daemon-log.d.ts +34 -0
- package/dist/managed-daemon-log.js +261 -0
- package/dist/managed-daemon.d.ts +220 -0
- package/dist/managed-daemon.js +1601 -0
- package/dist/policy/authorization-audit.d.ts +63 -0
- package/dist/policy/authorization-audit.js +94 -0
- package/dist/policy/copilot-permission.d.ts +15 -0
- package/dist/policy/copilot-permission.js +193 -0
- package/dist/policy/gateway-authorization.d.ts +42 -0
- package/dist/policy/gateway-authorization.js +162 -0
- package/dist/providers/awaiting-user.d.ts +12 -0
- package/dist/providers/awaiting-user.js +151 -0
- package/dist/providers/claude/adapter.d.ts +3 -1
- package/dist/providers/claude/adapter.js +8 -12
- package/dist/providers/claude/cli-client.d.ts +12 -5
- package/dist/providers/claude/cli-client.js +184 -37
- package/dist/providers/claude/session-store.d.ts +24 -0
- package/dist/providers/claude/session-store.js +65 -12
- package/dist/providers/codex/adapter.d.ts +11 -0
- package/dist/providers/codex/adapter.js +19 -0
- package/dist/providers/codex/cli-client.d.ts +103 -0
- package/dist/providers/codex/cli-client.js +1133 -0
- package/dist/providers/codex/project-doc.d.ts +3 -0
- package/dist/providers/codex/project-doc.js +66 -0
- package/dist/providers/codex/session-store.d.ts +38 -0
- package/dist/providers/codex/session-store.js +150 -0
- package/dist/providers/copilot/adapter.d.ts +3 -1
- package/dist/providers/copilot/adapter.js +8 -12
- package/dist/providers/copilot/cli-client.d.ts +20 -2
- package/dist/providers/copilot/cli-client.js +251 -71
- package/dist/providers/copilot/session-store.d.ts +24 -0
- package/dist/providers/copilot/session-store.js +65 -12
- package/dist/providers/create-provider.d.ts +11 -2
- package/dist/providers/create-provider.js +131 -12
- package/dist/run.d.ts +1 -0
- package/dist/run.js +5 -2
- package/dist/state-paths.d.ts +13 -1
- package/dist/state-paths.js +84 -3
- package/dist/task-thread-resolution.d.ts +10 -0
- package/dist/task-thread-resolution.js +48 -0
- package/dist/types.d.ts +174 -1
- package/dist/visible-mentions.d.ts +3 -0
- package/dist/visible-mentions.js +15 -0
- package/package.json +19 -17
- package/skills/borgee-agent/SKILL.md +33 -0
- package/skills/borgee-agent/borgee-agent.mjs +473 -0
- package/skills/borgee-agent/borgee-agent.py +409 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from urllib.error import HTTPError
|
|
9
|
+
from urllib.parse import quote, urlencode
|
|
10
|
+
from urllib.request import Request, urlopen
|
|
11
|
+
|
|
12
|
+
TASK_THREAD_COLLECTION_COMMAND_ERROR = (
|
|
13
|
+
"Task assignment threads only support --get-task and --update-task. "
|
|
14
|
+
"Create/list tasks belong to the parent channel."
|
|
15
|
+
)
|
|
16
|
+
TASK_THREAD_MISSING_TASK_ID_ERROR = (
|
|
17
|
+
"Task assignment thread could not resolve the current task from persisted context "
|
|
18
|
+
"or local fallback. Pass --task-id explicitly."
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def parse_int(flag: str, value: str | None) -> int:
|
|
23
|
+
if value is None:
|
|
24
|
+
raise ValueError(f"Missing value after {flag}")
|
|
25
|
+
try:
|
|
26
|
+
return int(value)
|
|
27
|
+
except ValueError as exc:
|
|
28
|
+
raise ValueError(f"Invalid integer for {flag}: {value}") from exc
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def parse_args(argv: list[str]) -> dict[str, object]:
|
|
32
|
+
context_path: Path | None = None
|
|
33
|
+
auth_path: Path | None = None
|
|
34
|
+
turn_execution_id: str | None = None
|
|
35
|
+
action = "print-bootstrap"
|
|
36
|
+
limit: int | None = None
|
|
37
|
+
before: int | None = None
|
|
38
|
+
after: int | None = None
|
|
39
|
+
body: str | None = None
|
|
40
|
+
reply_to_id: str | None = None
|
|
41
|
+
mention_target_id: str | None = None
|
|
42
|
+
mentions: list[str] = []
|
|
43
|
+
title: str | None = None
|
|
44
|
+
description: str | None = None
|
|
45
|
+
assignee_id: str | None = None
|
|
46
|
+
task_id: str | None = None
|
|
47
|
+
status: str | None = None
|
|
48
|
+
index = 0
|
|
49
|
+
|
|
50
|
+
def set_action(next_action: str) -> None:
|
|
51
|
+
nonlocal action
|
|
52
|
+
if action != "print-bootstrap":
|
|
53
|
+
raise ValueError("Only one action flag may be used per invocation")
|
|
54
|
+
action = next_action
|
|
55
|
+
|
|
56
|
+
while index < len(argv):
|
|
57
|
+
arg = argv[index]
|
|
58
|
+
if arg == "--context":
|
|
59
|
+
index += 1
|
|
60
|
+
if index >= len(argv):
|
|
61
|
+
raise ValueError("Missing path after --context")
|
|
62
|
+
context_path = Path(argv[index]).resolve()
|
|
63
|
+
elif arg == "--auth-path":
|
|
64
|
+
index += 1
|
|
65
|
+
if index >= len(argv):
|
|
66
|
+
raise ValueError("Missing path after --auth-path")
|
|
67
|
+
auth_path = Path(argv[index]).resolve()
|
|
68
|
+
elif arg == "--turn-execution-id":
|
|
69
|
+
index += 1
|
|
70
|
+
if index >= len(argv):
|
|
71
|
+
raise ValueError("Missing value after --turn-execution-id")
|
|
72
|
+
turn_execution_id = argv[index].strip()
|
|
73
|
+
elif arg == "--print-bootstrap":
|
|
74
|
+
action = "print-bootstrap"
|
|
75
|
+
elif arg == "--health":
|
|
76
|
+
set_action("health")
|
|
77
|
+
elif arg == "--read-bootstrap":
|
|
78
|
+
set_action("read-bootstrap")
|
|
79
|
+
elif arg == "--get-me":
|
|
80
|
+
set_action("get-me")
|
|
81
|
+
elif arg == "--read-history":
|
|
82
|
+
set_action("read-history")
|
|
83
|
+
elif arg == "--read-draft":
|
|
84
|
+
set_action("read-draft")
|
|
85
|
+
elif arg == "--list-users":
|
|
86
|
+
set_action("list-users")
|
|
87
|
+
elif arg == "--send-message":
|
|
88
|
+
set_action("send-message")
|
|
89
|
+
elif arg == "--send-mention":
|
|
90
|
+
set_action("send-mention")
|
|
91
|
+
index += 1
|
|
92
|
+
if index >= len(argv):
|
|
93
|
+
raise ValueError("Missing value after --send-mention")
|
|
94
|
+
mention_target_id = argv[index].strip()
|
|
95
|
+
if not mention_target_id:
|
|
96
|
+
raise ValueError("Missing value after --send-mention")
|
|
97
|
+
elif arg == "--create-task":
|
|
98
|
+
set_action("create-task")
|
|
99
|
+
elif arg == "--list-tasks":
|
|
100
|
+
set_action("list-tasks")
|
|
101
|
+
elif arg == "--get-task":
|
|
102
|
+
set_action("get-task")
|
|
103
|
+
elif arg == "--update-task":
|
|
104
|
+
set_action("update-task")
|
|
105
|
+
elif arg == "--limit":
|
|
106
|
+
index += 1
|
|
107
|
+
limit = parse_int(arg, argv[index] if index < len(argv) else None)
|
|
108
|
+
elif arg == "--before":
|
|
109
|
+
index += 1
|
|
110
|
+
before = parse_int(arg, argv[index] if index < len(argv) else None)
|
|
111
|
+
elif arg == "--after":
|
|
112
|
+
index += 1
|
|
113
|
+
after = parse_int(arg, argv[index] if index < len(argv) else None)
|
|
114
|
+
elif arg == "--body":
|
|
115
|
+
index += 1
|
|
116
|
+
if index >= len(argv):
|
|
117
|
+
raise ValueError("Missing value after --body")
|
|
118
|
+
body = argv[index]
|
|
119
|
+
elif arg == "--reply-to":
|
|
120
|
+
index += 1
|
|
121
|
+
if index >= len(argv):
|
|
122
|
+
raise ValueError("Missing value after --reply-to")
|
|
123
|
+
reply_to_id = argv[index]
|
|
124
|
+
elif arg == "--mention":
|
|
125
|
+
index += 1
|
|
126
|
+
if index >= len(argv):
|
|
127
|
+
raise ValueError("Missing value after --mention")
|
|
128
|
+
mention = argv[index].strip()
|
|
129
|
+
if not mention:
|
|
130
|
+
raise ValueError("Missing value after --mention")
|
|
131
|
+
mentions.append(mention)
|
|
132
|
+
elif arg == "--title":
|
|
133
|
+
index += 1
|
|
134
|
+
title = argv[index] if index < len(argv) else None
|
|
135
|
+
elif arg == "--description":
|
|
136
|
+
index += 1
|
|
137
|
+
description = argv[index] if index < len(argv) else None
|
|
138
|
+
elif arg == "--assignee-id":
|
|
139
|
+
index += 1
|
|
140
|
+
assignee_id = argv[index] if index < len(argv) else None
|
|
141
|
+
elif arg == "--task-id":
|
|
142
|
+
index += 1
|
|
143
|
+
task_id = argv[index] if index < len(argv) else None
|
|
144
|
+
elif arg == "--status":
|
|
145
|
+
index += 1
|
|
146
|
+
status = argv[index] if index < len(argv) else None
|
|
147
|
+
else:
|
|
148
|
+
raise ValueError(f"Unknown argument: {arg}")
|
|
149
|
+
index += 1
|
|
150
|
+
|
|
151
|
+
if context_path is None:
|
|
152
|
+
raise ValueError("Missing required --context <path> argument")
|
|
153
|
+
return {
|
|
154
|
+
"context_path": context_path,
|
|
155
|
+
"auth_path": auth_path,
|
|
156
|
+
"turn_execution_id": turn_execution_id,
|
|
157
|
+
"action": action,
|
|
158
|
+
"limit": limit,
|
|
159
|
+
"before": before,
|
|
160
|
+
"after": after,
|
|
161
|
+
"body": body,
|
|
162
|
+
"reply_to_id": reply_to_id,
|
|
163
|
+
"mention_target_id": mention_target_id,
|
|
164
|
+
"mentions": mentions,
|
|
165
|
+
"title": title,
|
|
166
|
+
"description": description,
|
|
167
|
+
"assignee_id": assignee_id,
|
|
168
|
+
"task_id": task_id,
|
|
169
|
+
"status": status,
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def ensure_visible_mention(body: str, participant_id: str) -> str:
|
|
174
|
+
token = f"<@{participant_id}>"
|
|
175
|
+
if token in body:
|
|
176
|
+
return body
|
|
177
|
+
separator = "" if body.endswith((" ", "\n", "\t")) else " "
|
|
178
|
+
return f"{body}{separator}{token}"
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def ensure_visible_mentions(body: str, participant_ids: list[str]) -> str:
|
|
182
|
+
next_body = body
|
|
183
|
+
for participant_id in participant_ids:
|
|
184
|
+
next_body = ensure_visible_mention(next_body, participant_id)
|
|
185
|
+
return next_body
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def explicit_task_id_provided(options: dict[str, object]) -> bool:
|
|
189
|
+
task_id = options.get("task_id")
|
|
190
|
+
return isinstance(task_id, str) and bool(task_id.strip())
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def resolve_task_id(payload: dict[str, object], action: str, options: dict[str, object]) -> str | None:
|
|
194
|
+
task_id = options.get("task_id")
|
|
195
|
+
if isinstance(task_id, str) and task_id.strip():
|
|
196
|
+
return task_id.strip()
|
|
197
|
+
task_assignment_context = payload.get("taskAssignmentContext")
|
|
198
|
+
if isinstance(task_assignment_context, dict) and task_assignment_context.get("active") is True:
|
|
199
|
+
current_task_id = task_assignment_context.get("currentTaskId")
|
|
200
|
+
if isinstance(current_task_id, str) and current_task_id.strip():
|
|
201
|
+
return current_task_id.strip()
|
|
202
|
+
return None
|
|
203
|
+
raise ValueError(f"Missing required --task-id <value> for --{action}")
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def resolve_gateway_request(
|
|
207
|
+
payload: dict[str, object],
|
|
208
|
+
action: str,
|
|
209
|
+
options: dict[str, object],
|
|
210
|
+
) -> tuple[str, str, object | None, bool]:
|
|
211
|
+
gateway = payload.get("localhostGateway")
|
|
212
|
+
if not isinstance(gateway, dict):
|
|
213
|
+
raise ValueError("Missing localhostGateway bootstrap metadata in the context payload")
|
|
214
|
+
base_url = gateway.get("baseUrl")
|
|
215
|
+
if not isinstance(base_url, str):
|
|
216
|
+
raise ValueError("Missing localhostGateway bootstrap metadata in the context payload")
|
|
217
|
+
task_assignment_context = payload.get("taskAssignmentContext")
|
|
218
|
+
if action in ("create-task", "list-tasks") and isinstance(task_assignment_context, dict) and task_assignment_context.get("active") is True:
|
|
219
|
+
raise ValueError(TASK_THREAD_COLLECTION_COMMAND_ERROR)
|
|
220
|
+
channel_id = quote(str(payload.get("channelId", "")), safe="")
|
|
221
|
+
if action == "health":
|
|
222
|
+
return f"{base_url}/health", "GET", None, False
|
|
223
|
+
if action == "read-bootstrap":
|
|
224
|
+
return f"{base_url}/v1/channels/{channel_id}/bootstrap", "GET", None, False
|
|
225
|
+
if action == "get-me":
|
|
226
|
+
return f"{base_url}/v1/channels/{channel_id}/me", "GET", None, False
|
|
227
|
+
if action == "read-history":
|
|
228
|
+
query: dict[str, str] = {}
|
|
229
|
+
if options.get("limit") is not None:
|
|
230
|
+
query["limit"] = str(options["limit"])
|
|
231
|
+
if options.get("before") is not None:
|
|
232
|
+
query["before"] = str(options["before"])
|
|
233
|
+
if options.get("after") is not None:
|
|
234
|
+
query["after"] = str(options["after"])
|
|
235
|
+
suffix = f"?{urlencode(query)}" if query else ""
|
|
236
|
+
return f"{base_url}/v1/channels/{channel_id}/history{suffix}", "GET", None, False
|
|
237
|
+
if action == "read-draft":
|
|
238
|
+
turn_execution_id = options.get("turn_execution_id")
|
|
239
|
+
if not isinstance(turn_execution_id, str) or not turn_execution_id.strip():
|
|
240
|
+
raise ValueError("Missing required --turn-execution-id value for --read-draft")
|
|
241
|
+
suffix = urlencode({"turnExecutionId": turn_execution_id.strip()})
|
|
242
|
+
return f"{base_url}/v1/channels/{channel_id}/draft?{suffix}", "GET", None, False
|
|
243
|
+
if action == "list-users":
|
|
244
|
+
return f"{base_url}/v1/channels/{channel_id}/users", "GET", None, False
|
|
245
|
+
if action in ("send-message", "send-mention"):
|
|
246
|
+
return f"{base_url}/v1/channels/{channel_id}/messages", "POST", None, False
|
|
247
|
+
if action == "create-task":
|
|
248
|
+
title = options.get("title")
|
|
249
|
+
if not isinstance(title, str) or title == "":
|
|
250
|
+
raise ValueError("Missing required --title <value> for --create-task")
|
|
251
|
+
request_body: dict[str, object] = {"title": title}
|
|
252
|
+
if options.get("description") is not None:
|
|
253
|
+
request_body["description"] = options["description"]
|
|
254
|
+
if options.get("assignee_id") is not None:
|
|
255
|
+
request_body["assigneeId"] = options["assignee_id"]
|
|
256
|
+
return f"{base_url}/v1/channels/{channel_id}/tasks", "POST", request_body, False
|
|
257
|
+
if action == "list-tasks":
|
|
258
|
+
return f"{base_url}/v1/channels/{channel_id}/tasks", "GET", None, False
|
|
259
|
+
if action == "get-task":
|
|
260
|
+
task_id = resolve_task_id(payload, action, options)
|
|
261
|
+
if isinstance(task_assignment_context, dict) and task_assignment_context.get("active") is True and not explicit_task_id_provided(options):
|
|
262
|
+
return f"{base_url}/v1/channels/{channel_id}/current-task", "GET", None, True
|
|
263
|
+
return f"{base_url}/v1/tasks/{quote(str(task_id), safe='')}", "GET", None, False
|
|
264
|
+
if action == "update-task":
|
|
265
|
+
task_id = resolve_task_id(payload, action, options)
|
|
266
|
+
request_body: dict[str, object] = {}
|
|
267
|
+
if options.get("status") is not None:
|
|
268
|
+
request_body["status"] = options["status"]
|
|
269
|
+
if options.get("assignee_id") is not None:
|
|
270
|
+
request_body["assigneeId"] = options["assignee_id"]
|
|
271
|
+
if options.get("title") is not None:
|
|
272
|
+
request_body["title"] = options["title"]
|
|
273
|
+
if not request_body:
|
|
274
|
+
raise ValueError("At least one of --status, --assignee-id, or --title is required for --update-task")
|
|
275
|
+
if isinstance(task_assignment_context, dict) and task_assignment_context.get("active") is True and not explicit_task_id_provided(options):
|
|
276
|
+
return f"{base_url}/v1/channels/{channel_id}/current-task", "PATCH", request_body, True
|
|
277
|
+
return f"{base_url}/v1/tasks/{quote(str(task_id), safe='')}", "PATCH", request_body, False
|
|
278
|
+
raise ValueError(f"Unsupported gateway action: {action}")
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def read_gateway_auth(auth_path: Path | None, expected_channel_id: object) -> dict[str, str | None]:
|
|
282
|
+
if auth_path is None:
|
|
283
|
+
raise ValueError("Missing required --auth-path <path> argument for gateway access")
|
|
284
|
+
auth_payload = json.loads(auth_path.read_text(encoding="utf-8"))
|
|
285
|
+
token = None
|
|
286
|
+
localhost_gateway = auth_payload.get("localhostGateway")
|
|
287
|
+
if isinstance(localhost_gateway, dict):
|
|
288
|
+
raw_token = localhost_gateway.get("token")
|
|
289
|
+
if isinstance(raw_token, str):
|
|
290
|
+
token = raw_token
|
|
291
|
+
if auth_payload.get("channelId") != expected_channel_id or not token:
|
|
292
|
+
raise ValueError("Missing localhost gateway auth payload for this channel")
|
|
293
|
+
return {"token": token}
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def call_gateway(payload: dict[str, object], action: str, options: dict[str, object]) -> object:
|
|
297
|
+
auth = read_gateway_auth(
|
|
298
|
+
options.get("auth_path") if isinstance(options.get("auth_path"), Path) else None,
|
|
299
|
+
payload.get("channelId"),
|
|
300
|
+
)
|
|
301
|
+
url, method, request_body, uses_current_thread_fallback = resolve_gateway_request(payload, action, options)
|
|
302
|
+
|
|
303
|
+
data = None
|
|
304
|
+
headers = {"Authorization": f"Bearer {auth['token']}"}
|
|
305
|
+
if action in ("send-message", "send-mention"):
|
|
306
|
+
body = options.get("body")
|
|
307
|
+
if not isinstance(body, str) or not body.strip():
|
|
308
|
+
raise ValueError(f"Missing required --body value for --{action}")
|
|
309
|
+
turn_execution_id = options.get("turn_execution_id")
|
|
310
|
+
if not isinstance(turn_execution_id, str) or not turn_execution_id.strip():
|
|
311
|
+
raise ValueError(f"Missing required --turn-execution-id value for --{action}")
|
|
312
|
+
request_mentions = options.get("mentions")
|
|
313
|
+
if action == "send-mention":
|
|
314
|
+
mention_target_id = options.get("mention_target_id")
|
|
315
|
+
if not isinstance(mention_target_id, str) or not mention_target_id.strip():
|
|
316
|
+
raise ValueError("Missing required target user id after --send-mention")
|
|
317
|
+
extra_mentions = options.get("mentions")
|
|
318
|
+
if isinstance(extra_mentions, list) and len(extra_mentions) > 0:
|
|
319
|
+
raise ValueError("Do not combine --send-mention with additional --mention flags")
|
|
320
|
+
request_mentions = [mention_target_id.strip()]
|
|
321
|
+
if isinstance(request_mentions, list) and len(request_mentions) > 0:
|
|
322
|
+
body = ensure_visible_mentions(body, request_mentions)
|
|
323
|
+
headers["Content-Type"] = "application/json; charset=utf-8"
|
|
324
|
+
request_body = {
|
|
325
|
+
"body": body,
|
|
326
|
+
"turnExecutionId": turn_execution_id,
|
|
327
|
+
}
|
|
328
|
+
reply_to_id = options.get("reply_to_id")
|
|
329
|
+
if isinstance(reply_to_id, str) and reply_to_id:
|
|
330
|
+
request_body["replyToId"] = reply_to_id
|
|
331
|
+
data = json.dumps(request_body).encode("utf-8")
|
|
332
|
+
elif request_body is not None:
|
|
333
|
+
headers["Content-Type"] = "application/json; charset=utf-8"
|
|
334
|
+
data = json.dumps(request_body).encode("utf-8")
|
|
335
|
+
|
|
336
|
+
request = Request(url, headers=headers, method=method, data=data)
|
|
337
|
+
try:
|
|
338
|
+
with urlopen(request) as response:
|
|
339
|
+
response_body = response.read().decode("utf-8")
|
|
340
|
+
return json.loads(response_body) if response_body else None
|
|
341
|
+
except HTTPError as exc:
|
|
342
|
+
if uses_current_thread_fallback and exc.code == 404:
|
|
343
|
+
raise RuntimeError(TASK_THREAD_MISSING_TASK_ID_ERROR) from exc
|
|
344
|
+
raise RuntimeError(f"Gateway request failed: {exc}") from exc
|
|
345
|
+
except Exception as exc:
|
|
346
|
+
raise RuntimeError(f"Gateway request failed: {exc}") from exc
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def redact_bootstrap(payload: dict[str, object], context_path: Path) -> dict[str, object]:
|
|
350
|
+
localhost_gateway = payload.get("localhostGateway")
|
|
351
|
+
base_url = None
|
|
352
|
+
collaboration = None
|
|
353
|
+
if isinstance(localhost_gateway, dict):
|
|
354
|
+
raw_base_url = localhost_gateway.get("baseUrl")
|
|
355
|
+
if isinstance(raw_base_url, str):
|
|
356
|
+
base_url = raw_base_url
|
|
357
|
+
raw_collaboration = localhost_gateway.get("collaboration")
|
|
358
|
+
if isinstance(raw_collaboration, dict):
|
|
359
|
+
collaboration = raw_collaboration
|
|
360
|
+
return {
|
|
361
|
+
"kind": "borgee-agent-skill-bootstrap",
|
|
362
|
+
"contextPath": str(context_path),
|
|
363
|
+
"channelId": payload.get("channelId"),
|
|
364
|
+
"skillRuntime": payload.get("skillRuntime"),
|
|
365
|
+
"taskAssignmentContext": payload.get("taskAssignmentContext"),
|
|
366
|
+
"localhostGateway": (
|
|
367
|
+
{
|
|
368
|
+
"baseUrl": base_url,
|
|
369
|
+
**({"collaboration": collaboration} if collaboration is not None else {}),
|
|
370
|
+
}
|
|
371
|
+
if base_url
|
|
372
|
+
else None
|
|
373
|
+
),
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
parsed = parse_args(sys.argv[1:])
|
|
378
|
+
context_path = parsed["context_path"]
|
|
379
|
+
payload = json.loads(context_path.read_text(encoding="utf-8"))
|
|
380
|
+
|
|
381
|
+
if parsed["action"] == "print-bootstrap":
|
|
382
|
+
print(json.dumps(redact_bootstrap(payload, context_path), indent=2))
|
|
383
|
+
else:
|
|
384
|
+
print(
|
|
385
|
+
json.dumps(
|
|
386
|
+
call_gateway(
|
|
387
|
+
payload,
|
|
388
|
+
str(parsed["action"]),
|
|
389
|
+
{
|
|
390
|
+
"context_path": context_path,
|
|
391
|
+
"auth_path": parsed["auth_path"],
|
|
392
|
+
"turn_execution_id": parsed["turn_execution_id"],
|
|
393
|
+
"limit": parsed["limit"],
|
|
394
|
+
"before": parsed["before"],
|
|
395
|
+
"after": parsed["after"],
|
|
396
|
+
"body": parsed["body"],
|
|
397
|
+
"reply_to_id": parsed["reply_to_id"],
|
|
398
|
+
"mention_target_id": parsed["mention_target_id"],
|
|
399
|
+
"mentions": parsed["mentions"],
|
|
400
|
+
"title": parsed["title"],
|
|
401
|
+
"description": parsed["description"],
|
|
402
|
+
"assignee_id": parsed["assignee_id"],
|
|
403
|
+
"task_id": parsed["task_id"],
|
|
404
|
+
"status": parsed["status"],
|
|
405
|
+
},
|
|
406
|
+
),
|
|
407
|
+
indent=2,
|
|
408
|
+
)
|
|
409
|
+
)
|