agent-relay-server 0.80.0 → 0.82.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 +103 -1
- package/package.json +2 -2
- package/public/assets/MessageBubble-ckJ2VVgq.js +3 -0
- package/public/assets/MessageBubble-ckJ2VVgq.js.map +1 -0
- package/public/assets/{PlanGraphPanel-o3u36Del.js → PlanGraphPanel-r3aVT4uc.js} +2 -2
- package/public/assets/{PlanGraphPanel-o3u36Del.js.map → PlanGraphPanel-r3aVT4uc.js.map} +1 -1
- package/public/assets/{activity-L3POfhGa.js → activity-DtMjjws8.js} +2 -2
- package/public/assets/{activity-L3POfhGa.js.map → activity-DtMjjws8.js.map} +1 -1
- package/public/assets/{agent-profiles-CeoqyRis.js → agent-profiles-eRlq98tp.js} +2 -2
- package/public/assets/{agent-profiles-CeoqyRis.js.map → agent-profiles-eRlq98tp.js.map} +1 -1
- package/public/assets/agents-DmbjRTA7.js +2 -0
- package/public/assets/{agents-DAdDtQb6.js.map → agents-DmbjRTA7.js.map} +1 -1
- package/public/assets/{analytics-B6wGSTf3.js → analytics-BW7ik_Ws.js} +2 -2
- package/public/assets/{analytics-B6wGSTf3.js.map → analytics-BW7ik_Ws.js.map} +1 -1
- package/public/assets/{automation-kakk3xZ9.js → automation-CxwGXWC7.js} +2 -2
- package/public/assets/{automation-kakk3xZ9.js.map → automation-CxwGXWC7.js.map} +1 -1
- package/public/assets/{badge-DGB2nVM0.js → badge-BwaoBnNO.js} +2 -2
- package/public/assets/{badge-DGB2nVM0.js.map → badge-BwaoBnNO.js.map} +1 -1
- package/public/assets/{branch-state-badge-BSwkl9A8.js → branch-state-badge-CvdKPTlV.js} +2 -2
- package/public/assets/{branch-state-badge-BSwkl9A8.js.map → branch-state-badge-CvdKPTlV.js.map} +1 -1
- package/public/assets/{button-D_Y8CEP4.js → button-CFIklTDX.js} +2 -2
- package/public/assets/{button-D_Y8CEP4.js.map → button-CFIklTDX.js.map} +1 -1
- package/public/assets/{card-DTLNgk0R.js → card-Bi94xEmr.js} +2 -2
- package/public/assets/{card-DTLNgk0R.js.map → card-Bi94xEmr.js.map} +1 -1
- package/public/assets/{channels-BzY-_4Zi.js → channels-D8UY3baa.js} +2 -2
- package/public/assets/{channels-BzY-_4Zi.js.map → channels-D8UY3baa.js.map} +1 -1
- package/public/assets/chat-CCPukbI9.js +2 -0
- package/public/assets/chat-CCPukbI9.js.map +1 -0
- package/public/assets/{connectors-empwp8UF.js → connectors-W2MslhQ2.js} +2 -2
- package/public/assets/{connectors-empwp8UF.js.map → connectors-W2MslhQ2.js.map} +1 -1
- package/public/assets/{copy-button-BpgTft5S.js → copy-button-A0pXLXBy.js} +2 -2
- package/public/assets/{copy-button-BpgTft5S.js.map → copy-button-A0pXLXBy.js.map} +1 -1
- package/public/assets/display-CWMHll1J.js +3 -0
- package/public/assets/display-CWMHll1J.js.map +1 -0
- package/public/assets/{dist-DetIq2Rn.js → dist--NYpzm4f.js} +2 -2
- package/public/assets/{dist-DetIq2Rn.js.map → dist--NYpzm4f.js.map} +1 -1
- package/public/assets/{dist-dffB6laV.js → dist-BODiHbq1.js} +2 -2
- package/public/assets/{dist-dffB6laV.js.map → dist-BODiHbq1.js.map} +1 -1
- package/public/assets/{dist-B7m1nK9-.js → dist-C4VoXCT-.js} +2 -2
- package/public/assets/{dist-B7m1nK9-.js.map → dist-C4VoXCT-.js.map} +1 -1
- package/public/assets/dist-D3jA_LvQ.js +2 -0
- package/public/assets/{dist-CoqsUXVF.js.map → dist-D3jA_LvQ.js.map} +1 -1
- package/public/assets/{dist-C9UjQOV6.js → dist-DVorlUcA.js} +2 -2
- package/public/assets/{dist-C9UjQOV6.js.map → dist-DVorlUcA.js.map} +1 -1
- package/public/assets/{dist-CrI1Uij-.js → dist-DY3KCMIN.js} +2 -2
- package/public/assets/{dist-CrI1Uij-.js.map → dist-DY3KCMIN.js.map} +1 -1
- package/public/assets/{dist-CyQcAgI5.js → dist-DhEz6YNy.js} +2 -2
- package/public/assets/{dist-CyQcAgI5.js.map → dist-DhEz6YNy.js.map} +1 -1
- package/public/assets/dist-HTxIFS7t.js +2 -0
- package/public/assets/{dist-DHiVCawj.js.map → dist-HTxIFS7t.js.map} +1 -1
- package/public/assets/{dist-CzelKhUn.js → dist-_EunAAFX.js} +2 -2
- package/public/assets/{dist-CzelKhUn.js.map → dist-_EunAAFX.js.map} +1 -1
- package/public/assets/dist-rLCXIl7x.js +2 -0
- package/public/assets/{dist-DRTRN4My.js.map → dist-rLCXIl7x.js.map} +1 -1
- package/public/assets/{dist-BvF_x64R.js → dist-yzKYLD10.js} +2 -2
- package/public/assets/{dist-BvF_x64R.js.map → dist-yzKYLD10.js.map} +1 -1
- package/public/assets/{es2015-CBZid1bm.js → es2015-BDZowz0r.js} +2 -2
- package/public/assets/{es2015-CBZid1bm.js.map → es2015-BDZowz0r.js.map} +1 -1
- package/public/assets/{formatted-body-impl-CEqSWNRL.js → formatted-body-impl-tIjgf9Kr.js} +2 -2
- package/public/assets/{formatted-body-impl-CEqSWNRL.js.map → formatted-body-impl-tIjgf9Kr.js.map} +1 -1
- package/public/assets/index-BfQFX8td.js +22 -0
- package/public/assets/{index-CtGaz-Yg.js.map → index-BfQFX8td.js.map} +1 -1
- package/public/assets/index-D8vc380x.css +2 -0
- package/public/assets/{input-C5FrEDmc.js → input-CD-ZcZIA.js} +2 -2
- package/public/assets/{input-C5FrEDmc.js.map → input-CD-ZcZIA.js.map} +1 -1
- package/public/assets/insights-B93PGmKq.js +2 -0
- package/public/assets/{insights-mf5sd483.js.map → insights-B93PGmKq.js.map} +1 -1
- package/public/assets/{integrations-4V9lOQ8b.js → integrations-BfWMAznM.js} +2 -2
- package/public/assets/{integrations-4V9lOQ8b.js.map → integrations-BfWMAznM.js.map} +1 -1
- package/public/assets/{lib-DjewNYeR.js → lib-BqL6WCDu.js} +2 -2
- package/public/assets/{lib-DjewNYeR.js.map → lib-BqL6WCDu.js.map} +1 -1
- package/public/assets/lucide-react-D78N6SwK.js +9 -0
- package/public/assets/lucide-react-D78N6SwK.js.map +1 -0
- package/public/assets/{maintenance-CruMfiA7.js → maintenance-CgRASTD0.js} +2 -2
- package/public/assets/{maintenance-CruMfiA7.js.map → maintenance-CgRASTD0.js.map} +1 -1
- package/public/assets/{managed-agents-fOhHGzNI.js → managed-agents-B1AdrEv4.js} +2 -2
- package/public/assets/{managed-agents-fOhHGzNI.js.map → managed-agents-B1AdrEv4.js.map} +1 -1
- package/public/assets/{markdown-preview-impl-g5-PTM1A.js → markdown-preview-impl-D2zEt-i-.js} +2 -2
- package/public/assets/{markdown-preview-impl-g5-PTM1A.js.map → markdown-preview-impl-D2zEt-i-.js.map} +1 -1
- package/public/assets/memory-nUBcij_9.js +2 -0
- package/public/assets/{memory-CRyq2WNC.js.map → memory-nUBcij_9.js.map} +1 -1
- package/public/assets/{messages-BqLp0X3y.js → messages-BNDs53bW.js} +2 -2
- package/public/assets/{messages-BqLp0X3y.js.map → messages-BNDs53bW.js.map} +1 -1
- package/public/assets/{orchestrators-BD4nZcG3.js → orchestrators-BouoI90a.js} +2 -2
- package/public/assets/{orchestrators-BD4nZcG3.js.map → orchestrators-BouoI90a.js.map} +1 -1
- package/public/assets/{overview-De-2GN06.js → overview-C8_hAGpC.js} +2 -2
- package/public/assets/{overview-De-2GN06.js.map → overview-C8_hAGpC.js.map} +1 -1
- package/public/assets/{pairs-DOqjBd0R.js → pairs-BcCOB1oO.js} +2 -2
- package/public/assets/{pairs-DOqjBd0R.js.map → pairs-BcCOB1oO.js.map} +1 -1
- package/public/assets/projects-MZ6CNrYO.js +2 -0
- package/public/assets/{projects-Byp_gLoD.js.map → projects-MZ6CNrYO.js.map} +1 -1
- package/public/assets/{react-dom--5xRjaey.js → react-dom-CU0WCHqq.js} +2 -2
- package/public/assets/{react-dom--5xRjaey.js.map → react-dom-CU0WCHqq.js.map} +1 -1
- package/public/assets/{security-DtoRSpIi.js → security-Bh8BGpZR.js} +2 -2
- package/public/assets/{security-DtoRSpIi.js.map → security-Bh8BGpZR.js.map} +1 -1
- package/public/assets/{select-esP750zQ.js → select-Drdvachg.js} +2 -2
- package/public/assets/{select-esP750zQ.js.map → select-Drdvachg.js.map} +1 -1
- package/public/assets/settings-IrNBT0hy.js +4 -0
- package/public/assets/{settings-U8788lYt.js.map → settings-IrNBT0hy.js.map} +1 -1
- package/public/assets/store-CqFZmc-B.js +9 -0
- package/public/assets/store-CqFZmc-B.js.map +1 -0
- package/public/assets/{tasks-CtiwQy9I.js → tasks-heEgx7vT.js} +2 -2
- package/public/assets/{tasks-CtiwQy9I.js.map → tasks-heEgx7vT.js.map} +1 -1
- package/public/assets/teams-BjETr-_W.js +2 -0
- package/public/assets/teams-BjETr-_W.js.map +1 -0
- package/public/assets/{terminal-viewer-impl-h9hvvB9S.js → terminal-viewer-impl-BDqmbWB3.js} +3 -3
- package/public/assets/{terminal-viewer-impl-h9hvvB9S.js.map → terminal-viewer-impl-BDqmbWB3.js.map} +1 -1
- package/public/assets/{use-keyboard-viewport-vC7NeLD9.js → use-keyboard-viewport-CichJ8Jn.js} +2 -2
- package/public/assets/{use-keyboard-viewport-vC7NeLD9.js.map → use-keyboard-viewport-CichJ8Jn.js.map} +1 -1
- package/public/assets/{work-queue-C-bS6YmI.js → work-queue-rgQs4Wis.js} +2 -2
- package/public/assets/{work-queue-C-bS6YmI.js.map → work-queue-rgQs4Wis.js.map} +1 -1
- package/public/assets/workspaces-hIjZicaF.js +3 -0
- package/public/assets/{workspaces-Bivhqw2N.js.map → workspaces-hIjZicaF.js.map} +1 -1
- package/public/index.html +22 -22
- package/src/agent-authz.ts +169 -0
- package/src/agent-ref.ts +7 -3
- package/src/dashboard-presence.ts +91 -0
- package/src/db/agent-ownership.ts +168 -0
- package/src/db/index.ts +2 -0
- package/src/db/migrations.ts +17 -0
- package/src/db/schema.ts +16 -0
- package/src/db/teams.ts +13 -4
- package/src/db/users.ts +120 -0
- package/src/maintenance/teams.ts +1 -7
- package/src/routes/_shared.ts +75 -1
- package/src/routes/agent-sessions.ts +57 -6
- package/src/routes/agents.ts +13 -4
- package/src/routes/index.ts +6 -1
- package/src/routes/settings.ts +33 -8
- package/src/routes/teams.ts +11 -4
- package/src/routes/users.ts +8 -0
- package/src/services/register-agent.ts +11 -1
- package/src/services/send-message.ts +7 -1
- package/src/services/team.ts +17 -4
- package/src/services/transient-agent-reaper.ts +36 -0
- package/src/settings/registry.ts +63 -0
- package/src/sse.ts +7 -0
- package/src/team-idle-tracker.ts +13 -0
- package/src/user-settings-store.ts +86 -0
- package/public/assets/MessageBubble-C-3IcqgU.js +0 -3
- package/public/assets/MessageBubble-C-3IcqgU.js.map +0 -1
- package/public/assets/agents-DAdDtQb6.js +0 -2
- package/public/assets/chat-DDlRjwGC.js +0 -2
- package/public/assets/chat-DDlRjwGC.js.map +0 -1
- package/public/assets/display-DHgdn4vN.js +0 -3
- package/public/assets/display-DHgdn4vN.js.map +0 -1
- package/public/assets/dist-CoqsUXVF.js +0 -2
- package/public/assets/dist-DHiVCawj.js +0 -2
- package/public/assets/dist-DRTRN4My.js +0 -2
- package/public/assets/index-BpsfMZ3T.css +0 -2
- package/public/assets/index-CtGaz-Yg.js +0 -22
- package/public/assets/insights-mf5sd483.js +0 -2
- package/public/assets/lucide-react-CNGB8fo1.js +0 -9
- package/public/assets/lucide-react-CNGB8fo1.js.map +0 -1
- package/public/assets/memory-CRyq2WNC.js +0 -2
- package/public/assets/projects-Byp_gLoD.js +0 -2
- package/public/assets/settings-U8788lYt.js +0 -4
- package/public/assets/store-Cjcd0egy.js +0 -9
- package/public/assets/store-Cjcd0egy.js.map +0 -1
- package/public/assets/teams-Cx29VUif.js +0 -2
- package/public/assets/teams-Cx29VUif.js.map +0 -1
- package/public/assets/workspaces-Bivhqw2N.js +0 -3
package/src/services/team.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { hasScope } from "agent-relay-sdk/types";
|
|
2
2
|
import { STALE_TTL_MS } from "../config";
|
|
3
|
-
import { claimTeam, countLiveTeamMembers, dissolveTeam, ensureTeam, getAgent, getPlanByTeam, getTeam, getTeamRoster, setTeamBrief } from "../db";
|
|
3
|
+
import { claimTeam, countLiveTeamMembers, dissolveTeam, ensureTeam, getAgent, getPlanByTeam, getTeam, getTeamBusyState, getTeamMemberStats, getTeamRoster, setTeamBrief } from "../db";
|
|
4
4
|
import { emitRelayEvent } from "../events";
|
|
5
5
|
import { listIssueRefsForEntity } from "./issue-associations";
|
|
6
|
+
import { getTeamIdleEntry } from "../team-idle-tracker";
|
|
6
7
|
import type { AuthContext } from "./auth-context";
|
|
7
|
-
import type { Team } from "../types";
|
|
8
|
+
import type { Plan, Team, TeamRuntimeState } from "../types";
|
|
8
9
|
|
|
9
10
|
export class TeamAuthError extends Error {}
|
|
10
11
|
export class TeamNotFoundError extends Error {}
|
|
@@ -30,6 +31,16 @@ export interface TeamDissolveServiceInput {
|
|
|
30
31
|
landsClean?: boolean;
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
export function deriveTeamRuntimeState(team: Team, plan: Plan | null, cutoff: number): TeamRuntimeState {
|
|
35
|
+
if (team.status === "dissolved") return "dissolved";
|
|
36
|
+
const busy = getTeamBusyState(team.id, cutoff);
|
|
37
|
+
if (busy.busyMemberIds.length > 0) return "busy";
|
|
38
|
+
if (getTeamIdleEntry(team.id)?.pinged) return "stalled";
|
|
39
|
+
const stats = getTeamMemberStats(team.id, cutoff);
|
|
40
|
+
if (stats.total > stats.live && plan && plan.nodes.some((n) => n.status !== "landed")) return "degraded";
|
|
41
|
+
return "idle";
|
|
42
|
+
}
|
|
43
|
+
|
|
33
44
|
function requireCallerAgentId(ctx: AuthContext): string {
|
|
34
45
|
if (!ctx.callerAgentId) throw new TeamAuthError("team operations require a single caller agent identity");
|
|
35
46
|
return ctx.callerAgentId;
|
|
@@ -39,12 +50,14 @@ function payloadForAgent(agentId: string, channel?: string): TeamPayload {
|
|
|
39
50
|
const agent = getAgent(agentId);
|
|
40
51
|
const team = agent?.teamId ? getTeam(agent.teamId) : null;
|
|
41
52
|
if (!team) throw new TeamNotFoundError("caller has no team");
|
|
53
|
+
const plan = getPlanByTeam(team.id, channel) ?? null;
|
|
54
|
+
const runtimeState = deriveTeamRuntimeState(team, plan, Date.now() - STALE_TTL_MS);
|
|
42
55
|
return {
|
|
43
|
-
team,
|
|
56
|
+
team: { ...team, runtimeState },
|
|
44
57
|
roster: getTeamRoster(team.id),
|
|
45
58
|
brief: team.brief ?? null,
|
|
46
59
|
definitionOfDone: team.definitionOfDone ?? null,
|
|
47
|
-
plan
|
|
60
|
+
plan,
|
|
48
61
|
issues: listIssueRefsForEntity("team", team.id),
|
|
49
62
|
};
|
|
50
63
|
}
|
|
@@ -4,6 +4,7 @@ import { createActivityEvent, getAgent, listAgents, listWorkspaces } from "../db
|
|
|
4
4
|
import { routeNotification } from "../notification-router";
|
|
5
5
|
import { isProviderBlocked } from "../provider-state";
|
|
6
6
|
import { TERMINAL_WORKSPACE_STATUSES } from "../workspace-phase";
|
|
7
|
+
import type { WorkspaceRecord } from "../types";
|
|
7
8
|
|
|
8
9
|
const envMsOrDefault = (name: string, fallback: number): number => {
|
|
9
10
|
const v = Number(process.env[name]);
|
|
@@ -17,6 +18,34 @@ export function resetTransientTrackerForTests(): void {
|
|
|
17
18
|
transientTracker.clear();
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
// How many commits the agent's branch has ahead of its base. Returns null when
|
|
22
|
+
// the check can't run (missing fields, git failure) — callers treat null as
|
|
23
|
+
// "unknown" and preserve the safe #614 hold-pending bias: only 0 is fast-reaped.
|
|
24
|
+
function defaultCommitsAhead(ws: WorkspaceRecord): number | null {
|
|
25
|
+
const base = ws.baseSha ?? ws.baseRef;
|
|
26
|
+
if (!base || !ws.branch || !ws.worktreePath) return null;
|
|
27
|
+
try {
|
|
28
|
+
const proc = Bun.spawnSync(
|
|
29
|
+
["git", "-C", ws.worktreePath, "rev-list", "--count", `${base}..${ws.branch}`],
|
|
30
|
+
{ stdin: "ignore", stdout: "pipe", stderr: "ignore" },
|
|
31
|
+
);
|
|
32
|
+
if (proc.exitCode !== 0) return null;
|
|
33
|
+
const n = parseInt(Buffer.from(proc.stdout).toString("utf8").trim(), 10);
|
|
34
|
+
return Number.isFinite(n) ? n : null;
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let _commitsAheadFn: (ws: WorkspaceRecord) => number | null = defaultCommitsAhead;
|
|
41
|
+
|
|
42
|
+
export function overrideCommitsAheadForTests(fn: (ws: WorkspaceRecord) => number | null): void {
|
|
43
|
+
_commitsAheadFn = fn;
|
|
44
|
+
}
|
|
45
|
+
export function resetCommitsAheadForTests(): void {
|
|
46
|
+
_commitsAheadFn = defaultCommitsAhead;
|
|
47
|
+
}
|
|
48
|
+
|
|
20
49
|
function transientLandComplete(agentId: string): { complete: boolean; workspaceId?: string; status?: string; reason?: string } {
|
|
21
50
|
const isolated = listWorkspaces({ ownerAgentId: agentId }).filter((ws) => ws.mode === "isolated");
|
|
22
51
|
if (!isolated.length) return { complete: true, reason: "no-isolated-workspace" };
|
|
@@ -27,6 +56,13 @@ function transientLandComplete(agentId: string): { complete: boolean; workspaceI
|
|
|
27
56
|
if (live.status === "active" && mergedAt !== undefined && mergedAt > (landReportedAt ?? 0)) {
|
|
28
57
|
return { complete: true, workspaceId: live.id, status: live.status, reason: "recycled-after-land" };
|
|
29
58
|
}
|
|
59
|
+
// Fast-path (#629): a zero-commit branch has nothing to preserve — reap immediately
|
|
60
|
+
// instead of holding it pending a land that will never happen. Only fires when the
|
|
61
|
+
// branch is provably empty (count === 0); null (unknown/git error) falls through to
|
|
62
|
+
// the safe #614 hold-pending bias below.
|
|
63
|
+
if (live.status === "active" && _commitsAheadFn(live) === 0) {
|
|
64
|
+
return { complete: true, workspaceId: live.id, status: live.status, reason: "empty-branch" };
|
|
65
|
+
}
|
|
30
66
|
return { complete: false, workspaceId: live.id, status: live.status, reason: "land-pending" };
|
|
31
67
|
}
|
|
32
68
|
|
package/src/settings/registry.ts
CHANGED
|
@@ -241,6 +241,41 @@ const LANDING_SCHEMA: JSONSchema = {
|
|
|
241
241
|
},
|
|
242
242
|
};
|
|
243
243
|
|
|
244
|
+
// Per-user preference schemas (#391, tier:"user"). These follow the human across devices via the
|
|
245
|
+
// `user_settings` table (keyed by `users.id`), replacing per-browser localStorage for genuinely
|
|
246
|
+
// user-level prefs. Field names mirror the dashboard store (dashboard/src/store) so the client
|
|
247
|
+
// migration is a lift, not a rename. Truly device-local view state stays in the browser.
|
|
248
|
+
const DISPLAY_PREFS_SCHEMA: JSONSchema = {
|
|
249
|
+
type: "object",
|
|
250
|
+
additionalProperties: false,
|
|
251
|
+
required: ["theme", "showReasoning"],
|
|
252
|
+
properties: {
|
|
253
|
+
theme: { type: "string", enum: ["light", "dark", "midnight", "nord", "ember", "parchment"] },
|
|
254
|
+
showReasoning: { type: "boolean" },
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const VOICE_PREFS_SCHEMA: JSONSchema = {
|
|
259
|
+
type: "object",
|
|
260
|
+
additionalProperties: false,
|
|
261
|
+
required: [
|
|
262
|
+
"voiceTtsEnabled",
|
|
263
|
+
"voiceTtsLang",
|
|
264
|
+
"voiceTtsMode",
|
|
265
|
+
"voiceTtsKokoroVoice",
|
|
266
|
+
"voiceTtsBrowserVoice",
|
|
267
|
+
"voiceInputMode",
|
|
268
|
+
],
|
|
269
|
+
properties: {
|
|
270
|
+
voiceTtsEnabled: { type: "boolean" },
|
|
271
|
+
voiceTtsLang: { type: "string", maxLength: 35 },
|
|
272
|
+
voiceTtsMode: { type: "string", enum: ["kokoro", "browser"] },
|
|
273
|
+
voiceTtsKokoroVoice: { type: "string", maxLength: 80 },
|
|
274
|
+
voiceTtsBrowserVoice: { type: "string", maxLength: 200 },
|
|
275
|
+
voiceInputMode: { type: "string", enum: ["compose", "autosend", "handsfree"] },
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
|
|
244
279
|
// Provider chat/reasoning capture toggles (source: runner/src/adapter.ts ProviderConfig).
|
|
245
280
|
// NOTE (#383 coordination): provider config storage is being centralized in #383;
|
|
246
281
|
// these are seeded instance-global under namespace "provider". Per-provider
|
|
@@ -393,6 +428,34 @@ function seedBuiltInSettings(): void {
|
|
|
393
428
|
tier: "server-runtime",
|
|
394
429
|
display: { group: "Providers", label: "Reasoning capture", description: "Stream reasoning/tool steps into chat.", order: 51 },
|
|
395
430
|
});
|
|
431
|
+
|
|
432
|
+
// Per-user prefs (#391) — tier:"user", stored per `users.id` so they follow the human across devices.
|
|
433
|
+
registerSetting({
|
|
434
|
+
namespace: "display",
|
|
435
|
+
key: "default",
|
|
436
|
+
schema: DISPLAY_PREFS_SCHEMA,
|
|
437
|
+
defaults: { theme: "dark", showReasoning: false },
|
|
438
|
+
scope: { read: "settings:read:display", write: "settings:write:display" },
|
|
439
|
+
tier: "user",
|
|
440
|
+
display: { group: "Preferences", label: "Display", description: "Per-user theme and reasoning visibility (follows you across devices).", order: 70 },
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
registerSetting({
|
|
444
|
+
namespace: "voice",
|
|
445
|
+
key: "default",
|
|
446
|
+
schema: VOICE_PREFS_SCHEMA,
|
|
447
|
+
defaults: {
|
|
448
|
+
voiceTtsEnabled: false,
|
|
449
|
+
voiceTtsLang: "en-US",
|
|
450
|
+
voiceTtsMode: "kokoro",
|
|
451
|
+
voiceTtsKokoroVoice: "am_michael",
|
|
452
|
+
voiceTtsBrowserVoice: "",
|
|
453
|
+
voiceInputMode: "compose",
|
|
454
|
+
},
|
|
455
|
+
scope: { read: "settings:read:voice", write: "settings:write:voice" },
|
|
456
|
+
tier: "user",
|
|
457
|
+
display: { group: "Preferences", label: "Voice", description: "Per-user text-to-speech and voice-input preferences.", order: 71 },
|
|
458
|
+
});
|
|
396
459
|
}
|
|
397
460
|
|
|
398
461
|
export function registerProviderConfigSetting(input: {
|
package/src/sse.ts
CHANGED
|
@@ -233,6 +233,13 @@ export function getConnectionCount(): number {
|
|
|
233
233
|
return connections.size;
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
// Dashboard viewer presence for an agent thread (#390): broadcast the live set of humans
|
|
237
|
+
// currently viewing/typing so every open dashboard can show "X is viewing". Ephemeral — the
|
|
238
|
+
// viewer list comes from the in-memory presence registry, not the DB.
|
|
239
|
+
export function emitDashboardPresence(agentId: string, viewers: unknown) {
|
|
240
|
+
emitRelayEvent({ type: "dashboard.presence", source: "server", subject: agentId, data: { agentId, viewers } });
|
|
241
|
+
}
|
|
242
|
+
|
|
236
243
|
export function emitOrchestratorStatus(orchestratorId: string) {
|
|
237
244
|
const orch = getOrchestrator(orchestratorId);
|
|
238
245
|
const data = orch ?? { id: orchestratorId, status: "offline" };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Singleton in-memory tracker shared by maintenance/teams.ts (writer) and
|
|
2
|
+
// services/team.ts (reader). Lives in its own module to avoid a circular dep:
|
|
3
|
+
// maintenance/teams.ts → services/team (dissolveTeamById) → team-idle-tracker ← maintenance/teams.ts
|
|
4
|
+
export interface TeamIdleEntry {
|
|
5
|
+
firstNoBusyAt: number;
|
|
6
|
+
pinged: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const teamIdleTracker = new Map<string, TeamIdleEntry>();
|
|
10
|
+
|
|
11
|
+
export function getTeamIdleEntry(teamId: string): TeamIdleEntry | undefined {
|
|
12
|
+
return teamIdleTracker.get(teamId);
|
|
13
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Per-user settings storage (#391, epic #388). The user dimension the global `config`
|
|
2
|
+
// table lacks: `tier:"user"` descriptors (settings/registry.ts) resolve the SAME
|
|
3
|
+
// `(namespace, key)` address to a per-user value, keyed by the resolved `users.id` (#393),
|
|
4
|
+
// so a human's pref follows them across devices. This is the storage seam ONLY — schema
|
|
5
|
+
// validation + scope enforcement stay in the registry/route; this module just persists the
|
|
6
|
+
// per-user JSON value and mirrors the `config`-table ConfigEntry shape so the settings API
|
|
7
|
+
// treats user-tier and server-runtime values uniformly.
|
|
8
|
+
//
|
|
9
|
+
// Deliberately NOT folded into config-store.ts: the global `config` table keeps its exact
|
|
10
|
+
// `(namespace, key)` PK + history semantics untouched (#391 back-compat), and the
|
|
11
|
+
// transport-thinness/file-size ratchets keep config-store as the instance-global home. Per-user
|
|
12
|
+
// prefs are low-stakes display state, so no config_history mirror — last-write-wins with a
|
|
13
|
+
// monotonic version is enough.
|
|
14
|
+
|
|
15
|
+
import { getDb } from "./db";
|
|
16
|
+
import type { ConfigEntry } from "agent-relay-sdk";
|
|
17
|
+
|
|
18
|
+
interface UserSettingRow {
|
|
19
|
+
user_id: string;
|
|
20
|
+
namespace: string;
|
|
21
|
+
key: string;
|
|
22
|
+
value: string;
|
|
23
|
+
version: number;
|
|
24
|
+
updated_at: string;
|
|
25
|
+
updated_by: string | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function rowToConfigEntry<T>(row: UserSettingRow): ConfigEntry<T> {
|
|
29
|
+
return {
|
|
30
|
+
namespace: row.namespace,
|
|
31
|
+
key: row.key,
|
|
32
|
+
value: JSON.parse(row.value) as T,
|
|
33
|
+
version: row.version,
|
|
34
|
+
updatedAt: row.updated_at,
|
|
35
|
+
updatedBy: row.updated_by ?? undefined,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** A single user's stored value for a `tier:"user"` descriptor, or null when unset (→ defaults). */
|
|
40
|
+
export function getUserSetting<T = unknown>(userId: string, namespace: string, key: string): ConfigEntry<T> | null {
|
|
41
|
+
const row = getDb()
|
|
42
|
+
.query("SELECT * FROM user_settings WHERE user_id = ? AND namespace = ? AND key = ?")
|
|
43
|
+
.get(userId, namespace, key) as UserSettingRow | undefined;
|
|
44
|
+
return row ? rowToConfigEntry<T>(row) : null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** All of a user's stored values in a namespace (ascending key). */
|
|
48
|
+
export function listUserSettings<T = unknown>(userId: string, namespace: string): ConfigEntry<T>[] {
|
|
49
|
+
const rows = getDb()
|
|
50
|
+
.query("SELECT * FROM user_settings WHERE user_id = ? AND namespace = ? ORDER BY key ASC")
|
|
51
|
+
.all(userId, namespace) as UserSettingRow[];
|
|
52
|
+
return rows.map(rowToConfigEntry<T>);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Upsert a user's value for a descriptor. Value is persisted verbatim — validate via the registry first. */
|
|
56
|
+
export function setUserSetting<T = unknown>(
|
|
57
|
+
userId: string,
|
|
58
|
+
namespace: string,
|
|
59
|
+
key: string,
|
|
60
|
+
value: T,
|
|
61
|
+
updatedBy?: string,
|
|
62
|
+
): ConfigEntry<T> {
|
|
63
|
+
const existing = getUserSetting(userId, namespace, key);
|
|
64
|
+
const now = new Date().toISOString();
|
|
65
|
+
const nextVersion = existing ? existing.version + 1 : 1;
|
|
66
|
+
getDb()
|
|
67
|
+
.query(`
|
|
68
|
+
INSERT INTO user_settings (user_id, namespace, key, value, version, updated_at, updated_by)
|
|
69
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
70
|
+
ON CONFLICT(user_id, namespace, key) DO UPDATE SET
|
|
71
|
+
value = excluded.value,
|
|
72
|
+
version = excluded.version,
|
|
73
|
+
updated_at = excluded.updated_at,
|
|
74
|
+
updated_by = excluded.updated_by
|
|
75
|
+
`)
|
|
76
|
+
.run(userId, namespace, key, JSON.stringify(value), nextVersion, now, updatedBy ?? null);
|
|
77
|
+
return getUserSetting<T>(userId, namespace, key)!;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Drop a user's stored value (reverts to descriptor defaults). Returns false when nothing was stored. */
|
|
81
|
+
export function deleteUserSetting(userId: string, namespace: string, key: string): boolean {
|
|
82
|
+
const existing = getUserSetting(userId, namespace, key);
|
|
83
|
+
if (!existing) return false;
|
|
84
|
+
getDb().query("DELETE FROM user_settings WHERE user_id = ? AND namespace = ? AND key = ?").run(userId, namespace, key);
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{$t as t,Bn as n,Ct as r,En as i,Ft as a,Gt as o,Hn as s,Kt as c,L as l,Mn as u,Nn as d,P as f,R as p,St as m,Wn as h,a as g,at as _,c as v,ct as y,dn as b,er as x,h as S,hn as C,i as ee,ln as w,mn as T,nn as E,p as D,pn as O,r as k,rn as te,un as ne,v as A,xn as j,y as re}from"./lucide-react-CNGB8fo1.js";import{g as M,r as N,t as P}from"./store-Cjcd0egy.js";import{D as F,I,M as ie,W as L,at as R,b as z,d as ae,f as oe,j as se,w as ce,z as le}from"./display-DHgdn4vN.js";import{C as B,a as ue,i as de,o as fe,t as V}from"./index-CtGaz-Yg.js";var H=e(x(),1),U={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`},pe=new Set(Object.keys(U)),me=3e3;function W(e){return new Date(e.occurredAt??e.createdAt).getTime()}function he(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:W(e),turnId:typeof t.turnId==`string`?t.turnId:void 0}}function ge(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:W(e)}}function _e(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:W(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 ve(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 ye(e){return e.kind===`system`&&e.from===`system`}var be=new Set([`agent.ready`,`agent.exited`,`agent.spawn_failed`]);function G(e){let t=new Date(e);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}`}function xe(e){let t=e.filter(e=>pe.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)<=me)||n.push(e);return n}function Se(e,t,n,r=[],i){let a=[];for(let e of r){let t=e.entries.reduce((e,t)=>Math.min(e,L(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:L(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`||ye(t)||ce(t)||!(t.from===`user`||o!==void 0&&t.from===o)||!F(t).trim())continue;let e=W(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=>ve(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=ve(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)&&le(e,r.body)){p.add(r.id);break}}}let m=new Map,h=[];for(let t of e){if(ye(t)){let e=typeof t.payload?.kind==`string`?t.payload.kind:``;if(be.has(e)){let n=t.payload,r=typeof n.agentId==`string`?n.agentId:``,i=W(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:W(t),entry:{type:`notice`,msg:t}});continue}let e=ge(t);if(e){h.push(e);continue}let n=he(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=_e(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:W(t),entry:{type:`message`,msg:{...t,body:e}}});continue}}}let i=t.id===s?`initial-prompt`:`message`;a.push({ts:W(t),entry:{type:i,msg:t}})}for(let e of xe([...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=G(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`&&Te(e,t)){e.steps.push(...t.steps);continue}}_.push(t)}return _}function Ce(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 we(e){return e.type===`message`||e.type===`initial-prompt`||e.type===`notice`?(e.msg.subject?`${e.msg.subject} `:``)+F(e.msg):e.type===`imported-message`?F(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 Te(e,t){let n=e.steps[e.steps.length-1]?.turnId,r=t.steps[0]?.turnId;return n&&r?n===r:!n&&!r}function Ee(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(1)} MB`}function De(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 Oe(e){let t=e.replace(/\/+$/,``),n=t.lastIndexOf(`/`);return n>0?t.slice(0,n):`/`}function ke(e,t){return e.filter(e=>e.status===`online`&&I(t,e.baseDir)).sort((e,t)=>se(t.baseDir).length-se(e.baseDir).length)[0]||e.find(e=>e.status===`online`)}function Ae(){return typeof window<`u`&&window.matchMedia(`(min-width: 1280px)`).matches}function je(){return typeof window<`u`&&!!window.getSelection()?.toString()}function Me(e){let t=e.payload?.attachments;return Array.isArray(t)?t.filter(e=>!!(e&&typeof e==`object`&&typeof e.artifactId==`string`)):[]}var Ne=[`👍`,`❤️`,`✅`,`👀`];function Pe(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 K(e){return ce(e)}function Fe(e,n){let r=e.readBy||[],i=e.resolvedToAgent||n||e.to,a=i?r.includes(i):!1,o=r.some(e=>e!==R);if(a||o){let e=a?i:r.find(e=>e!==R);return{label:`read`,title:e?`Read by ${e}`:`Read by agent`,tone:`ok`,icon:C}}if(e.deliveryStatus===`delivered`)return{label:`delivered`,title:`Delivered to agent inbox`,tone:`ok`,icon:C};if(e.deliveryStatus===`queued`)return{label:`queued`,title:`Queued until the target agent is available`,tone:`warn`,icon:t};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:T}}function Ie(e){let t=L(e.createdAt);return(e.reactions||[]).reduce((e,t)=>Math.max(e,L(t.updatedAt||t.createdAt)),t)}function Le(e){return e?e.messages.reduce((e,t)=>Math.max(e,Ie(t)),0):0}function Re(e,t,n){return(e-t)*n}function ze(e){if(!e)return 0;let t=0;for(let n of e.messages)z(n)&&(t=Math.max(t,L(n.createdAt)));return t}function q(e){return new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`})}function Be(e){for(let t of e)t.previewUrl&&URL.revokeObjectURL(t.previewUrl)}function Ve(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[N(e.threadId,e.channel)])??a[0];return o?.threadId?{threadId:o.threadId,...o.channel?{channel:o.channel}:{}}:null}var J=s(),He={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 Ue(e){let t=new Date,[n,r,i]=e.split(`-`).map(Number),a=new Date(n,r-1,i);if(e===G(t.getTime()))return`Today`;let o=new Date(t);return o.setDate(o.getDate()-1),e===G(o.getTime())?`Yesterday`:a.toLocaleDateString(void 0,{weekday:`short`,month:`short`,day:`numeric`,year:a.getFullYear()===t.getFullYear()?void 0:`numeric`})}function We({event:e}){return(0,J.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,J.jsxs)(`div`,{className:`flex items-center gap-1.5 text-xs text-muted-foreground`,children:[(0,J.jsx)(E,{className:n(`w-2 h-2 fill-current`,He[e.status]||`text-zinc-400`)}),(0,J.jsx)(`span`,{children:U[e.status]||e.status}),(0,J.jsx)(`span`,{className:`text-muted-foreground/60`,children:q(e.timestamp)})]}),(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}var Ge={"branch.landed":m,"context.warning":D,"agent.context_threshold":D,"agent.resume_budget_exhausted":D,"agent.rate_limit_resume":p},Ke={"branch.landed":`branch landed`,"context.warning":`context warning`,"agent.context_threshold":`context threshold reached`};function qe(e){return e&&(e.includes(`.`)?e.slice(e.indexOf(`.`)+1):e).replace(/[._-]+/g,` `).trim()||`system signal`}function Y({agentId:e,fallbackLabel:t,className:r,noIcon:i}){let a=P(t=>t.agentsById[e])||null,o=P(e=>e.openInboxThread),s=P(e=>e.switchView),c=a?ae(a):t||e;return(0,J.jsxs)(`button`,{type:`button`,className:n(`inline-flex max-w-full items-center gap-1 rounded px-1 text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground`,r),onClick:t=>{t.stopPropagation(),o(e),s(`chat`)},title:`Open chat for ${c}`,children:[!i&&(0,J.jsx)(B,{agent:a,className:`w-4 h-4 text-[10px]`}),(0,J.jsx)(`span`,{className:`max-w-[160px] truncate`,children:c})]})}function Je({msg:e}){let t=e.payload??{},n=typeof t.sha==`string`?t.sha:``,r=n?n.slice(0,7):``,i=typeof t.author==`string`?t.author:``,a=typeof t.branch==`string`?t.branch:``,o=typeof t.base==`string`?t.base:``,s=t.pushed;return(0,J.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,J.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,J.jsx)(m,{className:`h-3 w-3 shrink-0 text-emerald-600 dark:text-emerald-400`}),(0,J.jsx)(`span`,{className:`text-emerald-700 dark:text-emerald-300`,children:`branch landed`}),a&&o&&(0,J.jsxs)(`span`,{className:`font-mono text-emerald-700/80 dark:text-emerald-200/70`,title:`${a} → ${o}`,children:[a,(0,J.jsx)(`span`,{className:`opacity-50`,children:` → `}),o]}),r&&(0,J.jsx)(`span`,{className:`rounded bg-emerald-500/15 px-1 font-mono text-emerald-800 dark:text-emerald-200`,title:n,children:r}),i&&(0,J.jsxs)(`span`,{className:`inline-flex items-center gap-1 text-emerald-700/80 dark:text-emerald-300/80`,children:[(0,J.jsx)(`span`,{className:`opacity-70`,children:`by`}),(0,J.jsx)(Y,{agentId:i,className:`text-emerald-700 hover:text-emerald-900 dark:text-emerald-300/90 dark:hover:text-emerald-100`})]}),s===!1&&(0,J.jsx)(`span`,{className:`text-amber-600 dark:text-amber-300/80`,title:`Local-only land — not pushed to origin`,children:`· local only`}),(0,J.jsx)(`span`,{className:`text-emerald-700/60 dark:text-emerald-300/50`,children:q(e.occurredAt??e.createdAt)})]}),(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function Ye({msg:e}){let t=typeof e.payload?.kind==`string`?e.payload.kind:``;if(t===`branch.landed`)return(0,J.jsx)(Je,{msg:e});let n=Ge[t]??f,r=Ke[t]??qe(t);return(0,J.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,J.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,J.jsx)(n,{className:`h-3 w-3`}),(0,J.jsx)(`span`,{children:r}),(0,J.jsx)(`span`,{className:`text-muted-foreground/60`,children:q(e.occurredAt??e.createdAt)})]}),(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}var Xe={"spawned-child":{ready:`spawned`,exited:`spawned · exited`,failed:`spawn failed`},"spawned-by":{ready:`spawned by`,exited:`spawned by`,failed:`spawned by`}},Ze={"spawned-child-ready":l,"spawned-child-exited":_,"spawned-child-failed":w,"spawned-by-ready":d,"spawned-by-exited":d,"spawned-by-failed":d},Qe={"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 $e({entry:e}){let t=`${e.direction}-${e.status}`,r=Xe[e.direction]?.[e.status]??e.direction,i=Ze[t]??f,a=Qe[t]??`text-muted-foreground`,o=e.status===`failed`;return(0,J.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,J.jsxs)(`div`,{className:n(`flex items-center gap-1.5 rounded-full border bg-muted/30 px-2.5 py-1 text-xs`,o?`border-red-500/30`:`border-border`),children:[(0,J.jsx)(i,{className:n(`h-3 w-3 shrink-0`,a)}),(0,J.jsx)(`span`,{className:`text-muted-foreground`,children:r}),(0,J.jsx)(Y,{agentId:e.agentId}),e.reason&&o&&(0,J.jsxs)(`span`,{className:`text-red-400/80 max-w-[120px] truncate`,title:e.reason,children:[`— `,e.reason]}),(0,J.jsx)(`span`,{className:`text-muted-foreground/60 shrink-0`,children:q(e.timestamp)})]}),(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}var et={memory:j,instructions:a,tools:g,comms:f,knowledge:i,context:c},X={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 tt(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function nt({entry:e}){let[t,r]=(0,H.useState)(!1),i=e.event,a=et[i.category]??A;return(0,J.jsx)(`div`,{className:`flex justify-center py-2 my-1`,children:(0,J.jsxs)(`div`,{className:n(`w-full max-w-[85%] md:max-w-[75%] rounded-lg border px-2.5 py-1.5 text-xs shadow-sm`,X[i.category]??X.context),children:[(0,J.jsxs)(`button`,{type:`button`,className:`flex w-full min-w-0 items-center gap-1.5 text-left`,onClick:()=>r(e=>!e),children:[(0,J.jsx)(a,{className:`h-3.5 w-3.5 shrink-0`}),(0,J.jsx)(`span`,{className:`shrink-0 font-medium`,children:i.category}),(0,J.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-foreground/80`,children:i.summary}),(0,J.jsx)(`span`,{className:`shrink-0 text-muted-foreground/60`,children:q(i.timestamp)}),(0,J.jsx)(b,{className:n(`h-3.5 w-3.5 shrink-0 transition-transform`,t&&`rotate-90`)})]}),t&&(0,J.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:tt(i.detail)})]})})}function rt({blockedLabel:e,onInterrupt:t}){return e?(0,J.jsx)(`div`,{className:`flex justify-start mb-3 animate-in fade-in slide-in-from-bottom-1 duration-150`,children:(0,J.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,J.jsx)(w,{className:`w-3.5 h-3.5 text-red-400`}),(0,J.jsxs)(`span`,{className:`text-xs text-red-300`,children:[`blocked: `,e]})]})}):(0,J.jsx)(`div`,{className:`flex justify-start mb-3 animate-in fade-in slide-in-from-bottom-1 duration-150`,children:(0,J.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,J.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,J.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-yellow-400 animate-[pulse_1.4s_ease-in-out_infinite]`}),(0,J.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,J.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,J.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`working`}),t&&(0,J.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,J.jsx)(te,{className:`w-3.5 h-3.5`}),`Stop`]})]})})}var Z=`agent-relay:chat-hide-tools`,Q=(()=>{let e=new Set,t=(()=>{try{return window.localStorage.getItem(Z)===`on`}catch{return!1}})(),n=()=>e.forEach(e=>e());return typeof window<`u`&&window.addEventListener(`storage`,e=>{e.key===Z&&(t=e.newValue===`on`,n())}),{subscribe(t){return e.add(t),()=>e.delete(t)},get:()=>t,toggle(){t=!t;try{window.localStorage.setItem(Z,t?`on`:`off`)}catch{}n()}}})();function it(){return[(0,H.useSyncExternalStore)(Q.subscribe,Q.get,()=>!1),Q.toggle]}function at({steps:e,showReasoning:t,issueRepo:r}){let[i,a]=it(),o=t?e:e.filter(e=>e.kind!==`reasoning`);if(!o.length)return null;let s=o.filter(e=>e.kind===`tool`).length;return(0,J.jsx)(`div`,{className:`flex justify-start mb-2`,children:(0,J.jsxs)(`div`,{className:`max-w-[85%] md:max-w-[75%] min-w-0 space-y-1.5`,children:[o.map(e=>e.kind===`narration`?(0,J.jsx)(V,{text:e.text,issueRepo:r,className:`text-sm leading-relaxed break-words text-foreground/90 min-w-0`},e.id):e.kind===`reasoning`?(0,J.jsxs)(`div`,{className:`flex items-start gap-1.5 text-xs leading-relaxed text-muted-foreground/80`,children:[(0,J.jsx)(j,{className:`w-3.5 h-3.5 mt-0.5 shrink-0 opacity-70`}),(0,J.jsx)(V,{text:e.text,issueRepo:r,className:`italic break-words min-w-0`})]},e.id):i?null:(0,J.jsxs)(`div`,{className:`flex items-start gap-1.5 text-xs leading-relaxed text-muted-foreground`,children:[(0,J.jsx)(S,{className:`w-3 h-3 mt-0.5 shrink-0 opacity-70`}),(0,J.jsxs)(`span`,{className:`min-w-0 break-words`,children:[(0,J.jsx)(`span`,{className:`font-medium`,children:e.label||`tool`}),e.text&&e.text.trim()&&e.text.trim()!==(e.label??``).trim()?(0,J.jsxs)(`span`,{className:`opacity-70`,children:[` — `,e.text]}):null]})]},e.id)),s>0&&(0,J.jsxs)(`button`,{onClick:a,className:`flex items-center gap-1 text-[11px] text-muted-foreground/50 hover:text-muted-foreground transition-colors text-left`,children:[(0,J.jsx)(b,{className:n(`w-3 h-3 shrink-0 transition-transform`,!i&&`rotate-90`)}),(0,J.jsx)(`span`,{children:i?`show ${s} tool step${s===1?``:`s`}`:`hide tool steps`})]})]})})}function ot({date:e}){return(0,J.jsxs)(`div`,{className:`flex items-center justify-center gap-3 py-3 my-1`,children:[(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,J.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground`,children:Ue(e)}),(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function st({timestamp:e}){let t=new Date(e).toLocaleString(void 0,{month:`short`,day:`numeric`,year:`numeric`,hour:`2-digit`,minute:`2-digit`});return(0,J.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,J.jsxs)(`span`,{className:`text-xs text-muted-foreground/60`,children:[`created `,t]}),(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function ct({history:e}){let t=e.sourceAgentLabel||e.sourcePeerId,n=e.entries.length;return(0,J.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,J.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,J.jsx)(r,{className:`h-3 w-3`}),(0,J.jsxs)(`span`,{children:[`forked history from `,t]}),(0,J.jsxs)(`span`,{className:`text-muted-foreground/60`,children:[n,` `,n===1?`entry`:`entries`]})]}),(0,J.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function lt({entry:e,sourceLabel:t,issueRepo:r}){let i=e.message,a=F(i),o=e.originalFrom===R;return(0,J.jsx)(`div`,{className:n(`flex mb-3 opacity-80`,o?`justify-end`:`justify-start`),children:(0,J.jsx)(`div`,{className:`max-w-[85%] md:max-w-[75%]`,children:(0,J.jsxs)(`div`,{className:n(`rounded-2xl border border-dashed px-3.5 py-2 text-sm select-text`,o?`border-primary/25 bg-primary/10 text-foreground rounded-br-sm`:`border-border bg-card/70 rounded-bl-sm`),children:[(0,J.jsxs)(`div`,{className:n(`mb-1 text-[10px] uppercase tracking-normal`,o?`text-primary/70`:`text-muted-foreground`),children:[`forked history · `,o?`you`:t||e.originalFrom]}),(0,J.jsx)(V,{text:a,rawBody:i.body,issueRepo:r,className:`leading-relaxed`}),(0,J.jsxs)(`p`,{className:n(`mt-1 flex items-center justify-end gap-1.5 text-xs`,o?`text-primary/60`:`text-muted-foreground`),children:[(0,J.jsxs)(`span`,{className:`opacity-40`,children:[`#`,e.originalMessageId]}),(0,J.jsx)(`span`,{children:q(e.originalCreatedAt)})]})]})})})}function ut({msg:e,issueRepo:t}){let n=F(e),r=q(e.occurredAt??e.createdAt);return(0,J.jsx)(`div`,{"data-msg-id":e.id,className:`mb-3`,children:(0,J.jsxs)(`div`,{className:`rounded-xl border border-primary/30 bg-primary/[0.06] px-3.5 py-2.5 shadow-sm`,children:[(0,J.jsxs)(`div`,{className:`mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-primary/80`,children:[(0,J.jsx)(A,{className:`h-3.5 w-3.5`}),(0,J.jsx)(`span`,{children:`Initial prompt`}),(0,J.jsx)(`span`,{className:`ml-auto text-[10px] font-normal normal-case text-muted-foreground/60`,children:r})]}),(0,J.jsx)(V,{text:n,rawBody:e.body,issueRepo:t,className:`text-sm leading-relaxed text-foreground`})]})})}function dt({scrollEl:e,timeline:t}){let[r,i]=(0,H.useState)(!0),[a,o]=(0,H.useState)(null),[s,c]=(0,H.useState)(null),[l,u]=(0,H.useState)(!1),d=(0,H.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:F(n.msg)}}return null},[t]);if((0,H.useEffect)(()=>{if(!d||!e){i(!0);return}let t=null,n=null,r=()=>{let r=e.querySelector(`[data-msg-id="${d.id}"]`);if(!r){t?.disconnect(),t=null,n=null,i(!1);return}let a=r.getBoundingClientRect(),o=e.getBoundingClientRect();u(a.top<o.top),r!==n&&(t?.disconnect(),n=r,t=new IntersectionObserver(([e])=>{e&&i(e.isIntersecting)},{root:e,threshold:0}),t.observe(r))};return r(),e.addEventListener(`scroll`,r,{passive:!0}),()=>{t?.disconnect(),e.removeEventListener(`scroll`,r)}},[d?.id,e]),r||!d||!d.body.trim())return null;let f=a?.id===d.id?a.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,J.jsx)(`div`,{className:`flex shrink-0 bg-card/45 border-b border-border`,children:(0,J.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,J.jsx)(`span`,{children:`Your prompt`}),(0,J.jsx)(O,{className:`w-3 h-3`})]})}):(0,J.jsxs)(`section`,{className:`flex shrink-0 flex-col border-b border-border bg-card/45 px-3 py-2`,children:[(0,J.jsxs)(`div`,{className:`flex items-center gap-2 text-[11px] text-muted-foreground mb-0.5`,children:[(0,J.jsx)(`span`,{className:`font-medium text-primary/70`,children:`Your prompt`}),(0,J.jsxs)(`button`,{type:`button`,className:`ml-auto hover:text-foreground transition-colors`,onClick:m,children:[h,` scroll to original`]}),(0,J.jsx)(`button`,{type:`button`,className:`hover:text-foreground transition-colors`,onClick:()=>c({id:d.id,value:!0}),title:`Minimize`,children:(0,J.jsx)(ne,{className:`w-3 h-3`})})]}),(0,J.jsx)(`p`,{className:n(`text-sm text-foreground leading-snug cursor-pointer`,!f&&`line-clamp-2`),onClick:()=>o({id:d.id,value:!f}),children:d.body})]})}function ft(){return(0,H.useSyncExternalStore)(e=>M.subscribe(e),()=>M.getPlayingKey(),()=>null)}var pt={id:R};function mt({msg:e,peer:t}){return(0,J.jsx)(ut,{msg:e,issueRepo:P(e=>e.agentsById[t]?.issueRepo)})}function ht({agent:e,onClick:t}){let r=!!(t&&e);return(0,J.jsx)(`button`,{type:`button`,title:e?e.label||e.name||e.id:void 0,onClick:t,disabled:!r,className:n(`shrink-0 self-end transition-opacity`,r?`cursor-pointer hover:opacity-80`:`cursor-default opacity-60`),children:(0,J.jsx)(B,{agent:e})})}function gt({attachment:e,outbound:t}){let r=e.kind===`image`,i=e.title||e.artifactId,[s,c]=(0,H.useState)(null),[l,u]=(0,H.useState)(null),[d,f]=(0,H.useState)(!1),[p,m]=(0,H.useState)(!1);(0,H.useEffect)(()=>{let t=!1,n=null;async function r(){f(!0),u(null),c(null);try{let r=await h(`/artifacts/${encodeURIComponent(e.artifactId)}/content`);if(t)return;n=URL.createObjectURL(r),c(n)}catch(e){t||u(e.message)}finally{t||f(!1)}}return r(),()=>{t=!0,n&&URL.revokeObjectURL(n)}},[e.artifactId]);function g(){if(!s)return;let e=document.createElement(`a`);e.href=s,e.download=i,document.body.appendChild(e),e.click(),e.remove()}return r?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{type:`button`,onClick:()=>s&&m(!0),disabled:!s,className:`group/img mt-2 block overflow-hidden rounded-md border border-foreground/10 bg-black/10 text-left disabled:cursor-default relative`,children:s?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`img`,{src:s,alt:i,loading:`lazy`,className:`block max-h-72 max-w-full object-contain`}),(0,J.jsx)(`span`,{className:`absolute inset-0 flex items-center justify-center bg-black/0 group-hover/img:bg-black/30 transition-colors`,children:(0,J.jsx)(k,{className:`w-6 h-6 text-white opacity-0 group-hover/img:opacity-100 transition-opacity drop-shadow-md`})})]}):(0,J.jsxs)(`span`,{className:n(`flex min-h-20 items-center gap-2 px-3 py-2 text-xs`,l?`text-red-400`:`text-muted-foreground`),children:[d?(0,J.jsx)(y,{className:`h-4 w-4 animate-spin`}):(0,J.jsx)(w,{className:`h-4 w-4`}),l||`Loading image`]})}),s&&(0,J.jsx)(de,{open:p,onOpenChange:m,children:(0,J.jsxs)(ue,{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,J.jsx)(fe,{className:`sr-only`,children:i}),(0,J.jsxs)(`div`,{className:`relative flex items-center justify-center min-h-[200px]`,children:[(0,J.jsx)(`img`,{src:s,alt:i,className:`max-w-[93vw] max-h-[90vh] object-contain`}),(0,J.jsxs)(`div`,{className:`absolute top-2 right-2 flex gap-1`,children:[(0,J.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,J.jsx)(o,{className:`w-4 h-4`})}),(0,J.jsx)(`button`,{type:`button`,onClick:()=>m(!1),className:`rounded-md bg-black/60 hover:bg-black/80 p-2 text-white transition-colors`,title:`Close`,children:(0,J.jsx)(ee,{className:`w-4 h-4`})})]})]})]})})]}):(0,J.jsxs)(`button`,{type:`button`,onClick:g,disabled:!s,className:n(`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,J.jsx)(y,{className:`h-4 w-4 shrink-0 animate-spin`}):l?(0,J.jsx)(w,{className:`h-4 w-4 shrink-0 text-red-400`}):(0,J.jsx)(a,{className:`h-4 w-4 shrink-0`}),(0,J.jsx)(`span`,{className:n(`min-w-0 flex-1 truncate`,l&&`text-red-400`),children:l||i}),(0,J.jsx)(o,{className:`h-3.5 w-3.5 shrink-0`})]})}function $({open:e,onToggle:t,onReact:r}){return(0,J.jsxs)(`div`,{className:`relative shrink-0`,children:[(0,J.jsx)(`button`,{type:`button`,title:`Add reaction`,onClick:t,className:n(`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,J.jsx)(re,{className:`h-3 w-3`})}),e&&(0,J.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:Ne.map(e=>(0,J.jsx)(`button`,{type:`button`,title:`React ${e}`,onClick:()=>r(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 _t({msg:e,peer:t}){let[r,i]=(0,H.useState)(!1),a=P(e=>e.agentsById),o=P(e=>e.openAgentDetail),s=e.from===t,c=(s?e.to:e.from)||``,l=a[s?t:c]?.issueRepo??a[t]?.issueRepo,f=!c||c===`broadcast`||c.includes(`:`),p=F(e),m=q(e.occurredAt??e.createdAt),h=s?u:d,g=a[e.from??``]??null;function _(e){e.stopPropagation(),g&&o(g)}return(0,J.jsx)(`div`,{"data-msg-id":e.id,className:`flex justify-center mb-1.5`,children:(0,J.jsxs)(`div`,{className:`w-full max-w-[94%] rounded-md border border-border/50 bg-muted/15 px-2.5 py-1`,children:[(0,J.jsxs)(`div`,{className:`flex items-center gap-1.5 text-xs cursor-pointer select-none`,onClick:()=>i(e=>!e),children:[(0,J.jsx)(b,{className:n(`h-3 w-3 shrink-0 text-muted-foreground/60 transition-transform`,r&&`rotate-90`)}),(0,J.jsx)(`button`,{type:`button`,title:g?g.label||g.name||g.id:void 0,disabled:!g,onClick:_,className:n(`shrink-0 transition-opacity`,g?`cursor-pointer hover:opacity-80`:`cursor-default opacity-60`),children:(0,J.jsx)(B,{agent:g,className:`!w-4 !h-4 !rounded-sm opacity-70`})}),(0,J.jsx)(h,{className:`h-3 w-3 shrink-0 text-muted-foreground/70`}),(0,J.jsxs)(`span`,{className:`shrink-0 text-muted-foreground`,children:[`Message `,s?`to`:`from`]}),f?(0,J.jsx)(`span`,{className:`shrink-0 font-medium text-muted-foreground`,children:oe(c,a)}):(0,J.jsx)(Y,{agentId:c,className:`shrink-0 px-0.5 text-foreground/80`,noIcon:!0}),!r&&(0,J.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-muted-foreground/50`,children:p}),(0,J.jsx)(`span`,{className:`ml-auto shrink-0 text-muted-foreground/40`,children:m})]}),r&&(0,J.jsx)(`div`,{className:`mt-1.5 pl-5`,children:(0,J.jsx)(V,{text:p,rawBody:e.body,issueRepo:l,className:`text-sm leading-relaxed text-foreground/90`})})]})})}var vt=(0,H.memo)(function({msg:e,peer:t,showAvatar:r=!1,onOpenReferencedPath:i,onPreviewReferencedPath:a,onPreviewReferencedPathEnd:o}){if(e.from!==`user`&&e.to!==`user`)return(0,J.jsx)(_t,{msg:e,peer:t});let s=e.kind===`session`?e.payload?.session:void 0;if(s?.type===`prompt`&&s?.origin===`provider`)return(0,J.jsx)(mt,{msg:e,peer:t});let c=e.from===R,l=P(e=>e.reactToMessage),u=P(e=>e.voiceTtsEnabled),d=ft(),f=P(e=>{let n=e.agentsById[t]?.meta?.cwd;return typeof n==`string`?n:``}),p=P(e=>e.agentsById[t]?.issueRepo),m=P(e=>e.agentsById[t]??null),h=P(e=>e.agentsById.user??null)??pt,g=P(e=>e.openAgentDetail),[_,y]=(0,H.useState)(!1),b=(0,H.useRef)(null),x=(0,H.useRef)(null),S=(0,H.useRef)(!1),C=F(e),ee=q(e.occurredAt??e.createdAt),w=Me(e),T=Pe(e),E=c?Fe(e,t):null,D=E?.icon,O=d===String(e.id),k=u&&!c&&!K(e)&&C.trim().length>0;function ne(t){t.stopPropagation(),O?M.bargeIn():M.speak(e.body,String(e.id))}(0,H.useEffect)(()=>{if(!_)return;function e(e){je()||b.current&&!b.current.contains(e.target)&&y(!1)}return document.addEventListener(`mousedown`,e),document.addEventListener(`touchstart`,e),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`touchstart`,e)}},[_]);function A(e){return De(f||`/`,e)}function j(e,t){let n=A(e);i?.(n,t)}function re(e,t,n){let r=A(e);a?.(r,t,n)}function N(t){l(e,t),y(!1)}function I(e){e.button===0&&(x.current={x:e.clientX,y:e.clientY},S.current=!1)}function ie(e){let t=x.current;t&&(Math.abs(e.clientX-t.x)>3||Math.abs(e.clientY-t.y)>3)&&(S.current=!0)}function L(t){if(!(K(e)||c)&&!t.target.closest(`a,button,input,textarea,select,[role="button"]`)){if(S.current||je()){S.current=!1;return}y(e=>!e)}}let z=r&&!K(e);function ae(){!c&&m&&g(m)}return(0,J.jsxs)(`div`,{"data-msg-id":e.id,className:n(`group/msg flex mb-3 items-end`,c?`justify-end`:`justify-start`,z&&`gap-1.5`),children:[!c&&z&&(0,J.jsx)(ht,{agent:m,onClick:ae}),(0,J.jsxs)(`div`,{ref:b,className:n(`relative`,z?`max-w-[calc(85%-2rem)] md:max-w-[calc(75%-2rem)]`:`max-w-[85%] md:max-w-[75%]`),children:[k&&(0,J.jsx)(`button`,{type:`button`,title:O?`Stop playback`:`Play aloud`,onClick:ne,className:n(`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,J.jsx)(te,{className:`h-3.5 w-3.5 animate-pulse`}):(0,J.jsx)(v,{className:`h-3.5 w-3.5`})}),(0,J.jsxs)(`div`,{className:n(`rounded-2xl px-3.5 py-2 text-sm select-text`,!c&&!K(e)&&`cursor-pointer`,c?`bg-primary text-primary-foreground rounded-br-sm`:`bg-card ring-1 ring-foreground/10 rounded-bl-sm`),onPointerDown:I,onPointerMove:ie,onClick:L,children:[e.subject&&(0,J.jsx)(`p`,{className:n(`text-xs font-semibold mb-1`,c?`text-primary-foreground/70`:`text-muted-foreground`),children:e.subject}),(0,J.jsx)(V,{text:C,rawBody:e.body,issueRepo:p,className:`leading-relaxed`,onPrimary:c,onOpenPath:j,onPreviewPath:re,onPreviewPathEnd:o,resolvePathTitle:(e,t)=>`${A(e)}${t?`:${t}`:``}`}),w.map(t=>(0,J.jsx)(gt,{attachment:t,outbound:c},`${e.id}-${t.artifactId}-${t.role||``}`)),(0,J.jsxs)(`p`,{className:n(`text-xs mt-1 flex items-center gap-1.5`,c?`justify-end text-primary-foreground/60`:`justify-end text-muted-foreground`),children:[(0,J.jsxs)(`span`,{className:`opacity-40`,children:[`#`,e.id]}),(0,J.jsx)(`span`,{children:ee}),E&&D&&(0,J.jsxs)(`span`,{className:n(`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,J.jsx)(D,{className:`h-3 w-3`}),E.label]})]})]}),!K(e)&&T.length>0&&(0,J.jsxs)(`div`,{className:n(`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,J.jsx)($,{open:_,onToggle:()=>y(e=>!e),onReact:N}),T.map(e=>(0,J.jsxs)(`button`,{type:`button`,title:e.actors.join(`, `),onClick:()=>N(e.emoji),className:n(`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,J.jsx)(`span`,{children:e.emoji}),e.count>1&&(0,J.jsx)(`span`,{children:e.count})]},e.emoji))]}),!K(e)&&!c&&T.length===0&&(0,J.jsx)(`div`,{className:`absolute -bottom-2.5 left-1 z-20`,children:(0,J.jsx)($,{open:_,onToggle:()=>y(e=>!e),onReact:N})})]}),c&&z&&(0,J.jsx)(ht,{agent:h})]})});export{Se as C,Le as S,we as T,ke as _,st as a,Be as b,lt as c,nt as d,We as f,ze as g,Ee as h,rt as i,ut as l,Re as m,at as n,ot as o,dt as p,$e as r,ct as s,vt as t,Ye as u,Oe as v,Ce as w,Ae as x,Ve as y};
|
|
3
|
-
//# sourceMappingURL=MessageBubble-C-3IcqgU.js.map
|