@akira-tl/forgerelay 0.8.4 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +10 -10
  3. package/dist/activity/audit-store.js +44 -6
  4. package/dist/activity/mcp-query-tools.js +53 -36
  5. package/dist/activity/query-service.js +41 -11
  6. package/dist/cli.js +16 -17
  7. package/dist/composite-activity.js +124 -33
  8. package/dist/config.js +8 -13
  9. package/dist/lsp/test-support/server-fixture.js +7 -7
  10. package/dist/process-sessions.js +2 -2
  11. package/dist/remote-auth.js +11 -1
  12. package/dist/remote-mcp-connection-pool.js +90 -0
  13. package/dist/remote-transport.js +28 -14
  14. package/dist/remote-workspace-relay.js +203 -45
  15. package/dist/server.js +134 -64
  16. package/dist/skills.js +1 -1
  17. package/dist/subagents/profiles.js +1 -2
  18. package/dist/subagents/providers/adapters/pi.js +2 -2
  19. package/dist/subagents/providers/availability.js +2 -2
  20. package/dist/subagents/providers/path.js +4 -4
  21. package/dist/ui/.vite/manifest.json +32 -32
  22. package/dist/ui/activity-panel-app.html +3 -3
  23. package/dist/ui/assets/{activity-panel-app-E1ju2dqI.js → activity-panel-app-CUAN6zyW.js} +1 -1
  24. package/dist/ui/assets/{heavy-payload-CeW-n9w5.js → heavy-payload-CgzrutLm.js} +1 -1
  25. package/dist/ui/assets/{review-payload-B9CO298v.js → review-payload-BrLbezbq.js} +1 -1
  26. package/dist/ui/assets/{scrollbar-C2twAENW.js → scrollbar-CbhpdW05.js} +1 -1
  27. package/dist/ui/assets/workspace-app-Bhj96tsR.js +1 -0
  28. package/dist/ui/assets/{workspace-app-CwbJnb_w.js → workspace-app-CxwJuZyS.js} +1 -1
  29. package/dist/ui/assets/{workspace-app-BztEvZIC.js → workspace-app-D6UR0AFl.js} +3 -3
  30. package/dist/ui/assets/workspace-app-ldjBmCJR.css +1 -0
  31. package/dist/ui/assets/workspace-lifecycle-app-Cqfhx9pV.js +1 -0
  32. package/dist/ui/workspace-app.html +4 -4
  33. package/dist/ui/workspace-lifecycle-app.html +4 -4
  34. package/dist/user-config.js +3 -19
  35. package/dist/workspace-presentation.js +69 -0
  36. package/docs/agent-profile-schema.md +4 -9
  37. package/docs/artifact-exchange.md +2 -1
  38. package/docs/chatgpt-coding-workflow.md +9 -9
  39. package/docs/configuration.md +20 -29
  40. package/docs/gotchas.md +10 -7
  41. package/docs/roadmap.md +6 -3
  42. package/docs/security.md +3 -2
  43. package/docs/setup.md +8 -5
  44. package/docs/versioning.md +1 -1
  45. package/package.json +6 -2
  46. package/scripts/debug/accept.mjs +7 -1
  47. package/scripts/debug/relay-accept.mjs +889 -0
  48. package/scripts/debug/runtime.mjs +0 -4
  49. package/scripts/debug/runtime.test.mjs +0 -2
  50. package/scripts/debug/traffic/run.sh +5 -0
  51. package/scripts/debug/traffic/traffic-audit.mjs +907 -0
  52. package/scripts/release/push-ready.mjs +124 -0
  53. package/scripts/release/push-ready.test.mjs +108 -0
  54. package/scripts/release/release-gate.test.mjs +1 -0
  55. package/scripts/release-proof.mjs +16 -1
  56. package/scripts/wiki/sync.mjs +246 -0
  57. package/dist/ui/assets/workspace-app-YnUST8IP.css +0 -1
  58. package/dist/ui/assets/workspace-app-rKuhdae8.js +0 -1
  59. package/dist/ui/assets/workspace-lifecycle-app-CEfMdudP.js +0 -1
package/dist/server.js CHANGED
@@ -55,6 +55,7 @@ import { formatPathForPrompt } from "./skills.js";
55
55
  import { createWorkspaceStore } from "./workspace-store.js";
56
56
  import { WorkspaceTaskReminderTracker } from "./workspace-task-reminders.js";
57
57
  import { WorkspaceTaskStore } from "./workspace-tasks.js";
58
+ import { compactWorkspacePresentation } from "./workspace-presentation.js";
58
59
  import { formatAgentsPath, WorkspaceRegistry } from "./workspaces.js";
59
60
  import { formatAvailableSubagentProfile, summarizeSubagentProfile } from "./subagents/profiles.js";
60
61
  import { formatSubagentProviderAvailabilitySummary, formatUnavailableSubagentProvider, getSubagentProviderAvailabilitySnapshot, } from "./subagents/providers/availability.js";
@@ -311,8 +312,18 @@ const workspaceInspectionOutputSchema = z.union([
311
312
  location: z.literal("relay"),
312
313
  root: z.string(),
313
314
  routeState: z.literal("known"),
315
+ status: z.string().optional(),
316
+ state: z.enum(["active", "stale", "invalid", "closed"]).optional(),
314
317
  mode: z.enum(["checkout", "worktree"]),
315
318
  sourceRoot: z.string().optional(),
319
+ branch: z.string().optional(),
320
+ targetBranch: z.string().optional(),
321
+ managed: z.boolean().optional(),
322
+ createdAt: z.string().optional(),
323
+ lastUsedAt: z.string().optional(),
324
+ idleMs: z.number().nonnegative().optional(),
325
+ rootValid: z.boolean().optional(),
326
+ taskSummary: workspaceTaskInspectionSummaryOutputSchema.optional(),
316
327
  relay: z.string(),
317
328
  executionLocation: z.string(),
318
329
  }),
@@ -1332,10 +1343,14 @@ function registerProcessTools(server, config, workspaces, processSessions, hooks
1332
1343
  }
1333
1344
  export function createMcpServer(config, workspaces, reviewCheckpoints, processSessions, subagentProviders, incomingArtifactAdapters, codeIntelligence, activityLifecycle, bashOutputStore, activityQueries, options = {}) {
1334
1345
  const connectionScopeId = `mcp-connection:${randomUUID()}`;
1335
- const remoteWorkspaces = new RemoteWorkspaceRelay(config.configDir, config.stateDir);
1336
- const compositeWorkspaces = new CompositeWorkspaceRegistry(config.stateDir);
1346
+ const ownsRemoteWorkspaces = options.remoteWorkspaces === undefined;
1347
+ const remoteWorkspaces = options.remoteWorkspaces
1348
+ ?? new RemoteWorkspaceRelay(config.configDir, config.stateDir);
1349
+ const compositeWorkspaces = options.compositeWorkspaces
1350
+ ?? new CompositeWorkspaceRegistry(config.stateDir);
1337
1351
  const workspaceTasks = new WorkspaceTaskStore(config.stateDir);
1338
- const taskReminders = new WorkspaceTaskReminderTracker(config.taskReminderInterval, workspaceTasks);
1352
+ const taskReminders = options.taskReminders
1353
+ ?? new WorkspaceTaskReminderTracker(config.taskReminderInterval, workspaceTasks);
1339
1354
  const compositeTaskGuides = loadCapabilityGuides(config).filter((guide) => guide.name === "workspace-tasks");
1340
1355
  const compositeActivity = new CompositeActivityCoordinator(compositeWorkspaces, activityQueries, remoteWorkspaces);
1341
1356
  const resolveExecutionTarget = (workspaceId, memberName) => {
@@ -2094,19 +2109,21 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
2094
2109
  const workspacePanelStates = new Map();
2095
2110
  const workspacePanelState = (workspaceId) => {
2096
2111
  const remembered = workspacePanelStates.get(workspaceId);
2097
- if (remembered)
2112
+ if (remoteWorkspaces.has(workspaceId) || compositeWorkspaces.has(workspaceId)) {
2098
2113
  return remembered;
2114
+ }
2099
2115
  try {
2100
2116
  const workspace = workspaces.getWorkspace(workspaceId);
2101
- return {
2117
+ if (remembered)
2118
+ return remembered;
2119
+ return compactWorkspacePresentation({
2102
2120
  workspaceId: workspace.id,
2103
2121
  root: workspace.root,
2104
2122
  path: workspace.root,
2105
2123
  mode: workspace.mode,
2106
2124
  sourceRoot: workspace.sourceRoot,
2107
- instruction: `Use workspaceId ${workspace.id} for subsequent calls.`,
2108
2125
  summary: { mode: workspace.mode },
2109
- };
2126
+ });
2110
2127
  }
2111
2128
  catch {
2112
2129
  return undefined;
@@ -2119,7 +2136,11 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
2119
2136
  const card = meta.card;
2120
2137
  if (meta.tool !== toolNames.openWorkspace || typeof card !== "object" || card === null)
2121
2138
  return;
2122
- workspacePanelStates.set(workspaceId, card);
2139
+ const compact = compactWorkspacePresentation(card);
2140
+ workspacePanelStates.set(workspaceId, {
2141
+ ...(workspacePanelStates.get(workspaceId) ?? {}),
2142
+ ...compact,
2143
+ });
2123
2144
  };
2124
2145
  const workspaceAppResourceMetadata = {
2125
2146
  description: "Historical ForgeRelay tool card UI.",
@@ -2349,16 +2370,29 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
2349
2370
  };
2350
2371
  const inspectCompositeMember = async (entry) => {
2351
2372
  if (remoteWorkspaces.has(entry.workspaceId)) {
2352
- const inspected = remoteWorkspaces.inspectWorkspace(entry.workspaceId);
2353
- return {
2354
- name: entry.name,
2355
- purpose: entry.purpose,
2356
- workspaceId: entry.workspaceId,
2357
- known: true,
2358
- location: inspected.location,
2359
- routeState: inspected.routeState,
2360
- mode: inspected.mode,
2361
- };
2373
+ try {
2374
+ const inspected = await remoteWorkspaces.inspectWorkspace(entry.workspaceId);
2375
+ return {
2376
+ name: entry.name,
2377
+ purpose: entry.purpose,
2378
+ workspaceId: entry.workspaceId,
2379
+ known: true,
2380
+ location: inspected.location,
2381
+ routeState: inspected.routeState,
2382
+ state: inspected.state,
2383
+ status: inspected.status,
2384
+ mode: inspected.mode,
2385
+ rootValid: inspected.rootValid,
2386
+ };
2387
+ }
2388
+ catch {
2389
+ return {
2390
+ name: entry.name,
2391
+ purpose: entry.purpose,
2392
+ workspaceId: entry.workspaceId,
2393
+ known: false,
2394
+ };
2395
+ }
2362
2396
  }
2363
2397
  try {
2364
2398
  const inspected = await workspaces.inspectWorkspace(entry.workspaceId);
@@ -2412,7 +2446,7 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
2412
2446
  };
2413
2447
  }
2414
2448
  else if (remoteWorkspaces.has(workspaceId)) {
2415
- inspection = remoteWorkspaces.inspectWorkspace(workspaceId);
2449
+ inspection = await remoteWorkspaces.inspectWorkspace(workspaceId);
2416
2450
  }
2417
2451
  else {
2418
2452
  const inspected = await workspaces.inspectWorkspace(workspaceId);
@@ -2428,9 +2462,11 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
2428
2462
  inspection.kind === "composite"
2429
2463
  ? `State: ${inspection.state}; members=${inspection.members.length}.`
2430
2464
  : inspection.location === "relay"
2431
- ? `Route: ${inspection.routeState}; mode=${inspection.mode}; location=${inspection.location}. Remote lifecycle is not probed by inspection.`
2465
+ ? inspection.state
2466
+ ? `State: ${inspection.state}; route=${inspection.routeState}; mode=${inspection.mode}; location=${inspection.location}. Lifecycle and Task facts come from the Execution ForgeRelay.`
2467
+ : `Route: ${inspection.routeState}; mode=${inspection.mode}; location=${inspection.location}.`
2432
2468
  : `State: ${inspection.state}; mode=${inspection.mode}; location=${inspection.location}.`,
2433
- "Task summary is included only when durable local Task state already exists; Task bodies are never returned.",
2469
+ "Task summary is included only when durable Task state already exists on the owning Workspace; Task bodies are never returned.",
2434
2470
  instruction,
2435
2471
  ].join("\n");
2436
2472
  logToolCall(config, {
@@ -2754,10 +2790,16 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
2754
2790
  if (name !== undefined || memberName !== undefined) {
2755
2791
  throw new Error("open_workspace name/memberName are only valid for a Composite Workspace.");
2756
2792
  }
2757
- if (relay !== undefined) {
2758
- if (workspaceId !== undefined) {
2759
- throw new Error("Relayed open_workspace requires a path; resuming a relayed workspace is not available in this tracer bullet.");
2793
+ if (workspaceId !== undefined && remoteWorkspaces.has(workspaceId)) {
2794
+ if (path !== undefined || relay !== undefined || mode !== undefined || baseRef !== undefined ||
2795
+ newWorktree !== undefined || newWorkspace !== undefined) {
2796
+ throw new Error("Resuming a relayed Workspace by workspaceId accepts context only.");
2760
2797
  }
2798
+ const resumed = await remoteWorkspaces.resumeWorkspace(workspaceId, context ?? "auto", hostScopeIdFor(_meta, sessionId));
2799
+ rememberWorkspacePanelState(workspaceId, resumed);
2800
+ return resumed;
2801
+ }
2802
+ if (relay !== undefined) {
2761
2803
  if (!path)
2762
2804
  throw new Error("Relayed open_workspace requires path.");
2763
2805
  const opened = await remoteWorkspaces.openWorkspace(relay, {
@@ -2978,41 +3020,44 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
2978
3020
  success: true,
2979
3021
  durationMs: Math.round(performance.now() - startedAt),
2980
3022
  });
3023
+ const workspaceCard = {
3024
+ workspaceId: workspace.id,
3025
+ kind: "workspace",
3026
+ root: workspace.root,
3027
+ path: workspace.root,
3028
+ mode: workspace.mode,
3029
+ workspaceReused,
3030
+ includeBootstrapContext,
3031
+ sourceRoot: workspace.sourceRoot,
3032
+ worktree: workspace.worktree,
3033
+ worktrees: knownWorktrees,
3034
+ staleWorkspaces,
3035
+ capabilityFingerprint,
3036
+ contextFingerprint,
3037
+ capabilityCatalog,
3038
+ agentsFiles: cardAgentsFiles,
3039
+ availableAgentsFiles: cardAvailableAgentsFiles,
3040
+ skills: cardSkills,
3041
+ agentProviders: cardAgentProviders,
3042
+ agents: cardAgents,
3043
+ instruction: cardInstruction,
3044
+ summary: {
3045
+ mode: workspace.mode,
3046
+ agentsFiles: cardAgentsFiles.length,
3047
+ availableAgentsFiles: cardAvailableAgentsFiles.length,
3048
+ skills: cardSkills.length,
3049
+ capabilities: capabilityCatalog.length,
3050
+ agentProviders: cardAgentProviders.length,
3051
+ agents: cardAgents.length,
3052
+ },
3053
+ };
2981
3054
  const response = hooks.decorateResult(workspace.id, attachHookReports({
2982
3055
  content: resultContent,
2983
3056
  _meta: {
2984
3057
  tool: "open_workspace",
2985
- card: {
2986
- workspaceId: workspace.id,
2987
- kind: "workspace",
2988
- root: workspace.root,
2989
- path: workspace.root,
2990
- mode: workspace.mode,
2991
- workspaceReused,
2992
- includeBootstrapContext,
2993
- sourceRoot: workspace.sourceRoot,
2994
- worktree: workspace.worktree,
2995
- worktrees: knownWorktrees,
2996
- staleWorkspaces,
2997
- capabilityFingerprint,
2998
- contextFingerprint,
2999
- capabilityCatalog,
3000
- agentsFiles: cardAgentsFiles,
3001
- availableAgentsFiles: cardAvailableAgentsFiles,
3002
- skills: cardSkills,
3003
- agentProviders: cardAgentProviders,
3004
- agents: cardAgents,
3005
- instruction: cardInstruction,
3006
- summary: {
3007
- mode: workspace.mode,
3008
- agentsFiles: cardAgentsFiles.length,
3009
- availableAgentsFiles: cardAvailableAgentsFiles.length,
3010
- skills: cardSkills.length,
3011
- capabilities: capabilityCatalog.length,
3012
- agentProviders: cardAgentProviders.length,
3013
- agents: cardAgents.length,
3014
- },
3015
- },
3058
+ card: includeBootstrapContext
3059
+ ? workspaceCard
3060
+ : compactWorkspacePresentation(workspaceCard),
3016
3061
  },
3017
3062
  structuredContent: {
3018
3063
  action: "open",
@@ -3064,13 +3109,17 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
3064
3109
  }
3065
3110
  return remoteWorkspaces.activitySnapshot(input, conversationScopeId);
3066
3111
  },
3112
+ index: async (turnId, knownRevision, conversationScopeId) => {
3113
+ const composite = await compositeActivity.index(turnId, knownRevision);
3114
+ return composite ?? remoteWorkspaces.activityIndex(turnId, knownRevision, conversationScopeId);
3115
+ },
3067
3116
  detail: async (turnId, activityId, conversationScopeId) => {
3068
3117
  const composite = await compositeActivity.detail(turnId, activityId);
3069
3118
  return composite ?? remoteWorkspaces.activityDetail(turnId, activityId, conversationScopeId);
3070
3119
  },
3071
- output: async (turnId, outputId, conversationScopeId) => {
3072
- const composite = await compositeActivity.output(turnId, outputId);
3073
- return composite ?? remoteWorkspaces.activityOutput(turnId, outputId, conversationScopeId);
3120
+ output: async (turnId, outputId, conversationScopeId, cursor) => {
3121
+ const composite = await compositeActivity.output(turnId, outputId, cursor);
3122
+ return composite ?? remoteWorkspaces.activityOutput(turnId, outputId, conversationScopeId, cursor);
3074
3123
  },
3075
3124
  });
3076
3125
  registerAppTool(server, toolNames.capability, {
@@ -3306,7 +3355,7 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
3306
3355
  });
3307
3356
  registerAppTool(server, toolNames.closeWorkspace, {
3308
3357
  title: "Close workspace",
3309
- description: "Close or explicitly delete one Workspace after the user chooses cleanup. action=close (default) preserves checkout, managed-worktree, and Composite identity for later reopen. action=delete permanently removes ForgeRelay-owned state. Managed-worktree-backed Workspaces still finalize safely when active and require commitMessage. Composite delete dissolves only Composite-owned state and never closes member Workspaces. Checkout project files are never deleted; relayed delete remains unavailable.",
3358
+ description: "Close or explicitly delete one Workspace after the user chooses cleanup. action=close (default) preserves checkout, managed-worktree, Composite, and relayed identity for later reopen. action=delete permanently removes ForgeRelay-owned state. Managed-worktree-backed Workspaces still finalize safely when active and require commitMessage. Composite delete dissolves only Composite-owned state and never closes member Workspaces. Checkout project files are never deleted.",
3310
3359
  inputSchema: {
3311
3360
  workspaceId: z.string().describe("Workspace identifier to close or delete."),
3312
3361
  action: z
@@ -3393,10 +3442,7 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
3393
3442
  };
3394
3443
  }
3395
3444
  if (remoteWorkspaces.has(workspaceId)) {
3396
- if (action === "delete") {
3397
- throw new Error("close_workspace action=delete is not available for relayed Workspaces until Workspace Relay lifecycle parity is implemented.");
3398
- }
3399
- const response = await remoteWorkspaces.closeWorkspace(workspaceId, commitMessage, hostScopeIdFor(extra._meta, extra.sessionId));
3445
+ const response = await remoteWorkspaces.closeWorkspace(workspaceId, { action, ...(commitMessage !== undefined ? { commitMessage } : {}) }, hostScopeIdFor(extra._meta, extra.sessionId));
3400
3446
  workspacePanelStates.delete(workspaceId);
3401
3447
  return response;
3402
3448
  }
@@ -4201,6 +4247,21 @@ export function createMcpServer(config, workspaces, reviewCheckpoints, processSe
4201
4247
  writeStdinRemote: (workspaceId, input, conversationScopeId) => remoteWorkspaces.writeStdin(workspaceId, input, conversationScopeId),
4202
4248
  hostScopeIdFor,
4203
4249
  });
4250
+ if (ownsRemoteWorkspaces) {
4251
+ const closeServer = server.close.bind(server);
4252
+ let closePromise;
4253
+ server.close = () => {
4254
+ closePromise ??= (async () => {
4255
+ try {
4256
+ await closeServer();
4257
+ }
4258
+ finally {
4259
+ await remoteWorkspaces.shutdown();
4260
+ }
4261
+ })();
4262
+ return closePromise;
4263
+ };
4264
+ }
4204
4265
  return server;
4205
4266
  }
4206
4267
  export function createServer(config = loadConfig(), options = {}) {
@@ -4226,6 +4287,10 @@ export function createServer(config = loadConfig(), options = {}) {
4226
4287
  });
4227
4288
  const workspaceStore = createWorkspaceStore(config.stateDir);
4228
4289
  const workspaces = new WorkspaceRegistry(config, workspaceStore);
4290
+ const sharedRemoteWorkspaces = new RemoteWorkspaceRelay(config.configDir, config.stateDir);
4291
+ const sharedCompositeWorkspaces = new CompositeWorkspaceRegistry(config.stateDir);
4292
+ const sharedWorkspaceTasks = new WorkspaceTaskStore(config.stateDir);
4293
+ const sharedTaskReminders = new WorkspaceTaskReminderTracker(config.taskReminderInterval, sharedWorkspaceTasks);
4229
4294
  const activityAuditStore = new ActivityAuditStore(config.stateDir);
4230
4295
  const bashOutputStore = new BashOutputStore(config.stateDir);
4231
4296
  const hostTurnStore = new HostTurnStore(config.stateDir);
@@ -4420,7 +4485,11 @@ export function createServer(config = loadConfig(), options = {}) {
4420
4485
  });
4421
4486
  }
4422
4487
  };
4423
- const server = createMcpServer(config, workspaces, reviewCheckpoints, processSessions, subagentProviders, incomingArtifactAdapters, codeIntelligence, activityLifecycle, bashOutputStore, activityQueries);
4488
+ const server = createMcpServer(config, workspaces, reviewCheckpoints, processSessions, subagentProviders, incomingArtifactAdapters, codeIntelligence, activityLifecycle, bashOutputStore, activityQueries, {
4489
+ taskReminders: sharedTaskReminders,
4490
+ remoteWorkspaces: sharedRemoteWorkspaces,
4491
+ compositeWorkspaces: sharedCompositeWorkspaces,
4492
+ });
4424
4493
  await server.connect(transport);
4425
4494
  }
4426
4495
  else {
@@ -4449,6 +4518,7 @@ export function createServer(config = loadConfig(), options = {}) {
4449
4518
  clearInterval(transportCleanupTimer);
4450
4519
  const results = await transports.closeAll();
4451
4520
  logTransportCloseResults("server_shutdown", results);
4521
+ await sharedRemoteWorkspaces.shutdown();
4452
4522
  processSessions.shutdown();
4453
4523
  await codeIntelligence.shutdown();
4454
4524
  oauthProvider.close();
package/dist/skills.js CHANGED
@@ -9,7 +9,7 @@ export function effectiveSkillPaths(config, cwd) {
9
9
  const defaultPathCandidates = [
10
10
  join(homedir(), ".agents", "skills"),
11
11
  resolve(cwd, ".agents", "skills"),
12
- config.devspaceSkillsDir,
12
+ config.configSkillsDir,
13
13
  join(config.agentDir, "skills"),
14
14
  ];
15
15
  const defaultPaths = defaultPathCandidates.filter((path) => path !== undefined && existsSync(path));
@@ -16,8 +16,7 @@ export async function loadSubagentProfiles(config, workspaceRoot) {
16
16
  if (!config.subagents)
17
17
  return [];
18
18
  const profileDirs = [
19
- config.devspaceAgentsDir,
20
- join(workspaceRoot, ".devspace", "agents"),
19
+ config.configAgentsDir,
21
20
  join(workspaceRoot, ".forgerelay", "agents"),
22
21
  ];
23
22
  const profilesByName = new Map();
@@ -1,5 +1,5 @@
1
1
  import { spawn } from "node:child_process";
2
- import { removeDevspaceNodeModulesBinFromPath } from "../path.js";
2
+ import { removeForgeRelayNodeModulesBinFromPath } from "../path.js";
3
3
  import { asRecord, assertPipedChild, errorMessage, readArray, readNestedString, requireFinalResponse, terminateChildOnAbort, unwrapProviderPayload, } from "../shared.js";
4
4
  const PI_AGENT_TIMEOUT_MS = 120_000;
5
5
  export class PiRpcSubagentAdapter {
@@ -69,7 +69,7 @@ export function piCommandEnvironment(env) {
69
69
  return env;
70
70
  return {
71
71
  ...env,
72
- PATH: removeDevspaceNodeModulesBinFromPath(path),
72
+ PATH: removeForgeRelayNodeModulesBinFromPath(path),
73
73
  };
74
74
  }
75
75
  class JsonLineRpc {
@@ -1,7 +1,7 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  import { delimiter, resolve } from "node:path";
3
3
  import { subagentProviderContinuationSupported } from "./continuation.js";
4
- import { removeDevspaceNodeModulesBinFromPath } from "./path.js";
4
+ import { removeForgeRelayNodeModulesBinFromPath } from "./path.js";
5
5
  import { SUBAGENT_PROVIDERS, } from "../profiles.js";
6
6
  export function getSubagentProviderAvailabilitySnapshot(env = process.env) {
7
7
  return SUBAGENT_PROVIDERS.map((provider) => checkSubagentProviderAvailability(provider, env));
@@ -128,6 +128,6 @@ function piAvailabilityEnvironment(env) {
128
128
  return env;
129
129
  return {
130
130
  ...env,
131
- PATH: removeDevspaceNodeModulesBinFromPath(path),
131
+ PATH: removeForgeRelayNodeModulesBinFromPath(path),
132
132
  };
133
133
  }
@@ -1,12 +1,12 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { delimiter, resolve, sep } from "node:path";
3
- export function removeDevspaceNodeModulesBinFromPath(pathValue) {
3
+ export function removeForgeRelayNodeModulesBinFromPath(pathValue) {
4
4
  return pathValue
5
5
  .split(delimiter)
6
- .filter((entry) => entry && !isDevspaceNodeModulesBin(entry))
6
+ .filter((entry) => entry && !isForgeRelayNodeModulesBin(entry))
7
7
  .join(delimiter);
8
8
  }
9
- function isDevspaceNodeModulesBin(pathEntry) {
9
+ function isForgeRelayNodeModulesBin(pathEntry) {
10
10
  const resolvedEntry = resolve(pathEntry);
11
11
  if (!resolvedEntry.endsWith(`${sep}node_modules${sep}.bin`)) {
12
12
  return false;
@@ -17,7 +17,7 @@ function isDevspaceNodeModulesBin(pathEntry) {
17
17
  try {
18
18
  const packageInfo = JSON.parse(readFileSync(packageJson, "utf8"));
19
19
  const packageName = typeof packageInfo.name === "string" ? packageInfo.name : "";
20
- return ["@akira-tl/forgerelay", "@akira-tl/devspace", "@waishnav/devspace"].includes(packageName);
20
+ return packageName === "@akira-tl/forgerelay";
21
21
  }
22
22
  catch {
23
23
  return false;
@@ -2123,12 +2123,12 @@
2123
2123
  "_chunk-EyZ2wyi3.js"
2124
2124
  ]
2125
2125
  },
2126
- "_scrollbar-C2twAENW.js": {
2127
- "file": "assets/scrollbar-C2twAENW.js",
2126
+ "_scrollbar-CbhpdW05.js": {
2127
+ "file": "assets/scrollbar-CbhpdW05.js",
2128
2128
  "name": "scrollbar",
2129
2129
  "imports": [
2130
2130
  "_chunk-EyZ2wyi3.js",
2131
- "_workspace-app-CwbJnb_w.js"
2131
+ "_workspace-app-CxwJuZyS.js"
2132
2132
  ],
2133
2133
  "dynamicImports": [
2134
2134
  "../../node_modules/@shikijs/langs/dist/abap.mjs",
@@ -2474,33 +2474,33 @@
2474
2474
  "_chunk-EyZ2wyi3.js"
2475
2475
  ]
2476
2476
  },
2477
- "_workspace-app-BztEvZIC.js": {
2478
- "file": "assets/workspace-app-BztEvZIC.js",
2477
+ "_workspace-app-CxwJuZyS.js": {
2478
+ "file": "assets/workspace-app-CxwJuZyS.js",
2479
2479
  "name": "workspace-app",
2480
2480
  "imports": [
2481
- "_workspace-app-CwbJnb_w.js"
2481
+ "_chunk-EyZ2wyi3.js"
2482
2482
  ],
2483
2483
  "dynamicImports": [
2484
- "heavy-payload.tsx",
2485
- "review-payload.tsx"
2484
+ "_workspace-app-CxwJuZyS.js"
2485
+ ],
2486
+ "css": [
2487
+ "assets/workspace-app-ldjBmCJR.css"
2486
2488
  ]
2487
2489
  },
2488
- "_workspace-app-CwbJnb_w.js": {
2489
- "file": "assets/workspace-app-CwbJnb_w.js",
2490
+ "_workspace-app-D6UR0AFl.js": {
2491
+ "file": "assets/workspace-app-D6UR0AFl.js",
2490
2492
  "name": "workspace-app",
2491
2493
  "imports": [
2492
- "_chunk-EyZ2wyi3.js"
2494
+ "_workspace-app-CxwJuZyS.js"
2493
2495
  ],
2494
2496
  "dynamicImports": [
2495
- "_workspace-app-CwbJnb_w.js"
2496
- ],
2497
- "css": [
2498
- "assets/workspace-app-YnUST8IP.css"
2497
+ "heavy-payload.tsx",
2498
+ "review-payload.tsx"
2499
2499
  ]
2500
2500
  },
2501
- "_workspace-app-YnUST8IP.css": {
2502
- "file": "assets/workspace-app-YnUST8IP.css",
2503
- "src": "_workspace-app-YnUST8IP.css"
2501
+ "_workspace-app-ldjBmCJR.css": {
2502
+ "file": "assets/workspace-app-ldjBmCJR.css",
2503
+ "src": "_workspace-app-ldjBmCJR.css"
2504
2504
  },
2505
2505
  "_xml-JnmX6vyS.js": {
2506
2506
  "file": "assets/xml-JnmX6vyS.js",
@@ -2518,52 +2518,52 @@
2518
2518
  ]
2519
2519
  },
2520
2520
  "activity-panel-app.html": {
2521
- "file": "assets/activity-panel-app-E1ju2dqI.js",
2521
+ "file": "assets/activity-panel-app-CUAN6zyW.js",
2522
2522
  "name": "activity-panel-app",
2523
2523
  "src": "activity-panel-app.html",
2524
2524
  "isEntry": true,
2525
2525
  "imports": [
2526
- "_workspace-app-CwbJnb_w.js"
2526
+ "_workspace-app-CxwJuZyS.js"
2527
2527
  ]
2528
2528
  },
2529
2529
  "heavy-payload.tsx": {
2530
- "file": "assets/heavy-payload-CeW-n9w5.js",
2530
+ "file": "assets/heavy-payload-CgzrutLm.js",
2531
2531
  "name": "heavy-payload",
2532
2532
  "src": "heavy-payload.tsx",
2533
2533
  "isDynamicEntry": true,
2534
2534
  "imports": [
2535
- "_scrollbar-C2twAENW.js",
2536
- "_workspace-app-BztEvZIC.js"
2535
+ "_scrollbar-CbhpdW05.js",
2536
+ "_workspace-app-D6UR0AFl.js"
2537
2537
  ]
2538
2538
  },
2539
2539
  "review-payload.tsx": {
2540
- "file": "assets/review-payload-B9CO298v.js",
2540
+ "file": "assets/review-payload-BrLbezbq.js",
2541
2541
  "name": "review-payload",
2542
2542
  "src": "review-payload.tsx",
2543
2543
  "isDynamicEntry": true,
2544
2544
  "imports": [
2545
- "_scrollbar-C2twAENW.js",
2546
- "_workspace-app-BztEvZIC.js"
2545
+ "_scrollbar-CbhpdW05.js",
2546
+ "_workspace-app-D6UR0AFl.js"
2547
2547
  ]
2548
2548
  },
2549
2549
  "workspace-app.html": {
2550
- "file": "assets/workspace-app-rKuhdae8.js",
2550
+ "file": "assets/workspace-app-Bhj96tsR.js",
2551
2551
  "name": "workspace-app",
2552
2552
  "src": "workspace-app.html",
2553
2553
  "isEntry": true,
2554
2554
  "imports": [
2555
- "_workspace-app-CwbJnb_w.js",
2556
- "_workspace-app-BztEvZIC.js"
2555
+ "_workspace-app-CxwJuZyS.js",
2556
+ "_workspace-app-D6UR0AFl.js"
2557
2557
  ]
2558
2558
  },
2559
2559
  "workspace-lifecycle-app.html": {
2560
- "file": "assets/workspace-lifecycle-app-CEfMdudP.js",
2560
+ "file": "assets/workspace-lifecycle-app-Cqfhx9pV.js",
2561
2561
  "name": "workspace-lifecycle-app",
2562
2562
  "src": "workspace-lifecycle-app.html",
2563
2563
  "isEntry": true,
2564
2564
  "imports": [
2565
- "_workspace-app-CwbJnb_w.js",
2566
- "_workspace-app-BztEvZIC.js"
2565
+ "_workspace-app-CxwJuZyS.js",
2566
+ "_workspace-app-D6UR0AFl.js"
2567
2567
  ]
2568
2568
  }
2569
2569
  }
@@ -4,10 +4,10 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>ForgeRelay Panel</title>
7
- <script type="module" crossorigin src="./assets/activity-panel-app-E1ju2dqI.js"></script>
7
+ <script type="module" crossorigin src="./assets/activity-panel-app-CUAN6zyW.js"></script>
8
8
  <link rel="modulepreload" crossorigin href="./assets/chunk-EyZ2wyi3.js">
9
- <link rel="modulepreload" crossorigin href="./assets/workspace-app-CwbJnb_w.js">
10
- <link rel="stylesheet" crossorigin href="./assets/workspace-app-YnUST8IP.css">
9
+ <link rel="modulepreload" crossorigin href="./assets/workspace-app-CxwJuZyS.js">
10
+ <link rel="stylesheet" crossorigin href="./assets/workspace-app-ldjBmCJR.css">
11
11
  </head>
12
12
  <body>
13
13
  <main id="app" class="shell">
@@ -1,2 +1,2 @@
1
- import{a as e,c as t,i as n,l as r,o as i,s as a,t as o,u as s}from"./workspace-app-CwbJnb_w.js";function c(e){let t=m(e._meta),n=m(e.structuredContent),r=m(t?.[`forgerelay/activityPanelWorkspace`])??m(n?.[`forgerelay/activityPanelWorkspace`]);if(r&&!(typeof r.workspaceId!=`string`||r.workspaceId.length===0)&&!(typeof r.root!=`string`||r.root.length===0)&&!(r.mode!==void 0&&r.mode!==`checkout`&&r.mode!==`worktree`))return r}var l=class{root;card=null;openInstructionKey=null;showAvailableInstructions=!1;constructor(e){this.root=e}get active(){return this.card!==null}get workspaceId(){return this.card?.workspaceId}accept(e){let t=c(e);return t?(this.card?.workspaceId!==t.workspaceId&&(this.openInstructionKey=null,this.showAvailableInstructions=!1),this.card=t,!0):!1}clear(){this.card=null,this.openInstructionKey=null,this.showAvailableInstructions=!1,this.root.replaceChildren()}render(){return this.card?(this.root.replaceChildren(this.renderPanel(this.card)),!0):!1}renderPanel(t){let n=h(`section`,`workspace-panel`),r=h(`div`,`workspace-panel-header`),a=h(`span`,`workspace-panel-icon`);a.setAttribute(`aria-hidden`,`true`),a.append(e(i.folderOpen,`workspace-panel-icon-svg`));let o=h(`span`,`workspace-panel-title-group`),s=h(`span`,`workspace-panel-title`,`Workspace`),c=h(`span`,`workspace-panel-subtitle`,p(t.root));c.title=t.root,o.append(s,c);let l=h(`span`,`workspace-panel-mode`,t.mode??`workspace`);r.append(a,o,l);let d=h(`div`,`workspace-details`),f=h(`div`,`workspace-rows`);return u(f,`Root`,t.root,i.folderOpen,!0),u(f,`Mode`,t.mode??`workspace`,i.folderTree),t.worktree&&this.appendWorktreeRows(f,t),t.sourceRoot&&t.sourceRoot!==t.root&&u(f,`Source checkout`,t.sourceRoot,i.sourceCheckout,!0),this.appendInstructions(f,t.agentsFiles??[],t.availableAgentsFiles??[]),this.appendSkills(f,t.skills??[]),this.appendAgents(f,t),d.append(f),n.append(r,d),n}appendWorktreeRows(t,n){let r=n.worktree;if(!r)return;let a=[r.baseRef,r.baseSha?.slice(0,8)].filter(e=>!!e);if(a.length>0){let n=h(`span`,`workspace-base-value`),o=h(`span`,`workspace-value`,a.join(` · `));if(o.title=a.join(` · `),n.append(o),r.dirtySource){let t=h(`span`,`workspace-base-warning`);t.title=`The source checkout had uncommitted changes when this worktree was created.`,t.setAttribute(`role`,`img`),t.setAttribute(`aria-label`,`Source checkout changes are not included in this worktree`),t.append(e(i.warning,`workspace-base-warning-svg`)),n.append(t)}d(t,`Base`,n,i.base)}r.branch&&u(t,`Worktree branch`,r.branch,i.gitBranch),r.targetBranch&&u(t,`Merge target`,r.targetBranch,i.gitBranch)}appendInstructions(e,t,n){let r=t.map((e,t)=>({key:`loaded:${t}`,path:e.path,label:e.path??`Loaded instructions`,content:e.content,status:`loaded`})),a=new Set(r.map(e=>e.path).filter(Boolean)),o=n.flatMap((e,t)=>e.path&&a.has(e.path)?[]:[{key:`available:${t}`,path:e.path,label:e.path??`Nested instructions`,status:`available`}]);if(r.length===0&&o.length===0)return;let s=this.showAvailableInstructions?[...r,...o]:r,c=h(`span`,`workspace-instruction-list`);for(let e of s)c.append(this.renderInstruction(e,c));if(o.length>0){let e=h(`button`,`workspace-instructions-toggle`,this.showAvailableInstructions?`Show less`:`View all`);e.type=`button`,e.setAttribute(`aria-expanded`,String(this.showAvailableInstructions)),e.addEventListener(`click`,()=>{this.showAvailableInstructions=!this.showAvailableInstructions,this.showAvailableInstructions||(this.openInstructionKey=null),this.render()}),c.append(e)}let l=h(`div`,`workspace-instructions-content`);l.append(c),d(e,`Instructions`,l,i.instructions,`workspace-instructions-row`)}renderInstruction(t,n){let r=h(`span`,`workspace-instruction-item`);r.dataset.instructionKey=t.key;let a=t.status===`loaded`&&t.content!==void 0,o=h(a?`button`:`span`,`workspace-instruction-header${a?` interactive`:``}`);o instanceof HTMLButtonElement&&(o.type=`button`,o.setAttribute(`aria-expanded`,String(this.openInstructionKey===t.key)));let s=h(`span`,`workspace-instruction-status ${t.status}`);s.setAttribute(`role`,`img`),s.setAttribute(`aria-label`,t.status===`loaded`?`Loaded into the current workspace context`:`Available for a nested directory`),s.append(e(t.status===`loaded`?i.instructionLoaded:i.instructionAvailable,`workspace-instruction-status-svg`));let c=h(`span`,`workspace-instruction-text`),l=p(t.label);if(c.append(h(`span`,`workspace-instruction-name`,l)),t.path&&t.path!==l){let e=h(`span`,`workspace-instruction-path`,t.path);e.title=t.path,c.append(e)}if(o.append(s,c),!a)return r.append(o),r;let u=h(`span`,`workspace-instruction-chevron`);u.setAttribute(`aria-hidden`,`true`),u.append(e(i.chevronDown,`workspace-instruction-chevron-svg`)),o.append(u);let d=h(`pre`,`workspace-instruction-preview`,t.content);return o.addEventListener(`click`,()=>{this.openInstructionKey=this.openInstructionKey===t.key?null:t.key;for(let e of n.querySelectorAll(`.workspace-instruction-item`)){let t=e.querySelector(`.workspace-instruction-header.interactive`),n=e.querySelector(`.workspace-instruction-preview`),r=e.dataset.instructionKey===this.openInstructionKey;e.classList.toggle(`expanded`,r),t?.setAttribute(`aria-expanded`,String(r)),n&&(n.hidden=!r)}}),r.append(o,d),(()=>{let e=this.openInstructionKey===t.key;r.classList.toggle(`expanded`,e),o.setAttribute(`aria-expanded`,String(e)),d.hidden=!e})(),r}appendSkills(e,t){if(t.length===0)return;let n=f(t.map(e=>({label:e.name??`Unnamed skill`,title:e.description||void 0})));n.classList.add(`workspace-skills-list`),d(e,`Skills`,n,i.skills,`workspace-skills-row`)}appendAgents(e,t){let r=t.agentProviders??[],a=(t.agents??[]).map(e=>{let t=e.provider?.trim(),r=e.providerAvailable===!1;return{label:e.name??`Unnamed agent`,logo:t?n(t):void 0,profile:!0,tone:r?`muted`:void 0,title:[e.description,t?`Provider: ${t}`:void 0,e.model?`Model: ${e.model}`:void 0,e.thinking?`Thinking: ${e.thinking}`:void 0,r?e.providerUnavailableReason??`Provider unavailable`:void 0].filter(Boolean).join(`
1
+ import{a as e,c as t,i as n,l as r,o as i,s as a,t as o,u as s}from"./workspace-app-CxwJuZyS.js";function c(e){let t=m(e._meta),n=m(e.structuredContent),r=m(t?.[`forgerelay/activityPanelWorkspace`])??m(n?.[`forgerelay/activityPanelWorkspace`]);if(r&&!(typeof r.workspaceId!=`string`||r.workspaceId.length===0)&&!(typeof r.root!=`string`||r.root.length===0)&&!(r.mode!==void 0&&r.mode!==`checkout`&&r.mode!==`worktree`))return r}var l=class{root;card=null;openInstructionKey=null;showAvailableInstructions=!1;constructor(e){this.root=e}get active(){return this.card!==null}get workspaceId(){return this.card?.workspaceId}accept(e){let t=c(e);return t?(this.card?.workspaceId!==t.workspaceId&&(this.openInstructionKey=null,this.showAvailableInstructions=!1),this.card=t,!0):!1}clear(){this.card=null,this.openInstructionKey=null,this.showAvailableInstructions=!1,this.root.replaceChildren()}render(){return this.card?(this.root.replaceChildren(this.renderPanel(this.card)),!0):!1}renderPanel(t){let n=h(`section`,`workspace-panel`),r=h(`div`,`workspace-panel-header`),a=h(`span`,`workspace-panel-icon`);a.setAttribute(`aria-hidden`,`true`),a.append(e(i.folderOpen,`workspace-panel-icon-svg`));let o=h(`span`,`workspace-panel-title-group`),s=h(`span`,`workspace-panel-title`,`Workspace`),c=h(`span`,`workspace-panel-subtitle`,p(t.root));c.title=t.root,o.append(s,c);let l=h(`span`,`workspace-panel-mode`,t.mode??`workspace`);r.append(a,o,l);let d=h(`div`,`workspace-details`),f=h(`div`,`workspace-rows`);return u(f,`Root`,t.root,i.folderOpen,!0),u(f,`Mode`,t.mode??`workspace`,i.folderTree),t.worktree&&this.appendWorktreeRows(f,t),t.sourceRoot&&t.sourceRoot!==t.root&&u(f,`Source checkout`,t.sourceRoot,i.sourceCheckout,!0),this.appendInstructions(f,t.agentsFiles??[],t.availableAgentsFiles??[]),this.appendSkills(f,t.skills??[]),this.appendAgents(f,t),d.append(f),n.append(r,d),n}appendWorktreeRows(t,n){let r=n.worktree;if(!r)return;let a=[r.baseRef,r.baseSha?.slice(0,8)].filter(e=>!!e);if(a.length>0){let n=h(`span`,`workspace-base-value`),o=h(`span`,`workspace-value`,a.join(` · `));if(o.title=a.join(` · `),n.append(o),r.dirtySource){let t=h(`span`,`workspace-base-warning`);t.title=`The source checkout had uncommitted changes when this worktree was created.`,t.setAttribute(`role`,`img`),t.setAttribute(`aria-label`,`Source checkout changes are not included in this worktree`),t.append(e(i.warning,`workspace-base-warning-svg`)),n.append(t)}d(t,`Base`,n,i.base)}r.branch&&u(t,`Worktree branch`,r.branch,i.gitBranch),r.targetBranch&&u(t,`Merge target`,r.targetBranch,i.gitBranch)}appendInstructions(e,t,n){let r=t.map((e,t)=>({key:`loaded:${t}`,path:e.path,label:e.path??`Loaded instructions`,content:e.content,status:`loaded`})),a=new Set(r.map(e=>e.path).filter(Boolean)),o=n.flatMap((e,t)=>e.path&&a.has(e.path)?[]:[{key:`available:${t}`,path:e.path,label:e.path??`Nested instructions`,status:`available`}]);if(r.length===0&&o.length===0)return;let s=this.showAvailableInstructions?[...r,...o]:r,c=h(`span`,`workspace-instruction-list`);for(let e of s)c.append(this.renderInstruction(e,c));if(o.length>0){let e=h(`button`,`workspace-instructions-toggle`,this.showAvailableInstructions?`Show less`:`View all`);e.type=`button`,e.setAttribute(`aria-expanded`,String(this.showAvailableInstructions)),e.addEventListener(`click`,()=>{this.showAvailableInstructions=!this.showAvailableInstructions,this.showAvailableInstructions||(this.openInstructionKey=null),this.render()}),c.append(e)}let l=h(`div`,`workspace-instructions-content`);l.append(c),d(e,`Instructions`,l,i.instructions,`workspace-instructions-row`)}renderInstruction(t,n){let r=h(`span`,`workspace-instruction-item`);r.dataset.instructionKey=t.key;let a=t.status===`loaded`&&t.content!==void 0,o=h(a?`button`:`span`,`workspace-instruction-header${a?` interactive`:``}`);o instanceof HTMLButtonElement&&(o.type=`button`,o.setAttribute(`aria-expanded`,String(this.openInstructionKey===t.key)));let s=h(`span`,`workspace-instruction-status ${t.status}`);s.setAttribute(`role`,`img`),s.setAttribute(`aria-label`,t.status===`loaded`?`Loaded into the current workspace context`:`Available for a nested directory`),s.append(e(t.status===`loaded`?i.instructionLoaded:i.instructionAvailable,`workspace-instruction-status-svg`));let c=h(`span`,`workspace-instruction-text`),l=p(t.label);if(c.append(h(`span`,`workspace-instruction-name`,l)),t.path&&t.path!==l){let e=h(`span`,`workspace-instruction-path`,t.path);e.title=t.path,c.append(e)}if(o.append(s,c),!a)return r.append(o),r;let u=h(`span`,`workspace-instruction-chevron`);u.setAttribute(`aria-hidden`,`true`),u.append(e(i.chevronDown,`workspace-instruction-chevron-svg`)),o.append(u);let d=h(`pre`,`workspace-instruction-preview`,t.content);return o.addEventListener(`click`,()=>{this.openInstructionKey=this.openInstructionKey===t.key?null:t.key;for(let e of n.querySelectorAll(`.workspace-instruction-item`)){let t=e.querySelector(`.workspace-instruction-header.interactive`),n=e.querySelector(`.workspace-instruction-preview`),r=e.dataset.instructionKey===this.openInstructionKey;e.classList.toggle(`expanded`,r),t?.setAttribute(`aria-expanded`,String(r)),n&&(n.hidden=!r)}}),r.append(o,d),(()=>{let e=this.openInstructionKey===t.key;r.classList.toggle(`expanded`,e),o.setAttribute(`aria-expanded`,String(e)),d.hidden=!e})(),r}appendSkills(e,t){if(t.length===0)return;let n=f(t.map(e=>({label:e.name??`Unnamed skill`,title:e.description||void 0})));n.classList.add(`workspace-skills-list`),d(e,`Skills`,n,i.skills,`workspace-skills-row`)}appendAgents(e,t){let r=t.agentProviders??[],a=(t.agents??[]).map(e=>{let t=e.provider?.trim(),r=e.providerAvailable===!1;return{label:e.name??`Unnamed agent`,logo:t?n(t):void 0,profile:!0,tone:r?`muted`:void 0,title:[e.description,t?`Provider: ${t}`:void 0,e.model?`Model: ${e.model}`:void 0,e.thinking?`Thinking: ${e.thinking}`:void 0,r?e.providerUnavailableReason??`Provider unavailable`:void 0].filter(Boolean).join(`
2
2
  `)||void 0}}),o=r.map(e=>{let t=e.name?.trim()||`Unknown provider`,r=n(t);return{label:t,logo:r,bareLogo:!!r,ariaLabel:t,tone:e.available===!1?`muted`:void 0,title:e.available===!1?e.reason??`Provider unavailable`:t}});if(a.length>0){let t=f([...a,...o]);t.classList.add(`workspace-agents-list`),d(e,`Agents`,t,i.agents,`workspace-agents-row`)}else o.length>0&&d(e,`Providers`,f(o),i.providers)}};function u(e,t,n,r,i=!1){let a=h(`span`,`workspace-value${i?` mono`:``}`,n);a.title=n,d(e,t,a,r)}function d(t,n,r,i,a){let o=h(`div`,[`workspace-row`,a].filter(Boolean).join(` `)),s=h(`span`,`workspace-row-icon`);s.setAttribute(`aria-hidden`,`true`),s.append(e(i,`workspace-row-icon-svg`)),o.append(s,h(`span`,`workspace-key`,n),r),t.append(o)}function f(e){let t=h(`span`,`workspace-chip-list`);for(let n of e){let e=!!(n.bareLogo&&n.logo),r=h(`span`,[e?`workspace-provider-logo`:n.profile?`workspace-agent-profile`:`workspace-chip`,n.tone].filter(Boolean).join(` `));if(n.title&&(r.title=n.title),e&&(r.setAttribute(`role`,`img`),r.setAttribute(`aria-label`,n.ariaLabel??n.label)),n.logo){let t=document.createElement(`img`);t.className=e?`workspace-provider-logo-image`:n.profile?`workspace-agent-profile-logo`:`workspace-chip-logo`,t.src=n.logo,t.alt=``,t.setAttribute(`aria-hidden`,`true`),r.append(t)}e||r.append(h(`span`,`workspace-chip-label`,n.label)),t.append(r)}return t}function p(e){return e.replaceAll(`\\`,`/`).split(`/`).filter(Boolean).at(-1)??e}function m(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function h(e,t,n){let r=document.createElement(e);return r.className=t,n!==void 0&&(r.textContent=n),r}document.documentElement.dataset.forgerelayApp=`panel`;var g=document.querySelector(`#app`);if(!g)throw Error(`Missing #app root element.`);var _=g,v=I(`section`,`forgerelay-panel`),y=I(`div`,`workspace-panel-slot`),b=I(`div`,`activity-panel-slot`);v.append(y,b),_.replaceChildren(v);var x=new l(y),S=new o(b,{embedded:!0}),C=null,w,T=!1,E=null,D,O=!1,k;A();async function A(){P(),C=new r({name:`forgerelay-panel`,version:`0.1.0`},{}),C.ontoolinput=e=>{let t=e.arguments?.workspaceId;typeof t==`string`&&t.length>0&&(D=t,T&&!S.active&&M()),P()},C.ontoolresult=e=>{j(e)},C.onhostcontextchanged=e=>{w={...w,...e},N()},C.onteardown=async()=>(T=!1,S.detach(),x.clear(),{});try{await C.connect();let e=C.getHostContext();e&&(w=e),N(),T=!0,S.attach(C),D&&!S.active&&M()}catch(e){E=e instanceof Error?e.message:String(e)}P()}function j(e){x.accept(e)&&(D=x.workspaceId),S.accept(e),P()}async function M(){let e=D;if(!(!C||!T||!e||S.active||O||k===e)&&C.getHostCapabilities()?.serverTools){k=e,O=!0,P();try{let t=await C.callServerTool({name:`activity_snapshot`,arguments:{workspaceId:e}});t.isError||j(t)}finally{O=!1,P()}}}function N(){w?.theme&&s(w.theme),w?.styles?.variables&&t(w.styles.variables),w?.styles?.css?.fonts&&a(w.styles.css.fonts);let e=w?.safeAreaInsets;e&&(document.body.style.padding=`${e.top}px ${e.right}px ${e.bottom}px ${e.left}px`)}function P(){x.render()||F(),S.render()||b.replaceChildren()}function F(){let e=I(`section`,`workspace-panel pending`),t=I(`div`,`workspace-panel-header`),n=I(`span`,`workspace-panel-title-group`);n.append(I(`span`,`workspace-panel-title`,`Workspace`),I(`span`,`workspace-panel-subtitle`,E||(D?O?`Loading workspace…`:D:T?`Waiting for workspace…`:`Connecting to host…`))),t.append(n),e.append(t),y.replaceChildren(e)}function I(e,t,n){let r=document.createElement(e);return r.className=t,n!==void 0&&(r.textContent=n),r}
@@ -1,4 +1,4 @@
1
- import{a as e,c as t,i as n,o as r,s as i}from"./workspace-app-BztEvZIC.js";import{S as a,_ as o,a as s,b as c,c as l,d as u,f as d,g as f,h as p,i as m,l as h,m as g,n as _,o as v,p as y,r as b,s as x,t as S,u as C,v as w,x as T,y as E}from"./scrollbar-C2twAENW.js";var D=new Set,O=null;function k(e){D.add(e),O??=requestAnimationFrame(A)}function A(e){let t=new Set(D);D.clear();for(let n of t)try{n(e)}catch(e){console.error(e)}O=D.size>0?requestAnimationFrame(A):null}var j=class e{options;tokensStable=[];tokensUnstable=[];lastUnstableCodeChunk=``;lastStableGrammarState;constructor(e){this.options=e}async enqueue(e){let t=(this.lastUnstableCodeChunk+e).split(`
1
+ import{a as e,c as t,i as n,o as r,s as i}from"./workspace-app-D6UR0AFl.js";import{S as a,_ as o,a as s,b as c,c as l,d as u,f as d,g as f,h as p,i as m,l as h,m as g,n as _,o as v,p as y,r as b,s as x,t as S,u as C,v as w,x as T,y as E}from"./scrollbar-CbhpdW05.js";var D=new Set,O=null;function k(e){D.add(e),O??=requestAnimationFrame(A)}function A(e){let t=new Set(D);D.clear();for(let n of t)try{n(e)}catch(e){console.error(e)}O=D.size>0?requestAnimationFrame(A):null}var j=class e{options;tokensStable=[];tokensUnstable=[];lastUnstableCodeChunk=``;lastStableGrammarState;constructor(e){this.options=e}async enqueue(e){let t=(this.lastUnstableCodeChunk+e).split(`
2
2
  `),n=[],r=[],i=this.tokensUnstable.length;return t.forEach((e,i)=>{let a=i===t.length-1,o=this.options.highlighter.codeToTokens(e,{...this.options,grammarState:this.lastStableGrammarState}),s=o.tokens[0];a||s.push({content:`
3
3
  `,offset:0}),a?(r=s,this.lastUnstableCodeChunk=e):(this.lastStableGrammarState=o.grammarState,n.push(...s))}),this.tokensStable.push(...n),this.tokensUnstable=r,{recall:i,stable:n,unstable:r}}close(){let e=this.tokensUnstable;return this.tokensUnstable=[],this.lastUnstableCodeChunk=``,this.lastStableGrammarState=void 0,{stable:e}}clear(){this.tokensStable=[],this.tokensUnstable=[],this.lastUnstableCodeChunk=``,this.lastStableGrammarState=void 0}clone(){let t=new e(this.options);return t.lastUnstableCodeChunk=this.lastUnstableCodeChunk,t.tokensUnstable=this.tokensUnstable,t.tokensStable=this.tokensStable,t.lastStableGrammarState=this.lastStableGrammarState,t}},M=class extends TransformStream{tokenizer;options;constructor(e){let t=new j(e),{allowRecalls:n=!1}=e;super({async transform(e,r){let{stable:i,unstable:a,recall:o}=await t.enqueue(e);n&&o>0&&r.enqueue({recall:o});for(let e of i)r.enqueue(e);if(n)for(let e of a)r.enqueue(e)},async flush(e){let{stable:r}=t.close();if(!n)for(let t of r)e.enqueue(t)}}),this.tokenizer=t,this.options=e}};function N(e){let t=document.createElement(`span`);return t.style=w(e.htmlStyle??o(e)),t.textContent=e.content,t}var P=-1,F=class{__id=`file-stream:${++P}`;highlighter;stream;abortController;fileContainer;pre;code;gutterElement;contentElement;themeCSSStyle;appliedThemeCSS;currentRowCount=0;constructor(e={theme:E}){this.options=e,this.currentLineIndex=this.options.startingLineIndex??1}cleanUp(){this.abortController?.abort(),this.abortController=void 0}setThemeType(e){(this.options.themeType??`system`)!==e&&(this.options={...this.options,themeType:e},!(typeof this.options.theme==`string`||this.fileContainer==null||this.appliedThemeCSS==null)&&this.applyThemeState(this.fileContainer,this.appliedThemeCSS.themeStyles,e,this.appliedThemeCSS.baseThemeType))}async initializeHighlighter(){return this.highlighter=await f(g(this.options.lang,this.options)),this.highlighter}queuedSetupArgs;async setup(e,t){let n=this.queuedSetupArgs!=null;if(this.queuedSetupArgs=[e,t],n)return;this.highlighter??=await this.initializeHighlighter();let[r,i]=this.queuedSetupArgs;this.queuedSetupArgs=void 0;let a=r;this.setupStream(a,i,this.highlighter)}setupStream(e,t,n){let{disableLineNumbers:r=!1,overflow:i=`scroll`,theme:a=E,themeType:o=`system`}=this.options,s=this.getOrCreateFileContainer();s.parentElement??t.appendChild(s),this.pre??=document.createElement(`pre`),this.pre.parentElement??s.shadowRoot?.appendChild(this.pre);let c=typeof a==`string`?n.getTheme(a).type:void 0,u=d({theme:a,highlighter:n});this.applyThemeState(s,u,o,c);let f=l(this.pre,{type:`file`,diffIndicators:`none`,disableBackground:!0,disableLineNumbers:r,overflow:i,split:!1,totalLines:0});f.textContent=``,this.pre=f,this.code=h({code:this.code,pre:f}),this.gutterElement=void 0,this.contentElement=void 0,this.currentRowCount=0,this.currentLineElement=void 0,this.currentLineIndex=this.options.startingLineIndex??1,this.abortController?.abort(),this.abortController=new AbortController;let{onStreamStart:p,onStreamClose:m,onStreamAbort:g}=this.options;this.stream?.cancel().catch(()=>{}),this.stream=e,this.stream.pipeThrough(typeof a==`string`?new M({...this.options,theme:a,highlighter:n,allowRecalls:!0,defaultColor:!1,cssVariablePrefix:y(`token`)}):new M({...this.options,themes:a,highlighter:n,allowRecalls:!0,defaultColor:!1,cssVariablePrefix:y(`token`)})).pipeTo(new WritableStream({start(e){p?.(e)},close(){m?.()},abort(e){g?.(e)},write:this.handleWrite}),{signal:this.abortController.signal}).catch(e=>{e.name!==`AbortError`&&console.error(`FileStream pipe error:`,e)})}queuedTokens=[];handleWrite=e=>{`recall`in e&&this.queuedTokens.length>=e.recall?this.queuedTokens.length=this.queuedTokens.length-e.recall:this.queuedTokens.push(e),k(this.render),this.options.onStreamWrite?.(e)};currentLineIndex;currentLineElement;render=()=>{this.options.onPreRender?.(this);let{gutter:e,content:t}=this.getOrCreateStreamColumns(),n=document.createDocumentFragment(),r=document.createDocumentFragment();for(let e of this.queuedTokens)if(`recall`in e){if(this.currentLineElement==null)throw Error(`FileStream.render: no current line element, shouldnt be possible to get here`);if(e.recall>this.currentLineElement.childNodes.length)throw Error(`FileStream.render: Token recall exceed the current line, there's probably a bug...`);for(let t=0;t<e.recall;t++)this.currentLineElement.lastChild?.remove()}else{let t=N(e);if(this.currentLineElement==null){let{gutterLine:e,contentLine:t}=this.createLine();n.appendChild(e),r.appendChild(t)}if(this.currentLineElement?.appendChild(t),e.content===`
4
4
  `){this.currentLineIndex++;let{gutterLine:e,contentLine:t}=this.createLine();n.appendChild(e),r.appendChild(t)}}n.childNodes.length>0&&e.appendChild(n),r.childNodes.length>0&&t.appendChild(r),this.queuedTokens.length=0,this.options.onPostRender?.(this)};getOrCreateStreamColumns(){if(this.code==null)throw Error(`FileStream: expected code element to exist`);if(this.gutterElement!=null&&this.contentElement!=null)return{gutter:this.gutterElement,content:this.contentElement};let e=document.createElement(`div`);e.dataset.gutter=``;let t=document.createElement(`div`);return t.dataset.content=``,this.code.appendChild(e),this.code.appendChild(t),this.gutterElement=e,this.contentElement=t,{gutter:e,content:t}}updateRowSpan(){this.gutterElement!=null&&(this.gutterElement.style.gridRow=`span ${this.currentRowCount}`),this.contentElement!=null&&(this.contentElement.style.gridRow=`span ${this.currentRowCount}`)}createLine(){let e=this.currentLineIndex,t=`${e-1}`,n=document.createElement(`div`);n.dataset.columnNumber=`${e}`,n.dataset.lineType=`context`,n.dataset.lineIndex=t;let r=document.createElement(`span`);r.dataset.lineNumberContent=``,r.textContent=`${e}`,n.appendChild(r);let i=document.createElement(`div`);return i.dataset.line=`${e}`,i.dataset.lineType=`context`,i.dataset.lineIndex=t,this.currentRowCount+=1,this.updateRowSpan(),this.currentLineElement=i,{gutterLine:n,contentLine:i}}getOrCreateFileContainer(e){return e!=null&&e===this.fileContainer||e==null&&this.fileContainer!=null?this.fileContainer:(this.fileContainer!=null&&e!=null&&e!==this.fileContainer&&(this.themeCSSStyle=void 0,this.appliedThemeCSS=void 0),this.fileContainer=e??document.createElement(`diffs-container`),this.fileContainer)}applyThemeState(e,t,n,r){let i=e.shadowRoot??e.attachShadow({mode:`open`}),a=r??n,o=this.options.theme??E,s=typeof o==`string`?o:{...o},c=u(i);if(this.themeCSSStyle?.parentNode===i&&this.appliedThemeCSS?.themeStyles===t&&this.appliedThemeCSS.themeType===a&&this.appliedThemeCSS.scrollbarGutter===c){this.appliedThemeCSS.theme=s;return}this.themeCSSStyle=x({shadowRoot:i,currentNode:this.themeCSSStyle,themeCSS:C(t,a,c)}),this.appliedThemeCSS=this.themeCSSStyle==null?void 0:{theme:s,themeStyles:t,themeType:a,baseThemeType:r,scrollbarGutter:c}}};function I(e){let t=v(e);if(t.length!==1)throw console.error(t),Error(`PatchDiff: Provided patch must include only 1 patch, with 1 diff`);let{files:n}=t[0];if(n.length!==1)throw console.error(n),Error(`FileDiff: Provided patch must contain exactly 1 file diff`);return n[0]}var L=a(),R=s();function z({patch:e,options:t,metrics:n,lineAnnotations:r,selectedLines:i,className:a,style:o,prerenderedHTML:s,renderAnnotation:l,renderCustomHeader:u,renderHeaderPrefix:d,renderHeaderMetadata:f,renderGutterUtility:p,disableWorkerPool:h=!1}){let g=B(e),{ref:v,getHoveredLine:y}=_({fileDiff:g,options:t,metrics:n,lineAnnotations:r,selectedLines:i,prerenderedHTML:s,hasGutterRenderUtility:p!=null,hasCustomHeader:u!=null,disableWorkerPool:h});return(0,R.jsx)(c,{ref:v,className:a,style:o,children:b(m({fileDiff:g,renderCustomHeader:u,renderHeaderPrefix:d,renderHeaderMetadata:f,renderAnnotation:l,lineAnnotations:r,renderGutterUtility:p,getHoveredLine:y}),s)})}function B(e){return(0,L.useMemo)(()=>I(e),[e])}var V=T();function H(e,t){let n=(0,V.createRoot)(e);return n.render((0,R.jsx)(U,{...t})),{update(e){n.render((0,R.jsx)(U,{...e}))},unmount(){n.unmount()}}}function U({card:a,hostContext:o,errorMessage:s=null}){let c=o?.theme===`light`?`light`:`dark`;if(s)return(0,R.jsx)(K,{message:s,tone:`error`});if(n(a.tool)||r(a.tool)){let e=a.payload?.patch||a.payload?.diff;return e?(0,R.jsx)(G,{patch:e,themeType:c}):(0,R.jsx)(K,{message:`Diff payload is not available.`})}let l=i(a.payload);return l?e(a.tool)?(0,R.jsx)(W,{path:a.path??`file`,text:l,startLine:t(a.summary,`offset`)??1,themeType:c}):(0,R.jsx)(`pre`,{className:`text-payload pretty-scrollbar ${a.tool}`,children:l}):(0,R.jsx)(K,{message:`No details available.`})}function W({path:e,text:t,startLine:n,themeType:r}){let i=(0,L.useRef)(null),a=(0,L.useMemo)(()=>({theme:{light:`pierre-light`,dark:`pierre-dark`},themeType:r,overflow:`scroll`,unsafeCSS:S}),[r]);return(0,L.useEffect)(()=>{let r=i.current;if(!r)return;let o=new F({...a,lang:p(e),startingLineIndex:n}),s=new ReadableStream({start(e){e.enqueue(t),e.close()}}),c=!1;return o.setup(s,r).then(()=>{c&&(o.cleanUp(),r.replaceChildren())}),()=>{c=!0,o.cleanUp(),r.replaceChildren()}},[a,e,n,t]),(0,R.jsx)(`div`,{ref:i,className:`pierre-file pretty-scrollbar`})}function G({patch:e,themeType:t}){return(0,R.jsx)(z,{patch:e,options:{theme:{light:`pierre-light`,dark:`pierre-dark`},themeType:t,diffStyle:`unified`,diffIndicators:`bars`,hunkSeparators:`line-info`,lineDiffType:`word-alt`,overflow:`scroll`,unsafeCSS:S,collapsedContextThreshold:4,expansionLineCount:20,stickyHeader:!0,disableFileHeader:!0},className:`pierre-diff pretty-scrollbar`})}function K({message:e,tone:t=`muted`}){return(0,R.jsx)(`div`,{className:`status ${t}`,children:e})}export{H as mountHeavyPayload};