@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.
- package/CHANGELOG.md +30 -0
- package/README.md +10 -10
- package/dist/activity/audit-store.js +44 -6
- package/dist/activity/mcp-query-tools.js +53 -36
- package/dist/activity/query-service.js +41 -11
- package/dist/cli.js +16 -17
- package/dist/composite-activity.js +124 -33
- package/dist/config.js +8 -13
- package/dist/lsp/test-support/server-fixture.js +7 -7
- package/dist/process-sessions.js +2 -2
- package/dist/remote-auth.js +11 -1
- package/dist/remote-mcp-connection-pool.js +90 -0
- package/dist/remote-transport.js +28 -14
- package/dist/remote-workspace-relay.js +203 -45
- package/dist/server.js +134 -64
- package/dist/skills.js +1 -1
- package/dist/subagents/profiles.js +1 -2
- package/dist/subagents/providers/adapters/pi.js +2 -2
- package/dist/subagents/providers/availability.js +2 -2
- package/dist/subagents/providers/path.js +4 -4
- package/dist/ui/.vite/manifest.json +32 -32
- package/dist/ui/activity-panel-app.html +3 -3
- package/dist/ui/assets/{activity-panel-app-E1ju2dqI.js → activity-panel-app-CUAN6zyW.js} +1 -1
- package/dist/ui/assets/{heavy-payload-CeW-n9w5.js → heavy-payload-CgzrutLm.js} +1 -1
- package/dist/ui/assets/{review-payload-B9CO298v.js → review-payload-BrLbezbq.js} +1 -1
- package/dist/ui/assets/{scrollbar-C2twAENW.js → scrollbar-CbhpdW05.js} +1 -1
- package/dist/ui/assets/workspace-app-Bhj96tsR.js +1 -0
- package/dist/ui/assets/{workspace-app-CwbJnb_w.js → workspace-app-CxwJuZyS.js} +1 -1
- package/dist/ui/assets/{workspace-app-BztEvZIC.js → workspace-app-D6UR0AFl.js} +3 -3
- package/dist/ui/assets/workspace-app-ldjBmCJR.css +1 -0
- package/dist/ui/assets/workspace-lifecycle-app-Cqfhx9pV.js +1 -0
- package/dist/ui/workspace-app.html +4 -4
- package/dist/ui/workspace-lifecycle-app.html +4 -4
- package/dist/user-config.js +3 -19
- package/dist/workspace-presentation.js +69 -0
- package/docs/agent-profile-schema.md +4 -9
- package/docs/artifact-exchange.md +2 -1
- package/docs/chatgpt-coding-workflow.md +9 -9
- package/docs/configuration.md +20 -29
- package/docs/gotchas.md +10 -7
- package/docs/roadmap.md +6 -3
- package/docs/security.md +3 -2
- package/docs/setup.md +8 -5
- package/docs/versioning.md +1 -1
- package/package.json +6 -2
- package/scripts/debug/accept.mjs +7 -1
- package/scripts/debug/relay-accept.mjs +889 -0
- package/scripts/debug/runtime.mjs +0 -4
- package/scripts/debug/runtime.test.mjs +0 -2
- package/scripts/debug/traffic/run.sh +5 -0
- package/scripts/debug/traffic/traffic-audit.mjs +907 -0
- package/scripts/release/push-ready.mjs +124 -0
- package/scripts/release/push-ready.test.mjs +108 -0
- package/scripts/release/release-gate.test.mjs +1 -0
- package/scripts/release-proof.mjs +16 -1
- package/scripts/wiki/sync.mjs +246 -0
- package/dist/ui/assets/workspace-app-YnUST8IP.css +0 -1
- package/dist/ui/assets/workspace-app-rKuhdae8.js +0 -1
- 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
|
|
1336
|
-
const
|
|
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 =
|
|
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 (
|
|
2112
|
+
if (remoteWorkspaces.has(workspaceId) || compositeWorkspaces.has(workspaceId)) {
|
|
2098
2113
|
return remembered;
|
|
2114
|
+
}
|
|
2099
2115
|
try {
|
|
2100
2116
|
const workspace = workspaces.getWorkspace(workspaceId);
|
|
2101
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
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
|
-
?
|
|
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
|
|
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 (
|
|
2758
|
-
if (
|
|
2759
|
-
|
|
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
|
-
|
|
2987
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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 {
|
|
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:
|
|
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 {
|
|
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:
|
|
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
|
|
3
|
+
export function removeForgeRelayNodeModulesBinFromPath(pathValue) {
|
|
4
4
|
return pathValue
|
|
5
5
|
.split(delimiter)
|
|
6
|
-
.filter((entry) => entry && !
|
|
6
|
+
.filter((entry) => entry && !isForgeRelayNodeModulesBin(entry))
|
|
7
7
|
.join(delimiter);
|
|
8
8
|
}
|
|
9
|
-
function
|
|
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
|
|
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-
|
|
2127
|
-
"file": "assets/scrollbar-
|
|
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-
|
|
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-
|
|
2478
|
-
"file": "assets/workspace-app-
|
|
2477
|
+
"_workspace-app-CxwJuZyS.js": {
|
|
2478
|
+
"file": "assets/workspace-app-CxwJuZyS.js",
|
|
2479
2479
|
"name": "workspace-app",
|
|
2480
2480
|
"imports": [
|
|
2481
|
-
"
|
|
2481
|
+
"_chunk-EyZ2wyi3.js"
|
|
2482
2482
|
],
|
|
2483
2483
|
"dynamicImports": [
|
|
2484
|
-
"
|
|
2485
|
-
|
|
2484
|
+
"_workspace-app-CxwJuZyS.js"
|
|
2485
|
+
],
|
|
2486
|
+
"css": [
|
|
2487
|
+
"assets/workspace-app-ldjBmCJR.css"
|
|
2486
2488
|
]
|
|
2487
2489
|
},
|
|
2488
|
-
"_workspace-app-
|
|
2489
|
-
"file": "assets/workspace-app-
|
|
2490
|
+
"_workspace-app-D6UR0AFl.js": {
|
|
2491
|
+
"file": "assets/workspace-app-D6UR0AFl.js",
|
|
2490
2492
|
"name": "workspace-app",
|
|
2491
2493
|
"imports": [
|
|
2492
|
-
"
|
|
2494
|
+
"_workspace-app-CxwJuZyS.js"
|
|
2493
2495
|
],
|
|
2494
2496
|
"dynamicImports": [
|
|
2495
|
-
"
|
|
2496
|
-
|
|
2497
|
-
"css": [
|
|
2498
|
-
"assets/workspace-app-YnUST8IP.css"
|
|
2497
|
+
"heavy-payload.tsx",
|
|
2498
|
+
"review-payload.tsx"
|
|
2499
2499
|
]
|
|
2500
2500
|
},
|
|
2501
|
-
"_workspace-app-
|
|
2502
|
-
"file": "assets/workspace-app-
|
|
2503
|
-
"src": "_workspace-app-
|
|
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-
|
|
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-
|
|
2526
|
+
"_workspace-app-CxwJuZyS.js"
|
|
2527
2527
|
]
|
|
2528
2528
|
},
|
|
2529
2529
|
"heavy-payload.tsx": {
|
|
2530
|
-
"file": "assets/heavy-payload-
|
|
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-
|
|
2536
|
-
"_workspace-app-
|
|
2535
|
+
"_scrollbar-CbhpdW05.js",
|
|
2536
|
+
"_workspace-app-D6UR0AFl.js"
|
|
2537
2537
|
]
|
|
2538
2538
|
},
|
|
2539
2539
|
"review-payload.tsx": {
|
|
2540
|
-
"file": "assets/review-payload-
|
|
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-
|
|
2546
|
-
"_workspace-app-
|
|
2545
|
+
"_scrollbar-CbhpdW05.js",
|
|
2546
|
+
"_workspace-app-D6UR0AFl.js"
|
|
2547
2547
|
]
|
|
2548
2548
|
},
|
|
2549
2549
|
"workspace-app.html": {
|
|
2550
|
-
"file": "assets/workspace-app-
|
|
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-
|
|
2556
|
-
"_workspace-app-
|
|
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-
|
|
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-
|
|
2566
|
-
"_workspace-app-
|
|
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-
|
|
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-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="./assets/workspace-app-
|
|
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-
|
|
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-
|
|
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};
|