agent-relay-server 0.95.1 → 0.97.0
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/docs/openapi.json +39 -1
- package/package.json +3 -3
- package/public/assets/MessageBubble-CIDyX8f7.js +4 -0
- package/public/assets/MessageBubble-CIDyX8f7.js.map +1 -0
- package/public/assets/{PlanGraphPanel-DPgW_Ohe.js → PlanGraphPanel-BmWB81w_.js} +2 -2
- package/public/assets/{PlanGraphPanel-DPgW_Ohe.js.map → PlanGraphPanel-BmWB81w_.js.map} +1 -1
- package/public/assets/{activity-CRebaL8O.js → activity-QQikHZe4.js} +2 -2
- package/public/assets/{activity-CRebaL8O.js.map → activity-QQikHZe4.js.map} +1 -1
- package/public/assets/agent-profiles-WvAN5cR_.js +2 -0
- package/public/assets/agent-profiles-WvAN5cR_.js.map +1 -0
- package/public/assets/agents-BsFfumLn.js +2 -0
- package/public/assets/{agents-7WtV1Pf3.js.map → agents-BsFfumLn.js.map} +1 -1
- package/public/assets/{analytics-DpnJh9UQ.js → analytics-CUJbpoA7.js} +2 -2
- package/public/assets/{analytics-DpnJh9UQ.js.map → analytics-CUJbpoA7.js.map} +1 -1
- package/public/assets/{automation-CjQNCXlO.js → automation-BTbpiINE.js} +2 -2
- package/public/assets/{automation-CjQNCXlO.js.map → automation-BTbpiINE.js.map} +1 -1
- package/public/assets/{badge-BbfOskRI.js → badge-BLar6FjP.js} +2 -2
- package/public/assets/{badge-BbfOskRI.js.map → badge-BLar6FjP.js.map} +1 -1
- package/public/assets/branch-state-badge-CNko2_BL.js +2 -0
- package/public/assets/{branch-state-badge-BcObk0ca.js.map → branch-state-badge-CNko2_BL.js.map} +1 -1
- package/public/assets/{button-DWiw--lT.js → button-BrIB69qd.js} +2 -2
- package/public/assets/{button-DWiw--lT.js.map → button-BrIB69qd.js.map} +1 -1
- package/public/assets/card-lhnFnBoz.js +2 -0
- package/public/assets/{card-BeqvuYTT.js.map → card-lhnFnBoz.js.map} +1 -1
- package/public/assets/{channels-B2bftzgH.js → channels-Tg8l4n5J.js} +2 -2
- package/public/assets/{channels-B2bftzgH.js.map → channels-Tg8l4n5J.js.map} +1 -1
- package/public/assets/chat-BlFUmD3r.js +2 -0
- package/public/assets/chat-BlFUmD3r.js.map +1 -0
- package/public/assets/{connectors-CJOJirYT.js → connectors-B5wbjyUd.js} +2 -2
- package/public/assets/{connectors-CJOJirYT.js.map → connectors-B5wbjyUd.js.map} +1 -1
- package/public/assets/copy-button-Cd-LbSbg.js +2 -0
- package/public/assets/{copy-button-CIXy8ks6.js.map → copy-button-Cd-LbSbg.js.map} +1 -1
- package/public/assets/dist-30weaXto.js +2 -0
- package/public/assets/{dist-LFuRypZd.js.map → dist-30weaXto.js.map} +1 -1
- package/public/assets/{dist-CtuS_3Jl.js → dist-B5VvlkhI.js} +2 -2
- package/public/assets/{dist-CtuS_3Jl.js.map → dist-B5VvlkhI.js.map} +1 -1
- package/public/assets/dist-BEzpMqLy.js +2 -0
- package/public/assets/{dist-Q6OOS84U.js.map → dist-BEzpMqLy.js.map} +1 -1
- package/public/assets/{dist-CbxR2pzD.js → dist-BjOBkHHY.js} +2 -2
- package/public/assets/{dist-CbxR2pzD.js.map → dist-BjOBkHHY.js.map} +1 -1
- package/public/assets/{dist-zTw85jD8.js → dist-BnbGIUmi.js} +2 -2
- package/public/assets/{dist-zTw85jD8.js.map → dist-BnbGIUmi.js.map} +1 -1
- package/public/assets/{dist-BufB2Xy_.js → dist-Bp10H3oR.js} +2 -2
- package/public/assets/{dist-BufB2Xy_.js.map → dist-Bp10H3oR.js.map} +1 -1
- package/public/assets/{dist-Du_bcq-z.js → dist-CQF3Jiqg.js} +2 -2
- package/public/assets/{dist-Du_bcq-z.js.map → dist-CQF3Jiqg.js.map} +1 -1
- package/public/assets/dist-Cgy0FmP-.js +2 -0
- package/public/assets/{dist-CXkmW1Od.js.map → dist-Cgy0FmP-.js.map} +1 -1
- package/public/assets/{dist-KxiSP9h9.js → dist-DAl28ejX.js} +2 -2
- package/public/assets/{dist-KxiSP9h9.js.map → dist-DAl28ejX.js.map} +1 -1
- package/public/assets/{dist-eG_93I3z.js → dist-DDUGmmoi.js} +2 -2
- package/public/assets/{dist-eG_93I3z.js.map → dist-DDUGmmoi.js.map} +1 -1
- package/public/assets/{dist-BQXmO19g.js → dist-DZ97OosY.js} +2 -2
- package/public/assets/{dist-BQXmO19g.js.map → dist-DZ97OosY.js.map} +1 -1
- package/public/assets/{es2015-ibwCE_JR.js → es2015-B8Z9p8oQ.js} +2 -2
- package/public/assets/{es2015-ibwCE_JR.js.map → es2015-B8Z9p8oQ.js.map} +1 -1
- package/public/assets/{formatted-body-impl-CGACmUqI.js → formatted-body-impl-Dbjjdcu9.js} +2 -2
- package/public/assets/{formatted-body-impl-CGACmUqI.js.map → formatted-body-impl-Dbjjdcu9.js.map} +1 -1
- package/public/assets/index-CPWbr4sq.css +2 -0
- package/public/assets/index-CPXz74W5.js +23 -0
- package/public/assets/index-CPXz74W5.js.map +1 -0
- package/public/assets/{input-DUdtS3nG.js → input-B_fUHtLD.js} +2 -2
- package/public/assets/{input-DUdtS3nG.js.map → input-B_fUHtLD.js.map} +1 -1
- package/public/assets/{insights-DqXjTYai.js → insights-D1Oq25BL.js} +2 -2
- package/public/assets/{insights-DqXjTYai.js.map → insights-D1Oq25BL.js.map} +1 -1
- package/public/assets/{integrations-DEgLatDv.js → integrations-sYKtupOq.js} +2 -2
- package/public/assets/{integrations-DEgLatDv.js.map → integrations-sYKtupOq.js.map} +1 -1
- package/public/assets/{lib-Gp69YB9e.js → lib-ng6WZYjE.js} +2 -2
- package/public/assets/{lib-Gp69YB9e.js.map → lib-ng6WZYjE.js.map} +1 -1
- package/public/assets/{lucide-react-uFIMC7W7.js → lucide-react-BYZuAhQs.js} +2 -2
- package/public/assets/{lucide-react-uFIMC7W7.js.map → lucide-react-BYZuAhQs.js.map} +1 -1
- package/public/assets/maintenance-CgXJwFTo.js +2 -0
- package/public/assets/{maintenance-CcFJlNxt.js.map → maintenance-CgXJwFTo.js.map} +1 -1
- package/public/assets/{managed-agents-CHR4Hx1O.js → managed-agents-CbuFHwWE.js} +4 -4
- package/public/assets/{managed-agents-CHR4Hx1O.js.map → managed-agents-CbuFHwWE.js.map} +1 -1
- package/public/assets/markdown-preview-impl-B79bSsKK.js +2 -0
- package/public/assets/{markdown-preview-impl-BHaUcnfn.js.map → markdown-preview-impl-B79bSsKK.js.map} +1 -1
- package/public/assets/memory-Box_rMj_.js +2 -0
- package/public/assets/{memory-Uk0VfqnC.js.map → memory-Box_rMj_.js.map} +1 -1
- package/public/assets/{messages-D_juCBfr.js → messages-BXIHBaN2.js} +2 -2
- package/public/assets/{messages-D_juCBfr.js.map → messages-BXIHBaN2.js.map} +1 -1
- package/public/assets/{orchestrators-8IrmgeHV.js → orchestrators-MNj_mp3U.js} +2 -2
- package/public/assets/{orchestrators-8IrmgeHV.js.map → orchestrators-MNj_mp3U.js.map} +1 -1
- package/public/assets/{overview-D_DM0QHJ.js → overview-KfwJgCUa.js} +2 -2
- package/public/assets/{overview-D_DM0QHJ.js.map → overview-KfwJgCUa.js.map} +1 -1
- package/public/assets/{pairs-jciDuPLn.js → pairs-DfrGWlgL.js} +2 -2
- package/public/assets/{pairs-jciDuPLn.js.map → pairs-DfrGWlgL.js.map} +1 -1
- package/public/assets/{projects-C-QHyuMD.js → projects-BPI8z55X.js} +2 -2
- package/public/assets/{projects-C-QHyuMD.js.map → projects-BPI8z55X.js.map} +1 -1
- package/public/assets/{react-dom-DF2cuNaf.js → react-dom-Dbhs84ug.js} +2 -2
- package/public/assets/{react-dom-DF2cuNaf.js.map → react-dom-Dbhs84ug.js.map} +1 -1
- package/public/assets/{registry-D1EIvc8U.js → registry-CiBC97sL.js} +2 -2
- package/public/assets/{registry-D1EIvc8U.js.map → registry-CiBC97sL.js.map} +1 -1
- package/public/assets/{security-C0_Df9yI.js → security-BbU_vIdb.js} +2 -2
- package/public/assets/{security-C0_Df9yI.js.map → security-BbU_vIdb.js.map} +1 -1
- package/public/assets/{select-CXFXPZ7Z.js → select-CeQwmVTm.js} +2 -2
- package/public/assets/{select-CXFXPZ7Z.js.map → select-CeQwmVTm.js.map} +1 -1
- package/public/assets/settings-DBsL3jb7.js +6 -0
- package/public/assets/{settings-DGPpdFoq.js.map → settings-DBsL3jb7.js.map} +1 -1
- package/public/assets/{store-d-IbqTaD.js → store-pKbf_WYd.js} +5 -5
- package/public/assets/{store-d-IbqTaD.js.map → store-pKbf_WYd.js.map} +1 -1
- package/public/assets/{tasks-B_epVa5b.js → tasks-za0RxIQw.js} +2 -2
- package/public/assets/{tasks-B_epVa5b.js.map → tasks-za0RxIQw.js.map} +1 -1
- package/public/assets/{teams-D2hATpCD.js → teams-ByAqwLG9.js} +2 -2
- package/public/assets/{teams-D2hATpCD.js.map → teams-ByAqwLG9.js.map} +1 -1
- package/public/assets/{terminal-viewer-impl-CefeetWa.js → terminal-viewer-impl-CkoWD5D_.js} +3 -3
- package/public/assets/{terminal-viewer-impl-CefeetWa.js.map → terminal-viewer-impl-CkoWD5D_.js.map} +1 -1
- package/public/assets/types-Tv67voFu.js.map +1 -1
- package/public/assets/{use-keyboard-viewport-CeLM-PeW.js → use-keyboard-viewport-D8_NYDkh.js} +2 -2
- package/public/assets/{use-keyboard-viewport-CeLM-PeW.js.map → use-keyboard-viewport-D8_NYDkh.js.map} +1 -1
- package/public/assets/user-avatar-Q_N6iHEn.js +2 -0
- package/public/assets/{user-avatar-BOGZ21O8.js.map → user-avatar-Q_N6iHEn.js.map} +1 -1
- package/public/assets/{work-queue-C9wBOivX.js → work-queue-DfRo1B2P.js} +2 -2
- package/public/assets/{work-queue-C9wBOivX.js.map → work-queue-DfRo1B2P.js.map} +1 -1
- package/public/assets/workspaces-BolccWZy.js +3 -0
- package/public/assets/{workspaces-DKFmnOF8.js.map → workspaces-BolccWZy.js.map} +1 -1
- package/public/index.html +21 -21
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/src/agent-busy-health.ts +22 -20
- package/src/config-store.ts +72 -6
- package/src/db/migrations.ts +9 -0
- package/src/db/project-entries.ts +63 -9
- package/src/db/projects.ts +76 -4
- package/src/db/schema.ts +8 -0
- package/src/mcp/index.ts +4 -3
- package/src/mcp/tools-spawn.ts +13 -2
- package/src/mcp-memory-tools.ts +239 -0
- package/src/mcp-team-template-tools.ts +8 -1
- package/src/project-instructions.ts +48 -10
- package/src/routes/agent-profiles.ts +36 -8
- package/src/routes/agents-spawn.ts +4 -2
- package/src/routes/index.ts +2 -1
- package/src/runtime-tokens.ts +3 -0
- package/src/security.ts +1 -1
- package/src/services/spawn-agent.ts +57 -2
- package/public/assets/MessageBubble-CkPnAwxJ.js +0 -3
- package/public/assets/MessageBubble-CkPnAwxJ.js.map +0 -1
- package/public/assets/agent-profiles-BFpEQHKo.js +0 -2
- package/public/assets/agent-profiles-BFpEQHKo.js.map +0 -1
- package/public/assets/agents-7WtV1Pf3.js +0 -2
- package/public/assets/branch-state-badge-BcObk0ca.js +0 -2
- package/public/assets/card-BeqvuYTT.js +0 -2
- package/public/assets/chat-Dcwua_5V.js +0 -2
- package/public/assets/chat-Dcwua_5V.js.map +0 -1
- package/public/assets/copy-button-CIXy8ks6.js +0 -2
- package/public/assets/dist-CXkmW1Od.js +0 -2
- package/public/assets/dist-LFuRypZd.js +0 -2
- package/public/assets/dist-Q6OOS84U.js +0 -2
- package/public/assets/index-CKPsJqiW.css +0 -2
- package/public/assets/index-CwhhpGgX.js +0 -23
- package/public/assets/index-CwhhpGgX.js.map +0 -1
- package/public/assets/maintenance-CcFJlNxt.js +0 -2
- package/public/assets/markdown-preview-impl-BHaUcnfn.js +0 -2
- package/public/assets/memory-Uk0VfqnC.js +0 -2
- package/public/assets/settings-DGPpdFoq.js +0 -6
- package/public/assets/user-avatar-BOGZ21O8.js +0 -2
- package/public/assets/workspaces-DKFmnOF8.js +0 -3
|
@@ -44,6 +44,10 @@ interface ComposeProjectInstructionsOptions {
|
|
|
44
44
|
/** Hard byte cap on the rendered block (UTF-8). Default 8192. The block is truncated
|
|
45
45
|
* deterministically (lowest-priority entries dropped first) to stay within it. */
|
|
46
46
|
maxBytes?: number;
|
|
47
|
+
/** Header label prefix (#559). Default "Project knowledge"; the scoped stores pass
|
|
48
|
+
* "Profile memory" / "Operator memory" so an agent can tell role/operator memory from
|
|
49
|
+
* repo knowledge. The anchor title/slug is still appended. */
|
|
50
|
+
headerLabel?: string;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
interface SpawnInstructionInjectionEvent {
|
|
@@ -140,7 +144,7 @@ export function composeProjectInstructions(
|
|
|
140
144
|
|
|
141
145
|
// Greedy size-bounded render. Entries are contiguous by kind (primary sort key), so a
|
|
142
146
|
// per-kind `## heading` is emitted once when the first entry of that kind is included.
|
|
143
|
-
const header = `# Project knowledge: ${project.title?.trim() || project.slug}`;
|
|
147
|
+
const header = `# ${opts.headerLabel ?? "Project knowledge"}: ${project.title?.trim() || project.slug}`;
|
|
144
148
|
const budget = maxBytes - byteLen(`\n\n${TRUNCATION_NOTICE}`);
|
|
145
149
|
const lines: string[] = [header];
|
|
146
150
|
let bytes = byteLen(header);
|
|
@@ -181,18 +185,37 @@ export function composeProjectInstructions(
|
|
|
181
185
|
* Returns the joined block, or the caller's own systemPromptAppend untouched when no
|
|
182
186
|
* profile/project material applies — so a profile-less spawn stays byte-identical.
|
|
183
187
|
*
|
|
184
|
-
* ── #559
|
|
185
|
-
* Scoped {profile|user} memory
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* prompt.
|
|
190
|
-
*
|
|
191
|
-
* a refactor.
|
|
188
|
+
* ── #559 scoped memory ─────────────────────────────────────────────────────────────────
|
|
189
|
+
* Scoped {profile|user} memory (#559) composes in beside the project preamble: `profileAnchor`
|
|
190
|
+
* (role memory) and `userAnchor` (operator memory) each render via the same
|
|
191
|
+
* `composeProjectInstructions` renderer (scope-agnostic — a profile/user store is just a
|
|
192
|
+
* `projects` row of a different scope) and slot into `appendBlocks` before the profile system
|
|
193
|
+
* prompt. Unlike the project preamble they are UNGATED — relay-native, curated, small — so they
|
|
194
|
+
* inject whenever the resolved anchor holds active (promoted) entries.
|
|
192
195
|
*/
|
|
196
|
+
/** Kinds rendered into a scoped {profile|user} memory preamble (#559). Adds `memory` to the
|
|
197
|
+
* project default (rule/fact) because `memory` is the /remember capture kind — a promoted role
|
|
198
|
+
* principle or operator preference must reach the spawn. `decision` stays log-only. */
|
|
199
|
+
const SCOPED_MEMORY_KINDS: readonly ProjectEntryKind[] = ["rule", "fact", "memory"];
|
|
200
|
+
|
|
201
|
+
/** Render a {profile|user}-scoped store's promoted (active) entries into a preamble block, or "".
|
|
202
|
+
* Unlike the project preamble this is UNGATED by a policy: scoped memory is relay-native, curated
|
|
203
|
+
* (proposed→promoted), and small, so it always injects when present (#559). */
|
|
204
|
+
function composeScopedKnowledge(
|
|
205
|
+
anchor: Pick<Project, "id" | "slug" | "title">,
|
|
206
|
+
headerLabel: string,
|
|
207
|
+
): string {
|
|
208
|
+
return composeProjectInstructions(anchor, { includeKinds: SCOPED_MEMORY_KINDS, headerLabel });
|
|
209
|
+
}
|
|
210
|
+
|
|
193
211
|
export function composeSpawnInstructionsWithEvents(input: {
|
|
194
212
|
callerProject?: Pick<Project, "id" | "slug" | "title">;
|
|
195
213
|
projectInstructions?: ProjectInstructionPolicy;
|
|
214
|
+
/** #559 — the caller's resolved profile-scoped store (role memory), injected when it has
|
|
215
|
+
* active entries. Inheritance via the contains graph is handled inside the composer. */
|
|
216
|
+
profileAnchor?: Pick<Project, "id" | "slug" | "title">;
|
|
217
|
+
/** #559 — the caller's resolved user/operator-scoped store (operator memory). */
|
|
218
|
+
userAnchor?: Pick<Project, "id" | "slug" | "title">;
|
|
196
219
|
profile?: Pick<AgentProfile, "instructions" | "maxSpawnedAgents">;
|
|
197
220
|
spawnedBy?: string;
|
|
198
221
|
callerSystemPromptAppend?: string;
|
|
@@ -217,7 +240,22 @@ export function composeSpawnInstructionsWithEvents(input: {
|
|
|
217
240
|
});
|
|
218
241
|
}
|
|
219
242
|
}
|
|
220
|
-
// [#559
|
|
243
|
+
// [#559] profile/user-scoped knowledge preamble — beside the project preamble, before the
|
|
244
|
+
// profile system prompt. Ungated: injects whenever the resolved anchor holds active entries.
|
|
245
|
+
for (const scope of [
|
|
246
|
+
{ anchor: input.profileAnchor, label: "Profile memory", source: "profile-memory" as const, category: "knowledge" as const },
|
|
247
|
+
{ anchor: input.userAnchor, label: "Operator memory", source: "user-memory" as const, category: "knowledge" as const },
|
|
248
|
+
]) {
|
|
249
|
+
if (!scope.anchor) continue;
|
|
250
|
+
const block = composeScopedKnowledge(scope.anchor, scope.label);
|
|
251
|
+
if (!block.trim()) continue;
|
|
252
|
+
appendBlocks.push(block);
|
|
253
|
+
relayInjectionEvents.push({
|
|
254
|
+
category: scope.category,
|
|
255
|
+
summary: `injected ${scope.label.toLowerCase()}: ${scope.anchor.title?.trim() || scope.anchor.slug}`,
|
|
256
|
+
detail: { source: scope.source, anchor: scope.anchor, content: block },
|
|
257
|
+
});
|
|
258
|
+
}
|
|
221
259
|
if (input.spawnedBy) {
|
|
222
260
|
appendBlocks.push(SPAWNED_CHILD_REPORTUP_INSTRUCTION);
|
|
223
261
|
relayInjectionEvents.push({
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// Auto-split from routes.ts (#299). Domain: agent-profiles.
|
|
2
|
-
import { ValidationError } from "../db";
|
|
3
|
-
import { cleanString } from "../validation";
|
|
2
|
+
import { ValidationError, withResolvedProvisioning } from "../db";
|
|
3
|
+
import { cleanString, optionalEnum } from "../validation";
|
|
4
4
|
import { deleteAgentProfile, getAgentProfile, listAgentProfiles, setAgentProfile } from "../config-store";
|
|
5
5
|
import { emitConfigChanged } from "../sse";
|
|
6
|
-
import { error, json, normalizeConfigPathParam, parseBody, type Handler } from "./_shared";
|
|
6
|
+
import { error, isRootCredentialRequest, json, normalizeConfigPathParam, parseBody, type Handler } from "./_shared";
|
|
7
|
+
import { getComponentAuth, hasComponentScope } from "../security";
|
|
7
8
|
import { isRecord } from "agent-relay-sdk";
|
|
8
|
-
import { type AgentProfile } from "../types";
|
|
9
|
+
import { SPAWN_PROVIDERS, type AgentProfile, type SpawnProvider } from "../types";
|
|
9
10
|
|
|
10
11
|
export const getAgentProfilesRoute: Handler = () => json(listAgentProfiles());
|
|
11
12
|
|
|
@@ -15,6 +16,29 @@ export const getAgentProfileRoute: Handler = (_req, params) => {
|
|
|
15
16
|
return profile ? json(profile) : error("agent profile not found", 404);
|
|
16
17
|
};
|
|
17
18
|
|
|
19
|
+
function isAdminProfileRequest(req: Request): boolean {
|
|
20
|
+
if (isRootCredentialRequest(req)) return true;
|
|
21
|
+
const component = getComponentAuth(req);
|
|
22
|
+
return component ? hasComponentScope(component, "system:admin") : false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const getResolvedAgentProfileRoute: Handler = (req, params) => {
|
|
26
|
+
try {
|
|
27
|
+
if (!isAdminProfileRequest(req)) return error("system admin scope required", 403);
|
|
28
|
+
const name = normalizeConfigPathParam(params.name, "name");
|
|
29
|
+
const entry = getAgentProfile(name);
|
|
30
|
+
if (!entry) return error("agent profile not found", 404);
|
|
31
|
+
const requestedProvider = new URL(req.url).searchParams.get("provider") ?? undefined;
|
|
32
|
+
const profileProvider = entry.value.provider === "claude" || entry.value.provider === "codex" ? entry.value.provider : undefined;
|
|
33
|
+
const provider = optionalEnum(requestedProvider, "provider", SPAWN_PROVIDERS, profileProvider ?? "codex") as SpawnProvider;
|
|
34
|
+
const profile = withResolvedProvisioning(entry.value, provider);
|
|
35
|
+
return profile ? json({ provider, profile }) : error("agent profile not found", 404);
|
|
36
|
+
} catch (e) {
|
|
37
|
+
if (e instanceof ValidationError) return error(e.message, 400);
|
|
38
|
+
throw e;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
18
42
|
export const putAgentProfileRoute: Handler = async (req, params) => {
|
|
19
43
|
const parsed = await parseBody<unknown>(req);
|
|
20
44
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
@@ -22,9 +46,12 @@ export const putAgentProfileRoute: Handler = async (req, params) => {
|
|
|
22
46
|
if (!isRecord(parsed.body)) throw new ValidationError("agent profile body required");
|
|
23
47
|
const name = normalizeConfigPathParam(params.name, "name");
|
|
24
48
|
const updatedBy = cleanString(parsed.body.updatedBy, "updatedBy", { max: 200 });
|
|
25
|
-
const
|
|
49
|
+
const existing = getAgentProfile(name);
|
|
50
|
+
const profile = existing?.value.builtIn && isAdminProfileRequest(req)
|
|
51
|
+
? setAgentProfile({ ...parsed.body, name } as AgentProfile, updatedBy, { overrideBuiltIn: true })
|
|
52
|
+
: setAgentProfile({ ...parsed.body, name } as AgentProfile, updatedBy);
|
|
26
53
|
emitConfigChanged(profile.namespace, profile.key, profile.version);
|
|
27
|
-
return json(profile, profile.version === 1 ? 201 : 200);
|
|
54
|
+
return json(profile, existing ? 200 : profile.version === 1 ? 201 : 200);
|
|
28
55
|
} catch (e) {
|
|
29
56
|
if (e instanceof ValidationError) return error(e.message, 400);
|
|
30
57
|
throw e;
|
|
@@ -35,9 +62,10 @@ export const deleteAgentProfileRoute: Handler = (req, params) => {
|
|
|
35
62
|
try {
|
|
36
63
|
const name = normalizeConfigPathParam(params.name, "name");
|
|
37
64
|
const existing = getAgentProfile(name);
|
|
38
|
-
if (!existing
|
|
65
|
+
if (!existing) return error("agent profile not found", 404);
|
|
39
66
|
const updatedBy = cleanString(new URL(req.url).searchParams.get("updatedBy") ?? undefined, "updatedBy", { max: 200 });
|
|
40
|
-
|
|
67
|
+
if (existing.value.builtIn && !isAdminProfileRequest(req)) return error("built-in agent profiles are managed by Relay", 400);
|
|
68
|
+
deleteAgentProfile(name, updatedBy, { resetBuiltInOverride: existing.value.builtIn });
|
|
41
69
|
emitConfigChanged(existing.namespace, existing.key, existing.version + 1);
|
|
42
70
|
return json({ ok: true });
|
|
43
71
|
} catch (e) {
|
|
@@ -5,7 +5,7 @@ import { VALID_AGENT_STATUSES, error, json, parseBody, type Handler } from "./_s
|
|
|
5
5
|
import { ValidationError, listAgents } from "../db";
|
|
6
6
|
import { cleanMeta, cleanNullableString, cleanString, cleanStringArray, optionalEnum } from "../validation";
|
|
7
7
|
import { registerAgent } from "../services/register-agent";
|
|
8
|
-
import { spawnAgent, type SpawnAgentInput } from "../services/spawn-agent";
|
|
8
|
+
import { spawnAgent, summarizeSpawnCommandForCaller, type SpawnAgentInput } from "../services/spawn-agent";
|
|
9
9
|
import { parseProjectInstructions } from "../project-instructions";
|
|
10
10
|
import { parseProjectMcp } from "../project-mcp";
|
|
11
11
|
import { parseProjectSettings } from "../project-settings";
|
|
@@ -153,7 +153,9 @@ export const postAgentSpawn: Handler = async (req) => {
|
|
|
153
153
|
waitForRegistrationMs: 0,
|
|
154
154
|
};
|
|
155
155
|
const result = await spawnAgent(input, authContextFromRequest(req));
|
|
156
|
-
|
|
156
|
+
// #734 — the dispatched command carries the full resolved agentProfile to the orchestrator;
|
|
157
|
+
// strip the heavy inlined provisioning file contents from the echoed-back summary.
|
|
158
|
+
return json({ ok: true, orchestratorId: result.orchestratorId, provider: result.provider, command: summarizeSpawnCommandForCaller(result.command) }, 202);
|
|
157
159
|
} catch (e) {
|
|
158
160
|
if (e instanceof McpAuthError) return error(e.message, 403);
|
|
159
161
|
if (e instanceof McpNotFoundError) return error(e.message, 404);
|
package/src/routes/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Auto-split from routes.ts (#299). Router: route table + matchRoute dispatch.
|
|
2
2
|
import { deleteAgentActiveMemories, deleteAgentById, findAgents, getAgentActiveMemories, getAgentById, getAgentChatHistory, getAgentContextSnapshots, getAgentCrashReportRoute, getAgentQuotaSnapshots, getAgentReplyObligations, getAgentTimelineRoute, getAgents, getMessageArtifactsRoute, getTaskArtifactsRoute, patchAgentLabel, patchAgentReady, patchAgentStatus, patchAgentTags, postHeartbeat } from "./agents";
|
|
3
|
-
import { deleteAgentProfileRoute, getAgentProfileRoute, getAgentProfilesRoute, putAgentProfileRoute } from "./agent-profiles";
|
|
3
|
+
import { deleteAgentProfileRoute, getAgentProfileRoute, getAgentProfilesRoute, getResolvedAgentProfileRoute, putAgentProfileRoute } from "./agent-profiles";
|
|
4
4
|
import { deleteAgentTerminalSession, getAgentDrive, getAgentPresence, postAgentAction, postAgentDrive, postAgentPermissionDecision, postAgentPresence, postAgentPrompt, postAgentTerminalSession } from "./agent-sessions";
|
|
5
5
|
import { deleteMyAvatar, deleteUserAvatarById, getMe, getUserAvatar, getUsers, headUserAvatar, patchMe, patchUserById, postMyAvatar, postUserAvatarById } from "./users";
|
|
6
6
|
import { deleteArtifactById, getArtifactById, getArtifactContent, getArtifacts, headArtifactContent, postArtifact } from "./artifacts";
|
|
@@ -231,6 +231,7 @@ const routes: Route[] = [
|
|
|
231
231
|
route("PATCH", "/api/commands/:id", patchCommand),
|
|
232
232
|
route("DELETE", "/api/commands/:id", deleteCommandById),
|
|
233
233
|
route("GET", "/api/agent-profiles", getAgentProfilesRoute),
|
|
234
|
+
route("GET", "/api/agent-profiles/:name/resolved", getResolvedAgentProfileRoute),
|
|
234
235
|
route("GET", "/api/agent-profiles/:name", getAgentProfileRoute),
|
|
235
236
|
route("PUT", "/api/agent-profiles/:name", putAgentProfileRoute),
|
|
236
237
|
route("DELETE", "/api/agent-profiles/:name", deleteAgentProfileRoute),
|
package/src/runtime-tokens.ts
CHANGED
|
@@ -132,6 +132,9 @@ export function issueRunnerRuntimeToken(input: {
|
|
|
132
132
|
...(input.spawnedBy ? { spawnedBy: input.spawnedBy } : {}),
|
|
133
133
|
...(input.teamId ? { teamId: input.teamId } : {}),
|
|
134
134
|
...(input.projectId ? { projectId: input.projectId } : {}),
|
|
135
|
+
// #559 — stamp the resolved profile NAME so the scoped-memory tools resolve the
|
|
136
|
+
// caller's OWN profile store (self-scoped writes). Identity-only, like projectId.
|
|
137
|
+
...(input.profile ? { profile: input.profile } : {}),
|
|
135
138
|
...(toolGroups ? { toolGroups } : {}),
|
|
136
139
|
},
|
|
137
140
|
createdBy: input.createdBy ?? "runtime",
|
package/src/security.ts
CHANGED
|
@@ -545,7 +545,7 @@ function isTokenConstraints(value: unknown): value is TokenConstraints {
|
|
|
545
545
|
for (const [key, item] of Object.entries(record)) {
|
|
546
546
|
if (["terminalAttach", "logsRead", "canDelegate"].includes(key)) {
|
|
547
547
|
if (typeof item !== "boolean") return false;
|
|
548
|
-
} else if (key === "cwd" || key === "spawnedBy" || key === "teamId" || key === "projectId" || key === "tenantId") {
|
|
548
|
+
} else if (key === "cwd" || key === "spawnedBy" || key === "teamId" || key === "projectId" || key === "profile" || key === "tenantId") {
|
|
549
549
|
if (typeof item !== "string") return false;
|
|
550
550
|
} else if (key === "maxSpawnedAgents") {
|
|
551
551
|
if (typeof item !== "number") return false;
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
// them through `spawnAgent(systemCtx)` is a clean belt-and-suspenders follow-up (#342),
|
|
25
25
|
// deliberately out of scope here — this slice converges the two external TRANSPORTS.
|
|
26
26
|
import type { SpawnProvider } from "agent-relay-sdk";
|
|
27
|
-
import { errMessage, stringValue } from "agent-relay-sdk";
|
|
28
|
-
import { countLiveSpawnedAgents, createActivityEvent, ensureTeam, getAgent, listAgents, listWorkspaces, resolveProjectForCwd, setAgentTeam, ValidationError, withResolvedProvisioning } from "../db";
|
|
27
|
+
import { DEFAULT_USER_ID, errMessage, isRecord, stringValue } from "agent-relay-sdk";
|
|
28
|
+
import { countLiveSpawnedAgents, createActivityEvent, ensureTeam, getAgent, listAgents, listWorkspaces, resolveAgentOwnership, resolveProjectForCwd, resolveScopedAnchor, setAgentTeam, ValidationError, withResolvedProvisioning } from "../db";
|
|
29
29
|
import { createCommand } from "../commands-db";
|
|
30
30
|
import { emitCommandEvent } from "../command-events";
|
|
31
31
|
import { buildSpawnCommand, generateSpawnRequestId, resolveSpawnModelParams } from "../spawn-command";
|
|
@@ -318,9 +318,19 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
|
|
|
318
318
|
// carries the #559 scoped-knowledge seam. Spawns without profile/project material stay
|
|
319
319
|
// byte-identical to the caller-provided systemPromptAppend.
|
|
320
320
|
const projectInstructions = input.projectInstructions ?? agentProfile?.projectInstructions;
|
|
321
|
+
// #559 — resolve the child's {profile|user} memory stores READ-ONLY (never create an empty
|
|
322
|
+
// anchor just by spawning). The profile store is keyed on the resolved profile name; the user
|
|
323
|
+
// store on the spawn-chain operator (the requesting agent's owner, else the default operator).
|
|
324
|
+
// Both resolve null until someone has actually written to them, so a fresh deployment stays
|
|
325
|
+
// byte-identical. Injection of their active (promoted) entries happens in the composer.
|
|
326
|
+
const profileAnchor = resolveScopedAnchor("profile", profileName);
|
|
327
|
+
const operatorId = callerId ? resolveAgentOwnership(callerId).ownerUserId : DEFAULT_USER_ID;
|
|
328
|
+
const userAnchor = resolveScopedAnchor("user", operatorId);
|
|
321
329
|
const composedInstructions = composeSpawnInstructionsWithEvents({
|
|
322
330
|
...(callerProject ? { callerProject } : {}),
|
|
323
331
|
...(projectInstructions ? { projectInstructions } : {}),
|
|
332
|
+
...(profileAnchor ? { profileAnchor } : {}),
|
|
333
|
+
...(userAnchor ? { userAnchor } : {}),
|
|
324
334
|
...(agentProfile ? { profile: agentProfile } : {}),
|
|
325
335
|
...(callerId ? { spawnedBy: callerId } : {}),
|
|
326
336
|
...(input.systemPromptAppend ? { callerSystemPromptAppend: input.systemPromptAppend } : {}),
|
|
@@ -436,6 +446,51 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
|
|
|
436
446
|
};
|
|
437
447
|
}
|
|
438
448
|
|
|
449
|
+
/**
|
|
450
|
+
* #734 — strip the heavy resolved-provisioning file CONTENTS from a spawn command before
|
|
451
|
+
* echoing it back to the CALLER. `withResolvedProvisioning` inlines every bundled plugin/skill
|
|
452
|
+
* file under `params.agentProfile.provisioning.{skills,plugins}[].files[].content` (~90KB for a
|
|
453
|
+
* bundled-plugin profile like default-relay), which blows the MCP result token cap and hard-errors
|
|
454
|
+
* the call. The ORCHESTRATOR-bound command — dispatched on the command bus inside `spawnAgent`
|
|
455
|
+
* (the row in `listCommands`, not this returned object) — keeps the full bytes so it can still
|
|
456
|
+
* materialize the plugins on the target host. This returns a structural summary (paths + byte
|
|
457
|
+
* counts, contents dropped) leaving the dispatched command untouched (the mutated path is
|
|
458
|
+
* shallow-cloned, never mutated in place).
|
|
459
|
+
*/
|
|
460
|
+
export function summarizeSpawnCommandForCaller(command: Command): Command {
|
|
461
|
+
const profile = command.params.agentProfile;
|
|
462
|
+
if (!isRecord(profile) || !isRecord(profile.provisioning)) return command;
|
|
463
|
+
const provisioning = profile.provisioning;
|
|
464
|
+
const stripContents = (assets: unknown): unknown => {
|
|
465
|
+
if (!Array.isArray(assets)) return assets;
|
|
466
|
+
return assets.map((asset) => {
|
|
467
|
+
if (!isRecord(asset) || !Array.isArray(asset.files)) return asset;
|
|
468
|
+
return {
|
|
469
|
+
...asset,
|
|
470
|
+
files: asset.files.map((file) =>
|
|
471
|
+
isRecord(file) && typeof file.content === "string"
|
|
472
|
+
? { path: file.path, contentBytes: file.content.length }
|
|
473
|
+
: file,
|
|
474
|
+
),
|
|
475
|
+
};
|
|
476
|
+
});
|
|
477
|
+
};
|
|
478
|
+
return {
|
|
479
|
+
...command,
|
|
480
|
+
params: {
|
|
481
|
+
...command.params,
|
|
482
|
+
agentProfile: {
|
|
483
|
+
...profile,
|
|
484
|
+
provisioning: {
|
|
485
|
+
...provisioning,
|
|
486
|
+
skills: stripContents(provisioning.skills),
|
|
487
|
+
plugins: stripContents(provisioning.plugins),
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
|
|
439
494
|
/** Poll the agents table for the child that registers with this spawnRequestId (#255). */
|
|
440
495
|
async function waitForSpawnedAgent(spawnRequestId: string, timeoutMs: number, pollMs = 300): Promise<string | null> {
|
|
441
496
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{B as t,Bn as n,Bt as r,Dt as i,Et as a,Jn as o,L as s,Nn as c,On as l,Qn as u,V as d,Vn as f,Xn as p,Xt as m,Zt as h,_n as g,a as _,b as v,bn as y,c as ee,cn as b,ft as x,g as S,gn as C,hn as w,i as te,in as ne,lr as T,lt as E,m as D,r as O,sn as k,x as A,xn as j,yn as M}from"./lucide-react-uFIMC7W7.js";import{g as N,r as P,t as F}from"./store-d-IbqTaD.js";import{E as I,H as re,N as L,P as ie,R,S as ae,V as oe,_ as se,d as ce,f as le,k as z,q as B,rt as V,v as ue}from"./display-DRiGi1zj.js";import{t as H}from"./types-Tv67voFu.js";import{a as de,i as fe,o as pe,t as U,w as W}from"./index-CwhhpGgX.js";import{t as me}from"./user-avatar-BOGZ21O8.js";var G=e(T(),1),he={online:`came online`,offline:`went offline`,shutdown:`shut down`,restarted:`restarted`,"compaction-requested":`compaction requested`,compacting:`compaction started`,compacted:`context compacted`,"compaction-stalled":`compaction stalled — may need manual intervention`,"clear-requested":`clear requested`,"clearing-context":`clear started`,"context-cleared":`context cleared`,"clear-stalled":`context clear stalled — may need manual intervention`,"shutting-down":`shutting down`},ge=new Set(Object.keys(he)),_e=3e3;function K(e){return new Date(e.occurredAt??e.createdAt).getTime()}function ve(e){if(e.kind!==`session`)return null;let t=e.payload?.session;return!t||t.type!==`narration`&&t.type!==`reasoning`&&t.type!==`tool`?null:{id:e.id,kind:t.type,label:typeof t.label==`string`?t.label:void 0,text:e.body,ts:K(e),turnId:typeof t.turnId==`string`?t.turnId:void 0}}function ye(e){if(e.kind!==`session`)return null;let t=e.payload?.session;if(t?.type!==`notice`)return null;let n=typeof t.label==`string`&&t.label?t.label:`compacted`;return{id:`notice-${e.id}`,status:n,timestamp:K(e)}}function be(e){if(e.kind!==`session`)return null;let t=e.payload?.session;if(t?.type!==`relay-injection`)return null;let n=t.relayInjection&&typeof t.relayInjection==`object`&&!Array.isArray(t.relayInjection)?t.relayInjection:{},r=typeof n.category==`string`&&[`memory`,`instructions`,`tools`,`comms`,`knowledge`,`context`].includes(n.category)?n.category:`context`,i=typeof n.timestamp==`number`&&Number.isFinite(n.timestamp)?n.timestamp:K(e),a=n.detail&&typeof n.detail==`object`&&!Array.isArray(n.detail)?n.detail:{};return{id:e.id,category:r,summary:typeof n.summary==`string`&&n.summary.trim()?n.summary:e.body,detail:a,agentId:typeof n.agentId==`string`&&n.agentId?n.agentId:e.from,timestamp:i}}function xe(e,t){let n=e.trim();for(let e of t){let t=e.trim();if(t){if(n===t)break;n.startsWith(`${t}\n\n`)&&(n=n.slice(t.length+2).trimStart())}}return n.trim()||e.trim()}function Se(e){return e.kind===`system`&&e.from===`system`}var Ce=new Set([`agent.ready`,`agent.exited`,`agent.spawn_failed`]);function q(e){let t=new Date(e);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}`}function we(e){let t=e.filter(e=>ge.has(e.status)).slice().sort((e,t)=>e.timestamp-t.timestamp),n=[];for(let e of t)n.some(t=>t.id===e.id)||n.some(t=>t.status===e.status&&Math.abs(t.timestamp-e.timestamp)<=_e)||n.push(e);return n}function Te(e,t,n,r=[],i){let a=[];for(let e of r){let t=e.entries.reduce((e,t)=>Math.min(e,B(t.originalCreatedAt)),1/0),n=Number.isFinite(t)?t-1:e.importedAt;a.push({ts:n,entry:{type:`import-boundary`,history:e,timestamp:n}});for(let t of e.entries)a.push({ts:B(t.originalCreatedAt),entry:{type:`imported-message`,history:e,entry:t}})}if(n){let e=new Date(n).getTime();Number.isFinite(e)&&a.push({ts:e,entry:{type:`created`,timestamp:e}})}if(i?.spawnedBy){let e=n?new Date(n).getTime():0,t=Number.isFinite(e)?e:0;a.push({ts:t,entry:{type:`agent-action`,direction:`spawned-by`,agentId:i.spawnedBy.agentId,provider:i.spawnedBy.provider,status:`ready`,timestamp:t}})}let o=i?.spawnedBy?.agentId,s=null,c=1/0;for(let t of e){if(t.kind===`session`||Se(t)||I(t)||!(t.from===`user`||o!==void 0&&t.from===o)||!z(t).trim())continue;let e=K(t);e<c&&(c=e,s=t.id)}let l=new Map,u=new Map,d=new Map;for(let t of e){if(t.kind!==`session`)continue;let e=t.payload?.session;if(e?.type===`narration`&&typeof e.turnId==`string`){let n=u.get(e.turnId)??[];n.push({id:t.id,body:t.body.trim()}),u.set(e.turnId,n)}else if(e?.type===`response`&&typeof e.turnId==`string`){let n=l.get(e.turnId)??[];n.push(t.body.trim()),l.set(e.turnId,n)}}let f=new Map;for(let[e,t]of l){let n=(u.get(e)??[]).map(e=>e.body);f.set(e,t.map(e=>xe(e,n)))}for(let t of e){if(t.kind!==`session`)continue;let e=t.payload?.session;if(e?.type!==`response`||typeof e.turnId!=`string`)continue;let n=xe(t.body,(u.get(e.turnId)??[]).map(e=>e.body));n&&n!==t.body&&d.set(t.id,n)}let p=new Set;for(let[e,t]of f){let n=u.get(e)??[];for(let e of t)for(let t=n.length-1;t>=0;t--){let r=n[t];if(!p.has(r.id)&&re(e,r.body)){p.add(r.id);break}}}let m=new Map,h=[];for(let t of e){if(Se(t)){let e=typeof t.payload?.kind==`string`?t.payload.kind:``;if(Ce.has(e)){let n=t.payload,r=typeof n.agentId==`string`?n.agentId:``,i=K(t);if(!r){a.push({ts:i,entry:{type:`notice`,msg:t}});continue}let o=e===`agent.ready`?`ready`:e===`agent.exited`?`exited`:`failed`,s=m.get(r);if(s)s.entry.status=o,typeof n.reason==`string`&&(s.entry.reason=n.reason),s.entry.timestamp=i,s.ts=i;else{let e={ts:i,entry:{type:`agent-action`,direction:`spawned-child`,agentId:r,provider:typeof n.provider==`string`?n.provider:void 0,status:o,reason:typeof n.reason==`string`?n.reason:void 0,timestamp:i}};m.set(r,e),a.push(e)}continue}a.push({ts:K(t),entry:{type:`notice`,msg:t}});continue}let e=ye(t);if(e){h.push(e);continue}let n=ve(t);if(n){if(n.kind===`narration`&&p.has(n.id))continue;a.push({ts:n.ts,entry:{type:`activity`,steps:[n],timestamp:n.ts}});continue}let r=be(t);if(r){a.push({ts:r.timestamp,entry:{type:`relay-injection`,event:r}});continue}if(t.kind===`session`){let e=t.payload?.session;if(e?.type===`response`&&typeof e.turnId==`string`){let e=d.get(t.id);if(e&&e!==t.body){a.push({ts:K(t),entry:{type:`message`,msg:{...t,body:e}}});continue}}}let i=t.id===s?`initial-prompt`:`message`;a.push({ts:K(t),entry:{type:i,msg:t}})}for(let e of we([...t,...h]))a.push({ts:e.timestamp,entry:{type:`status`,event:e}});let g={created:0,date:1,"import-boundary":2,"imported-message":3,"initial-prompt":4,message:4,activity:4,notice:4,"agent-action":4,"relay-injection":4,status:5};a.sort((e,t)=>{let n=e.ts-t.ts;return Math.abs(n)<3e3&&g[e.entry.type]-g[t.entry.type]||n});let _=[],v=``;for(let{ts:e,entry:t}of a){if(t.type===`created`){_.push(t);continue}let n=q(e);if(n!==v&&(_.push({type:`date`,date:n,timestamp:e}),v=n),t.type===`activity`){let e=_[_.length-1];if(e&&e.type===`activity`&&Oe(e,t)){e.steps.push(...t.steps);continue}}_.push(t)}return _}function Ee(e){return e.type===`message`?`msg-${e.msg.id}`:e.type===`initial-prompt`?`initprompt-${e.msg.id}`:e.type===`notice`?`notice-${e.msg.id}`:e.type===`relay-injection`?`relay-injection-${e.event.id}`:e.type===`agent-action`?`agent-action-${e.direction}-${e.agentId}`:e.type===`activity`?`act-${e.steps[0]?.id??e.timestamp}`:e.type===`import-boundary`?`import-${e.history.id}`:e.type===`imported-message`?`import-msg-${e.history.id}-${e.entry.originalMessageId}-${e.entry.position}`:e.type===`status`?`status-${e.event.id}`:e.type===`date`?`date-${e.date}`:`created-${e.timestamp}`}function De(e){return e.type===`message`||e.type===`initial-prompt`||e.type===`notice`?(e.msg.subject?`${e.msg.subject} `:``)+z(e.msg):e.type===`imported-message`?z(e.entry.message):e.type===`activity`?e.steps.map(e=>[e.label,e.text].filter(Boolean).join(` `)).join(`
|
|
2
|
-
`):e.type===`relay-injection`?`${e.event.category} ${e.event.summary}\n${JSON.stringify(e.event.detail)}`:``}function Oe(e,t){let n=e.steps[e.steps.length-1]?.turnId,r=t.steps[0]?.turnId;return n&&r?n===r:!n&&!r}function ke(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(1)} MB`}function Ae(e,t){if(t.startsWith(`/`))return t;let n=`${e.replace(/\/+$/,``)}/${t}`.split(`/`),r=[];for(let e of n)!e||e===`.`||(e===`..`?r.pop():r.push(e));return`/`+r.join(`/`)}function je(e){let t=e.replace(/\/+$/,``),n=t.lastIndexOf(`/`);return n>0?t.slice(0,n):`/`}function Me(e,t){return e.filter(e=>e.status===`online`&&R(t,e.baseDir)).sort((e,t)=>L(t.baseDir).length-L(e.baseDir).length)[0]||e.find(e=>e.status===`online`)}function Ne(){return typeof window<`u`&&window.matchMedia(`(min-width: 1280px)`).matches}function Pe(){return typeof window<`u`&&!!window.getSelection()?.toString()}function Fe(e){let t=e.payload?.attachments;return Array.isArray(t)?t.filter(e=>!!(e&&typeof e==`object`&&typeof e.artifactId==`string`)):[]}var Ie=[`👍`,`❤️`,`✅`,`👀`];function Le(e){let t=new Map;for(let n of e.reactions||[]){let e=ie(n.emoji),r=t.get(e)??{emoji:e,count:0,mine:!1,actors:[]};r.count+=1,r.mine=r.mine||n.actorId===`user`,r.actors.push(n.actorId),t.set(e,r)}return[...t.values()].sort((e,t)=>t.count-e.count||e.emoji.localeCompare(t.emoji))}function J(e){return I(e)}function Re(e,t){let n=e.readBy||[],r=e.resolvedToAgent||t||e.to,i=r?n.includes(r):!1,a=n.some(e=>e!==V);if(i||a){let e=i?r:n.find(e=>e!==V);return{label:`read`,title:e?`Read by ${e}`:`Read by agent`,tone:`ok`,icon:j}}if(e.deliveryStatus===`delivered`)return{label:`delivered`,title:`Delivered to agent inbox`,tone:`ok`,icon:j};if(e.deliveryStatus===`queued`)return{label:`queued`,title:`Queued until the target agent is available`,tone:`warn`,icon:ne};if(e.deliveryStatus===`failed`||e.deliveryStatus===`dead`){let t=e.deliveryPoisonReason||e.deliveryLastError||e.deliveryStatus;return{label:e.deliveryStatus,title:t,tone:`danger`,icon:w}}return{label:`sent`,title:`Accepted by Relay`,tone:`muted`,icon:y}}function ze(e){let t=B(e.createdAt);return(e.reactions||[]).reduce((e,t)=>Math.max(e,B(t.updatedAt||t.createdAt)),t)}function Be(e){return e?e.messages.reduce((e,t)=>Math.max(e,ze(t)),0):0}function Ve(e,t,n){return(e-t)*n}function He(e){if(!e)return 0;let t=0;for(let n of e.messages)ae(n)&&(t=Math.max(t,B(n.createdAt)));return t}function Y(e){return new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`})}function Ue(e){for(let t of e)t.previewUrl&&URL.revokeObjectURL(t.previewUrl)}function We(e,t,n,r){if(e?.teamId)return{teamId:e.teamId};let i=[...t];n&&!i.some(e=>e.id===n.id)&&i.push(n);let a=i.filter(e=>e.threadId).reverse(),o=a.find(e=>!!r[P(e.threadId,e.channel)])??a[0];return o?.threadId?{threadId:o.threadId,...o.channel?{channel:o.channel}:{}}:null}var X=p(),Ge={online:`text-emerald-400`,offline:`text-zinc-400`,shutdown:`text-zinc-400`,restarted:`text-blue-400`,"compaction-requested":`text-zinc-400`,compacting:`text-amber-400`,compacted:`text-amber-400`,"compaction-stalled":`text-red-400`,"clear-requested":`text-zinc-400`,"clearing-context":`text-amber-400`,"context-cleared":`text-amber-400`,"clear-stalled":`text-red-400`,"shutting-down":`text-zinc-400`};function Ke(e){let t=new Date,[n,r,i]=e.split(`-`).map(Number),a=new Date(n,r-1,i);if(e===q(t.getTime()))return`Today`;let o=new Date(t);return o.setDate(o.getDate()-1),e===q(o.getTime())?`Yesterday`:a.toLocaleDateString(void 0,{weekday:`short`,month:`short`,day:`numeric`,year:a.getFullYear()===t.getFullYear()?void 0:`numeric`})}function qe({event:e}){return(0,X.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,X.jsxs)(`div`,{className:`flex items-center gap-1.5 text-xs text-muted-foreground`,children:[(0,X.jsx)(k,{className:o(`w-2 h-2 fill-current`,Ge[e.status]||`text-zinc-400`)}),(0,X.jsx)(`span`,{children:he[e.status]||e.status}),(0,X.jsx)(`span`,{className:`text-muted-foreground/60`,children:Y(e.timestamp)})]}),(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}var Je={"branch.landed":a,"context.warning":D,"agent.context_threshold":D,"agent.resume_budget_exhausted":D,"agent.rate_limit_resume":d},Ye={"branch.landed":`branch landed`,"context.warning":`context warning`,"agent.context_threshold":`context threshold reached`};function Xe(e){return e&&(e.includes(`.`)?e.slice(e.indexOf(`.`)+1):e).replace(/[._-]+/g,` `).trim()||`system signal`}function Z({agentId:e,fallbackLabel:t,className:n,noIcon:r}){let i=F(t=>t.agentsById[e])||null,a=F(e=>e.openInboxThread),s=F(e=>e.switchView),c=i?ce(i):t||e;return(0,X.jsxs)(`button`,{type:`button`,className:o(`inline-flex max-w-full items-center gap-1 rounded px-1 text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground`,n),onClick:t=>{t.stopPropagation(),a(e),s(`chat`)},title:`Open chat for ${c}`,children:[!r&&(0,X.jsx)(W,{agent:i,className:`w-4 h-4 text-[10px]`}),(0,X.jsx)(`span`,{className:`max-w-[160px] truncate`,children:c})]})}function Ze({msg:e}){let t=e.payload??{},n=$e(e),r=typeof t.sha==`string`?t.sha:``,i=r?r.slice(0,7):``,o=typeof t.author==`string`?t.author:``,s=typeof t.branch==`string`?t.branch:``,c=typeof t.base==`string`?t.base:``,l=t.pushed;return(0,X.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,X.jsxs)(`div`,{className:`flex max-w-full flex-wrap items-center justify-center gap-x-1.5 gap-y-0.5 rounded-full border border-emerald-600/35 bg-emerald-500/10 px-2.5 py-1 text-xs text-emerald-700 dark:border-emerald-500/25 dark:text-emerald-300/90`,children:[(0,X.jsx)(a,{className:`h-3 w-3 shrink-0 text-emerald-600 dark:text-emerald-400`}),(0,X.jsx)(`span`,{className:`text-emerald-700 dark:text-emerald-300`,children:`branch landed`}),s&&c&&(0,X.jsxs)(`span`,{className:`font-mono text-emerald-700/80 dark:text-emerald-200/70`,title:`${s} → ${c}`,children:[s,(0,X.jsx)(`span`,{className:`opacity-50`,children:` → `}),c]}),i&&(0,X.jsx)(`span`,{className:`rounded bg-emerald-500/15 px-1 font-mono text-emerald-800 dark:text-emerald-200`,title:r,children:i}),o&&(0,X.jsxs)(`span`,{className:`inline-flex items-center gap-1 text-emerald-700/80 dark:text-emerald-300/80`,children:[(0,X.jsx)(`span`,{className:`opacity-70`,children:`by`}),(0,X.jsx)(Z,{agentId:o,className:`text-emerald-700 hover:text-emerald-900 dark:text-emerald-300/90 dark:hover:text-emerald-100`})]}),l===!1&&(0,X.jsx)(`span`,{className:`text-amber-600 dark:text-amber-300/80`,title:`Local-only land — not pushed to origin`,children:`· local only`}),n&&(0,X.jsxs)(`span`,{className:`max-w-[220px] truncate text-emerald-700/70 dark:text-emerald-300/70`,title:n,children:[`· because `,n]}),(0,X.jsx)(`span`,{className:`text-emerald-700/60 dark:text-emerald-300/50`,children:Y(e.occurredAt??e.createdAt)})]}),(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function Qe({msg:e}){let t=typeof e.payload?.kind==`string`?e.payload.kind:``;if(t===`branch.landed`)return(0,X.jsx)(Ze,{msg:e});let n=Je[t]??s,r=Ye[t]??Xe(t),i=$e(e);return(0,X.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,X.jsxs)(`div`,{className:`flex items-center gap-1.5 rounded-full border border-border bg-muted/30 px-2.5 py-1 text-xs text-muted-foreground`,children:[(0,X.jsx)(n,{className:`h-3 w-3`}),(0,X.jsx)(`span`,{children:r}),i&&(0,X.jsxs)(`span`,{className:`max-w-[220px] truncate text-muted-foreground/80`,title:i,children:[`· because `,i]}),(0,X.jsx)(`span`,{className:`text-muted-foreground/60`,children:Y(e.occurredAt??e.createdAt)})]}),(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function $e(e){let t=e.payload?.routing;if(!t||typeof t!=`object`||Array.isArray(t))return``;let n=t.reason;return typeof n==`string`?n:``}var et={"spawned-child":{ready:`spawned`,exited:`spawned · exited`,failed:`spawn failed`},"spawned-by":{ready:`spawned by`,exited:`spawned by`,failed:`spawned by`}},tt={"spawned-child-ready":t,"spawned-child-exited":E,"spawned-child-failed":w,"spawned-by-ready":f,"spawned-by-exited":f,"spawned-by-failed":f},nt={"spawned-child-ready":`text-emerald-400`,"spawned-child-exited":`text-zinc-400`,"spawned-child-failed":`text-red-400`,"spawned-by-ready":`text-blue-400`,"spawned-by-exited":`text-blue-400`,"spawned-by-failed":`text-blue-400`};function rt({entry:e}){let t=`${e.direction}-${e.status}`,n=et[e.direction]?.[e.status]??e.direction,r=tt[t]??s,i=nt[t]??`text-muted-foreground`,a=e.status===`failed`;return(0,X.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,X.jsxs)(`div`,{className:o(`flex items-center gap-1.5 rounded-full border bg-muted/30 px-2.5 py-1 text-xs`,a?`border-red-500/30`:`border-border`),children:[(0,X.jsx)(r,{className:o(`h-3 w-3 shrink-0`,i)}),(0,X.jsx)(`span`,{className:`text-muted-foreground`,children:n}),(0,X.jsx)(Z,{agentId:e.agentId}),e.reason&&a&&(0,X.jsxs)(`span`,{className:`text-red-400/80 max-w-[120px] truncate`,title:e.reason,children:[`— `,e.reason]}),(0,X.jsx)(`span`,{className:`text-muted-foreground/60 shrink-0`,children:Y(e.timestamp)})]}),(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}var it={memory:l,instructions:r,tools:_,comms:s,knowledge:c,context:h},at={memory:`border-emerald-500/25 bg-emerald-500/10 text-emerald-300`,instructions:`border-sky-500/25 bg-sky-500/10 text-sky-300`,tools:`border-amber-500/25 bg-amber-500/10 text-amber-300`,comms:`border-violet-500/25 bg-violet-500/10 text-violet-300`,knowledge:`border-cyan-500/25 bg-cyan-500/10 text-cyan-300`,context:`border-zinc-500/25 bg-zinc-500/10 text-zinc-300`};function ot(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function st({entry:e}){let[t,n]=(0,G.useState)(!1),r=e.event,i=it[r.category]??v;return(0,X.jsx)(`div`,{className:`flex justify-center py-2 my-1`,children:(0,X.jsxs)(`div`,{className:o(`w-full max-w-[85%] md:max-w-[75%] rounded-lg border px-2.5 py-1.5 text-xs shadow-sm`,at[r.category]??at.context),children:[(0,X.jsxs)(`button`,{type:`button`,className:`flex w-full min-w-0 items-center gap-1.5 text-left`,onClick:()=>n(e=>!e),children:[(0,X.jsx)(i,{className:`h-3.5 w-3.5 shrink-0`}),(0,X.jsx)(`span`,{className:`shrink-0 font-medium`,children:r.category}),(0,X.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-foreground/80`,children:r.summary}),(0,X.jsx)(`span`,{className:`shrink-0 text-muted-foreground/60`,children:Y(r.timestamp)}),(0,X.jsx)(g,{className:o(`h-3.5 w-3.5 shrink-0 transition-transform`,t&&`rotate-90`)})]}),t&&(0,X.jsx)(`pre`,{className:`mt-2 max-h-72 overflow-auto rounded-md border border-border/60 bg-background/75 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground whitespace-pre-wrap break-words`,children:ot(r.detail)})]})})}function ct({blockedLabel:e,onInterrupt:t}){return e?(0,X.jsx)(`div`,{className:`flex justify-start mb-3 animate-in fade-in slide-in-from-bottom-1 duration-150`,children:(0,X.jsxs)(`div`,{className:`flex h-9 items-center gap-2 rounded-2xl rounded-bl-sm bg-card ring-1 ring-red-500/30 px-4`,children:[(0,X.jsx)(w,{className:`w-3.5 h-3.5 text-red-400`}),(0,X.jsxs)(`span`,{className:`text-xs text-red-300`,children:[`blocked: `,e]})]})}):(0,X.jsx)(`div`,{className:`flex justify-start mb-3 animate-in fade-in slide-in-from-bottom-1 duration-150`,children:(0,X.jsxs)(`div`,{className:`flex h-9 items-center gap-2 rounded-2xl rounded-bl-sm bg-card ring-1 ring-foreground/10 px-4`,children:[(0,X.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,X.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-yellow-400 animate-[pulse_1.4s_ease-in-out_infinite]`}),(0,X.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-yellow-400 animate-[pulse_1.4s_ease-in-out_0.2s_infinite]`}),(0,X.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-yellow-400 animate-[pulse_1.4s_ease-in-out_0.4s_infinite]`})]}),(0,X.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`working`}),t&&(0,X.jsxs)(`button`,{onClick:t,title:`Interrupt`,className:`ml-1 flex items-center gap-1 rounded-full px-1.5 py-0.5 text-xs text-muted-foreground hover:text-red-300 hover:bg-red-500/10 transition-colors`,children:[(0,X.jsx)(b,{className:`w-3.5 h-3.5`}),`Stop`]})]})})}var Q=`agent-relay:chat-hide-tools`,$=(()=>{let e=new Set,t=(()=>{try{return window.localStorage.getItem(Q)===`on`}catch{return!1}})(),n=()=>e.forEach(e=>e());return typeof window<`u`&&window.addEventListener(`storage`,e=>{e.key===Q&&(t=e.newValue===`on`,n())}),{subscribe(t){return e.add(t),()=>e.delete(t)},get:()=>t,toggle(){t=!t;try{window.localStorage.setItem(Q,t?`on`:`off`)}catch{}n()}}})();function lt(){return[(0,G.useSyncExternalStore)($.subscribe,$.get,()=>!1),$.toggle]}function ut({steps:e,showReasoning:t,issueRepo:n}){let[r,i]=lt(),a=t?e:e.filter(e=>e.kind!==`reasoning`);if(!a.length)return null;let s=a.filter(e=>e.kind===`tool`).length;return(0,X.jsx)(`div`,{className:`flex justify-start mb-2`,children:(0,X.jsxs)(`div`,{className:`max-w-[85%] md:max-w-[75%] min-w-0 space-y-1.5`,children:[a.map(e=>e.kind===`narration`?(0,X.jsx)(U,{text:e.text,issueRepo:n,className:`text-sm leading-relaxed break-words text-foreground/90 min-w-0`},e.id):e.kind===`reasoning`?(0,X.jsxs)(`div`,{className:`flex items-start gap-1.5 text-xs leading-relaxed text-muted-foreground/80`,children:[(0,X.jsx)(l,{className:`w-3.5 h-3.5 mt-0.5 shrink-0 opacity-70`}),(0,X.jsx)(U,{text:e.text,issueRepo:n,className:`italic break-words min-w-0`})]},e.id):r?null:(0,X.jsxs)(`div`,{className:`flex items-start gap-1.5 text-xs leading-relaxed text-muted-foreground`,children:[(0,X.jsx)(S,{className:`w-3 h-3 mt-0.5 shrink-0 opacity-70`}),(0,X.jsxs)(`span`,{className:`min-w-0 break-words`,children:[(0,X.jsx)(`span`,{className:`font-medium`,children:e.label||`tool`}),e.text&&e.text.trim()&&e.text.trim()!==(e.label??``).trim()?(0,X.jsxs)(`span`,{className:`opacity-70`,children:[` — `,e.text]}):null]})]},e.id)),s>0&&(0,X.jsxs)(`button`,{onClick:i,className:`flex items-center gap-1 text-[11px] text-muted-foreground/50 hover:text-muted-foreground transition-colors text-left`,children:[(0,X.jsx)(g,{className:o(`w-3 h-3 shrink-0 transition-transform`,!r&&`rotate-90`)}),(0,X.jsx)(`span`,{children:r?`show ${s} tool step${s===1?``:`s`}`:`hide tool steps`})]})]})})}function dt({date:e}){return(0,X.jsxs)(`div`,{className:`flex items-center justify-center gap-3 py-3 my-1`,children:[(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,X.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground`,children:Ke(e)}),(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function ft({timestamp:e}){let t=new Date(e).toLocaleString(void 0,{month:`short`,day:`numeric`,year:`numeric`,hour:`2-digit`,minute:`2-digit`});return(0,X.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,X.jsxs)(`span`,{className:`text-xs text-muted-foreground/60`,children:[`created `,t]}),(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function pt({history:e}){let t=e.sourceAgentLabel||e.sourcePeerId,n=e.entries.length;return(0,X.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,X.jsxs)(`div`,{className:`flex items-center gap-1.5 rounded-full border border-dashed border-border bg-muted/30 px-2 py-1 text-[11px] text-muted-foreground`,children:[(0,X.jsx)(i,{className:`h-3 w-3`}),(0,X.jsxs)(`span`,{children:[`forked history from `,t]}),(0,X.jsxs)(`span`,{className:`text-muted-foreground/60`,children:[n,` `,n===1?`entry`:`entries`]})]}),(0,X.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function mt({entry:e,sourceLabel:t,issueRepo:n}){let r=e.message,i=z(r),a=e.originalFrom===V;return(0,X.jsx)(`div`,{className:o(`flex mb-3 opacity-80`,a?`justify-end`:`justify-start`),children:(0,X.jsx)(`div`,{className:`max-w-[85%] md:max-w-[75%]`,children:(0,X.jsxs)(`div`,{className:o(`rounded-2xl border border-dashed px-3.5 py-2 text-sm select-text`,a?`border-primary/25 bg-primary/10 text-foreground rounded-br-sm`:`border-border bg-card/70 rounded-bl-sm`),children:[(0,X.jsxs)(`div`,{className:o(`mb-1 text-[10px] uppercase tracking-normal`,a?`text-primary/70`:`text-muted-foreground`),children:[`forked history · `,a?`you`:t||e.originalFrom]}),(0,X.jsx)(U,{text:i,rawBody:r.body,issueRepo:n,className:`leading-relaxed`}),(0,X.jsxs)(`p`,{className:o(`mt-1 flex items-center justify-end gap-1.5 text-xs`,a?`text-primary/60`:`text-muted-foreground`),children:[(0,X.jsxs)(`span`,{className:`opacity-40`,children:[`#`,e.originalMessageId]}),(0,X.jsx)(`span`,{children:Y(e.originalCreatedAt)})]})]})})})}function ht({msg:e,issueRepo:t}){let n=z(e),r=Y(e.occurredAt??e.createdAt);return(0,X.jsx)(`div`,{"data-msg-id":e.id,className:`mb-3`,children:(0,X.jsxs)(`div`,{className:`rounded-xl border border-primary/30 bg-primary/[0.06] px-3.5 py-2.5 shadow-sm`,children:[(0,X.jsxs)(`div`,{className:`mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-primary/80`,children:[(0,X.jsx)(v,{className:`h-3.5 w-3.5`}),(0,X.jsx)(`span`,{children:`Initial prompt`}),(0,X.jsx)(`span`,{className:`ml-auto text-[10px] font-normal normal-case text-muted-foreground/60`,children:r})]}),(0,X.jsx)(U,{text:n,rawBody:e.body,issueRepo:t,className:`text-sm leading-relaxed text-foreground`})]})})}function gt({scrollEl:e,timeline:t}){let[n,r]=(0,G.useState)(!0),[i,a]=(0,G.useState)(null),[s,c]=(0,G.useState)(null),[l,u]=(0,G.useState)(!1),d=(0,G.useMemo)(()=>{for(let e=t.length-1;e>=0;e--){let n=t[e];if(!(!n||n.type!==`message`&&n.type!==`initial-prompt`)&&n.msg.from===`user`)return{id:n.msg.id,body:z(n.msg)}}return null},[t]);if((0,G.useEffect)(()=>{if(!d||!e){r(!0);return}let t=null,n=null,i=()=>{let i=e.querySelector(`[data-msg-id="${d.id}"]`);if(!i){t?.disconnect(),t=null,n=null,r(!1);return}let a=i.getBoundingClientRect(),o=e.getBoundingClientRect();u(a.top<o.top),i!==n&&(t?.disconnect(),n=i,t=new IntersectionObserver(([e])=>{e&&r(e.isIntersecting)},{root:e,threshold:0}),t.observe(i))};return i(),e.addEventListener(`scroll`,i,{passive:!0}),()=>{t?.disconnect(),e.removeEventListener(`scroll`,i)}},[d?.id,e]),n||!d||!d.body.trim())return null;let f=i?.id===d.id?i.value:!1,p=s?.id===d.id?s.value:!1;function m(){!e||!d||e.querySelector(`[data-msg-id="${d.id}"]`)?.scrollIntoView({behavior:`smooth`,block:`center`})}let h=l?`↑`:`↓`;return p?(0,X.jsx)(`div`,{className:`flex shrink-0 bg-card/45 border-b border-border`,children:(0,X.jsxs)(`button`,{type:`button`,className:`w-full flex items-center justify-center gap-1.5 py-1 text-[11px] text-primary/60 hover:text-primary transition-colors`,onClick:()=>c({id:d.id,value:!1}),children:[(0,X.jsx)(`span`,{children:`Your prompt`}),(0,X.jsx)(M,{className:`w-3 h-3`})]})}):(0,X.jsxs)(`section`,{className:`flex shrink-0 flex-col border-b border-border bg-card/45 px-3 py-2`,children:[(0,X.jsxs)(`div`,{className:`flex items-center gap-2 text-[11px] text-muted-foreground mb-0.5`,children:[(0,X.jsx)(`span`,{className:`font-medium text-primary/70`,children:`Your prompt`}),(0,X.jsxs)(`button`,{type:`button`,className:`ml-auto hover:text-foreground transition-colors`,onClick:m,children:[h,` scroll to original`]}),(0,X.jsx)(`button`,{type:`button`,className:`hover:text-foreground transition-colors`,onClick:()=>c({id:d.id,value:!0}),title:`Minimize`,children:(0,X.jsx)(C,{className:`w-3 h-3`})})]}),(0,X.jsx)(`p`,{className:o(`text-sm text-foreground leading-snug cursor-pointer`,!f&&`line-clamp-2`),onClick:()=>a({id:d.id,value:!f}),children:d.body})]})}function _t(){return(0,G.useSyncExternalStore)(e=>N.subscribe(e),()=>N.getPlayingKey(),()=>null)}function vt({msg:e,peer:t}){return(0,X.jsx)(ht,{msg:e,issueRepo:F(e=>e.agentsById[t]?.issueRepo)})}function yt({agent:e,onClick:t}){let n=!!(t&&e);return(0,X.jsx)(`button`,{type:`button`,title:e?e.label||e.name||e.id:void 0,onClick:t,disabled:!n,className:o(`shrink-0 self-end transition-opacity`,n?`cursor-pointer hover:opacity-80`:`cursor-default opacity-60`),children:(0,X.jsx)(W,{agent:e})})}function bt({agentId:e,onOpen:t}){let n=F(t=>t.agentsById[e]??null);return(0,X.jsx)(yt,{agent:n,onClick:n?()=>t(n):void 0})}function xt({attachment:e,outbound:t}){let n=e.kind===`image`,i=e.title||e.artifactId,[a,s]=(0,G.useState)(null),[c,l]=(0,G.useState)(null),[d,f]=(0,G.useState)(!1),[p,h]=(0,G.useState)(!1);(0,G.useEffect)(()=>{let t=!1,n=null;async function r(){f(!0),l(null),s(null);try{let r=await u(`/artifacts/${encodeURIComponent(e.artifactId)}/content`);if(t)return;n=URL.createObjectURL(r),s(n)}catch(e){t||l(e.message)}finally{t||f(!1)}}return r(),()=>{t=!0,n&&URL.revokeObjectURL(n)}},[e.artifactId]);function g(){if(!a)return;let e=document.createElement(`a`);e.href=a,e.download=i,document.body.appendChild(e),e.click(),e.remove()}return n?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`button`,{type:`button`,onClick:()=>a&&h(!0),disabled:!a,className:`group/img mt-2 block overflow-hidden rounded-md border border-foreground/10 bg-black/10 text-left disabled:cursor-default relative`,children:a?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`img`,{src:a,alt:i,loading:`lazy`,className:`block max-h-72 max-w-full object-contain`}),(0,X.jsx)(`span`,{className:`absolute inset-0 flex items-center justify-center bg-black/0 group-hover/img:bg-black/30 transition-colors`,children:(0,X.jsx)(O,{className:`w-6 h-6 text-white opacity-0 group-hover/img:opacity-100 transition-opacity drop-shadow-md`})})]}):(0,X.jsxs)(`span`,{className:o(`flex min-h-20 items-center gap-2 px-3 py-2 text-xs`,c?`text-red-400`:`text-muted-foreground`),children:[d?(0,X.jsx)(x,{className:`h-4 w-4 animate-spin`}):(0,X.jsx)(w,{className:`h-4 w-4`}),c||`Loading image`]})}),a&&(0,X.jsx)(fe,{open:p,onOpenChange:h,children:(0,X.jsxs)(de,{className:`max-w-[95vw] max-h-[95vh] w-auto p-0 bg-black/95 border-zinc-800 gap-0 overflow-hidden`,showCloseButton:!1,children:[(0,X.jsx)(pe,{className:`sr-only`,children:i}),(0,X.jsxs)(`div`,{className:`relative flex items-center justify-center min-h-[200px]`,children:[(0,X.jsx)(`img`,{src:a,alt:i,className:`max-w-[93vw] max-h-[90vh] object-contain`}),(0,X.jsxs)(`div`,{className:`absolute top-2 right-2 flex gap-1`,children:[(0,X.jsx)(`button`,{type:`button`,onClick:g,className:`rounded-md bg-black/60 hover:bg-black/80 p-2 text-white transition-colors`,title:`Download`,children:(0,X.jsx)(m,{className:`w-4 h-4`})}),(0,X.jsx)(`button`,{type:`button`,onClick:()=>h(!1),className:`rounded-md bg-black/60 hover:bg-black/80 p-2 text-white transition-colors`,title:`Close`,children:(0,X.jsx)(te,{className:`w-4 h-4`})})]})]})]})})]}):(0,X.jsxs)(`button`,{type:`button`,onClick:g,disabled:!a,className:o(`mt-2 flex w-full items-center gap-2 rounded-md border px-2.5 py-2 text-left text-xs transition-colors disabled:cursor-default disabled:opacity-70`,t?`border-primary-foreground/20 bg-primary-foreground/10 hover:bg-primary-foreground/15`:`border-border bg-background hover:bg-muted`),children:[d?(0,X.jsx)(x,{className:`h-4 w-4 shrink-0 animate-spin`}):c?(0,X.jsx)(w,{className:`h-4 w-4 shrink-0 text-red-400`}):(0,X.jsx)(r,{className:`h-4 w-4 shrink-0`}),(0,X.jsx)(`span`,{className:o(`min-w-0 flex-1 truncate`,c&&`text-red-400`),children:c||i}),(0,X.jsx)(m,{className:`h-3.5 w-3.5 shrink-0`})]})}function St({open:e,onToggle:t,onReact:n}){return(0,X.jsxs)(`div`,{className:`relative shrink-0`,children:[(0,X.jsx)(`button`,{type:`button`,title:`Add reaction`,onClick:t,className:o(`inline-flex h-5 w-6 items-center justify-center rounded-full border border-border bg-popover text-muted-foreground shadow-sm transition hover:bg-muted hover:text-foreground`,e?`opacity-100`:`opacity-0 pointer-events-none md:group-hover/msg:opacity-100 md:group-hover/msg:pointer-events-auto`),children:(0,X.jsx)(A,{className:`h-3 w-3`})}),e&&(0,X.jsx)(`div`,{className:`absolute bottom-full left-0 z-30 mb-1 flex gap-0.5 rounded-full border border-border bg-popover p-0.5 shadow-md`,children:Ie.map(e=>(0,X.jsx)(`button`,{type:`button`,title:`React ${e}`,onClick:()=>n(e),className:`inline-flex h-6 w-7 items-center justify-center rounded-full text-xs transition-colors hover:bg-muted`,children:e},e))})]})}function Ct({msg:e,peer:t}){let[r,i]=(0,G.useState)(!1),a=F(e=>e.agentsById),s=F(e=>e.openAgentDetail),c=e.from===t,l=(c?e.to:e.from)||``,u=a[c?t:l]?.issueRepo??a[t]?.issueRepo,d=!l||l===`broadcast`||l.includes(`:`),p=z(e),m=Y(e.occurredAt??e.createdAt),h=c?n:f,_=a[e.from??``]??null;function v(e){e.stopPropagation(),_&&s(_)}return(0,X.jsx)(`div`,{"data-msg-id":e.id,className:`flex justify-center mb-1.5`,children:(0,X.jsxs)(`div`,{className:`w-full max-w-[94%] rounded-md border border-border/50 bg-muted/15 px-2.5 py-1`,children:[(0,X.jsxs)(`div`,{className:`flex items-center gap-1.5 text-xs cursor-pointer select-none`,onClick:()=>i(e=>!e),children:[(0,X.jsx)(g,{className:o(`h-3 w-3 shrink-0 text-muted-foreground/60 transition-transform`,r&&`rotate-90`)}),(0,X.jsx)(`button`,{type:`button`,title:_?_.label||_.name||_.id:void 0,disabled:!_,onClick:v,className:o(`shrink-0 transition-opacity`,_?`cursor-pointer hover:opacity-80`:`cursor-default opacity-60`),children:(0,X.jsx)(W,{agent:_,className:`!w-4 !h-4 !rounded-sm opacity-70`})}),(0,X.jsx)(h,{className:`h-3 w-3 shrink-0 text-muted-foreground/70`}),(0,X.jsxs)(`span`,{className:`shrink-0 text-muted-foreground`,children:[`Message `,c?`to`:`from`]}),d?(0,X.jsx)(`span`,{className:`shrink-0 font-medium text-muted-foreground`,children:le(l,a)}):(0,X.jsx)(Z,{agentId:l,className:`shrink-0 px-0.5 text-foreground/80`,noIcon:!0}),!r&&(0,X.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-muted-foreground/50`,children:p}),(0,X.jsx)(`span`,{className:`ml-auto shrink-0 text-muted-foreground/40`,children:m})]}),r&&(0,X.jsx)(`div`,{className:`mt-1.5 pl-5`,children:(0,X.jsx)(U,{text:p,rawBody:e.body,issueRepo:u,className:`text-sm leading-relaxed text-foreground/90`})})]})})}var wt=(0,G.memo)(function({msg:e,peer:t,showAvatar:n=!1,onOpenReferencedPath:r,onPreviewReferencedPath:i,onPreviewReferencedPathEnd:a}){if(!H(e.from)&&!H(e.to))return(0,X.jsx)(Ct,{msg:e,peer:t});let s=e.kind===`session`?e.payload?.session:void 0;if(s?.type===`prompt`&&s?.origin===`provider`)return(0,X.jsx)(vt,{msg:e,peer:t});let c=H(e.from),l=F(e=>e.reactToMessage),u=F(e=>e.voiceTtsEnabled),d=_t(),f=F(e=>{let n=e.agentsById[t]?.meta?.cwd;return typeof n==`string`?n:``}),p=F(e=>e.agentsById[t]?.issueRepo),m=F(e=>e.usersById),h=F(e=>e.users.length>1),g=c?oe(e.from,m):void 0,_=F(e=>e.openAgentDetail),[v,y]=(0,G.useState)(!1),x=(0,G.useRef)(null),S=(0,G.useRef)(null),C=(0,G.useRef)(!1),w=z(e),te=Y(e.occurredAt??e.createdAt),ne=Fe(e),T=Le(e),E=c?Re(e,t):null,D=E?.icon,O=d===String(e.id),k=u&&!c&&!J(e)&&w.trim().length>0;function A(t){t.stopPropagation(),O?N.bargeIn():N.speak(e.body,String(e.id))}(0,G.useEffect)(()=>{if(!v)return;function e(e){Pe()||x.current&&!x.current.contains(e.target)&&y(!1)}return document.addEventListener(`mousedown`,e),document.addEventListener(`touchstart`,e),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`touchstart`,e)}},[v]);function j(e){return Ae(f||`/`,e)}function M(e,t){let n=j(e);r?.(n,t)}function P(e,t,n){let r=j(e);i?.(r,t,n)}function I(t){l(e,t),y(!1)}function re(e){e.button===0&&(S.current={x:e.clientX,y:e.clientY},C.current=!1)}function L(e){let t=S.current;t&&(Math.abs(e.clientX-t.x)>3||Math.abs(e.clientY-t.y)>3)&&(C.current=!0)}function ie(t){if(!(J(e)||c)&&!t.target.closest(`a,button,input,textarea,select,[role="button"]`)){if(C.current||Pe()){C.current=!1;return}y(e=>!e)}}let R=n&&!J(e);return(0,X.jsxs)(`div`,{"data-msg-id":e.id,className:o(`group/msg flex mb-3 items-end`,c?`justify-end`:`justify-start`,R&&`gap-1.5`),children:[!c&&R&&(0,X.jsx)(bt,{agentId:t,onOpen:_}),(0,X.jsxs)(`div`,{ref:x,className:o(`relative`,R?`max-w-[calc(85%-2rem)] md:max-w-[calc(75%-2rem)]`:`max-w-[85%] md:max-w-[75%]`),children:[k&&(0,X.jsx)(`button`,{type:`button`,title:O?`Stop playback`:`Play aloud`,onClick:A,className:o(`absolute -top-2 -right-2 z-20 inline-flex h-6 w-6 items-center justify-center rounded-full border bg-popover shadow-sm transition`,O?`border-primary/50 text-primary opacity-100`:`border-border text-muted-foreground opacity-70 hover:bg-muted hover:text-foreground hover:opacity-100 [@media(hover:hover)]:md:opacity-0 [@media(hover:hover)]:md:group-hover/msg:opacity-100`),children:O?(0,X.jsx)(b,{className:`h-3.5 w-3.5 animate-pulse`}):(0,X.jsx)(ee,{className:`h-3.5 w-3.5`})}),(0,X.jsxs)(`div`,{className:o(`rounded-2xl px-3.5 py-2 text-sm select-text`,!c&&!J(e)&&`cursor-pointer`,c?`bg-primary text-primary-foreground rounded-br-sm`:`bg-card ring-1 ring-foreground/10 rounded-bl-sm`),onPointerDown:re,onPointerMove:L,onClick:ie,children:[c&&h&&(0,X.jsx)(`p`,{className:o(`text-[11px] font-semibold mb-0.5 text-right`,se(e.from)),children:ue(e.from,m)}),e.subject&&(0,X.jsx)(`p`,{className:o(`text-xs font-semibold mb-1`,c?`text-primary-foreground/70`:`text-muted-foreground`),children:e.subject}),(0,X.jsx)(U,{text:w,rawBody:e.body,issueRepo:p,className:`leading-relaxed`,onPrimary:c,onOpenPath:M,onPreviewPath:P,onPreviewPathEnd:a,resolvePathTitle:(e,t)=>`${j(e)}${t?`:${t}`:``}`}),ne.map(t=>(0,X.jsx)(xt,{attachment:t,outbound:c},`${e.id}-${t.artifactId}-${t.role||``}`)),(0,X.jsxs)(`p`,{className:o(`text-xs mt-1 flex items-center gap-1.5`,c?`justify-end text-primary-foreground/60`:`justify-end text-muted-foreground`),children:[(0,X.jsxs)(`span`,{className:`opacity-40`,children:[`#`,e.id]}),(0,X.jsx)(`span`,{children:te}),E&&D&&(0,X.jsxs)(`span`,{className:o(`inline-flex items-center gap-1`,E.tone===`ok`&&`text-emerald-300`,E.tone===`warn`&&`text-amber-200`,E.tone===`danger`&&`text-red-200`),title:E.title,children:[(0,X.jsx)(D,{className:`h-3 w-3`}),E.label]})]})]}),!J(e)&&T.length>0&&(0,X.jsxs)(`div`,{className:o(`flex flex-wrap items-center gap-0.5 -mt-1 relative z-10`,c?`justify-end pr-2`:`justify-start pl-2`),children:[!c&&(0,X.jsx)(St,{open:v,onToggle:()=>y(e=>!e),onReact:I}),T.map(e=>(0,X.jsxs)(`button`,{type:`button`,title:e.actors.join(`, `),onClick:()=>I(e.emoji),className:o(`inline-flex h-5 items-center gap-0.5 rounded-full border px-1.5 text-[11px] shadow-sm transition-colors`,e.mine?`border-primary/40 bg-primary/10 text-primary`:`border-border bg-background hover:bg-muted text-foreground`),children:[(0,X.jsx)(`span`,{children:e.emoji}),e.count>1&&(0,X.jsx)(`span`,{children:e.count})]},e.emoji))]}),!J(e)&&!c&&T.length===0&&(0,X.jsx)(`div`,{className:`absolute -bottom-2.5 left-1 z-20`,children:(0,X.jsx)(St,{open:v,onToggle:()=>y(e=>!e),onReact:I})})]}),c&&R&&(0,X.jsx)(`span`,{className:`shrink-0 self-end opacity-60`,children:(0,X.jsx)(me,{user:g,address:e.from,distinct:h})})]})});export{Te as C,Be as S,De as T,Me as _,ft as a,Ue as b,mt as c,st as d,qe as f,He as g,ke as h,ct as i,ht as l,Ve as m,ut as n,dt as o,gt as p,rt as r,pt as s,wt as t,Qe as u,je as v,Ee as w,Ne as x,We as y};
|
|
3
|
-
//# sourceMappingURL=MessageBubble-CkPnAwxJ.js.map
|