@akira-tl/forgerelay 0.6.1 → 0.7.1
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 +43 -0
- package/README.md +38 -0
- package/capabilities/subagents/GUIDE.md +100 -40
- package/dist/activity/lifecycle.js +1 -1
- package/dist/activity/mcp-query-tools.js +1 -0
- package/dist/activity/query-service.js +1 -0
- package/dist/capabilities.js +1 -1
- package/dist/capability-registry.js +34 -0
- package/dist/cli.js +80 -165
- package/dist/composite-activity.js +155 -0
- package/dist/composite-workspaces.js +197 -0
- package/dist/db/migrations.js +14 -0
- package/dist/db/schema.js +6 -0
- package/dist/remote-workspace-relay.js +16 -0
- package/dist/server.js +698 -172
- package/dist/{local-agent-targets.js → subagents/cli-target.js} +6 -6
- package/dist/{local-agent-profiles.js → subagents/profiles.js} +13 -5
- package/dist/subagents/providers/adapters/acp.js +148 -0
- package/dist/subagents/providers/adapters/claude.js +75 -0
- package/dist/{local-agent-runtime.js → subagents/providers/adapters/codex.js} +10 -4
- package/dist/subagents/providers/adapters/opencode.js +137 -0
- package/dist/subagents/providers/adapters/pi.js +232 -0
- package/dist/{local-agent-availability.js → subagents/providers/availability.js} +24 -10
- package/dist/subagents/providers/continuation.js +11 -0
- package/dist/subagents/providers/contract.js +1 -0
- package/dist/subagents/providers/registry.js +26 -0
- package/dist/subagents/providers/shared.js +40 -0
- package/dist/subagents/sessions/capability.js +214 -0
- package/dist/subagents/sessions/delivery-mailbox.js +115 -0
- package/dist/subagents/sessions/execution.js +171 -0
- package/dist/subagents/sessions/manager.js +107 -0
- package/dist/subagents/sessions/mcp/audit.js +85 -0
- package/dist/subagents/sessions/mcp/runtime.js +19 -0
- package/dist/{local-agent-store.js → subagents/sessions/store.js} +75 -39
- package/dist/ui/.vite/manifest.json +33 -33
- package/dist/ui/activity-panel-app.html +3 -3
- package/dist/ui/assets/{activity-panel-app-CjZVvVNc.js → activity-panel-app-E1ju2dqI.js} +1 -1
- package/dist/ui/assets/{heavy-payload-vGgBRvNX.js → heavy-payload-CeW-n9w5.js} +1 -1
- package/dist/ui/assets/{review-payload-4erWKckt.js → review-payload-B9CO298v.js} +1 -1
- package/dist/ui/assets/{scrollbar-CaOPzUJd.js → scrollbar-C2twAENW.js} +1 -1
- package/dist/ui/assets/workspace-app-BztEvZIC.js +5 -0
- package/dist/ui/assets/{workspace-app-DkAiSl_0.js → workspace-app-CwbJnb_w.js} +1 -1
- package/dist/ui/assets/workspace-app-YnUST8IP.css +1 -0
- package/dist/ui/assets/workspace-app-rKuhdae8.js +1 -0
- package/dist/ui/assets/workspace-lifecycle-app-CEfMdudP.js +1 -0
- package/dist/ui/workspace-app.html +4 -4
- package/dist/ui/workspace-lifecycle-app.html +4 -4
- package/dist/workspaces.js +3 -3
- package/docs/chatgpt-coding-workflow.md +2 -9
- package/docs/configuration.md +23 -0
- package/docs/debugging.md +7 -0
- package/docs/roadmap.md +42 -7
- package/package.json +2 -2
- package/scripts/debug/runtime.mjs +23 -1
- package/scripts/debug/runtime.test.mjs +14 -2
- package/scripts/debug/serve.mjs +4 -4
- package/scripts/release/release-gate.test.mjs +2 -2
- package/dist/local-agent-adapters.js +0 -653
- package/dist/ui/assets/workspace-app-CcrHAUIn.css +0 -1
- package/dist/ui/assets/workspace-app-DJmkPYJC.js +0 -1
- package/dist/ui/assets/workspace-app-QyauBrJX.js +0 -5
- package/dist/ui/assets/workspace-lifecycle-app-BIXEo53I.js +0 -1
- /package/dist/{local-agent-path.js → subagents/providers/path.js} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.forgerelay-panel{border:1px solid var(--tool-card-border);background:var(--tool-card-header-bg);width:100%;color:var(--color-text-primary,#f5f5f6);border-radius:12px;overflow:hidden}.workspace-panel{background:var(--tool-card-header-bg);width:100%}.workspace-panel-header{grid-template-columns:22px minmax(0,1fr) auto;align-items:center;gap:10px;min-height:58px;padding:9px 12px;display:grid}.workspace-panel-icon{background:color-mix(in srgb, var(--tool-accent) 9%, transparent);width:22px;height:22px;color:color-mix(in srgb, var(--tool-accent) 72%, var(--color-text-tertiary,#a3a3aa));border-radius:6px;place-items:center;display:grid}.workspace-panel-icon-svg{stroke-width:1.8px;width:14px;height:14px}.workspace-panel-title-group{gap:2px;min-width:0;display:grid}.workspace-panel-title{font-size:var(--font-text-sm-size,14px);font-weight:600;line-height:1.3}.workspace-panel-subtitle,.workspace-panel-mode{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,11px);line-height:1.35}.workspace-panel-subtitle{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.workspace-panel-mode{border:1px solid color-mix(in srgb, var(--tool-card-divider) 76%, transparent);white-space:nowrap;border-radius:999px;padding:2px 7px}.workspace-panel .workspace-details{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg);max-height:none}.workspace-panel-pending-dot{background:var(--color-text-info,#38bdf8);width:8px;height:8px;box-shadow:0 0 0 3px color-mix(in srgb, var(--color-text-info,#38bdf8) 12%, transparent);border-radius:999px;justify-self:center}.activity-panel{border:1px solid var(--tool-card-border);background:var(--tool-card-header-bg);width:100%;color:var(--color-text-primary,#f5f5f6);border-radius:12px;overflow:hidden}.forgerelay-panel .activity-panel{border:0;border-top:1px solid var(--tool-card-divider);border-radius:0}.activity-panel-header{width:100%;min-height:58px;color:inherit;cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:14px minmax(0,1fr) auto 20px;align-items:center;gap:10px;padding:9px 12px;display:grid}.activity-panel-header:hover{background:var(--tool-card-hover-bg)}.activity-panel-header:focus-visible{outline:2px solid color-mix(in srgb, var(--color-text-info,#38bdf8) 72%, transparent);outline-offset:-2px}.activity-panel-header-pending{cursor:default}.activity-panel-header-pending:hover{background:0 0}.activity-panel-pending-spacer{width:20px}.activity-panel-status{background:var(--color-text-info,#38bdf8);width:8px;height:8px;box-shadow:0 0 0 3px color-mix(in srgb, var(--color-text-info,#38bdf8) 12%, transparent);border-radius:9999px;justify-self:center}.activity-panel-status.state-done{background:var(--color-success-text,#6fda83);box-shadow:0 0 0 3px color-mix(in srgb, var(--color-success-text,#6fda83) 12%, transparent)}.activity-panel-status.state-error{background:var(--color-danger-text,#ee7676);box-shadow:0 0 0 3px color-mix(in srgb, var(--color-danger-text,#ee7676) 12%, transparent)}.activity-panel-title-group{gap:2px;min-width:0;display:grid}.activity-panel-title{font-size:var(--font-text-sm-size,14px);font-weight:600;line-height:1.3}.activity-panel-subtitle,.activity-panel-count{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,11px);line-height:1.35}.activity-panel-count{white-space:nowrap}.activity-panel-body{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg);display:grid}.activity-viewport{overscroll-behavior:contain;max-height:420px;overflow:hidden auto}.activity-list{display:grid}.activity-group+.activity-group{border-top:1px solid var(--tool-card-divider)}.activity-group.grouped>.activity-row.parent{background:color-mix(in srgb, var(--color-background-secondary,#272727) 54%, transparent)}.activity-children{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 72%, transparent);display:grid}.activity-row{--activity-accent:var(--color-text-secondary,#b6b6bd);--activity-phase:var(--color-text-tertiary,#a3a3aa);width:100%;min-height:46px;color:inherit;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:28px minmax(0,1fr) auto 16px;align-items:center;gap:10px;padding:7px 12px;display:grid}.activity-row.interactive{cursor:pointer}.activity-row.interactive:hover{background:var(--tool-card-hover-bg)}.activity-row.interactive:focus-visible{outline:2px solid color-mix(in srgb, var(--activity-accent) 68%, transparent);outline-offset:-2px}.activity-row.child{padding-left:34px;position:relative}.activity-row.child:before{background:color-mix(in srgb, var(--activity-accent) 26%, var(--tool-card-divider));content:"";width:1px;position:absolute;top:0;bottom:0;left:20px}.activity-row.child+.activity-row.child{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 52%, transparent)}.activity-row.kind-read{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 32%, #06b6d4 68%)}.activity-row.kind-write{--activity-accent:var(--color-success-text,#6fda83)}.activity-row.kind-edit,.activity-row.kind-rename{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 28%, #d99742 72%)}.activity-row.kind-delete{--activity-accent:var(--color-danger-text,#ee7676)}.activity-row.kind-shell{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 42%, #64748b 58%)}.activity-row.kind-shell-result{--activity-accent:color-mix(in srgb, var(--color-success-text,#6fda83) 72%, var(--color-text-secondary,#b6b6bd))}.activity-row.kind-capability{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 34%, #3b82f6 66%)}.activity-row.kind-batch{--activity-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 34%, #8b5cf6 66%)}.activity-row.phase-executing{--activity-phase:var(--color-text-info,#38bdf8)}.activity-row.phase-returned{--activity-phase:var(--color-warning-text,#e6b566)}.activity-row.phase-done{--activity-phase:var(--color-success-text,#6fda83)}.activity-row.phase-error{--activity-phase:var(--color-danger-text,#ee7676)}.activity-row.shell-result{box-shadow:inset 2px 0 0 color-mix(in srgb, var(--activity-accent) 68%, transparent)}.activity-icon{border:1px solid color-mix(in srgb, var(--activity-accent) 18%, transparent);background:color-mix(in srgb, var(--activity-accent) 9%, transparent);width:28px;height:28px;color:var(--activity-accent);border-radius:7px;place-items:center;display:grid}.activity-icon-svg{stroke-width:1.8px;width:15px;height:15px}.activity-main{gap:4px;min-width:0;display:grid}.activity-title-line{align-items:baseline;gap:8px;min-width:0;display:flex}.activity-title{color:var(--color-text-primary,#f5f5f6);font-size:var(--font-text-sm-size,12px);flex:none;font-weight:600;line-height:1.35}.activity-member{color:var(--color-text-secondary,#d4d4d8);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,10px);flex:none;line-height:1.4}.activity-target{min-width:0;color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,11px);text-overflow:ellipsis;white-space:nowrap;line-height:1.4;overflow:hidden}.activity-meta{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);font-variant-numeric:tabular-nums;white-space:nowrap;justify-content:flex-end;align-items:center;gap:8px;display:inline-flex}.activity-phase{color:var(--activity-phase);align-items:center;gap:5px;display:inline-flex}.activity-phase:before{content:"";background:currentColor;border-radius:9999px;width:6px;height:6px}.activity-progress-wrap{grid-template-columns:auto minmax(48px,110px);align-items:center;gap:8px;max-width:220px;display:grid}.activity-progress-counts{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);font-variant-numeric:tabular-nums;white-space:nowrap}.activity-progress-track{background:color-mix(in srgb, var(--activity-accent) 14%, var(--tool-card-divider));border-radius:9999px;height:3px;display:block;overflow:hidden}.activity-progress-fill{border-radius:inherit;background:var(--activity-accent);height:100%;display:block}.activity-empty,.activity-refresh-error{color:var(--color-text-secondary,#b7b7bf);font-size:var(--font-text-sm-size,12px);padding:12px}.activity-refresh-error{border-top:1px solid var(--tool-card-divider);color:var(--color-danger-text,#ee7676)}.activity-detail-chevron,.activity-detail-spacer,.activity-detail-chevron.chevron{width:16px;height:16px}.activity-detail-chevron .icon-svg{width:13px;height:13px}.activity-entry.expanded>.activity-row{background:color-mix(in srgb, var(--activity-accent) 6%, transparent)}.activity-detail{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 72%, transparent);background:color-mix(in srgb, var(--color-background-primary,#101114) 90%, transparent);display:grid}.activity-detail-section+.activity-detail-section{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 62%, transparent)}.activity-detail-label{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);letter-spacing:.02em;padding:8px 12px 0;font-weight:600}.activity-detail-section.error .activity-detail-label,.activity-detail-section.error .activity-detail-value{color:var(--color-danger-text,#ee7676)}.activity-detail-value{max-height:260px;color:var(--color-text-secondary,#c7c7ce);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,11px);white-space:pre-wrap;overflow-wrap:break-word;margin:0;padding:6px 12px 10px;line-height:1.5;overflow:auto}.activity-detail-status{color:var(--color-text-secondary,#b7b7bf);font-size:var(--font-text-sm-size,12px);padding:10px 12px}.activity-detail-status.error{color:var(--color-danger-text,#ee7676)}.activity-terminal{background:var(--color-background-primary,#101114)}.activity-terminal-command,.activity-terminal-output{color:var(--color-text-primary,#f5f5f6);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,11px);white-space:pre-wrap;overflow-wrap:break-word;background:0 0;border:0;border-radius:0;margin:0;line-height:1.55}.activity-terminal-command{border-bottom:1px solid color-mix(in srgb, var(--tool-card-divider) 74%, transparent);color:var(--color-text-secondary,#c7c7ce);padding:9px 12px}.activity-terminal-output{max-height:320px;padding:10px 12px;overflow:auto}.activity-terminal-meta{border-top:1px solid color-mix(in srgb, var(--tool-card-divider) 74%, transparent);color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-xs-size,10px);font-variant-numeric:tabular-nums;padding:7px 12px}.activity-terminal-meta.status-running{color:var(--color-text-info,#38bdf8)}.activity-terminal-meta.status-done{color:var(--color-success-text,#6fda83)}.activity-terminal-meta.status-failed{color:var(--color-danger-text,#ee7676)}@media (width<=520px){.activity-panel-header{grid-template-columns:12px minmax(0,1fr) auto 18px;gap:8px;min-height:54px;padding:8px 10px}.activity-panel-subtitle,.activity-panel-count{font-size:10px}.activity-row{grid-template-columns:26px minmax(0,1fr) 18px;gap:6px 8px;min-height:48px;padding:8px 10px}.activity-row.child{padding-left:28px}.activity-row.child:before{left:16px}.activity-icon{align-self:start;width:26px;height:26px}.activity-title-line{gap:2px;display:grid}.activity-meta{grid-column:2;justify-content:flex-start}.activity-detail-chevron,.activity-detail-spacer{grid-area:1/3/span 2}.activity-progress-wrap{grid-template-columns:auto minmax(40px,1fr);max-width:none}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);color:var(--color-text-primary,#f5f5f6);--tool-card-border:color-mix(in srgb, var(--color-border-primary,#414141) 74%, transparent);--tool-card-header-bg:color-mix(in srgb, var(--color-background-secondary,#272727) 88%, transparent);--tool-card-body-bg:color-mix(in srgb, var(--color-background-primary,#181818) 94%, transparent);--tool-card-hover-bg:color-mix(in srgb, var(--color-background-tertiary,#343434) 46%, transparent);--tool-card-divider:color-mix(in srgb, var(--color-border-primary,#414141) 66%, transparent);--tool-accent:var(--color-text-secondary,#b6b6bd);--scrollbar-thumb:color-mix(in srgb, var(--color-text-tertiary,#8a8a8a) 56%, transparent);--scrollbar-thumb-hover:color-mix(in srgb, var(--color-text-secondary,#a8a8a8) 82%, transparent);background:0 0}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}*{box-sizing:border-box}html,body{background:0 0;margin:0;overflow:hidden}.shell{width:100%;padding:0;overflow:hidden}.empty,.tool-card{--tool-accent-soft:color-mix(in srgb, var(--tool-accent) 12%, transparent);border:1px solid var(--tool-card-border);background:var(--tool-card-header-bg);width:100%;box-shadow:none;color:var(--color-text-primary,#f5f5f6);border-radius:12px;overflow:hidden}.tool-card.workspace,.tool-card.directory{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 34%, #3b82f6 66%)}.tool-card.read,.tool-card.search{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 32%, #06b6d4 68%)}.tool-card.write{--tool-accent:var(--color-success-text,#6fda83)}.tool-card.edit,.tool-card.review{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 28%, #d99742 72%)}.tool-card.delete{--tool-accent:var(--color-danger-text,#ee7676)}.tool-card.shell{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 42%, #64748b 58%)}.tool-card.state-success{--tool-accent:var(--color-success-text,#6fda83)}.tool-card.state-error{--tool-accent:var(--color-danger-text,#ee7676)}.tool-card.state-running{--tool-accent:color-mix(in srgb, var(--color-text-primary,#f5f5f6) 30%, #38bdf8 70%)}@supports selector(::-webkit-scrollbar){.pretty-scrollbar::-webkit-scrollbar{width:12px;height:12px}.pretty-scrollbar::-webkit-scrollbar-button{width:0;height:0;display:none}.pretty-scrollbar::-webkit-scrollbar-track{background:0 0}.pretty-scrollbar::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb);background-clip:content-box;border:4px solid #0000;border-radius:9999px}.pretty-scrollbar::-webkit-scrollbar-thumb:hover{background-color:var(--scrollbar-thumb-hover)}.pretty-scrollbar::-webkit-scrollbar-thumb:active{background-color:var(--scrollbar-thumb-hover)}.pretty-scrollbar::-webkit-scrollbar-corner{background:0 0}}.empty{color:var(--color-text-secondary,#b6b6bd);font-size:var(--font-text-sm-size,13px);padding:14px 16px}.tool-header{width:100%;min-height:64px;color:inherit;cursor:pointer;text-align:left;background:0 0;border:0;border-radius:11px;grid-template-columns:40px minmax(0,1fr) auto 20px;align-items:center;gap:12px;padding:10px 12px;display:grid}.tool-header:focus-visible,.review-diff-file-header:focus-visible,.review-more:focus-visible{outline:2px solid color-mix(in srgb, var(--tool-accent) 72%, transparent);outline-offset:-2px}.tool-header:hover:not(:disabled){background:var(--tool-card-hover-bg)}.tool-header:disabled{cursor:default}.tool-icon{border:1px solid color-mix(in srgb, var(--tool-accent) 18%, transparent);background:var(--tool-accent-soft);width:40px;height:40px;color:var(--tool-accent);border-radius:10px;place-items:center;display:grid}.icon-svg{stroke-width:1.8px;width:20px;height:20px;display:block}.tool-main{gap:2px;min-width:0;display:grid}.tool-title{color:var(--color-text-primary,#f5f5f6);font-size:var(--font-text-sm-size,14px);font-weight:550;line-height:1.3}.tool-label{color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,12px);text-overflow:ellipsis;white-space:nowrap;line-height:1.4;overflow:hidden}.stats{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-xs-size,12px);font-variant-numeric:tabular-nums;white-space:nowrap;align-items:center;gap:5px;display:inline-flex}.header-meta{color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-sm-size,12px);text-align:right;white-space:nowrap;line-height:1.35}.header-meta.empty{width:0}.add{color:var(--color-success-text,#6fda83)}.remove{color:var(--color-danger-text,#ee7676)}.chevron{width:20px;height:20px;color:var(--color-text-tertiary,#a3a3aa);border-radius:7px;place-items:center;transition:background .14s,color .14s,transform .14s;display:grid}.tool-header:hover:not(:disabled) .chevron{color:var(--color-text-primary,#f5f5f6)}.chevron .icon-svg{width:15px;height:15px}.chevron.expanded{transform:rotate(180deg)}.chevron.loading{transform:none}.chevron.loading .icon-svg{fill:none;stroke-linecap:round;stroke-dasharray:38 14;animation:.7s linear infinite payload-spinner}@keyframes payload-spinner{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.chevron.loading .icon-svg{animation:none}}.tool-body{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg)}.workspace-details{max-height:420px;display:grid;overflow:auto}.workspace-rows{padding:4px 0;display:grid}.workspace-row{grid-template-columns:22px minmax(116px,.24fr) minmax(0,1fr);align-items:center;gap:10px;min-height:40px;padding:7px 12px;display:grid}.workspace-row-icon{background:color-mix(in srgb, var(--tool-accent) 9%, transparent);width:22px;height:22px;color:color-mix(in srgb, var(--tool-accent) 72%, var(--color-text-tertiary,#a3a3aa));border-radius:6px;place-items:center;display:grid}.workspace-row-icon-svg{stroke-width:1.8px;width:14px;height:14px}.workspace-key{min-height:22px;color:var(--color-text-tertiary,#a3a3aa);font-size:var(--font-text-sm-size,12px);align-items:center;font-weight:500;display:flex}.workspace-value{min-width:0;color:var(--color-text-secondary,#c7c7ce);font-size:var(--font-text-sm-size,12px);text-overflow:ellipsis;white-space:nowrap;line-height:1.45;overflow:hidden}.workspace-value.mono{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace)}.workspace-base-value{align-items:center;gap:7px;min-width:0;display:flex}.workspace-base-value .workspace-value{flex:0 auto}.workspace-base-warning{width:18px;height:18px;color:var(--color-warning-text,#e6b566);cursor:help;flex:none;place-items:center;display:grid}.workspace-base-warning-svg{stroke-width:2px;width:14px;height:14px}.workspace-chip-list{flex-wrap:nowrap;align-items:center;gap:6px;min-width:0;display:flex;overflow:hidden}.workspace-chip{border:1px solid color-mix(in srgb, var(--tool-accent) 16%, var(--tool-card-divider));background:color-mix(in srgb, var(--tool-accent) 7%, transparent);max-width:100%;min-height:24px;color:var(--color-text-secondary,#c7c7ce);text-overflow:ellipsis;white-space:nowrap;border-radius:9999px;flex:none;align-items:center;gap:5px;padding:3px 8px;font-size:11px;line-height:1.25;display:inline-flex;overflow:hidden}.workspace-chip-logo{object-fit:contain;flex:none;width:13px;height:13px;display:block}.workspace-chip-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.workspace-agent-profile{border:0;border-bottom:1px solid color-mix(in srgb, var(--tool-accent) 34%, var(--tool-card-divider));max-width:100%;min-height:24px;color:var(--color-text-secondary,#c7c7ce);white-space:nowrap;background:0 0;border-radius:0;align-items:center;gap:5px;padding:3px 2px 4px;font-size:11px;line-height:1.25;display:inline-flex;overflow:hidden}.workspace-agent-profile-logo{object-fit:contain;flex:none;width:14px;height:14px;display:block}.workspace-agent-profile:hover{border-bottom-color:var(--tool-accent);color:var(--color-text-primary,#f5f5f6)}.workspace-agent-profile.muted{color:var(--color-text-tertiary,#a3a3aa);opacity:.72;border-bottom-style:dashed}.workspace-provider-logo{cursor:help;flex:none;place-items:center;width:20px;height:24px;display:inline-grid}.workspace-provider-logo-image{object-fit:contain;width:16px;height:16px;display:block}.workspace-provider-logo.muted{opacity:.62}.workspace-chip.muted{color:var(--color-text-tertiary,#a3a3aa);opacity:.72;border-style:dashed}.workspace-skills-row,.workspace-instructions-row,.workspace-agents-row{align-items:start}.workspace-skills-list,.workspace-agents-list{flex-wrap:wrap;overflow:visible}.workspace-instruction-status{border-radius:5px;flex:none;place-items:center;width:18px;height:18px;display:grid}.workspace-instruction-status.loaded{background:color-mix(in srgb, var(--color-success-text,#6fda83) 12%, transparent);color:var(--color-success-text,#6fda83)}.workspace-instruction-status.available{background:color-mix(in srgb, var(--color-text-tertiary,#a3a3aa) 9%, transparent);color:var(--color-text-tertiary,#a3a3aa)}.workspace-instruction-status-svg{stroke-width:1.9px;width:12px;height:12px}.workspace-instruction-list{border:1px solid var(--tool-card-divider);background:color-mix(in srgb, var(--tool-card-body-bg) 88%, transparent);border-radius:9px;min-width:0;display:grid;overflow:hidden}.workspace-instructions-content{min-width:0;display:block}.workspace-instructions-toggle{border:0;border-top:1px solid var(--tool-card-divider);background:color-mix(in srgb, var(--tool-card-body-bg) 72%, transparent);width:100%;min-height:32px;color:var(--tool-accent);cursor:pointer;font:inherit;font-size:var(--font-text-sm-size,11px);white-space:nowrap;border-radius:0 0 9px 9px;justify-content:center;align-items:center;padding:6px 10px;font-weight:550;line-height:1.25;display:flex}.workspace-instructions-toggle:hover{background:var(--tool-card-hover-bg)}.workspace-instructions-toggle:focus-visible{outline:2px solid color-mix(in srgb, var(--tool-accent) 72%, transparent);outline-offset:2px}.workspace-instruction-item+.workspace-instruction-item{border-top:1px solid var(--tool-card-divider)}.workspace-instruction-header{width:100%;min-width:0;color:inherit;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:22px minmax(0,1fr) 18px;align-items:center;gap:9px;padding:8px 10px;display:grid}.workspace-instruction-header.interactive{cursor:pointer}.workspace-instruction-header.interactive:hover{background:var(--tool-card-hover-bg)}.workspace-instruction-header.interactive:focus-visible{outline:2px solid color-mix(in srgb, var(--tool-accent) 72%, transparent);outline-offset:-2px}.workspace-instruction-text{gap:2px;min-width:0;display:grid}.workspace-instruction-name{min-width:0;color:var(--color-text-primary,#f5f5f6);font-size:var(--font-text-sm-size,12px);text-overflow:ellipsis;white-space:nowrap;font-weight:550;overflow:hidden}.workspace-instruction-path{min-width:0;color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);text-overflow:ellipsis;white-space:nowrap;font-size:10px;line-height:1.35;overflow:hidden}.workspace-instruction-chevron{width:18px;height:18px;color:var(--color-text-tertiary,#a3a3aa);place-items:center;transition:transform .14s;display:grid}.workspace-instruction-item.expanded .workspace-instruction-chevron{transform:rotate(180deg)}.workspace-instruction-chevron-svg{width:14px;height:14px}.workspace-instruction-preview{border-top:1px solid var(--tool-card-divider);background:color-mix(in srgb, var(--color-background-primary,#101114) 92%, transparent);max-height:300px;color:var(--color-text-secondary,#c7c7ce);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);white-space:pre-wrap;overflow-wrap:break-word;margin:0;padding:10px 12px;font-size:11px;line-height:1.55;overflow:auto}.workspace-instruction-preview[hidden]{display:none}.review-header{grid-template-columns:40px minmax(0,1fr) auto 20px}.review-title-group{gap:3px;min-width:0;display:grid}.review-summary{border-top:1px solid var(--tool-card-divider);background:var(--tool-card-body-bg);display:grid}.review-diff-file-stats{align-items:center;gap:8px;display:flex}.review-empty{color:var(--color-text-secondary,#b7b7bf);font-size:var(--font-text-sm-size,13px)}.review-more{border:0;border-top:1px solid var(--tool-card-divider);width:100%;min-height:40px;color:var(--color-text-tertiary,#a3a3aa);cursor:pointer;font:inherit;font-size:var(--font-text-sm-size,12px);text-align:left;background:0 0;padding:0 12px}.review-more:hover{background:var(--tool-card-hover-bg);color:var(--color-text-primary,#f5f5f6)}.review-diff{max-height:520px;display:grid;overflow:hidden auto}.review-diff-files{gap:0;padding:0;display:grid}.review-diff-file{border:0;border-radius:0;overflow:hidden}.review-diff-file+.review-diff-file{border-top:1px solid var(--tool-card-divider)}.review-diff-file-header{width:100%;min-height:42px;color:var(--color-text-primary,#f5f5f6);cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;grid-template-columns:22px minmax(0,1fr) auto;align-items:center;gap:10px;padding:0 12px;display:grid}.review-file-kind{background:color-mix(in srgb, var(--color-text-tertiary,#a3a3aa) 10%, transparent);width:20px;height:20px;color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);border-radius:6px;align-self:center;place-items:center;font-size:10px;font-weight:700;display:grid}.review-file-kind.added{background:color-mix(in srgb, var(--color-success-text,#6fda83) 12%, transparent);color:var(--color-success-text,#6fda83)}.review-file-kind.edited,.review-file-kind.renamed,.review-file-kind.renamed-edited{background:color-mix(in srgb, var(--color-warning-text,#e6b566) 12%, transparent);color:var(--color-warning-text,#e6b566)}.review-file-kind.deleted{background:color-mix(in srgb, var(--color-danger-text,#ee7676) 12%, transparent);color:var(--color-danger-text,#ee7676)}.review-single-file{overflow:hidden}.review-diff-file-header:hover{background:var(--tool-card-hover-bg)}.review-diff-file-name,.review-diff-file-stats{text-overflow:ellipsis;white-space:nowrap;font-size:13px;line-height:20px;overflow:hidden}.review-diff-file-name{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace)}.review-diff-file-name.renamed{text-overflow:clip;align-items:center;gap:6px;min-width:0;display:flex}.review-diff-file-path{text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:calc(50% - 10px);overflow:hidden}.review-diff-file-path.previous{color:var(--color-text-tertiary,#a3a3aa)}.review-diff-file-path.current{color:var(--color-text-primary,#f5f5f6)}.review-diff-file-arrow{color:var(--color-text-tertiary,#a3a3aa);font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);flex:none}.review-diff-file-stats{font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-sm-size,12px);font-variant-numeric:tabular-nums;justify-content:flex-end;overflow:visible}.status{font-size:var(--font-text-sm-size,12px);padding:10px 12px}.status.muted{color:var(--color-text-secondary,#b7b7bf)}.status.error{color:var(--color-danger-text,#ee7676)}.pierre-diff,.pierre-file{--diffs-bg:var(--tool-payload-bg,var(--color-background-primary,#101114));--diffs-light-bg:var(--color-background-primary,#fff);--diffs-dark-bg:var(--tool-payload-bg,var(--color-background-primary,#101114));--diffs-font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);--diffs-header-font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);--diffs-font-size:var(--font-text-sm-size,12px);--diffs-line-height:20px;border-bottom-right-radius:8px;border-bottom-left-radius:8px;max-height:420px;display:block;overflow:auto}.text-payload{max-height:420px;color:var(--color-text-secondary,#c7c7ce);font-family:var(--font-mono,ui-monospace, SFMono-Regular, monospace);font-size:var(--font-text-sm-size,12px);white-space:pre-wrap;overflow-wrap:break-word;margin:0;padding:10px 12px;line-height:1.55;overflow:auto}.text-payload.bash{color:var(--color-text-primary,#f5f5f6);background:var(--color-background-primary,#101114)}@media (width<=520px){.tool-header{grid-template-columns:36px minmax(0,1fr) auto 18px;gap:9px;min-height:58px;padding:9px 10px}.tool-icon{border-radius:9px;width:36px;height:36px}.chevron{width:18px;height:18px}.review-header{grid-template-columns:36px minmax(0,1fr) auto 18px}.workspace-row{grid-template-columns:22px minmax(0,1fr);gap:2px 8px;padding-block:8px}.workspace-row-icon{grid-row:1/span 2;align-self:start}.workspace-row>.workspace-key,.workspace-row>.workspace-value,.workspace-row>.workspace-chip-list,.workspace-row>.workspace-instructions-content{grid-column:2}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./workspace-app-CwbJnb_w.js";import"./workspace-app-BztEvZIC.js";document.documentElement.dataset.forgerelayApp=`historical-tool-card`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./workspace-app-CwbJnb_w.js";import"./workspace-app-BztEvZIC.js";document.documentElement.dataset.forgerelayApp=`workspace-lifecycle-compatibility`;
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>ForgeRelay Diff</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/workspace-app-
|
|
7
|
+
<script type="module" crossorigin src="./assets/workspace-app-rKuhdae8.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="modulepreload" crossorigin href="./assets/workspace-app-
|
|
11
|
-
<link rel="stylesheet" crossorigin href="./assets/workspace-app-
|
|
9
|
+
<link rel="modulepreload" crossorigin href="./assets/workspace-app-CwbJnb_w.js">
|
|
10
|
+
<link rel="modulepreload" crossorigin href="./assets/workspace-app-BztEvZIC.js">
|
|
11
|
+
<link rel="stylesheet" crossorigin href="./assets/workspace-app-YnUST8IP.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<main id="app" class="shell">
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>ForgeRelay Workspace Lifecycle</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/workspace-lifecycle-app-
|
|
7
|
+
<script type="module" crossorigin src="./assets/workspace-lifecycle-app-CEfMdudP.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="modulepreload" crossorigin href="./assets/workspace-app-
|
|
11
|
-
<link rel="stylesheet" crossorigin href="./assets/workspace-app-
|
|
9
|
+
<link rel="modulepreload" crossorigin href="./assets/workspace-app-CwbJnb_w.js">
|
|
10
|
+
<link rel="modulepreload" crossorigin href="./assets/workspace-app-BztEvZIC.js">
|
|
11
|
+
<link rel="stylesheet" crossorigin href="./assets/workspace-app-YnUST8IP.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<main id="app" class="shell">
|
package/dist/workspaces.js
CHANGED
|
@@ -7,7 +7,7 @@ import { HookRunner } from "./hooks.js";
|
|
|
7
7
|
import { closeManagedWorktree, createManagedWorktree, resolveManagedWorktreeBase, } from "./git-worktrees.js";
|
|
8
8
|
import { AccessDeniedError, assertAllowedPath, isPathInsideRoot, resolveAllowedPath, } from "./roots.js";
|
|
9
9
|
import { loadWorkspaceSkills, markSkillActivated, resolveSkillReadPath, } from "./skills.js";
|
|
10
|
-
import {
|
|
10
|
+
import { loadSubagentProfiles, } from "./subagents/profiles.js";
|
|
11
11
|
const WORKSPACE_STALE_REMINDER_MS = 2 * 24 * 60 * 60 * 1_000;
|
|
12
12
|
const WORKSPACE_SESSION_IDLE_TTL_MS = 30 * 24 * 60 * 60 * 1_000;
|
|
13
13
|
const WORKSPACE_GC_INTERVAL_MS = 60 * 60 * 1_000;
|
|
@@ -634,7 +634,7 @@ export class WorkspaceRegistry {
|
|
|
634
634
|
async reusedWorkspaceContext(workspace) {
|
|
635
635
|
Object.assign(workspace, this.loadSkillsForWorkspace(workspace.root));
|
|
636
636
|
workspace.capabilityGuides = loadCapabilityGuides(this.config);
|
|
637
|
-
workspace.agentProfiles = await
|
|
637
|
+
workspace.agentProfiles = await loadSubagentProfiles(this.config, workspace.root);
|
|
638
638
|
workspace.scannedInstructionDirs.clear();
|
|
639
639
|
workspace.knownInstructionPathsByDir.clear();
|
|
640
640
|
workspace.loadedInstructionRealPaths.clear();
|
|
@@ -800,7 +800,7 @@ export class WorkspaceRegistry {
|
|
|
800
800
|
worktree: input.worktree,
|
|
801
801
|
...this.loadSkillsForWorkspace(input.root),
|
|
802
802
|
capabilityGuides: loadCapabilityGuides(this.config),
|
|
803
|
-
agentProfiles: await
|
|
803
|
+
agentProfiles: await loadSubagentProfiles(this.config, input.root),
|
|
804
804
|
activatedSkillDirs: new Set(),
|
|
805
805
|
activatedCapabilityGuideDirs: new Set(),
|
|
806
806
|
scannedInstructionDirs: new Set(),
|
|
@@ -235,16 +235,9 @@ ForgeRelay-owned `subagents` capability guide when delegation is actually needed
|
|
|
235
235
|
new setups. Existing user-authored or previously seeded Skills remain normal
|
|
236
236
|
user configuration and are not deleted.
|
|
237
237
|
|
|
238
|
-
|
|
238
|
+
Host 正常委派通过现有 `capability` Gateway 中的 `subagent.session` 完成,不增加新的 Core MCP tool。支持的生命周期操作包括 `start`、`resume`、`status`、`list`、`stop` 和 `delete`;具体参数与 provider continuation 能力以 `subagents` capability guide 为准。
|
|
239
239
|
|
|
240
|
-
|
|
241
|
-
forgerelay agents ls
|
|
242
|
-
forgerelay agents run <profile-or-provider-or-id> "<prompt>"
|
|
243
|
-
forgerelay agents show <id>
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
A first-class MCP subagent interface is planned so this CLI indirection can be
|
|
247
|
-
removed.
|
|
240
|
+
`forgerelay agents` CLI 继续保留给本地诊断和兼容场景,但 first-class MCP 路径不会通过 `bash -> forgerelay agents ...` 间接执行。Subagent Session 绑定实际 Execution Workspace,provider 原生 session/thread 保存 conversation history,ForgeRelay 只持久化必要的 ownership、continuation 和当前执行协调元数据。
|
|
248
241
|
|
|
249
242
|
## Tool modes
|
|
250
243
|
|
package/docs/configuration.md
CHANGED
|
@@ -305,6 +305,25 @@ switching a logical workspace therefore does not by itself cause unchanged proje
|
|
|
305
305
|
context to be injected again, while changed context produces a new fingerprint and
|
|
306
306
|
is delivered on the next `auto` open.
|
|
307
307
|
|
|
308
|
+
Composite Workspaces use the same `open_workspace` entry point with
|
|
309
|
+
`kind="composite"` and a human-readable `name`. They have no filesystem root of
|
|
310
|
+
their own and may contain zero or more named members. Member management also stays
|
|
311
|
+
on `open_workspace` through `action="member"`; an added member either references an
|
|
312
|
+
existing `workspaceId` or reuses the normal local/managed/relay Workspace open
|
|
313
|
+
definition (`path`, optional `relay`, `mode`, and worktree options). Every Composite
|
|
314
|
+
open returns its `kind`, name, and member purposes regardless of
|
|
315
|
+
`context="auto"|"full"|"none"`. To receive one member's heavy project bootstrap,
|
|
316
|
+
reopen the Composite with `memberName=<name>`; this does not create an implicit
|
|
317
|
+
current member. Core work calls against a Composite require an explicit `member`
|
|
318
|
+
and retain the `cws_...` ID as the Host-facing Workspace identity.
|
|
319
|
+
|
|
320
|
+
Composite member purpose text is descriptive only. ForgeRelay never routes by tool
|
|
321
|
+
type, hardware role, load, or availability, and a missing/offline member never falls
|
|
322
|
+
back to another member or local execution. Member filesystems, Git state, processes,
|
|
323
|
+
Hooks, Skills, language services, and Activity facts remain owned by the underlying
|
|
324
|
+
Workspace. The Composite Activity Panel only aggregates their presentation into one
|
|
325
|
+
Host Turn.
|
|
326
|
+
|
|
308
327
|
Use `open_workspace(action="list")` only when the Agent needs to continue an older
|
|
309
328
|
logical workspace, choose among multiple handles, or organize workspace state. The
|
|
310
329
|
inventory is paginated (50 records by default, at most 100) and can filter by
|
|
@@ -321,6 +340,10 @@ or externally removed managed-worktree root can therefore remain diagnostically
|
|
|
321
340
|
files. For a managed-worktree-backed workspace, `close_workspace` requires
|
|
322
341
|
`commitMessage` and runs the existing safe worktree finalize lifecycle: close Hooks,
|
|
323
342
|
commit when needed, fast-forward-only integration, cleanup, and alias invalidation.
|
|
343
|
+
For a Composite Workspace, the same tool means dissolve: it removes only the
|
|
344
|
+
Composite identity, membership, and Composite-facing panel/lifecycle state. It does
|
|
345
|
+
not close members, finalize member worktrees, interrupt member processes, delete
|
|
346
|
+
files, or remove remote registrations and relayed Workspace routes.
|
|
324
347
|
|
|
325
348
|
Hot workspace/session activity timestamps are coalesced in memory and flushed to the
|
|
326
349
|
SQLite state database in a transaction at most every five minutes; normal shutdown
|
package/docs/debugging.md
CHANGED
|
@@ -50,6 +50,13 @@ To relocate the entire interactive debug config explicitly, use:
|
|
|
50
50
|
FORGERELAY_DEBUG_CONFIG_DIR=/path/to/debug-config npm run dev
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
The selected debug config is authoritative for its own `host` and `port`; the
|
|
54
|
+
launcher reports endpoints derived from that file instead of assuming `7677`.
|
|
55
|
+
This makes parallel isolated instances straightforward: give each instance its
|
|
56
|
+
own config, state, and worktree directories and configure different ports (for
|
|
57
|
+
example `7677` for a Gateway and `6768` for an Execution ForgeRelay), then launch
|
|
58
|
+
each with its own `FORGERELAY_DEBUG_CONFIG_DIR`.
|
|
59
|
+
|
|
53
60
|
## Run a local MCP Apps Host
|
|
54
61
|
|
|
55
62
|
Use MCP Inspector as the fast local Host for MCP App/resource iteration:
|
package/docs/roadmap.md
CHANGED
|
@@ -250,16 +250,51 @@ fake-LSP coverage remains the primary cross-platform protocol/lifecycle gate, wh
|
|
|
250
250
|
`rust-analyzer`, `gopls`, and `clangd` only when those external executables are
|
|
251
251
|
already present and otherwise reports explicit skips without installing them.
|
|
252
252
|
|
|
253
|
-
## 0.5 —
|
|
253
|
+
## 0.5 — Durable Activity and batch execution
|
|
254
254
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
255
|
+
0.5 established the execution-history substrate used by the later MCP App and
|
|
256
|
+
multi-workspace features:
|
|
257
|
+
|
|
258
|
+
- immutable local Audit Events and restart-safe Activity Records;
|
|
259
|
+
- durable Bash output plus late `bash_result` delivery;
|
|
260
|
+
- Host Turn snapshots with lazy detail/output queries for MCP Apps;
|
|
261
|
+
- native bulk read/edit/delete and heterogeneous `batch.execute` orchestration;
|
|
262
|
+
- parent/child Activity relationships and bounded capability batch policies;
|
|
263
|
+
- Windows-safe Activity/SQLite cleanup and release-test hardening.
|
|
264
|
+
|
|
265
|
+
Activity remains an observation of semantic ForgeRelay operations rather than a
|
|
266
|
+
second task/session runtime. Files, processes, Git state, and audit truth continue
|
|
267
|
+
to belong to the Workspace that actually executes the operation.
|
|
268
|
+
|
|
269
|
+
## 0.6 — Host UI, Workspace Relay, and Composite Workspace
|
|
270
|
+
|
|
271
|
+
0.6 turned the Activity substrate into a Host-facing multi-environment workflow:
|
|
258
272
|
|
|
259
|
-
|
|
273
|
+
- **0.6.0** — one ForgeRelay Panel per Host Turn, MCP Inspector/debug lifecycle,
|
|
274
|
+
virtual `skills://` loading, bounded process waits, and release-candidate support;
|
|
275
|
+
- **0.6.1** — Workspace Relay, authenticated direct/SSH-routed remote execution,
|
|
276
|
+
restart-safe relay identity/routes, and remote Activity/bootstrap forwarding;
|
|
277
|
+
- **0.6.2** — Composite Workspace as a first-class Workspace kind with named local,
|
|
278
|
+
managed-worktree, and relayed members, explicit member routing, aggregated
|
|
279
|
+
Composite Activity, and `close_workspace` dissolution that preserves members.
|
|
280
|
+
|
|
281
|
+
The 0.6 contract keeps execution ownership explicit: Gateway ForgeRelay presents
|
|
282
|
+
and routes; the selected member Workspace and its Execution ForgeRelay own files,
|
|
283
|
+
Git state, processes, Hooks, Skills, Language services, Activity, and Audit facts.
|
|
284
|
+
Workspace Relay is not file synchronization or failover, and Composite Workspace
|
|
285
|
+
never silently chooses a member.
|
|
286
|
+
|
|
287
|
+
## Later: first-class subagent MCP
|
|
288
|
+
|
|
289
|
+
ForgeRelay already owns provider adapters and resumable local agent sessions. A
|
|
290
|
+
future release may remove the current `bash -> forgerelay agents ...` indirection
|
|
291
|
+
for MCP hosts.
|
|
260
292
|
|
|
261
|
-
|
|
262
|
-
|
|
293
|
+
First-class subagent operations should reuse the Capability Gateway rather than
|
|
294
|
+
add another top-level MCP tool. The parent agent should continue choosing from
|
|
295
|
+
available provider/profile metadata while ForgeRelay owns provider-backed worker
|
|
296
|
+
lifecycle state. This remains provider-backed delegation, not an attempt to
|
|
297
|
+
emulate a Host-native subagent implementation.
|
|
263
298
|
|
|
264
299
|
## Worktree and history refinements
|
|
265
300
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akira-tl/forgerelay",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Local development control plane for MCP coding agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://github.com/Akira-TL/forgerelay#readme",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"release:publish": "node scripts/release/publish.mjs",
|
|
48
48
|
"postinstall": "node scripts/fix-node-pty-permissions.mjs",
|
|
49
49
|
"start": "node dist/cli.js serve",
|
|
50
|
-
"test": "node --test scripts/debug/runtime.test.mjs scripts/release-proof.test.mjs scripts/release/release-gate.test.mjs scripts/release/release-version.test.mjs && tsx src/oauth/router.test.ts && tsx src/remote-auth-cli.test.ts && tsx src/remote-ssh-auth-cli.test.ts && tsx src/remote-workspace-relay.test.ts && tsx src/remote-workspace-relay-process.test.ts && tsx src/config.test.ts && tsx src/lsp/language-server-config.test.ts && tsx src/lsp/normalization/hover.test.ts && tsx src/lsp/references.server.test.ts && tsx src/lsp/operations/document-symbols.server.test.ts && tsx src/lsp/operations/workspace-symbols.server.test.ts && tsx src/lsp/operations/diagnostics-push.server.test.ts && tsx src/lsp/operations/diagnostics-pull.server.test.ts && tsx src/lsp/operations/request-hardening.server.test.ts && tsx src/lsp/operations/recovery.server.test.ts && tsx src/lsp/operations/lifecycle.server.test.ts && tsx src/lsp/runtime/semantic-requests.test.ts && tsx src/logger.test.ts && tsx src/proxy-trust.test.ts && tsx src/mcp-app-template.test.ts && tsx src/hooks.test.ts && tsx src/capability-registry.test.ts && tsx src/mcp/server-instructions.test.ts && tsx src/request-meta.test.ts && tsx src/incoming-artifacts.test.ts && tsx src/artifact-download.test.ts && tsx src/ui/card-types.test.ts && tsx src/ui/workspace-lifecycle-app.test.ts && tsx src/ui/activity/model.test.ts && tsx src/ui/patch-display.test.ts && tsx src/ui/tool-display.test.ts && tsx src/apply-patch.test.ts && tsx src/process-platform.test.ts && tsx src/process-sessions.test.ts && tsx src/mcp-sessions.test.ts && tsx src/server-shutdown.test.ts && tsx src/
|
|
50
|
+
"test": "node --test scripts/debug/runtime.test.mjs scripts/release-proof.test.mjs scripts/release/release-gate.test.mjs scripts/release/release-version.test.mjs && tsx src/oauth/router.test.ts && tsx src/remote-auth-cli.test.ts && tsx src/remote-ssh-auth-cli.test.ts && tsx src/remote-workspace-relay.test.ts && tsx src/remote-workspace-relay-process.test.ts && tsx src/config.test.ts && tsx src/lsp/language-server-config.test.ts && tsx src/lsp/normalization/hover.test.ts && tsx src/lsp/references.server.test.ts && tsx src/lsp/operations/document-symbols.server.test.ts && tsx src/lsp/operations/workspace-symbols.server.test.ts && tsx src/lsp/operations/diagnostics-push.server.test.ts && tsx src/lsp/operations/diagnostics-pull.server.test.ts && tsx src/lsp/operations/request-hardening.server.test.ts && tsx src/lsp/operations/recovery.server.test.ts && tsx src/lsp/operations/lifecycle.server.test.ts && tsx src/lsp/runtime/semantic-requests.test.ts && tsx src/logger.test.ts && tsx src/proxy-trust.test.ts && tsx src/mcp-app-template.test.ts && tsx src/hooks.test.ts && tsx src/capability-registry.test.ts && tsx src/mcp/server-instructions.test.ts && tsx src/request-meta.test.ts && tsx src/incoming-artifacts.test.ts && tsx src/artifact-download.test.ts && tsx src/ui/card-types.test.ts && tsx src/ui/workspace-lifecycle-app.test.ts && tsx src/ui/activity/model.test.ts && tsx src/ui/patch-display.test.ts && tsx src/ui/tool-display.test.ts && tsx src/apply-patch.test.ts && tsx src/process-platform.test.ts && tsx src/process-sessions.test.ts && tsx src/mcp-sessions.test.ts && tsx src/server-shutdown.test.ts && tsx src/subagents/providers/adapters/codex.test.ts && tsx src/subagents/providers/registry.test.ts && tsx src/subagents/providers/availability.test.ts && tsx src/subagents/profiles.test.ts && tsx src/subagents/cli-target.test.ts && tsx src/subagents/sessions/store.test.ts && tsx src/subagents/sessions/manager.test.ts && tsx src/subagents/sessions/mcp/capability.server.test.ts && tsx src/subagents/sessions/mcp/continuation.server.test.ts && tsx src/roots.test.ts && tsx src/file-mutations.test.ts && tsx src/operations/edit-preflight.test.ts && tsx src/skills.test.ts && tsx src/db/migrations.test.ts && tsx src/workspace-store.test.ts && tsx src/activity/audit-store.test.ts && tsx src/activity/bash-output-store.test.ts && tsx src/activity/lifecycle.test.ts && tsx src/activity/query-service.test.ts && tsx src/operations/core-operation-executor.test.ts && tsx src/operations/bulk-mutation.test.ts && tsx src/operations/batch/scheduler.test.ts && tsx src/operations/batch/executor-policy.test.ts && tsx src/workspaces.test.ts && tsx src/workspace-conversation.test.ts && tsx src/review-checkpoints.test.ts && tsx src/lsp/code-intelligence.server.test.ts && npm run build:app && tsx src/server.test.ts && tsx src/oauth-store.test.ts && tsx src/cli.test.ts",
|
|
51
51
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
52
52
|
"release:check": "node scripts/release-version.mjs check",
|
|
53
53
|
"release:tag-check": "node scripts/release-version.mjs tag",
|
|
@@ -22,6 +22,27 @@ export function interactiveDebugConfigDir({ env = process.env, home = homedir()
|
|
|
22
22
|
return resolve(join(home, ".forgerelay", "debug"));
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export function interactiveDebugUrls(configDir) {
|
|
26
|
+
let config = {};
|
|
27
|
+
try {
|
|
28
|
+
config = JSON.parse(readFileSync(join(configDir, "config.json"), "utf8"));
|
|
29
|
+
} catch {
|
|
30
|
+
// Keep the historical debug defaults when the selected config has not been created yet.
|
|
31
|
+
}
|
|
32
|
+
const configuredHost = typeof config.host === "string" && config.host.trim()
|
|
33
|
+
? config.host.trim()
|
|
34
|
+
: "127.0.0.1";
|
|
35
|
+
const host = configuredHost === "0.0.0.0" || configuredHost === "::"
|
|
36
|
+
? "127.0.0.1"
|
|
37
|
+
: configuredHost;
|
|
38
|
+
const port = Number.isInteger(config.port) && config.port > 0 && config.port <= 65_535
|
|
39
|
+
? config.port
|
|
40
|
+
: 7677;
|
|
41
|
+
const displayHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
42
|
+
const baseUrl = `http://${displayHost}:${port}`;
|
|
43
|
+
return { baseUrl, mcpUrl: `${baseUrl}/mcp` };
|
|
44
|
+
}
|
|
45
|
+
|
|
25
46
|
function interactiveDebugOwnerToken(configDir) {
|
|
26
47
|
const authPath = join(configDir, "auth.json");
|
|
27
48
|
let auth;
|
|
@@ -45,6 +66,7 @@ export function createInteractiveDebugEnvironment({
|
|
|
45
66
|
} = {}) {
|
|
46
67
|
const configDir = interactiveDebugConfigDir({ env, home });
|
|
47
68
|
const ownerToken = interactiveDebugOwnerToken(configDir);
|
|
69
|
+
const { baseUrl, mcpUrl } = interactiveDebugUrls(configDir);
|
|
48
70
|
mkdirSync(debugRoot, { recursive: true });
|
|
49
71
|
|
|
50
72
|
const debugEnv = { ...env };
|
|
@@ -67,7 +89,7 @@ export function createInteractiveDebugEnvironment({
|
|
|
67
89
|
}
|
|
68
90
|
debugEnv.FORGERELAY_CONFIG_DIR = configDir;
|
|
69
91
|
|
|
70
|
-
return { ownerToken, configDir, env: debugEnv };
|
|
92
|
+
return { ownerToken, configDir, baseUrl, mcpUrl, env: debugEnv };
|
|
71
93
|
}
|
|
72
94
|
|
|
73
95
|
export function createDebugEnvironment({
|
|
@@ -4,7 +4,11 @@ import { tmpdir } from "node:os";
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import test from "node:test";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
createInteractiveDebugEnvironment,
|
|
9
|
+
interactiveDebugConfigDir,
|
|
10
|
+
interactiveDebugUrls,
|
|
11
|
+
} from "./runtime.mjs";
|
|
8
12
|
|
|
9
13
|
async function withDebugConfig(t) {
|
|
10
14
|
const home = await mkdtemp(join(tmpdir(), "forgerelay-interactive-debug-"));
|
|
@@ -45,6 +49,12 @@ test("interactive debug uses one dedicated persisted config under ~/.forgerelay/
|
|
|
45
49
|
assert.equal(result.ownerToken, "debug-owner-password-123456");
|
|
46
50
|
assert.equal(result.configDir, configDir);
|
|
47
51
|
assert.equal(result.env.FORGERELAY_CONFIG_DIR, configDir);
|
|
52
|
+
assert.equal(result.baseUrl, "http://127.0.0.1:7677");
|
|
53
|
+
assert.equal(result.mcpUrl, "http://127.0.0.1:7677/mcp");
|
|
54
|
+
assert.deepEqual(interactiveDebugUrls(configDir), {
|
|
55
|
+
baseUrl: "http://127.0.0.1:7677",
|
|
56
|
+
mcpUrl: "http://127.0.0.1:7677/mcp",
|
|
57
|
+
});
|
|
48
58
|
assert.equal(result.env.HOST, undefined);
|
|
49
59
|
assert.equal(result.env.PORT, undefined);
|
|
50
60
|
assert.equal(result.env.FORGERELAY_PUBLIC_BASE_URL, undefined);
|
|
@@ -60,7 +70,7 @@ test("interactive debug config directory may be explicitly relocated without fal
|
|
|
60
70
|
const { home } = await withDebugConfig(t);
|
|
61
71
|
const customDir = join(home, "custom-debug-config");
|
|
62
72
|
await mkdir(customDir, { recursive: true });
|
|
63
|
-
await writeFile(join(customDir, "config.json"), "
|
|
73
|
+
await writeFile(join(customDir, "config.json"), JSON.stringify({ host: "127.0.0.1", port: 6768 }) + "\n");
|
|
64
74
|
await writeFile(join(customDir, "auth.json"), JSON.stringify({ ownerToken: "custom-debug-password-123456" }) + "\n");
|
|
65
75
|
|
|
66
76
|
const result = createInteractiveDebugEnvironment({
|
|
@@ -71,4 +81,6 @@ test("interactive debug config directory may be explicitly relocated without fal
|
|
|
71
81
|
assert.equal(result.configDir, customDir);
|
|
72
82
|
assert.equal(result.ownerToken, "custom-debug-password-123456");
|
|
73
83
|
assert.equal(result.env.FORGERELAY_CONFIG_DIR, customDir);
|
|
84
|
+
assert.equal(result.baseUrl, "http://127.0.0.1:6768");
|
|
85
|
+
assert.equal(result.mcpUrl, "http://127.0.0.1:6768/mcp");
|
|
74
86
|
});
|
package/scripts/debug/serve.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
import { createInteractiveDebugEnvironment,
|
|
2
|
+
import { createInteractiveDebugEnvironment, repoRoot } from "./runtime.mjs";
|
|
3
3
|
|
|
4
|
-
const { configDir, env } = createInteractiveDebugEnvironment();
|
|
4
|
+
const { configDir, baseUrl, mcpUrl, env } = createInteractiveDebugEnvironment();
|
|
5
5
|
|
|
6
6
|
console.error("[forgerelay:debug] local debug server");
|
|
7
7
|
console.error(`[forgerelay:debug] debug config: ${configDir}/config.json`);
|
|
8
|
-
console.error(`[forgerelay:debug] health: ${
|
|
9
|
-
console.error(`[forgerelay:debug] MCP: ${
|
|
8
|
+
console.error(`[forgerelay:debug] health: ${baseUrl}/healthz`);
|
|
9
|
+
console.error(`[forgerelay:debug] MCP: ${mcpUrl}`);
|
|
10
10
|
console.error(`[forgerelay:debug] Owner password loaded from ${configDir}/auth.json`);
|
|
11
11
|
console.error("[forgerelay:debug] all runtime state is under .forgerelay-debug/");
|
|
12
12
|
|
|
@@ -79,7 +79,7 @@ test("release runtime and local parity share the checked-in Node contract", asyn
|
|
|
79
79
|
test("cloud verification produces one reusable npm package on Linux", async () => {
|
|
80
80
|
const workflow = await readFile(resolve(repoRoot, ".github/workflows/ci.yml"), "utf8");
|
|
81
81
|
assert.match(workflow, /if:\s*runner\.os == 'Linux'[\s\S]*run:\s*npm run release:pack/);
|
|
82
|
-
assert.match(workflow, /uses:\s*actions\/upload-artifact@
|
|
82
|
+
assert.match(workflow, /uses:\s*actions\/upload-artifact@v7/);
|
|
83
83
|
assert.match(workflow, /name:\s*npm-package/);
|
|
84
84
|
assert.match(workflow, /include-hidden-files:\s*true/);
|
|
85
85
|
assert.match(workflow, /overwrite:\s*true/);
|
|
@@ -89,7 +89,7 @@ test("release workflow is tag-only and promotes the verified npm artifact withou
|
|
|
89
89
|
const workflow = await readFile(resolve(repoRoot, ".github/workflows/release.yml"), "utf8");
|
|
90
90
|
assert.doesNotMatch(workflow, /workflow_dispatch:/);
|
|
91
91
|
assert.match(workflow, /needs:\s*verify/);
|
|
92
|
-
assert.match(workflow, /uses:\s*actions\/download-artifact@
|
|
92
|
+
assert.match(workflow, /uses:\s*actions\/download-artifact@v7/);
|
|
93
93
|
assert.match(workflow, /name:\s*npm-package/);
|
|
94
94
|
assert.match(workflow, /run:\s*npm run release:publish/);
|
|
95
95
|
assert.match(workflow, /npm install --global npm@11\.19\.1/);
|