@theihtisham/agent-shadow-brain 7.1.3 → 7.1.4
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 +20 -0
- package/README.md +125 -90
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/brain/activity-journal.d.ts.map +1 -1
- package/dist/brain/activity-journal.js +2 -1
- package/dist/brain/activity-journal.js.map +1 -1
- package/dist/brain/auto-update.js +1 -1
- package/dist/brain/brain-portability.js +1 -1
- package/dist/brain/client-config.d.ts +19 -0
- package/dist/brain/client-config.d.ts.map +1 -0
- package/dist/brain/client-config.js +40 -0
- package/dist/brain/client-config.js.map +1 -0
- package/dist/brain/client-integrations.d.ts +2 -0
- package/dist/brain/client-integrations.d.ts.map +1 -1
- package/dist/brain/client-integrations.js +8 -27
- package/dist/brain/client-integrations.js.map +1 -1
- package/dist/brain/context-assembly.d.ts +10 -2
- package/dist/brain/context-assembly.d.ts.map +1 -1
- package/dist/brain/context-assembly.js +238 -14
- package/dist/brain/context-assembly.js.map +1 -1
- package/dist/brain/context-request.d.ts +4 -0
- package/dist/brain/context-request.d.ts.map +1 -0
- package/dist/brain/context-request.js +22 -0
- package/dist/brain/context-request.js.map +1 -0
- package/dist/brain/context-retrieval.d.ts +88 -0
- package/dist/brain/context-retrieval.d.ts.map +1 -0
- package/dist/brain/context-retrieval.js +300 -0
- package/dist/brain/context-retrieval.js.map +1 -0
- package/dist/brain/feature-settings.d.ts.map +1 -1
- package/dist/brain/feature-settings.js +2 -1
- package/dist/brain/feature-settings.js.map +1 -1
- package/dist/brain/file-identity.d.ts +4 -0
- package/dist/brain/file-identity.d.ts.map +1 -0
- package/dist/brain/file-identity.js +27 -0
- package/dist/brain/file-identity.js.map +1 -0
- package/dist/brain/global-brain.d.ts +11 -1
- package/dist/brain/global-brain.d.ts.map +1 -1
- package/dist/brain/global-brain.js +58 -6
- package/dist/brain/global-brain.js.map +1 -1
- package/dist/brain/mcp-server.d.ts +9 -0
- package/dist/brain/mcp-server.d.ts.map +1 -1
- package/dist/brain/mcp-server.js +237 -53
- package/dist/brain/mcp-server.js.map +1 -1
- package/dist/brain/mcp-stdio.d.ts.map +1 -1
- package/dist/brain/mcp-stdio.js +10 -4
- package/dist/brain/mcp-stdio.js.map +1 -1
- package/dist/brain/memory-annotations.d.ts.map +1 -1
- package/dist/brain/memory-annotations.js +2 -1
- package/dist/brain/memory-annotations.js.map +1 -1
- package/dist/brain/memory-inspection.d.ts +72 -0
- package/dist/brain/memory-inspection.d.ts.map +1 -0
- package/dist/brain/memory-inspection.js +131 -0
- package/dist/brain/memory-inspection.js.map +1 -0
- package/dist/brain/memory-mcp-content.d.ts +44 -0
- package/dist/brain/memory-mcp-content.d.ts.map +1 -0
- package/dist/brain/memory-mcp-content.js +91 -0
- package/dist/brain/memory-mcp-content.js.map +1 -0
- package/dist/brain/orchestrator.js +1 -1
- package/dist/brain/project-feedback.d.ts +63 -0
- package/dist/brain/project-feedback.d.ts.map +1 -0
- package/dist/brain/project-feedback.js +289 -0
- package/dist/brain/project-feedback.js.map +1 -0
- package/dist/brain/project-hub-contract.d.ts +326 -0
- package/dist/brain/project-hub-contract.d.ts.map +1 -0
- package/dist/brain/project-hub-contract.js +56 -0
- package/dist/brain/project-hub-contract.js.map +1 -0
- package/dist/brain/project-hub-mcp.d.ts +168 -0
- package/dist/brain/project-hub-mcp.d.ts.map +1 -0
- package/dist/brain/project-hub-mcp.js +41 -0
- package/dist/brain/project-hub-mcp.js.map +1 -0
- package/dist/brain/project-hub-pdf-worker.d.ts +13 -0
- package/dist/brain/project-hub-pdf-worker.d.ts.map +1 -0
- package/dist/brain/project-hub-pdf-worker.js +84 -0
- package/dist/brain/project-hub-pdf-worker.js.map +1 -0
- package/dist/brain/project-hub-store.d.ts +38 -0
- package/dist/brain/project-hub-store.d.ts.map +1 -0
- package/dist/brain/project-hub-store.js +189 -0
- package/dist/brain/project-hub-store.js.map +1 -0
- package/dist/brain/project-hub.d.ts +127 -0
- package/dist/brain/project-hub.d.ts.map +1 -0
- package/dist/brain/project-hub.js +381 -0
- package/dist/brain/project-hub.js.map +1 -0
- package/dist/brain/project-kit-inspection.d.ts +28 -0
- package/dist/brain/project-kit-inspection.d.ts.map +1 -0
- package/dist/brain/project-kit-inspection.js +200 -0
- package/dist/brain/project-kit-inspection.js.map +1 -0
- package/dist/brain/project-kit-paths.d.ts +13 -0
- package/dist/brain/project-kit-paths.d.ts.map +1 -0
- package/dist/brain/project-kit-paths.js +141 -0
- package/dist/brain/project-kit-paths.js.map +1 -0
- package/dist/brain/project-kit.d.ts +41 -0
- package/dist/brain/project-kit.d.ts.map +1 -0
- package/dist/brain/project-kit.js +255 -0
- package/dist/brain/project-kit.js.map +1 -0
- package/dist/brain/project-memory.d.ts +38 -0
- package/dist/brain/project-memory.d.ts.map +1 -0
- package/dist/brain/project-memory.js +76 -0
- package/dist/brain/project-memory.js.map +1 -0
- package/dist/brain/subconscious.js +2 -2
- package/dist/brain/subconscious.js.map +1 -1
- package/dist/brain/workflow-skills.d.ts.map +1 -1
- package/dist/brain/workflow-skills.js +3 -2
- package/dist/brain/workflow-skills.js.map +1 -1
- package/dist/cli.js +22 -3
- package/dist/cli.js.map +1 -1
- package/dist/context-cli.d.ts.map +1 -1
- package/dist/context-cli.js +39 -5
- package/dist/context-cli.js.map +1 -1
- package/dist/dashboard/brain-hub-actions.d.ts +2 -0
- package/dist/dashboard/brain-hub-actions.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-actions.js +137 -0
- package/dist/dashboard/brain-hub-actions.js.map +1 -0
- package/dist/dashboard/brain-hub-client.d.ts +2 -0
- package/dist/dashboard/brain-hub-client.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-client.js +335 -0
- package/dist/dashboard/brain-hub-client.js.map +1 -0
- package/dist/dashboard/brain-hub-graph.d.ts +2 -0
- package/dist/dashboard/brain-hub-graph.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-graph.js +176 -0
- package/dist/dashboard/brain-hub-graph.js.map +1 -0
- package/dist/dashboard/brain-hub-html.d.ts +2 -0
- package/dist/dashboard/brain-hub-html.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-html.js +30 -0
- package/dist/dashboard/brain-hub-html.js.map +1 -0
- package/dist/dashboard/brain-hub-project-views.d.ts +2 -0
- package/dist/dashboard/brain-hub-project-views.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-project-views.js +79 -0
- package/dist/dashboard/brain-hub-project-views.js.map +1 -0
- package/dist/dashboard/brain-hub-views.d.ts +2 -0
- package/dist/dashboard/brain-hub-views.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-views.js +150 -0
- package/dist/dashboard/brain-hub-views.js.map +1 -0
- package/dist/dashboard/demo-workspace.d.ts +11 -0
- package/dist/dashboard/demo-workspace.d.ts.map +1 -0
- package/dist/dashboard/demo-workspace.js +178 -0
- package/dist/dashboard/demo-workspace.js.map +1 -0
- package/dist/dashboard/live-workspace-html.d.ts.map +1 -1
- package/dist/dashboard/live-workspace-html.js +177 -28
- package/dist/dashboard/live-workspace-html.js.map +1 -1
- package/dist/dashboard/project-feedback-html.d.ts +5 -0
- package/dist/dashboard/project-feedback-html.d.ts.map +1 -0
- package/dist/dashboard/project-feedback-html.js +216 -0
- package/dist/dashboard/project-feedback-html.js.map +1 -0
- package/dist/dashboard/project-hub-api.d.ts +5 -0
- package/dist/dashboard/project-hub-api.d.ts.map +1 -0
- package/dist/dashboard/project-hub-api.js +121 -0
- package/dist/dashboard/project-hub-api.js.map +1 -0
- package/dist/dashboard/project-kit-html.d.ts +4 -0
- package/dist/dashboard/project-kit-html.d.ts.map +1 -0
- package/dist/dashboard/project-kit-html.js +359 -0
- package/dist/dashboard/project-kit-html.js.map +1 -0
- package/dist/dashboard/project-workspace.d.ts +16 -0
- package/dist/dashboard/project-workspace.d.ts.map +1 -0
- package/dist/dashboard/project-workspace.js +106 -0
- package/dist/dashboard/project-workspace.js.map +1 -0
- package/dist/dashboard/server.d.ts +1 -0
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +15 -4
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/v6-dashboard-html.d.ts +1 -1
- package/dist/dashboard/v6-dashboard-html.d.ts.map +1 -1
- package/dist/dashboard/v6-dashboard-html.js +27 -27
- package/dist/dashboard/workspace-api.d.ts +6 -0
- package/dist/dashboard/workspace-api.d.ts.map +1 -1
- package/dist/dashboard/workspace-api.js +154 -34
- package/dist/dashboard/workspace-api.js.map +1 -1
- package/dist/dashboard/workspace-html.d.ts.map +1 -1
- package/dist/dashboard/workspace-html.js +487 -81
- package/dist/dashboard/workspace-html.js.map +1 -1
- package/dist/dashboard/workspace-status.d.ts +50 -0
- package/dist/dashboard/workspace-status.d.ts.map +1 -0
- package/dist/dashboard/workspace-status.js +22 -0
- package/dist/dashboard/workspace-status.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/integration-cli.d.ts.map +1 -1
- package/dist/integration-cli.js +6 -4
- package/dist/integration-cli.js.map +1 -1
- package/dist/project-cli.d.ts +3 -0
- package/dist/project-cli.d.ts.map +1 -0
- package/dist/project-cli.js +100 -0
- package/dist/project-cli.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/COMPARISON.md +22 -0
- package/docs/COMPONENTS.md +66 -0
- package/docs/CONTEXT_LAB.md +79 -0
- package/docs/FEATURES_AND_LIMITS.md +24 -0
- package/docs/INTEGRATIONS.md +68 -0
- package/docs/LEARNING.md +46 -0
- package/docs/PROJECT_KIT.md +93 -0
- package/docs/QUICKSTART.md +44 -0
- package/docs/README.md +33 -0
- package/docs/ROADMAP-v7.md +147 -0
- package/docs/SHARING.md +13 -0
- package/docs/SHOWCASE.md +87 -0
- package/docs/STATS.md +21 -0
- package/docs/TROUBLESHOOTING.md +42 -0
- package/docs/UPGRADE_PLAN_v7.0.0.md +203 -0
- package/docs/VIRAL-PLAYBOOK.md +259 -0
- package/docs/VISUAL_GUIDE_v7.1.4.md +70 -0
- package/docs/WORKFLOW_INTEGRATION.md +19 -1
- package/docs/WORKSPACE.md +17 -91
- package/docs/assets/7.1.4-collaboration-design-preview.png +0 -0
- package/docs/assets/7.1.4-comparison.png +0 -0
- package/docs/assets/7.1.4-context-lab.png +0 -0
- package/docs/assets/7.1.4-control-room-dense-preview.png +0 -0
- package/docs/assets/7.1.4-control-room-focus-preview.png +0 -0
- package/docs/assets/7.1.4-features.png +0 -0
- package/docs/assets/7.1.4-graph.png +0 -0
- package/docs/assets/7.1.4-hub-control-room.png +0 -0
- package/docs/assets/7.1.4-hub-empty.png +0 -0
- package/docs/assets/7.1.4-hub-knowledge.png +0 -0
- package/docs/assets/7.1.4-hub-learning.png +0 -0
- package/docs/assets/7.1.4-hub-mobile.png +0 -0
- package/docs/assets/7.1.4-hub-public-docs-source.png +0 -0
- package/docs/assets/7.1.4-hub-public-docs.gif +0 -0
- package/docs/assets/7.1.4-hub-public-docs.png +0 -0
- package/docs/assets/7.1.4-hub-setup.png +0 -0
- package/docs/assets/7.1.4-hub-walkthrough.gif +0 -0
- package/docs/assets/7.1.4-integrations.png +0 -0
- package/docs/assets/7.1.4-knowledge-design-preview.png +0 -0
- package/docs/assets/7.1.4-learning-design-preview.png +0 -0
- package/docs/assets/7.1.4-learning.png +0 -0
- package/docs/assets/7.1.4-live.png +0 -0
- package/docs/assets/7.1.4-memory-review.png +0 -0
- package/docs/assets/7.1.4-mobile.png +0 -0
- package/docs/assets/7.1.4-models-design-preview.png +0 -0
- package/docs/assets/7.1.4-outcome-ranking.png +0 -0
- package/docs/assets/7.1.4-overview.png +0 -0
- package/docs/assets/7.1.4-project-kit.png +0 -0
- package/docs/assets/7.1.4-project-skill-preview.png +0 -0
- package/docs/assets/7.1.4-replay.png +0 -0
- package/docs/assets/7.1.4-setup-design-preview.png +0 -0
- package/docs/assets/7.1.4-usage-design-preview.png +0 -0
- package/docs/assets/context-v7.1.3.png +0 -0
- package/docs/assets/features-v7.1.3.png +0 -0
- package/docs/assets/graph-v7.1.3.png +0 -0
- package/docs/assets/integrations-v7.1.3.png +0 -0
- package/docs/assets/live-v7.1.4.gif +0 -0
- package/docs/evaluation/CONTEXT_EVALUATION_v7.1.4.json +1818 -0
- package/docs/evaluation/CONTEXT_EVALUATION_v7.1.4.md +36 -0
- package/docs/launch/COMPONENT_MAP_v7.1.4.md +307 -0
- package/docs/launch/PROJECT_KIT_PLAN_v7.1.4.md +110 -0
- package/docs/launch/PROJECT_LEARNING_PLAN_v7.1.4.md +63 -0
- package/docs/launch/RELEASE_NOTES_v7.1.4.md +30 -0
- package/docs/launch/RESEARCH_AND_PLAN_v7.1.4.md +255 -0
- package/package.json +25 -7
- package/skills/shadow-research/SKILL.md +2 -0
- package/skills/shadow-workflow/SKILL.md +6 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/** Project Kit uses the same local workspace shell and HTTP helpers. */
|
|
2
|
+
import { PROJECT_FEEDBACK_MARKUP, PROJECT_FEEDBACK_SCRIPT, PROJECT_FEEDBACK_STYLE } from './project-feedback-html.js';
|
|
3
|
+
export const PROJECT_KIT_STYLE = String.raw `
|
|
4
|
+
html[data-project-local="true"] .advanced-link { display: none; }
|
|
5
|
+
.project-local-notice { display: none; }
|
|
6
|
+
html[data-project-local="true"] .project-local-notice { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; padding: 8px 12px; margin-bottom: 16px; border-radius: 7px; background: var(--tint); color: var(--project); font-size: .83rem; }
|
|
7
|
+
.project-local-notice a { font-weight: 680; text-decoration: underline; text-underline-offset: 3px; }
|
|
8
|
+
.kit-identity { display: grid; grid-template-columns: minmax(150px,.8fr) minmax(0,1.2fr); align-items: center; gap: 16px; padding: 18px 20px; border-radius: 10px; color: var(--instrument-ink); background: var(--instrument); }
|
|
9
|
+
.kit-identity p { color: var(--instrument-muted); margin-top: 5px; }
|
|
10
|
+
.kit-identity .mono { color: var(--instrument-ink); }
|
|
11
|
+
.kit-identity dl { display: grid; gap: 6px; min-width: 0; }
|
|
12
|
+
.kit-identity dt { color: var(--instrument-muted); font-size: .78rem; }
|
|
13
|
+
.kit-identity dd { margin-top: 1px; }
|
|
14
|
+
.kit-identity summary { cursor: pointer; color: var(--signal); margin-top: 5px; }
|
|
15
|
+
.kit-identity details[open] > summary { margin-bottom: 6px; }
|
|
16
|
+
.kit-layout { grid-template-columns: minmax(280px,.88fr) minmax(0,1.25fr); }
|
|
17
|
+
.kit-form { display: grid; gap: 12px; }
|
|
18
|
+
.kit-form .button { justify-self: start; }
|
|
19
|
+
.kit-fields { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 8px; }
|
|
20
|
+
.kit-form-status { min-width: 0; }
|
|
21
|
+
.kit-form-status:empty { display: none; }
|
|
22
|
+
.kit-profile { display: grid; gap: 11px; }
|
|
23
|
+
.kit-profile summary { cursor: pointer; color: var(--teal); font-weight: 650; }
|
|
24
|
+
.kit-profile details[open] > summary { margin-bottom: 6px; }
|
|
25
|
+
.kit-evidence, .kit-checks { max-height: 300px; overflow: auto; }
|
|
26
|
+
.kit-evidence li, .kit-checks li { padding: 7px 0; }
|
|
27
|
+
.kit-evidence .tags { margin-top: 4px; }
|
|
28
|
+
.kit-checks .form-actions { margin-top: 3px; }
|
|
29
|
+
.kit-preview { border-top: 1px solid var(--line); min-width: 0; }
|
|
30
|
+
.kit-preview > .panel-head { background: var(--inset); }
|
|
31
|
+
.kit-preview-file { display: grid; gap: 8px; min-width: 0; }
|
|
32
|
+
.kit-file-header { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 6px; }
|
|
33
|
+
.kit-preview-file .context-preview { max-height: 440px; }
|
|
34
|
+
.kit-apply-controls { border-top: 1px solid var(--line); }
|
|
35
|
+
.kit-apply-controls .form-actions { margin-bottom: 6px; }
|
|
36
|
+
.kit-applied-list { padding-left: 18px; margin-top: 5px; }
|
|
37
|
+
@media (max-width: 985px) { .kit-layout { grid-template-columns: minmax(0,1fr); } }
|
|
38
|
+
@media (max-width: 690px) {
|
|
39
|
+
.kit-identity { grid-template-columns: minmax(0,1fr); gap: 10px; padding: 13px 14px; }
|
|
40
|
+
.kit-preview { scroll-margin-top: 55px; }
|
|
41
|
+
}
|
|
42
|
+
${PROJECT_FEEDBACK_STYLE}
|
|
43
|
+
`;
|
|
44
|
+
export const PROJECT_KIT_MARKUP = String.raw `
|
|
45
|
+
<section id="page-project-kit" aria-labelledby="title-project-kit" hidden>
|
|
46
|
+
<div class="page-head">
|
|
47
|
+
<div><h1 id="title-project-kit" tabindex="-1">Project Kit</h1><p class="muted">Inspect this project, save knowledge, and prepare a skill for a coding agent.</p></div>
|
|
48
|
+
<button class="button" type="button" id="kit-refresh" hidden><span data-icon="refresh"></span>Refresh profile</button>
|
|
49
|
+
</div>
|
|
50
|
+
<div id="kit-gate" class="panel" role="status"></div>
|
|
51
|
+
<div id="kit-workbench" class="stack" hidden>
|
|
52
|
+
<section id="kit-identity" class="kit-identity" aria-label="Pinned project and storage"></section>
|
|
53
|
+
<div class="split kit-layout">
|
|
54
|
+
<div class="stack">
|
|
55
|
+
<section class="panel" aria-labelledby="kit-profile-heading">
|
|
56
|
+
<div class="panel-head"><h2 id="kit-profile-heading">Observed project profile</h2></div>
|
|
57
|
+
<div id="kit-profile" aria-busy="true"></div>
|
|
58
|
+
</section>
|
|
59
|
+
<section class="panel" aria-labelledby="kit-knowledge-heading">
|
|
60
|
+
<div class="panel-head"><div><h2 id="kit-knowledge-heading">Project knowledge</h2><p class="small muted">Record a decision, constraint, or lesson you want agents to recall.</p></div></div>
|
|
61
|
+
<form class="panel-body kit-form" id="kit-knowledge-form">
|
|
62
|
+
<label class="label" for="kit-knowledge-title">Title<input id="kit-knowledge-title" maxlength="160" required placeholder="Retry rules for checkout"></label>
|
|
63
|
+
<label class="label" for="kit-knowledge-content">Knowledge<textarea id="kit-knowledge-content" maxlength="8000" rows="4" required placeholder="Describe the rule and when it applies."></textarea></label>
|
|
64
|
+
<div class="kit-fields">
|
|
65
|
+
<label class="label" for="kit-knowledge-category">Category <span class="small muted">Optional</span><input id="kit-knowledge-category" maxlength="64" pattern="[A-Za-z0-9][A-Za-z0-9 _.\-]*" placeholder="knowledge"></label>
|
|
66
|
+
<label class="label" for="kit-knowledge-source">Source reference <span class="small muted">Optional</span><input id="kit-knowledge-source" maxlength="500" placeholder="docs/checkout.md"></label>
|
|
67
|
+
</div>
|
|
68
|
+
<button class="button primary" type="submit" id="kit-knowledge-save"><span data-icon="memory"></span>Save knowledge</button>
|
|
69
|
+
<div class="kit-form-status" id="kit-knowledge-status" role="status"></div>
|
|
70
|
+
</form>
|
|
71
|
+
</section>
|
|
72
|
+
</div>
|
|
73
|
+
<section class="panel" aria-labelledby="kit-skill-heading">
|
|
74
|
+
<div class="panel-head"><div><h2 id="kit-skill-heading">Skill builder</h2><p class="small muted">Describe the workflow, then review the generated file before applying it.</p></div></div>
|
|
75
|
+
<form class="panel-body kit-form" id="kit-skill-form">
|
|
76
|
+
<label class="label" for="kit-requirement">Requirement<textarea id="kit-requirement" rows="4" maxlength="8000" required placeholder="When a checkout retry changes, verify idempotency and add a regression case."></textarea></label>
|
|
77
|
+
<div class="kit-fields">
|
|
78
|
+
<label class="label" for="kit-target">Agent target<select id="kit-target"><option value="codex">Codex</option><option value="claude-code">Claude Code</option><option value="opencode">OpenCode</option><option value="deepseek-harness">DeepSeek Harness</option><option value="portable">Portable</option></select></label>
|
|
79
|
+
<label class="label" for="kit-skill-name">Skill name<input id="kit-skill-name" maxlength="63" pattern="[a-z0-9]+(?:-[a-z0-9]+)*" placeholder="Generated from requirement"></label>
|
|
80
|
+
</div>
|
|
81
|
+
<label class="label" for="kit-skill-knowledge">Supporting knowledge <span class="small muted">Optional reference material</span><textarea id="kit-skill-knowledge" maxlength="8000" rows="3" placeholder="Add the project rule or evidence the skill should carry."></textarea></label>
|
|
82
|
+
<button class="button primary" type="submit" id="kit-preview-submit"><span data-icon="context"></span>Preview skill</button>
|
|
83
|
+
</form>
|
|
84
|
+
<section class="kit-preview" id="kit-preview" aria-labelledby="kit-preview-heading">
|
|
85
|
+
<div class="panel-head"><h3 id="kit-preview-heading" tabindex="-1">Skill preview</h3><span id="kit-preview-state" class="small muted" role="status"></span></div>
|
|
86
|
+
<div id="kit-preview-body"></div>
|
|
87
|
+
<div class="panel-body kit-apply-controls" id="kit-apply-controls" hidden>
|
|
88
|
+
<div class="form-actions"><button class="button primary" type="button" id="kit-apply"><span data-icon="plus"></span>Apply local skill</button></div>
|
|
89
|
+
<p class="small muted">Writes the displayed project-relative file. Confirm the path and content above.</p>
|
|
90
|
+
<div class="kit-form-status" id="kit-apply-status" role="status"></div>
|
|
91
|
+
</div>
|
|
92
|
+
</section>
|
|
93
|
+
</section>
|
|
94
|
+
</div>
|
|
95
|
+
${PROJECT_FEEDBACK_MARKUP}
|
|
96
|
+
</div>
|
|
97
|
+
</section>
|
|
98
|
+
`;
|
|
99
|
+
export const PROJECT_KIT_SCRIPT = String.raw `
|
|
100
|
+
const kit = { profile: null, profileLoading: false, saving: false, savedKnowledge: '', preview: null, previewInput: null,
|
|
101
|
+
previewing: false, applying: false, dirty: false, previewError: '', applied: null };
|
|
102
|
+
|
|
103
|
+
function renderKitIdentity(info) {
|
|
104
|
+
const root = String(info.root || '').replace(/\\/g, '/').replace(/\/$/, '') + '/';
|
|
105
|
+
const storage = String(info.storagePath || '').replace(/\\/g, '/');
|
|
106
|
+
const relativeStorage = storage.startsWith(root) ? storage.slice(root.length) : 'Project-local store';
|
|
107
|
+
$('kit-identity').innerHTML = '<div><h2>' + esc(info.projectName || info.projectId) + '</h2><p class="small">Project-local memory and skills</p>' +
|
|
108
|
+
'<button class="button quiet kit-outcomes-jump" type="button" id="kit-outcomes-jump">Record a memory outcome ' + icon('chevron', true) + '</button></div>' +
|
|
109
|
+
'<div><p class="small">Memory store</p><code class="mono">' + esc(relativeStorage) + '</code><details><summary class="small">Show full paths</summary>' +
|
|
110
|
+
'<dl><div><dt>Project root</dt><dd class="mono">' + esc(info.root) + '</dd></div><div><dt>Memory store</dt><dd class="mono">' +
|
|
111
|
+
esc(info.storagePath) + '</dd></div></dl></details></div>';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function renderKitProfile(profile) {
|
|
115
|
+
const coverage = profile.coverage || {};
|
|
116
|
+
const entries = list(profile.evidence);
|
|
117
|
+
const checks = list(profile.checks);
|
|
118
|
+
const findings = entries.map((entry) => '<li><strong class="mono">' + esc(entry.path) + '</strong>' +
|
|
119
|
+
tags([['project', nice(entry.kind)], ...list(entry.signals).map((signal) => ['memory', signal])]) + '</li>').join('');
|
|
120
|
+
const commands = checks.map((check) => '<li><strong>' + esc(check.label) + '</strong><p class="small muted">' +
|
|
121
|
+
esc(check.source) + '</p>' + commandMarkup(check.command) + '</li>').join('');
|
|
122
|
+
$('kit-profile').innerHTML = '<div class="panel-body kit-profile"><p class="small muted">Observed ' + dateMarkup(profile.observedAt, true) +
|
|
123
|
+
' · ' + number(coverage.entries) + ' entries inspected' + (coverage.truncated ? ' (inspection limit reached)' : '') + '.</p>' +
|
|
124
|
+
'<div><h3>Detected stack</h3>' + (list(profile.stack).length ? tags(profile.stack.map((value) => ['project', value])) :
|
|
125
|
+
'<p class="small muted">No supported stack markers found.</p>') + '</div>' +
|
|
126
|
+
(list(profile.packageManagers).length ? '<div><h3>Package managers</h3>' + tags(profile.packageManagers.map((value) => ['memory', value])) + '</div>' : '') +
|
|
127
|
+
(findings ? '<details open><summary>File evidence · ' + number(entries.length) + '</summary><ul class="list kit-evidence">' + findings + '</ul></details>' : '') +
|
|
128
|
+
(commands ? '<details><summary>Suggested project checks · ' + number(checks.length) + '</summary><ul class="list kit-checks">' + commands + '</ul></details>' : '') +
|
|
129
|
+
list(profile.warnings).map((warning) => '<p class="small muted">' + esc(warning) + '</p>').join('') + '</div>';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function loadProjectKit(force = false) {
|
|
133
|
+
const gate = $('kit-gate');
|
|
134
|
+
const workbench = $('kit-workbench');
|
|
135
|
+
if (!state.overviewLoaded) {
|
|
136
|
+
gate.hidden = false;
|
|
137
|
+
gate.innerHTML = skeleton('Checking project workspace…');
|
|
138
|
+
await loadOverview();
|
|
139
|
+
}
|
|
140
|
+
if (!state.overviewLoaded) {
|
|
141
|
+
gate.innerHTML = errorMarkup('Could not check the project workspace.', 'kit-profile');
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const info = state.projectKit;
|
|
145
|
+
const enabled = info?.available === true;
|
|
146
|
+
workbench.hidden = !enabled;
|
|
147
|
+
$('kit-refresh').hidden = !enabled;
|
|
148
|
+
gate.hidden = enabled;
|
|
149
|
+
if (!enabled) {
|
|
150
|
+
gate.innerHTML = blank('project', 'Start a project workspace', 'Run this command from the project folder to use Project Kit with a project-local store.',
|
|
151
|
+
commandMarkup('shadow-brain project workspace .'));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
renderKitIdentity(info);
|
|
155
|
+
void loadProjectFeedback();
|
|
156
|
+
const focusMemory = state.view === 'project-kit' ? routeParams().get('memory') || '' : '';
|
|
157
|
+
if (focusMemory || outcomes.project !== info.projectId) void loadFeedbackMemories(focusMemory);
|
|
158
|
+
if (focusMemory && (document.activeElement === $('title-project-kit') || document.activeElement === document.body)) openOutcomeEditor();
|
|
159
|
+
if (kit.profileLoading || kit.profile && !force) return;
|
|
160
|
+
kit.profileLoading = true;
|
|
161
|
+
const target = $('kit-profile');
|
|
162
|
+
$('kit-refresh').disabled = true;
|
|
163
|
+
target.innerHTML = skeleton('Inspecting the pinned project…');
|
|
164
|
+
setBusy(target, true);
|
|
165
|
+
try {
|
|
166
|
+
const profile = await api('project-profile');
|
|
167
|
+
if (profile.projectId !== info.projectId) throw new Error('The server returned a different project profile.');
|
|
168
|
+
kit.profile = profile;
|
|
169
|
+
renderKitProfile(profile);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
kit.profile = null;
|
|
172
|
+
target.innerHTML = errorMarkup(error.message, 'kit-profile');
|
|
173
|
+
} finally {
|
|
174
|
+
kit.profileLoading = false;
|
|
175
|
+
$('kit-refresh').disabled = false;
|
|
176
|
+
setBusy(target, false);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function saveKitKnowledge() {
|
|
181
|
+
if (kit.saving || state.projectKit?.available !== true) return;
|
|
182
|
+
const title = $('kit-knowledge-title').value.trim();
|
|
183
|
+
const content = $('kit-knowledge-content').value;
|
|
184
|
+
const category = $('kit-knowledge-category').value.trim();
|
|
185
|
+
const source = $('kit-knowledge-source').value.trim();
|
|
186
|
+
if (!title || !content.trim()) {
|
|
187
|
+
$('kit-knowledge-status').innerHTML = errorMarkup('Enter a title and knowledge text.');
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const form = $('kit-knowledge-form');
|
|
191
|
+
const status = $('kit-knowledge-status');
|
|
192
|
+
const button = $('kit-knowledge-save');
|
|
193
|
+
kit.saving = true;
|
|
194
|
+
button.disabled = true;
|
|
195
|
+
status.textContent = 'Saving to the project store…';
|
|
196
|
+
try {
|
|
197
|
+
const result = await api('project-knowledge', { body: { title, content, ...(category ? { category } : {}), ...(source ? { source } : {}) } });
|
|
198
|
+
if (!result.ok || !result.memoryId || result.projectId !== state.projectKit.projectId) throw new Error('The server returned an unreadable saved memory.');
|
|
199
|
+
kit.savedKnowledge = [title, content, source ? 'Recorded reference: ' + source : ''].filter(Boolean).join('\n\n');
|
|
200
|
+
if ($('kit-knowledge-title').value.trim() === title && $('kit-knowledge-content').value === content &&
|
|
201
|
+
$('kit-knowledge-category').value.trim() === category && $('kit-knowledge-source').value.trim() === source) form.reset();
|
|
202
|
+
state.overviewLoaded = false;
|
|
203
|
+
state.graph.snapshot = null;
|
|
204
|
+
void loadFeedbackMemories();
|
|
205
|
+
if (state.context.pack || state.context.pending) {
|
|
206
|
+
state.context.dirty = true;
|
|
207
|
+
if (!state.context.pending) renderContext();
|
|
208
|
+
}
|
|
209
|
+
status.innerHTML = '<div class="stack"><p class="small">Saved as user-provided project knowledge.</p><div class="form-actions">' +
|
|
210
|
+
memoryLink(result.memoryId, result.projectId, 'View saved memory') + '<button class="button quiet" type="button" id="kit-use-knowledge">Use in skill</button>' +
|
|
211
|
+
'<a class="button quiet" href="' + esc(routeLink('context', { project: result.projectId })) + '">Open Context Lab ' + icon('chevron', true) +
|
|
212
|
+
'</a></div><p class="small muted" id="kit-use-status" role="status"></p></div>';
|
|
213
|
+
} catch (error) {
|
|
214
|
+
status.innerHTML = errorMarkup(error.message);
|
|
215
|
+
} finally {
|
|
216
|
+
kit.saving = false;
|
|
217
|
+
button.disabled = false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function useKitKnowledge() {
|
|
222
|
+
const status = $('kit-use-status');
|
|
223
|
+
const field = $('kit-skill-knowledge');
|
|
224
|
+
if (!status || !kit.savedKnowledge) return;
|
|
225
|
+
if (field.value.includes(kit.savedKnowledge)) {
|
|
226
|
+
status.textContent = 'This knowledge is already in the skill draft.';
|
|
227
|
+
field.focus();
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const next = [field.value, kit.savedKnowledge].filter((value) => value.trim()).join('\n\n');
|
|
231
|
+
if (next.length > field.maxLength) {
|
|
232
|
+
status.textContent = 'The skill draft exceeds 8,000 characters. Use a shorter excerpt from the saved memory.';
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
field.value = next;
|
|
236
|
+
field.dispatchEvent(new Event('input', { bubbles: true }));
|
|
237
|
+
status.textContent = 'Added to the skill draft as reference material.';
|
|
238
|
+
field.focus();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const kitFileStates = { create: ['ok', 'Ready to create'], update: ['ok', 'Ready to update'], unchanged: ['', 'Already current'], conflict: ['warn', 'Protected file'] };
|
|
242
|
+
const kitApplyStates = { created: 'Created', updated: 'Updated', unchanged: 'Already current' };
|
|
243
|
+
|
|
244
|
+
function renderKitPreview() {
|
|
245
|
+
const target = $('kit-preview-body');
|
|
246
|
+
const status = $('kit-preview-state');
|
|
247
|
+
const files = list(kit.preview?.files);
|
|
248
|
+
const conflict = files.some((file) => file.status === 'conflict');
|
|
249
|
+
const ready = !!kit.preview && files.length > 0;
|
|
250
|
+
const controls = $('kit-apply-controls');
|
|
251
|
+
controls.hidden = !ready;
|
|
252
|
+
$('kit-apply').disabled = !ready || conflict || kit.dirty || kit.applying || !!kit.applied;
|
|
253
|
+
$('kit-preview-submit').disabled = kit.previewing || kit.applying;
|
|
254
|
+
$('kit-preview').setAttribute('aria-busy', String(kit.previewing || kit.applying));
|
|
255
|
+
if (kit.previewing) {
|
|
256
|
+
status.textContent = 'Generating preview';
|
|
257
|
+
target.innerHTML = skeleton('Building the exact file preview…');
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (kit.previewError) {
|
|
261
|
+
status.textContent = 'Preview failed';
|
|
262
|
+
target.innerHTML = errorMarkup(kit.previewError);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (!ready) {
|
|
266
|
+
status.textContent = '';
|
|
267
|
+
target.innerHTML = blank('context', 'Ready to preview', 'Enter a requirement and choose an agent target.');
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
status.textContent = kit.dirty ? 'Preview out of date' : conflict ? 'Protected file' : kit.applied ? 'Applied locally' : kit.applying ? 'Applying' : 'Ready to review';
|
|
271
|
+
const preview = kit.preview;
|
|
272
|
+
const warnings = list(preview.warnings).map((warning) => '<p class="small muted">' + esc(warning) + '</p>').join('');
|
|
273
|
+
const stale = kit.dirty ? '<p class="status small" role="status">Preview again to review the current file plan.</p>' : '';
|
|
274
|
+
target.innerHTML = '<div class="panel-body stack">' + stale + warnings + files.map((file) => {
|
|
275
|
+
const [tone, label] = kitFileStates[file.status] || ['', 'Review'];
|
|
276
|
+
return '<div class="kit-preview-file"><div class="kit-file-header"><strong class="mono">' + esc(file.relativePath) +
|
|
277
|
+
'</strong><span class="tag check-' + tone + '">' + label + '</span></div>' +
|
|
278
|
+
(file.reason ? '<p class="small muted">' + esc(file.reason) + '</p>' : '') +
|
|
279
|
+
'<pre class="context-preview mono" tabindex="0" aria-label="Generated skill file">' + esc(file.content) + '</pre></div>';
|
|
280
|
+
}).join('') + '</div>';
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async function previewKitSkill() {
|
|
284
|
+
if (kit.previewing || kit.applying || state.projectKit?.available !== true) return;
|
|
285
|
+
const requirement = $('kit-requirement').value;
|
|
286
|
+
const target = $('kit-target').value;
|
|
287
|
+
const name = $('kit-skill-name').value.trim();
|
|
288
|
+
const knowledge = $('kit-skill-knowledge').value;
|
|
289
|
+
if (!requirement.trim()) {
|
|
290
|
+
kit.previewError = 'Enter a requirement for the skill.';
|
|
291
|
+
renderKitPreview();
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const body = { requirement, target, ...(name ? { name } : {}), ...(knowledge.trim() ? { knowledge } : {}) };
|
|
295
|
+
kit.previewing = true;
|
|
296
|
+
kit.preview = null;
|
|
297
|
+
kit.previewInput = body;
|
|
298
|
+
kit.previewError = '';
|
|
299
|
+
kit.applied = null;
|
|
300
|
+
kit.dirty = false;
|
|
301
|
+
$('kit-apply-status').replaceChildren();
|
|
302
|
+
renderKitPreview();
|
|
303
|
+
try {
|
|
304
|
+
const preview = await api('project-skill-preview', { body });
|
|
305
|
+
if (preview.projectId !== state.projectKit.projectId || !preview.planHash || !list(preview.files).length) {
|
|
306
|
+
throw new Error('The server returned an unreadable skill preview.');
|
|
307
|
+
}
|
|
308
|
+
kit.preview = preview;
|
|
309
|
+
} catch (error) {
|
|
310
|
+
kit.previewError = error.message;
|
|
311
|
+
} finally {
|
|
312
|
+
kit.previewing = false;
|
|
313
|
+
renderKitPreview();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async function applyKitSkill() {
|
|
318
|
+
if (!kit.preview || !kit.previewInput || kit.dirty || kit.applying || kit.applied ||
|
|
319
|
+
list(kit.preview.files).some((file) => file.status === 'conflict') || state.projectKit?.available !== true) return;
|
|
320
|
+
const status = $('kit-apply-status');
|
|
321
|
+
kit.applying = true;
|
|
322
|
+
status.textContent = 'Applying the reviewed plan…';
|
|
323
|
+
renderKitPreview();
|
|
324
|
+
try {
|
|
325
|
+
const result = await api('project-skill-apply', { body: { ...kit.previewInput, expectedPlanHash: kit.preview.planHash } });
|
|
326
|
+
if (result.projectId !== state.projectKit.projectId || !list(result.files).length) throw new Error('The server returned an unreadable apply result.');
|
|
327
|
+
kit.applied = result;
|
|
328
|
+
status.innerHTML = '<p class="small">Skill saved in this project.</p><ul class="kit-applied-list small">' + result.files.map((file) =>
|
|
329
|
+
'<li>' + esc(kitApplyStates[file.status] || nice(file.status)) + ' <code class="mono">' + esc(file.relativePath) + '</code></li>').join('') + '</ul>' +
|
|
330
|
+
list(result.warnings).map((warning) => '<p class="small muted">' + esc(warning) + '</p>').join('');
|
|
331
|
+
} catch (error) {
|
|
332
|
+
if (error.status === 409) kit.dirty = true;
|
|
333
|
+
status.innerHTML = errorMarkup(error.message);
|
|
334
|
+
} finally {
|
|
335
|
+
kit.applying = false;
|
|
336
|
+
renderKitPreview();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
$('kit-refresh').addEventListener('click', () => { void loadProjectKit(true); });
|
|
341
|
+
$('kit-identity').addEventListener('click', (event) => {
|
|
342
|
+
if (event.target.closest('#kit-outcomes-jump')) openOutcomeEditor();
|
|
343
|
+
});
|
|
344
|
+
$('kit-knowledge-form').addEventListener('submit', (event) => { event.preventDefault(); void saveKitKnowledge(); });
|
|
345
|
+
$('kit-knowledge-status').addEventListener('click', (event) => {
|
|
346
|
+
if (event.target.closest('#kit-use-knowledge')) useKitKnowledge();
|
|
347
|
+
});
|
|
348
|
+
$('kit-skill-form').addEventListener('submit', (event) => { event.preventDefault(); void previewKitSkill(); });
|
|
349
|
+
$('kit-skill-form').addEventListener('input', () => {
|
|
350
|
+
if (kit.previewInput && !kit.dirty) {
|
|
351
|
+
kit.dirty = true;
|
|
352
|
+
renderKitPreview();
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
$('kit-apply').addEventListener('click', () => { void applyKitSkill(); });
|
|
356
|
+
${PROJECT_FEEDBACK_SCRIPT}
|
|
357
|
+
renderKitPreview();
|
|
358
|
+
`;
|
|
359
|
+
//# sourceMappingURL=project-kit-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-kit-html.js","sourceRoot":"","sources":["../../src/dashboard/project-kit-html.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEtH,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuCzC,sBAAsB;CACvB,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmD1C,uBAAuB;;;CAGxB,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiQ1C,uBAAuB;;CAExB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Persistent, provider-free project portal. Closing never deletes project files. */
|
|
2
|
+
export declare function startProjectWorkspace(directory: string, options?: {
|
|
3
|
+
port?: number;
|
|
4
|
+
}): Promise<{
|
|
5
|
+
url: string;
|
|
6
|
+
close: () => Promise<void>;
|
|
7
|
+
root: string;
|
|
8
|
+
projectId: string;
|
|
9
|
+
projectName: string;
|
|
10
|
+
storagePath: string;
|
|
11
|
+
settingsPath: string;
|
|
12
|
+
annotationsPath: string;
|
|
13
|
+
journalPath: string;
|
|
14
|
+
feedbackPath: string;
|
|
15
|
+
}>;
|
|
16
|
+
//# sourceMappingURL=project-workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-workspace.d.ts","sourceRoot":"","sources":["../../src/dashboard/project-workspace.ts"],"names":[],"mappings":"AAaA,qFAAqF;AACrF,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO;;;;;;;;;;;GA4D7F"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import * as http from 'node:http';
|
|
2
|
+
import { GlobalBrain } from '../brain/global-brain.js';
|
|
3
|
+
import { projectStorage } from '../brain/project-memory.js';
|
|
4
|
+
import { FeatureSettingsStore } from '../brain/feature-settings.js';
|
|
5
|
+
import { memoryAnnotationsFor } from '../brain/memory-annotations.js';
|
|
6
|
+
import { ActivityJournal } from '../brain/activity-journal.js';
|
|
7
|
+
import { handleWorkspaceRequest } from './workspace-api.js';
|
|
8
|
+
import { WORKSPACE_HTML } from './workspace-html.js';
|
|
9
|
+
import { LIVE_WORKSPACE_HTML } from './live-workspace-html.js';
|
|
10
|
+
import { BRAIN_HUB_HTML } from './brain-hub-html.js';
|
|
11
|
+
import { WorkspaceRuntime } from './workspace-status.js';
|
|
12
|
+
import { ProjectHubService } from '../brain/project-hub.js';
|
|
13
|
+
/** Persistent, provider-free project portal. Closing never deletes project files. */
|
|
14
|
+
export async function startProjectWorkspace(directory, options = {}) {
|
|
15
|
+
const port = options.port ?? 0;
|
|
16
|
+
if (!Number.isSafeInteger(port) || port < 0 || port > 65535)
|
|
17
|
+
throw new TypeError('Project port must be an integer from 0 to 65535.');
|
|
18
|
+
const store = projectStorage(directory);
|
|
19
|
+
const brain = GlobalBrain.createIsolated({ dbPath: store.storagePath });
|
|
20
|
+
const settings = new FeatureSettingsStore({ filePath: store.settingsPath });
|
|
21
|
+
const journal = new ActivityJournal({ filePath: store.journalPath });
|
|
22
|
+
const annotations = memoryAnnotationsFor(brain);
|
|
23
|
+
const requests = new Set();
|
|
24
|
+
const runtime = new WorkspaceRuntime('project', { id: store.projectId, name: store.projectName, root: store.root });
|
|
25
|
+
let hub;
|
|
26
|
+
const prepareStorage = async () => {
|
|
27
|
+
try {
|
|
28
|
+
await brain.init();
|
|
29
|
+
brain.refresh();
|
|
30
|
+
if (brain.getStorageHealth().lastError)
|
|
31
|
+
return 'Project memory could not be read. Repair the project store, then retry.';
|
|
32
|
+
hub ?? (hub = new ProjectHubService(store.root, brain));
|
|
33
|
+
hub.checkStorage();
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return 'Project storage could not be opened. Check its files and permissions, then retry.';
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
let listener;
|
|
41
|
+
let closing;
|
|
42
|
+
const close = () => closing ?? (closing = (async () => {
|
|
43
|
+
if (listener?.listening) {
|
|
44
|
+
listener.closeAllConnections();
|
|
45
|
+
await new Promise((resolve, reject) => listener.close(error => error ? reject(error) : resolve()));
|
|
46
|
+
}
|
|
47
|
+
await Promise.allSettled([...requests]);
|
|
48
|
+
hub?.close();
|
|
49
|
+
await brain.shutdown();
|
|
50
|
+
})());
|
|
51
|
+
try {
|
|
52
|
+
await prepareStorage();
|
|
53
|
+
listener = http.createServer((req, res) => {
|
|
54
|
+
const actualPort = listener.address().port;
|
|
55
|
+
if (!['127.0.0.1:' + actualPort, 'localhost:' + actualPort].includes(req.headers.host ?? '')) {
|
|
56
|
+
res.writeHead(403);
|
|
57
|
+
res.end('Unsupported host.');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (req.url?.startsWith('/api/workspace/')) {
|
|
61
|
+
const task = handleWorkspaceRequest(req, res, { brain, settings, annotations, journal, projectDir: store.root, localProject: true,
|
|
62
|
+
runtime, get hub() { return hub; }, prepareStorage });
|
|
63
|
+
requests.add(task);
|
|
64
|
+
void task.finally(() => requests.delete(task));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (req.method !== 'GET') {
|
|
68
|
+
res.writeHead(405);
|
|
69
|
+
res.end('Method not allowed.');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
let pathname;
|
|
73
|
+
try {
|
|
74
|
+
pathname = new URL(req.url ?? '/', 'http://localhost').pathname;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
res.writeHead(400);
|
|
78
|
+
res.end('Invalid request URL.');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (pathname === '/favicon.ico') {
|
|
82
|
+
res.writeHead(204);
|
|
83
|
+
res.end();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const html = pathname === '/' || pathname === '/hub' ? BRAIN_HUB_HTML : pathname === '/workspace' || pathname === '/memory-workspace' ? WORKSPACE_HTML : pathname === '/live' ? LIVE_WORKSPACE_HTML : null;
|
|
87
|
+
if (!html) {
|
|
88
|
+
res.writeHead(404);
|
|
89
|
+
res.end('This project portal serves /hub, /workspace and /live.');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-store', 'X-Content-Type-Options': 'nosniff', 'Referrer-Policy': 'no-referrer' });
|
|
93
|
+
res.end(html.replace('<html ', '<html data-project-local="true" '));
|
|
94
|
+
});
|
|
95
|
+
await new Promise((resolve, reject) => {
|
|
96
|
+
listener.once('error', reject);
|
|
97
|
+
listener.listen(port, '127.0.0.1', () => { listener.off('error', reject); resolve(); });
|
|
98
|
+
});
|
|
99
|
+
return { ...store, url: 'http://127.0.0.1:' + listener.address().port, close };
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
await close();
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=project-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-workspace.js","sourceRoot":"","sources":["../../src/dashboard/project-workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/dashboard/server.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/dashboard/server.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAcxD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAmYD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkC;IACnE,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,iBAAiB,CAA+B;gBAE5C,YAAY,EAAE,YAAY,EAAE,OAAO,GAAE,gBAAqB;IAmBtE,gFAAgF;IAChF,OAAO,CAAC,mBAAmB;IAM3B;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;IAoB7B,OAAO,CAAC,iBAAiB;IAQzB,yEAAyE;IACzE,OAAO,CAAC,aAAa;IAuDrB,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,aAAa;YA8DP,eAAe;IA4vB7B,kFAAkF;YACpE,kBAAkB;YAkFlB,YAAY;IAY1B,OAAO,CAAC,cAAc;IA+CtB,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,iBAAiB;IAkDzB,OAAO,CAAC,YAAY;IA0BpB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,4BAA4B;YAQtB,UAAU;YASV,sBAAsB;IAuCpC,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,cAAc;IA4CtB,OAAO,CAAC,uBAAuB;IA2C/B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,SAAS;IAWX,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAYxB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB3B,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
package/dist/dashboard/server.js
CHANGED
|
@@ -14,6 +14,8 @@ import { WORKSPACE_HTML } from './workspace-html.js';
|
|
|
14
14
|
import { LIVE_WORKSPACE_HTML } from './live-workspace-html.js';
|
|
15
15
|
import { handleWorkspaceRequest } from './workspace-api.js';
|
|
16
16
|
import { getFeatureSettings } from '../brain/feature-settings.js';
|
|
17
|
+
import { BRAIN_HUB_HTML } from './brain-hub-html.js';
|
|
18
|
+
import { WorkspaceRuntime } from './workspace-status.js';
|
|
17
19
|
// ── Embedded HTML Client ──────────────────────────────────────────────────────
|
|
18
20
|
const HTML_CLIENT = `<!DOCTYPE html>
|
|
19
21
|
<html lang="en">
|
|
@@ -400,6 +402,7 @@ connect();
|
|
|
400
402
|
// ── Dashboard Server ──────────────────────────────────────────────────────────
|
|
401
403
|
export class DashboardServer {
|
|
402
404
|
constructor(orchestrator, options = {}) {
|
|
405
|
+
this.workspaceRuntime = new WorkspaceRuntime('shared');
|
|
403
406
|
this.clients = new Set();
|
|
404
407
|
this.brainBusUnsub = null;
|
|
405
408
|
this.brainWatcher = null;
|
|
@@ -539,7 +542,11 @@ export class DashboardServer {
|
|
|
539
542
|
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
540
543
|
res.end(JSON.stringify(data, null, 2));
|
|
541
544
|
};
|
|
542
|
-
if (url === '/' || url === '/index.html' || url === '/
|
|
545
|
+
if (url === '/' || url === '/index.html' || url === '/hub') {
|
|
546
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-store' });
|
|
547
|
+
res.end(BRAIN_HUB_HTML);
|
|
548
|
+
}
|
|
549
|
+
else if (url === '/workspace' || url === '/memory-workspace') {
|
|
543
550
|
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-cache' });
|
|
544
551
|
res.end(WORKSPACE_HTML);
|
|
545
552
|
}
|
|
@@ -548,7 +555,7 @@ export class DashboardServer {
|
|
|
548
555
|
res.end(LIVE_WORKSPACE_HTML);
|
|
549
556
|
}
|
|
550
557
|
else if (url.startsWith('/api/workspace/')) {
|
|
551
|
-
void handleWorkspaceRequest(req, res, { projectDir: this.orchestrator.getStatus().projectDir });
|
|
558
|
+
void handleWorkspaceRequest(req, res, { projectDir: this.orchestrator.getStatus().projectDir, runtime: this.workspaceRuntime });
|
|
552
559
|
}
|
|
553
560
|
else if (url === '/advanced' || url === '/hive' || url === '/v6' || url === '/hive.html') {
|
|
554
561
|
// Existing advanced tools remain available with their original routes.
|
|
@@ -643,10 +650,12 @@ export class DashboardServer {
|
|
|
643
650
|
const tokenReport = await tokens.report();
|
|
644
651
|
const runtime = this.getRuntimeContext();
|
|
645
652
|
return send({
|
|
646
|
-
version: '7.1.
|
|
653
|
+
version: '7.1.4',
|
|
647
654
|
localFirst: true,
|
|
648
655
|
runtime,
|
|
649
656
|
totalAgentsConnected: brain.getStats().totalAgents,
|
|
657
|
+
totalRecordedAgents: brain.getStats().totalAgents,
|
|
658
|
+
agentCountEvidence: 'Historical tools recorded in memory; not current connections.',
|
|
650
659
|
totalMemoriesStored: brain.getStats().totalEntries,
|
|
651
660
|
modules: {
|
|
652
661
|
sabb: sabb.getStats(),
|
|
@@ -1405,7 +1414,9 @@ export class DashboardServer {
|
|
|
1405
1414
|
const agents = knownAgents.map(name => ({
|
|
1406
1415
|
id: name,
|
|
1407
1416
|
displayName: displayNames[name] ?? name,
|
|
1408
|
-
connected:
|
|
1417
|
+
connected: false,
|
|
1418
|
+
configurationDetected: !!hooks.find((h) => h.agent === name) || !!detected.find((d) => d.name === name),
|
|
1419
|
+
connectionStatus: 'not-verified',
|
|
1409
1420
|
}));
|
|
1410
1421
|
// Sub-agents — pull from recent SABB spawn log
|
|
1411
1422
|
const sabb = getSubAgentBridge();
|