pmx-canvas 0.7.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/extensions/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
- package/.github/extensions/pmx-canvas/extension.mjs +25 -172
- package/.github/extensions/pmx-canvas/mcp-bootstrap.ts +198 -0
- package/.github/extensions/pmx-canvas/runtime.d.mts +41 -0
- package/.github/extensions/pmx-canvas/runtime.json +3 -0
- package/.github/extensions/pmx-canvas/runtime.mjs +194 -0
- package/.github/extensions/pmx-canvas/start-mcp.mjs +51 -0
- package/.github/extensions/pmx-canvas/tools.json +2560 -0
- package/CHANGELOG.md +47 -0
- package/Readme.md +21 -7
- package/dist/canvas/fonts/OFL.txt +93 -0
- package/dist/canvas/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-mono-latin-ext-400-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-mono-latin-ext-500-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-ext-400-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-ext-500-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-ext-600-normal.woff2 +0 -0
- package/dist/canvas/global.css +723 -672
- package/dist/canvas/index.js +90 -88
- package/dist/canvas/mcp-app.html +7878 -0
- package/dist/canvas/mermaid-entry.js +1 -1
- package/dist/canvas/surface-theme.css +151 -46
- package/dist/json-render/index.css +1 -1
- package/dist/types/cli/commands/record.d.ts +1 -1
- package/dist/types/client/canvas/NodeContextMark.d.ts +24 -0
- package/dist/types/client/canvas/SessionReceipt.d.ts +3 -1
- package/dist/types/client/icons.d.ts +1 -2
- package/dist/types/client/mcp-app/index.d.ts +1 -0
- package/dist/types/client/nodes/ax-node-actions.d.ts +2 -2
- package/dist/types/client/nodes/markdown-sanitize.d.ts +2 -0
- package/dist/types/client/nodes/use-workbench-asset.d.ts +2 -0
- package/dist/types/client/state/attention-store.d.ts +0 -5
- package/dist/types/client/state/context-status-store.d.ts +53 -0
- package/dist/types/client/state/intent-bridge.d.ts +3 -0
- package/dist/types/client/state/near-pin-store.d.ts +16 -0
- package/dist/types/client/state/presence-store.d.ts +5 -0
- package/dist/types/client/state/session-store.d.ts +33 -3
- package/dist/types/client/state/workbench-transport.d.ts +16 -0
- package/dist/types/client/theme/tokens.d.ts +1 -3
- package/dist/types/client/types.d.ts +9 -0
- package/dist/types/json-render/server.d.ts +1 -1
- package/dist/types/mcp/app-server.d.ts +3 -0
- package/dist/types/mcp/canvas-access.d.ts +1 -1
- package/dist/types/mcp/canvas-app.d.ts +4 -0
- package/dist/types/mcp/workbench-app.d.ts +4 -0
- package/dist/types/server/agent-presence.d.ts +1 -1
- package/dist/types/server/ax-state.d.ts +1 -1
- package/dist/types/server/canvas-db.d.ts +8 -0
- package/dist/types/server/canvas-geometry.d.ts +25 -0
- package/dist/types/server/canvas-operations.d.ts +1 -11
- package/dist/types/server/canvas-state.d.ts +25 -3
- package/dist/types/server/context-brief.d.ts +8 -1
- package/dist/types/server/context-reads.d.ts +30 -7
- package/dist/types/server/index.d.ts +6 -1
- package/dist/types/server/mcp-app-runtime.d.ts +1 -0
- package/dist/types/server/operations/http.d.ts +2 -0
- package/dist/types/server/operations/invoker.d.ts +4 -2
- package/dist/types/server/operations/ops/nodes.d.ts +0 -6
- package/dist/types/server/server.d.ts +1 -0
- package/dist/types/server/spatial-analysis.d.ts +2 -0
- package/dist/types/shared/agent-context.d.ts +22 -0
- package/dist/types/shared/agent-presence.d.ts +3 -10
- package/dist/types/shared/canvas-app.d.ts +54 -0
- package/dist/types/shared/themes.d.ts +1 -1
- package/docs/RELEASE.md +7 -3
- package/docs/agent-plugin.md +123 -0
- package/docs/ax-state-contract.md +40 -0
- package/docs/cli.md +7 -2
- package/docs/design/AgentContext.dc.html +186 -0
- package/docs/design/Before.dc.html +208 -0
- package/docs/design/BoardPins.dc.html +151 -0
- package/docs/design/Chrome.dc.html +208 -0
- package/docs/design/Context.dc.html +239 -0
- package/docs/design/Flows.dc.html +181 -0
- package/docs/design/Home.dc.html +209 -0
- package/docs/design/HomeGraph.dc.html +211 -0
- package/docs/design/HomeMap.dc.html +117 -0
- package/docs/design/HomeTeam.dc.html +176 -0
- package/docs/design/Light.dc.html +28 -0
- package/docs/design/Main.dc.html +280 -0
- package/docs/design/NearPin.dc.html +260 -0
- package/docs/design/Pane600.dc.html +120 -0
- package/docs/design/Relations.dc.html +297 -0
- package/docs/design/Themes.dc.html +121 -0
- package/docs/design/TokenSystem.dc.html +136 -0
- package/docs/design/Tokens.dc.html +163 -0
- package/docs/design/Types1.dc.html +177 -0
- package/docs/design/Types2.dc.html +226 -0
- package/docs/design/Types3.dc.html +195 -0
- package/docs/design/Uses.dc.html +152 -0
- package/docs/design/Vision.dc.html +116 -0
- package/docs/design/Zoom.dc.html +82 -0
- package/docs/design/canvas.json +274 -0
- package/docs/design.md +214 -0
- package/docs/environment.md +1 -1
- package/docs/http-api.md +80 -15
- package/docs/mcp.md +198 -3
- package/docs/node-types.md +34 -10
- package/docs/plans/plan-009-tech-debt-backlog.md +1 -1
- package/docs/plans/plan-015-design-foundation-wave-0.md +177 -0
- package/docs/plans/plan-016-context-made-visible-wave-1.md +148 -0
- package/docs/product-vision-2026-09.md +47 -7
- package/docs/screenshot.png +0 -0
- package/docs/sdk.md +1 -0
- package/package.json +10 -4
- package/plugins/pmx-canvas/LICENSE +21 -0
- package/plugins/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
- package/plugins/pmx-canvas/assets/preview.png +0 -0
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/extension.mjs +930 -0
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +3 -0
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.mjs +194 -0
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/steering-delivery.mjs +79 -0
- package/plugins/pmx-canvas/mcp.json +12 -0
- package/plugins/pmx-canvas/plugin.json +24 -0
- package/plugins/pmx-canvas/runtime.json +3 -0
- package/plugins/pmx-canvas/runtime.mjs +194 -0
- package/plugins/pmx-canvas/start-mcp.mjs +51 -0
- package/plugins/pmx-canvas/tools.json +2560 -0
- package/skills/pmx-canvas/SKILL.md +10 -7
- package/skills/pmx-canvas/references/full-reference.md +11 -7
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +20 -8
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
- package/skills/pmx-canvas-testing/SKILL.md +5 -4
- package/src/cli/commands/copilot.ts +5 -0
- package/src/cli/commands/view.ts +1 -1
- package/src/cli/index.ts +8 -3
- package/src/client/App.tsx +6 -1
- package/src/client/canvas/AgentPresenceLayer.tsx +3 -3
- package/src/client/canvas/AnnotationLayer.tsx +1 -1
- package/src/client/canvas/CanvasNode.tsx +32 -49
- package/src/client/canvas/CanvasViewport.tsx +0 -2
- package/src/client/canvas/CommandPalette.tsx +3 -2
- package/src/client/canvas/ContextMenu.tsx +11 -0
- package/src/client/canvas/EdgeLayer.tsx +1 -1
- package/src/client/canvas/ExportDialog.tsx +33 -6
- package/src/client/canvas/IntentLayer.tsx +2 -2
- package/src/client/canvas/Minimap.tsx +12 -7
- package/src/client/canvas/NodeContextMark.tsx +156 -0
- package/src/client/canvas/SessionPanel.tsx +4 -7
- package/src/client/canvas/SessionReceipt.tsx +114 -17
- package/src/client/canvas/ShortcutOverlay.tsx +6 -1
- package/src/client/canvas/SnapshotPanel.tsx +11 -2
- package/src/client/canvas/ToolRail.tsx +12 -9
- package/src/client/canvas/TopBar.tsx +16 -11
- package/src/client/icons.tsx +2 -12
- package/src/client/mcp-app/index.tsx +137 -0
- package/src/client/mcp-app/style.css +10 -0
- package/src/client/nodes/AttachmentNode.tsx +8 -1
- package/src/client/nodes/AxStepControls.tsx +1 -1
- package/src/client/nodes/ContextNode.tsx +9 -9
- package/src/client/nodes/ExtAppFrame.tsx +13 -8
- package/src/client/nodes/FileNode.tsx +8 -5
- package/src/client/nodes/ImageNode.tsx +4 -2
- package/src/client/nodes/InlineMarkdownEditor.tsx +2 -1
- package/src/client/nodes/LedgerNode.tsx +2 -2
- package/src/client/nodes/MarkdownNode.tsx +44 -9
- package/src/client/nodes/McpAppNode.tsx +6 -4
- package/src/client/nodes/PromptNode.tsx +5 -17
- package/src/client/nodes/ResponseNode.tsx +3 -15
- package/src/client/nodes/StatusNode.tsx +2 -2
- package/src/client/nodes/StatusSummary.tsx +3 -1
- package/src/client/nodes/TraceNode.tsx +6 -4
- package/src/client/nodes/WebpageNode.tsx +1 -1
- package/src/client/nodes/ax-node-actions.ts +2 -2
- package/src/client/nodes/iframe-document-url.ts +3 -2
- package/src/client/nodes/markdown-sanitize.ts +10 -0
- package/src/client/nodes/surface-url.ts +10 -0
- package/src/client/nodes/use-surface-frame.ts +3 -1
- package/src/client/nodes/use-workbench-asset.ts +26 -0
- package/src/client/state/attention-bridge.ts +0 -8
- package/src/client/state/attention-store.ts +0 -17
- package/src/client/state/canvas-store.ts +4 -2
- package/src/client/state/context-status-store.ts +66 -0
- package/src/client/state/human-store.ts +2 -0
- package/src/client/state/iframe-mode.ts +5 -0
- package/src/client/state/intent-bridge.ts +10 -4
- package/src/client/state/near-pin-store.ts +53 -0
- package/src/client/state/presence-store.ts +5 -10
- package/src/client/state/session-store.ts +106 -9
- package/src/client/state/sse-bridge.ts +26 -7
- package/src/client/state/theme-override.ts +1 -1
- package/src/client/state/workbench-transport.ts +36 -0
- package/src/client/theme/global.css +723 -672
- package/src/client/theme/surface-theme.css +151 -46
- package/src/client/theme/tokens.ts +7 -11
- package/src/client/types.ts +10 -0
- package/src/json-render/server.ts +71 -14
- package/src/mcp/app-server.ts +64 -0
- package/src/mcp/canvas-access.ts +14 -11
- package/src/mcp/canvas-app.ts +318 -0
- package/src/mcp/server.ts +1 -1
- package/src/mcp/workbench-app.ts +211 -0
- package/src/server/agent-presence.ts +45 -6
- package/src/server/ax-context.ts +1 -1
- package/src/server/ax-state.ts +1 -1
- package/src/server/board-export.ts +5 -2
- package/src/server/canvas-db.ts +46 -12
- package/src/server/canvas-geometry.ts +64 -0
- package/src/server/canvas-operations.ts +6 -24
- package/src/server/canvas-state.ts +105 -15
- package/src/server/canvas-validation.ts +19 -4
- package/src/server/context-brief.ts +39 -2
- package/src/server/context-reads.ts +86 -15
- package/src/server/demo-state.json +31 -31
- package/src/server/html-surface.ts +4 -5
- package/src/server/index.ts +19 -3
- package/src/server/mcp-app-runtime.ts +11 -0
- package/src/server/operations/composites.ts +4 -3
- package/src/server/operations/http.ts +4 -4
- package/src/server/operations/invoker.ts +13 -4
- package/src/server/operations/ops/ax-read.ts +1 -1
- package/src/server/operations/ops/ax-timeline.ts +37 -0
- package/src/server/operations/ops/boards.ts +1 -1
- package/src/server/operations/ops/canvas-wire.ts +3 -6
- package/src/server/operations/ops/intent.ts +31 -2
- package/src/server/operations/ops/json-render.ts +1 -1
- package/src/server/operations/ops/nodes.ts +8 -76
- package/src/server/operations/ops/query.ts +8 -2
- package/src/server/operations/ops/snapshots.ts +4 -1
- package/src/server/operations/ops/viewport.ts +29 -5
- package/src/server/operations/registry.ts +38 -4
- package/src/server/scope-fence.ts +55 -10
- package/src/server/server.ts +83 -5
- package/src/server/spatial-analysis.ts +2 -2
- package/src/server/workboard.ts +6 -1
- package/src/{server → shared}/agent-context.ts +2 -2
- package/src/shared/agent-presence.ts +3 -15
- package/src/shared/canvas-app.ts +62 -0
- package/src/shared/themes.ts +5 -5
- package/src/client/canvas/FocusFieldLayer.tsx +0 -116
- package/src/client/canvas/kind-colors.ts +0 -23
package/docs/RELEASE.md
CHANGED
|
@@ -11,6 +11,9 @@ single source of truth for the release dance — see also
|
|
|
11
11
|
|
|
12
12
|
1. Land all the changes you want in the release on `main` with green CI.
|
|
13
13
|
2. Bump `package.json` `version`.
|
|
14
|
+
Run `bun run build:plugin` to update the Agent Plugins manifest, canonical adapter runtime
|
|
15
|
+
pin, and generated plugin copies. Publish that exact npm runtime version before advertising
|
|
16
|
+
a GitHub plugin release pinned to it.
|
|
14
17
|
3. Add a `## [X.Y.Z]` block to `CHANGELOG.md`.
|
|
15
18
|
4. Commit, push, wait for `test.yml` green.
|
|
16
19
|
5. `git tag -a vX.Y.Z -m "..." && git push origin vX.Y.Z` →
|
|
@@ -40,9 +43,10 @@ bun run pack:dry-run # confirms the tarball shape
|
|
|
40
43
|
do not call `bun x playwright test` directly; it fails before test
|
|
41
44
|
discovery with a `.esm.preflight` loader error (ERR-20260508-001).
|
|
42
45
|
|
|
43
|
-
The
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
The reference cases (`tests/e2e/reference-pane.pw.ts`) run in three
|
|
47
|
+
Playwright projects, `narrow-600`, `middle-1024` and `wide-1920`: the
|
|
48
|
+
workbench lives anywhere from a narrow side pane to a full window. Every
|
|
49
|
+
node type must paint at all three or the release does not ship.
|
|
46
50
|
Embedded WebKit panes (the Copilot app) stay best-effort.
|
|
47
51
|
|
|
48
52
|
`bun run test:e2e-cli` starts a local server in a fresh temp workspace
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# PMX Canvas agent plugin
|
|
2
|
+
|
|
3
|
+
`plugins/pmx-canvas/` is a self-contained [Agent Plugins 1.0](https://agent-plugins.org/)
|
|
4
|
+
package. It contains only PMX Canvas: the portable MCP server configuration and a native
|
|
5
|
+
canvas extension for the GitHub Copilot app. It does not include frame integrations,
|
|
6
|
+
general-purpose skills, or custom agents.
|
|
7
|
+
|
|
8
|
+
## Client support
|
|
9
|
+
|
|
10
|
+
| Client | Experience |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| GitHub Copilot app | PMX MCP tools and the native PMX Canvas side panel |
|
|
13
|
+
| Other Agent Plugins-compatible clients | PMX MCP tools; open the workbench in a browser or the client's browser surface |
|
|
14
|
+
| Clients without Agent Plugins support | Configure the MCP launcher manually using the client's MCP settings |
|
|
15
|
+
|
|
16
|
+
The native Copilot canvas is **not** a portable capability. Other clients ignore the
|
|
17
|
+
`com.github.copilot/` namespace. Supporting the package format also does not guarantee a
|
|
18
|
+
client has an embedded browser, canvas panel, or host-specific steering adapter.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
The local package can be loaded without changing the user's installed plugins:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
copilot --plugin-dir /absolute/path/to/pmx-canvas/plugins/pmx-canvas
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Once the plugin directory is published in the GitHub repository, install it with:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
copilot plugin install pskoett/pmx-canvas:plugins/pmx-canvas
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
In the Copilot app, enable the plugin and start a new project session. Open the **PMX Canvas**
|
|
35
|
+
canvas. Ask the agent to connect PMX to the active project; it calls `canvas_connect_workspace`
|
|
36
|
+
with the project's absolute directory before using board tools. Do not separately install its
|
|
37
|
+
project adapter or configure a second PMX MCP server.
|
|
38
|
+
An existing project adapter can coexist with the plugin canvas. If both declare `pmx-canvas`,
|
|
39
|
+
select the provider explicitly when opening: `plugin:pmx-canvas:pmx-canvas` for this plugin,
|
|
40
|
+
or `project:pmx-canvas` for the project extension. An unqualified open can be ambiguous.
|
|
41
|
+
|
|
42
|
+
Other clients should install the same plugin directory using their Agent Plugins support.
|
|
43
|
+
For a manual MCP setup, invoke `bun /absolute/path/to/plugin/start-mcp.mjs` from the intended
|
|
44
|
+
project directory. The launcher returns MCP JSON-RPC on stdout; diagnostics go to stderr.
|
|
45
|
+
|
|
46
|
+
## Connect the workspace
|
|
47
|
+
|
|
48
|
+
Agent Plugins launches MCP processes from the **plugin installation directory**, not the active
|
|
49
|
+
project. Installing or initializing this plugin therefore does not create a board or start a
|
|
50
|
+
daemon. Before any board operation, the agent calls:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"name": "canvas_connect_workspace",
|
|
55
|
+
"arguments": { "workspaceRoot": "/absolute/path/to/project" }
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The result contains `serverUrl` and `workbenchUrl`. Other harnesses can open `workbenchUrl`
|
|
60
|
+
in a browser. Copilot's native panel resolves the same workspace server.
|
|
61
|
+
|
|
62
|
+
Board tools are advertised from a generated catalog so clients with a fixed initial tool list
|
|
63
|
+
can discover them, but refuse execution until connected. Relative roots and the plugin
|
|
64
|
+
installation directory are rejected. A connected MCP session cannot silently switch projects;
|
|
65
|
+
start a new session for a different workspace.
|
|
66
|
+
|
|
67
|
+
Clients advertising exactly one standard MCP file root can connect automatically. An explicit
|
|
68
|
+
absolute `PMX_CANVAS_WORKSPACE_ROOT` in the MCP process environment also permits auto-connection.
|
|
69
|
+
Neither `process.cwd()` nor an inherited `PWD` is used to guess the project.
|
|
70
|
+
|
|
71
|
+
## Runtime and workspace ownership
|
|
72
|
+
|
|
73
|
+
[Bun](https://bun.sh/) must be installed and available on the host's `PATH`. No globally
|
|
74
|
+
installed `pmx-canvas` executable is required. The first workspace connection downloads the exact package
|
|
75
|
+
version in `runtime.json` using `bun x --bun pmx-canvas@<version>`; it therefore needs npm
|
|
76
|
+
access unless that version is already cached.
|
|
77
|
+
|
|
78
|
+
Both the native canvas and the MCP launcher use the same resolver. It discovers the
|
|
79
|
+
workspace's daemon port from `.pmx-canvas/daemon-<port>.pid` filenames, checks `/health`
|
|
80
|
+
ownership, and serializes concurrent startup with `.pmx-canvas/plugin-start.lock`.
|
|
81
|
+
The MCP subprocess receives the selected `PMX_CANVAS_URL` and an absolute workspace root.
|
|
82
|
+
A foreign server on the preferred port is never treated as this project's server. Each forwarded
|
|
83
|
+
MCP request rechecks ownership; a server replaced by another workspace is refused.
|
|
84
|
+
|
|
85
|
+
The adapter uses the session's **working directory**, not Copilot's session-state
|
|
86
|
+
`workspacePath` or the plugin installation directory. Boards remain in the project's
|
|
87
|
+
`.pmx-canvas/canvas.db`.
|
|
88
|
+
|
|
89
|
+
The daemon belongs to the workspace and stays running when one client closes, so closing
|
|
90
|
+
the native panel cannot break another MCP client. Stop it explicitly from the project:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
bun x --bun pmx-canvas@<version> serve stop --port=<port>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Use the exact version from `runtime.json` and the port from the panel's `status` action.
|
|
97
|
+
`PMX_CANVAS_PORT` selects a preferred port; `PMX_CANVAS_URL` targets an existing server.
|
|
98
|
+
An explicit URL that fails ownership checks is reported rather than silently replaced.
|
|
99
|
+
|
|
100
|
+
## Package maintenance
|
|
101
|
+
|
|
102
|
+
The plugin's adapter copies are generated from `.github/extensions/pmx-canvas/`:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
bun run build:plugin
|
|
106
|
+
bun test tests/unit/agent-plugin.test.js tests/unit/agent-plugin-mcp.test.ts tests/unit/copilot-runtime.test.js
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The build bundles the MCP bootstrap with the existing SDK, generates its initial tool catalog
|
|
110
|
+
through the real MCP `tools/list` API, and copies the canonical adapter and shared resolver into
|
|
111
|
+
the plugin boundary. It pins their runtime to `package.json`'s version. No plugin code
|
|
112
|
+
imports files outside the installed package. `bun run build` also regenerates the plugin,
|
|
113
|
+
and drift tests byte-compare the distributed files against their canonical sources.
|
|
114
|
+
|
|
115
|
+
The portable root contains `plugin.json`, `mcp.json`, `start-mcp.mjs`, `tools.json`, `runtime.mjs`,
|
|
116
|
+
`runtime.json`, and license notices for the bundled dependencies. Copilot auto-discovers the native adapter at
|
|
117
|
+
`com.github.copilot/extensions/pmx-canvas/extension.mjs`.
|
|
118
|
+
|
|
119
|
+
The marketplace preview is copied from `docs/screenshot.png` to `assets/preview.png` on each
|
|
120
|
+
plugin build. The manifest's `extensions.com.github.copilot.logo` points to that packaged PNG.
|
|
121
|
+
|
|
122
|
+
Publishing a repository package does not register it in a curated marketplace or make it
|
|
123
|
+
Featured in the Copilot app. Those are separate submission and review steps.
|
|
@@ -71,3 +71,43 @@ record; redo replays `removeNode` inside suppressed recording
|
|
|
71
71
|
**not** append a second note. Consumers should read `reanchoredIds` /
|
|
72
72
|
`removedReviewIds` against the *current* canvas-bound state, not assume the
|
|
73
73
|
referenced items are still re-anchored.
|
|
74
|
+
|
|
75
|
+
## Agent presence (contract)
|
|
76
|
+
|
|
77
|
+
Presence is the shape behind every agent surface in the rail chrome: the agent
|
|
78
|
+
cursor and phase chip, the session panel, the command bar and the external
|
|
79
|
+
steering indicator. It is **derived, in-memory and never persisted** — not a
|
|
80
|
+
fourth partition, and not a second source of truth for work items, gates or
|
|
81
|
+
steering, which stay in the AX state above. The shared shape lives in
|
|
82
|
+
`src/shared/agent-presence.ts` (server and client import the same types and
|
|
83
|
+
constants, so they cannot drift); the registry is `src/server/agent-presence.ts`.
|
|
84
|
+
|
|
85
|
+
- **Sources.** Agent-originated mutations through `executeOperation` (no
|
|
86
|
+
workbench marker), `ax.activity.ingest` kinds (`session-start` /
|
|
87
|
+
`session-end` attach and detach; `tool-start` / `tool-result` / `failure` /
|
|
88
|
+
`error` drive the phase), and an explicit `ax.presence.set` for adapters with
|
|
89
|
+
richer hooks (`thinking`, cursor, focus).
|
|
90
|
+
- **Modes.** `sessionActive` = any presence with `attached: true`. No presences →
|
|
91
|
+
quiet board; live but unattached writers → external steering (passive
|
|
92
|
+
indicator only); an attached session → the session panel and command bar.
|
|
93
|
+
Presence cursors render for every live writer regardless.
|
|
94
|
+
- **Phase.** An agent mutation or `tool-start` → `tooling` (detail = op or tool
|
|
95
|
+
name), settling to `idle` after `PRESENCE_TOOLING_SETTLE_MS`; `thinking` only
|
|
96
|
+
via the explicit set, settling after `PRESENCE_THINKING_SETTLE_MS`. A cursor
|
|
97
|
+
update that moves the cursor restarts the settle window of a live explicit
|
|
98
|
+
`tooling`; a stationary cursor or focus heartbeat does not, and neither
|
|
99
|
+
extends `thinking`. An idle writer that reported a cursor keeps painting it.
|
|
100
|
+
An attached session with a pending approval gate reads as `waiting-approval`.
|
|
101
|
+
- **Lifetime.** Unattached writers fade `PRESENCE_ACTIVITY_TTL_MS` after their
|
|
102
|
+
last write; attached sessions expire after `PRESENCE_ATTACHED_IDLE_TTL_MS`
|
|
103
|
+
without activity; `session-end` or an explicit `attached: false` removes the
|
|
104
|
+
presence immediately; at most `MAX_PRESENCES`, oldest evicted. Expiry emits,
|
|
105
|
+
so clients never run their own ticker.
|
|
106
|
+
- **Transport.** One SSE frame, `agent-presence`, carries the full snapshot on
|
|
107
|
+
every change, including the last `MAX_ACTIVITY_ENTRIES` agent writes with a
|
|
108
|
+
one-line summary. `GET /api/canvas/ax/presence` for the connect-time read;
|
|
109
|
+
`POST /api/canvas/ax/presence` (`canvas_ax_state { action: "set-presence" }`)
|
|
110
|
+
for explicit updates.
|
|
111
|
+
- **Budget.** `used` = estimated tokens of the `pinned-context.get` payload;
|
|
112
|
+
`total` = `PMX_CANVAS_CONTEXT_BUDGET_TOKENS` (default
|
|
113
|
+
`CONTEXT_BUDGET_DEFAULT_TOKENS`).
|
package/docs/cli.md
CHANGED
|
@@ -159,12 +159,17 @@ pmx-canvas # Start canvas, open browser
|
|
|
159
159
|
pmx-canvas --demo # Start with the showcase demo board
|
|
160
160
|
pmx-canvas --port=8080 # Custom port
|
|
161
161
|
pmx-canvas --no-open # Headless (for agents/CI)
|
|
162
|
-
pmx-canvas --theme=
|
|
162
|
+
pmx-canvas --theme=daylight # harbor | daylight | high-contrast | midnight | sepia | arctic | ember | forest | volt
|
|
163
163
|
pmx-canvas --mcp # Run as MCP server (stdio)
|
|
164
|
+
pmx-canvas --mcp-app # Private MCP App preview (stdio; shared active board)
|
|
164
165
|
pmx-canvas --webview-automation # Start headless Bun.WebView session
|
|
165
166
|
pmx-canvas open # Open the current workbench in a browser
|
|
166
167
|
```
|
|
167
168
|
|
|
169
|
+
The experimental `--mcp-app` profile has ten assistant tools plus an app-only
|
|
170
|
+
transport for the real PMX workbench, separate from the standard MCP tool set. See
|
|
171
|
+
[private MCP App setup and limitations](mcp.md#private-mcp-app-preview).
|
|
172
|
+
|
|
168
173
|
### Daemon mode
|
|
169
174
|
|
|
170
175
|
Run detached with pid/log tracking instead of holding a terminal:
|
|
@@ -223,7 +228,7 @@ content.
|
|
|
223
228
|
|
|
224
229
|
```bash
|
|
225
230
|
pmx-canvas node schema --type json-render --component Table --summary
|
|
226
|
-
pmx-canvas validate # Layout validation
|
|
231
|
+
pmx-canvas validate # Layout validation (collisions, groupFrameOverlaps, sizeWarnings)
|
|
227
232
|
pmx-canvas validate spec --type json-render --spec-file ./dashboard.json --summary
|
|
228
233
|
pmx-canvas validate spec --type html-primitive --kind choice-grid --data-json '{"items":[{"title":"A"}]}' --summary
|
|
229
234
|
```
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>What the agent did with context</title>
|
|
6
|
+
<script src="./support.js"></script>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<x-dc>
|
|
10
|
+
<helmet>
|
|
11
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=IBM+Plex+Sans:wght@400;500;600&display=swap">
|
|
12
|
+
<style>
|
|
13
|
+
body{margin:0}
|
|
14
|
+
</style>
|
|
15
|
+
</helmet>
|
|
16
|
+
<div style="width: 1440px; height: 1500px; box-sizing: border-box; padding: 48px 56px; background: #081524; color: #e6eef7; font-family: 'IBM Plex Sans', system-ui, sans-serif; font-size: 13px; line-height: 1.5; display: flex; flex-direction: column; gap: 28px">
|
|
17
|
+
|
|
18
|
+
<div style="display: flex; gap: 40px; align-items: flex-end">
|
|
19
|
+
<div style="flex: 1">
|
|
20
|
+
<h1 style="margin: 0; font-size: 28px; font-weight: 600; letter-spacing: -0.015em">What the agent did with context</h1>
|
|
21
|
+
<p style="margin: 4px 0 0; font-size: 13px; color: #8ea3bd">Two questions, two colours. Every mark has a glyph and a word, so it reads without the colour, and every mark explains itself on hover.</p>
|
|
22
|
+
</div>
|
|
23
|
+
<div style="display: flex; gap: 10px">
|
|
24
|
+
<div style="{{s.rule}} border-color: rgba(75,188,255,0.4)"><span style="{{s.ruleDot}} background: #4BBCFF"></span><span><b style="font-weight: 600; color: #4BBCFF">Blue</b> — what's in context<br><span style="color: #8ea3bd">You or the agent pinned it</span></span></div>
|
|
25
|
+
<div style="{{s.rule}} border-color: rgba(179,136,255,0.4)"><span style="{{s.ruleDot}} background: #B388FF"></span><span><b style="font-weight: 600; color: #B388FF">Violet</b> — what the agent did<br><span style="color: #8ea3bd">Read, created, edited, suggested</span></span></div>
|
|
26
|
+
<div style="{{s.rule}} border-color: rgba(244,197,66,0.4)"><span style="{{s.ruleDot}} background: #f4c542"></span><span><b style="font-weight: 600; color: #f4c542">Amber</b> — needs a look<br><span style="color: #8ea3bd">The agent's copy is out of date</span></span></div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<section style="display: flex; flex-direction: column; gap: 12px">
|
|
31
|
+
<h2 style="margin: 0; font-size: 15px; font-weight: 600">The key</h2>
|
|
32
|
+
<div style="display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px">
|
|
33
|
+
<sc-for list="{{key}}" as="k" hint-placeholder-count="8">
|
|
34
|
+
<div style="display: flex; flex-direction: column; gap: 8px">
|
|
35
|
+
<div style="position: relative; height: 104px; border-radius: 8px; background: #06111e; padding: 12px; box-sizing: border-box">
|
|
36
|
+
<div style="{{k.node}}">
|
|
37
|
+
<sc-if value="{{k.bar}}" hint-placeholder-val="{{ false }}"><div style="position: absolute; left: 0; right: 0; top: 0; height: 2.5px; background: #B388FF"></div></sc-if>
|
|
38
|
+
<div style="{{k.head}}">
|
|
39
|
+
<span style="flex: 1; min-width: 0; font-size: 12px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">{{k.title}}</span>
|
|
40
|
+
<sc-if value="{{k.mark}}" hint-placeholder-val="{{ true }}"><span style="{{k.markStyle}}"><svg width="12" height="12" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="{{k.icon}}"></path></svg>{{k.markText}}</span></sc-if>
|
|
41
|
+
<sc-if value="{{k.pin}}" hint-placeholder-val="{{ false }}"><span style="position: relative; width: 18px; height: 18px; border-radius: 999px; background: #4BBCFF; color: #081524; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round"><path d="M9 4h6l-.8 5.5 2.8 3H7l2.8-3zM12 12.5V20"></path></svg><sc-if value="{{k.byAgent}}" hint-placeholder-val="{{ false }}"><span style="position: absolute; right: -3px; bottom: -3px; width: 9px; height: 9px; border-radius: 999px; background: #B388FF; border: 2px solid #0f1d31"></span></sc-if></span></sc-if>
|
|
42
|
+
</div>
|
|
43
|
+
<div style="padding: 6px 10px; font-size: 11px; color: #8ea3bd">{{k.meta}}</div>
|
|
44
|
+
<sc-if value="{{k.actions}}" hint-placeholder-val="{{ false }}"><div style="position: absolute; right: 8px; bottom: 6px; display: flex; gap: 4px"><span style="{{s.mini}} background: rgba(179,136,255,0.16); color: #B388FF">Accept</span><span style="{{s.mini}} color: #8ea3bd">Dismiss</span></div></sc-if>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
<div><div style="font-size: 12px; font-weight: 600">{{k.name}}</div><div style="font-size: 11px; color: #8ea3bd">{{k.desc}}</div></div>
|
|
48
|
+
</div>
|
|
49
|
+
</sc-for>
|
|
50
|
+
</div>
|
|
51
|
+
</section>
|
|
52
|
+
|
|
53
|
+
<section style="display: flex; flex-direction: column; gap: 12px">
|
|
54
|
+
<h2 style="margin: 0; font-size: 15px; font-weight: 600">After a session — the agent-activity lens</h2>
|
|
55
|
+
<div style="display: flex; gap: 24px">
|
|
56
|
+
|
|
57
|
+
<div style="position: relative; width: 900px; height: 600px; border-radius: 10px; border: 1px solid #1b2c44; overflow: hidden; background-color: #081524; background-image: radial-gradient(rgba(142,163,189,0.14) 1px, transparent 1.2px); background-size: 24px 24px">
|
|
58
|
+
<svg width="900" height="600" viewBox="0 0 900 600" style="position: absolute; left: 0; top: 0; fill: none; stroke-linecap: round">
|
|
59
|
+
<path d="M 170 172 C 170 140, 400 160, 400 130" style="stroke: #5FCFC0; stroke-width: 2"></path><path d="M 400 126 L 395.5 135 L 404.5 135 Z" style="fill: #5FCFC0"></path>
|
|
60
|
+
<path d="M 470 172 L 470 130" style="stroke: #E59B6B; stroke-width: 2"></path><path d="M 470 126 L 465.5 135 L 474.5 135 Z" style="fill: #E59B6B"></path>
|
|
61
|
+
<path d="M 640 214 C 600 214, 560 170, 560 130" style="stroke: #B388FF; stroke-width: 2; stroke-dasharray: 6 5"></path><path d="M 560 126 L 555.5 135 L 564.5 135 Z" style="fill: #B388FF"></path>
|
|
62
|
+
</svg>
|
|
63
|
+
<span style="position: absolute; left: 596px; top: 136px; height: 20px; padding: 0 8px; border-radius: 999px; background: rgba(179,136,255,0.16); color: #B388FF; font-size: 11px; font-weight: 500; line-height: 20px">suggested: supports</span>
|
|
64
|
+
|
|
65
|
+
<div style="{{sc.node}} left: 360px; top: 40px; border: 1.5px solid #4BBCFF"><div style="{{sc.head}} background: rgba(75,188,255,0.10)"><span style="{{sc.title}}">Raise Pro to $24?</span><span style="{{sc.read}}"><svg width="12" height="12" viewBox="0 0 24 24" style="{{sc.ic}}"><path d="{{i.eye}}"></path></svg>read</span><button aria-label="Expand (Enter)" style="width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7"></path></svg></button><span style="{{sc.pin}}"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round"><path d="{{i.pin}}"></path></svg></span></div><div style="{{sc.body}}">question · pinned by you</div></div>
|
|
66
|
+
|
|
67
|
+
<div style="{{sc.node}} left: 640px; top: 30px; border: 1.5px dashed #B388FF; background: rgba(179,136,255,0.06)"><div style="{{sc.head}}"><span style="{{sc.title}} color: #d9c7ff">Summary: case for $24</span><span style="{{sc.read}}"><svg width="12" height="12" viewBox="0 0 24 24" style="{{sc.ic}}"><path d="{{i.spark}}"></path></svg>suggested</span></div><div style="{{sc.body}} display: flex; gap: 6px"><span style="{{s.mini}} background: rgba(179,136,255,0.16); color: #B388FF">Accept</span><span style="{{s.mini}} color: #8ea3bd">Dismiss</span></div></div>
|
|
68
|
+
|
|
69
|
+
<div style="{{sc.node}} left: 60px; top: 172px"><div style="{{sc.head}}"><span style="{{sc.title}}">Churn flat after last raise</span><span style="{{sc.read}}"><svg width="12" height="12" viewBox="0 0 24 24" style="{{sc.ic}}"><path d="{{i.spark}}"></path></svg>by Claude</span><button aria-label="Expand (Enter)" style="width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7"></path></svg></button><button aria-label="Add to context (P)" style="width: 18px; height: 18px; box-sizing: border-box; border: 1.5px solid #6b7d94; border-radius: 999px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round"><path d="M9 4h6l-.8 5.5 2.8 3H7l2.8-3zM12 12.5V20"></path></svg></button></div><div style="{{sc.body}}">finding · created 14:06</div></div>
|
|
70
|
+
|
|
71
|
+
<div style="{{sc.node}} left: 360px; top: 172px; border: 1.5px solid #4BBCFF"><div style="position: absolute; left: 0; right: 0; top: 0; height: 2.5px; background: #B388FF"></div><div style="{{sc.head}} background: rgba(75,188,255,0.10)"><span style="{{sc.title}}">SMB is price-sensitive</span><span style="{{sc.read}}"><svg width="12" height="12" viewBox="0 0 24 24" style="{{sc.ic}}"><path d="{{i.pen}}"></path></svg>edited</span><button aria-label="Expand (Enter)" style="width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7"></path></svg></button><span style="{{sc.pin}}"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round"><path d="{{i.pin}}"></path></svg></span></div><div style="{{sc.body}}">finding · edited 14:12 · <span style="color: #B388FF">see change</span></div></div>
|
|
72
|
+
|
|
73
|
+
<div style="{{sc.node}} left: 640px; top: 172px"><div style="{{sc.head}}"><span style="{{sc.title}}">Competitor pricing</span><span style="{{sc.read}}"><svg width="12" height="12" viewBox="0 0 24 24" style="{{sc.ic}}"><path d="{{i.eye}}"></path></svg>read</span><button aria-label="Expand (Enter)" style="width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7"></path></svg></button><button aria-label="Add to context (P)" style="width: 18px; height: 18px; box-sizing: border-box; border: 1.5px solid #6b7d94; border-radius: 999px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round"><path d="M9 4h6l-.8 5.5 2.8 3H7l2.8-3zM12 12.5V20"></path></svg></button></div><div style="{{sc.body}}">webpage · not pinned, read anyway</div></div>
|
|
74
|
+
|
|
75
|
+
<div style="{{sc.node}} left: 60px; top: 330px; border: 1.5px solid #4BBCFF"><div style="{{sc.head}} background: rgba(75,188,255,0.10)"><span style="{{sc.title}}">Churn by plan</span><span style="{{sc.read}}"><svg width="12" height="12" viewBox="0 0 24 24" style="{{sc.ic}}"><path d="{{i.eye}}"></path></svg>read</span><button aria-label="Expand (Enter)" style="width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7"></path></svg></button><span style="{{sc.pin}} position: relative"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round"><path d="{{i.pin}}"></path></svg><span style="position: absolute; right: -3px; bottom: -3px; width: 9px; height: 9px; border-radius: 999px; background: #B388FF; border: 2px solid #0f1d31"></span></span></div><div style="{{sc.body}}">chart · pinned by Claude</div></div>
|
|
76
|
+
|
|
77
|
+
<div style="{{sc.node}} left: 360px; top: 330px; border: 1.5px solid #4BBCFF"><div style="{{sc.head}} background: rgba(75,188,255,0.10)"><span style="{{sc.title}}">SMB interviews</span><span style="{{sc.read}} background: rgba(244,197,66,0.14); color: #f4c542"><svg width="12" height="12" viewBox="0 0 24 24" style="{{sc.ic}}"><path d="{{i.warn}}"></path></svg>changed</span><button aria-label="Expand (Enter)" style="width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7"></path></svg></button><span style="{{sc.pin}}"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round"><path d="{{i.pin}}"></path></svg></span></div><div style="{{sc.body}}">notes · you added 2 calls at 14:15</div></div>
|
|
78
|
+
|
|
79
|
+
<div style="{{sc.node}} left: 640px; top: 330px; opacity: 0.35"><div style="{{sc.head}}"><span style="{{sc.title}}">Pricing notes</span><button aria-label="Expand (Enter)" style="width: 22px; height: 22px; border: 0; border-radius: 6px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7"></path></svg></button><button aria-label="Add to context (P)" style="width: 18px; height: 18px; box-sizing: border-box; border: 1.5px solid #6b7d94; border-radius: 999px; padding: 0; background: transparent; color: #b9c6d6; display: flex; align-items: center; justify-content: center; flex-shrink: 0"><svg width="10" height="10" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round"><path d="M9 4h6l-.8 5.5 2.8 3H7l2.8-3zM12 12.5V20"></path></svg></button></div><div style="{{sc.body}}">markdown · untouched by the agent</div></div>
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
<div style="position: absolute; left: 60px; top: 424px; width: 300px; box-sizing: border-box; padding: 10px 12px; border-radius: 10px; border: 1px solid #2a4566; background: #13243b; box-shadow: 0 10px 30px rgba(0,0,0,0.55); display: flex; flex-direction: column; gap: 6px; font-size: 11px">
|
|
83
|
+
<span style="font-size: 12px; font-weight: 600; color: #e6eef7">Churn by plan</span>
|
|
84
|
+
<span style="color: #b9c6d6"><span style="color: #B388FF">Pinned by Claude</span> · 14:04 — “the chart the churn finding rests on”</span>
|
|
85
|
+
<span style="color: #b9c6d6"><span style="color: #B388FF">Read 3 times</span> · last 14:11</span>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div style="position: absolute; left: 380px; top: 452px; width: 300px; display: flex; flex-direction: column; gap: 8px">
|
|
89
|
+
<button style="align-self: flex-start; display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px; border-radius: 999px; border: 1px solid rgba(75,188,255,0.3); background: #0f1d31; color: #4BBCFF; font-family: inherit; font-size: 12px; font-weight: 500"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round"><path d="M9 4h6l-.8 5.5 2.8 3H7l2.8-3zM12 12.5V20"></path></svg>4 in context<span style="color: #f4c542">· 1 out of date</span></button>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<div style="position: absolute; left: 16px; right: 16px; bottom: 14px; display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 10px; border: 1px solid rgba(179,136,255,0.35); background: rgba(10,23,41,0.94)">
|
|
93
|
+
<span style="display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: #B388FF"><span style="width: 8px; height: 8px; border-radius: 999px; background: #B388FF"></span>Claude · this session</span>
|
|
94
|
+
<sc-for list="{{lens}}" as="l" hint-placeholder-count="5">
|
|
95
|
+
<span style="display: flex; align-items: center; gap: 5px; height: 24px; padding: 0 9px; border-radius: 999px; border: 1px solid #2a4566; font-size: 11px; color: #e6eef7"><svg width="12" height="12" viewBox="0 0 24 24" style="fill: none; stroke: #B388FF; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="{{l.icon}}"></path></svg>{{l.name}}<span style="color: #6b7d94">{{l.n}}</span></span>
|
|
96
|
+
</sc-for>
|
|
97
|
+
<span style="flex: 1"></span>
|
|
98
|
+
<span style="font-size: 11px; color: #8ea3bd">Untouched nodes dimmed</span>
|
|
99
|
+
<span role="switch" aria-checked="true" aria-label="Agent activity lens" style="width: 32px; height: 18px; border-radius: 999px; background: #B388FF; position: relative"><span style="position: absolute; right: 2px; top: 2px; width: 14px; height: 14px; border-radius: 999px; background: #081524"></span></span>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<aside style="width: 360px; height: 600px; box-sizing: border-box; padding: 16px; border-radius: 10px; border: 1px solid #1b2c44; background: #0b1828; display: flex; flex-direction: column; gap: 12px; overflow: hidden">
|
|
104
|
+
<div><div style="font-size: 13px; font-weight: 600">What Claude did</div><div style="font-size: 11px; color: #8ea3bd">This session · 14:02–14:20 · saved as a snapshot</div></div>
|
|
105
|
+
<div style="display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 8px; background: rgba(244,197,66,0.10); color: #f4c542; font-size: 11px"><svg width="13" height="13" viewBox="0 0 24 24" style="flex-shrink: 0; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round"><path d="{{i.warn}}"></path></svg><span style="flex: 1">SMB interviews changed after Claude read it.</span><span style="{{s.mini}} background: rgba(244,197,66,0.16)">Tell Claude</span></div>
|
|
106
|
+
<sc-for list="{{activity}}" as="a" hint-placeholder-count="5">
|
|
107
|
+
<div style="display: flex; flex-direction: column; gap: 3px; padding-bottom: 8px; border-bottom: 1px solid #1b2c44">
|
|
108
|
+
<div style="display: flex; align-items: center; gap: 6px"><svg width="13" height="13" viewBox="0 0 24 24" style="fill: none; stroke: #B388FF; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round"><path d="{{a.icon}}"></path></svg><span style="font-size: 12px; font-weight: 600; flex: 1">{{a.name}}</span><span style="font-size: 11px; color: #6b7d94">{{a.n}}</span><sc-if value="{{a.action}}" hint-placeholder-val="{{ false }}"><span style="{{s.mini}} color: #e6eef7; border: 1px solid #2a4566">{{a.action}}</span></sc-if></div>
|
|
109
|
+
<div style="font-size: 11px; color: #8ea3bd; padding-left: 19px">{{a.items}}</div>
|
|
110
|
+
</div>
|
|
111
|
+
</sc-for>
|
|
112
|
+
</aside>
|
|
113
|
+
|
|
114
|
+
</div>
|
|
115
|
+
</section>
|
|
116
|
+
|
|
117
|
+
</div>
|
|
118
|
+
</x-dc>
|
|
119
|
+
<script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":1440,"height":1500}}'>
|
|
120
|
+
class Component extends DCLogic {
|
|
121
|
+
renderVals() {
|
|
122
|
+
var i = {
|
|
123
|
+
eye: 'M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12zM12 9.5a2.5 2.5 0 1 0 0 5a2.5 2.5 0 1 0 0-5',
|
|
124
|
+
eyeOff: 'M3 3l18 18M10.6 6.1A10 10 0 0 1 12 6c6.5 0 10 6 10 6a17 17 0 0 1-3 3.6M6.6 6.6C3.8 8.3 2 12 2 12s3.5 6 10 6a9.6 9.6 0 0 0 4.4-1',
|
|
125
|
+
spark: 'M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8z',
|
|
126
|
+
pen: 'M4 20l4.2-1L19 8.2 15.8 5 5 15.8z',
|
|
127
|
+
warn: 'M12 4l9 16H3zM12 10v4M12 17v.5',
|
|
128
|
+
pin: 'M9 4h6l-.8 5.5 2.8 3H7l2.8-3zM12 12.5V20',
|
|
129
|
+
link: 'M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1'
|
|
130
|
+
};
|
|
131
|
+
var V = '#B388FF', VA = 'rgba(179,136,255,0.16)';
|
|
132
|
+
var nodeBase = 'position:relative;height:80px;box-sizing:border-box;overflow:hidden;border-radius:10px;background:#0f1d31;box-shadow:0 1px 2px rgba(0,0,0,0.4),0 6px 20px rgba(0,0,0,0.24);';
|
|
133
|
+
var headBase = 'display:flex;align-items:center;gap:6px;height:34px;padding:0 8px 0 10px;border-bottom:1px solid #1b2c44;';
|
|
134
|
+
function mark(text, color, bg) { return 'display:flex;align-items:center;gap:4px;height:20px;padding:0 7px;border-radius:999px;font-size:11px;font-weight:500;flex-shrink:0;color:' + color + ';background:' + bg + ';'; }
|
|
135
|
+
function k(o) {
|
|
136
|
+
var pinned = !!o.pin;
|
|
137
|
+
return {
|
|
138
|
+
name: o.name, desc: o.desc, title: o.title, meta: o.meta,
|
|
139
|
+
node: nodeBase + (o.dashed ? 'border:1.5px dashed ' + V + ';background:rgba(179,136,255,0.06);' : pinned ? 'border:1.5px solid #4BBCFF;' : 'border:1px solid #1b2c44;'),
|
|
140
|
+
head: headBase + (pinned ? 'background:rgba(75,188,255,0.10);' : ''),
|
|
141
|
+
bar: !!o.bar, pin: pinned, byAgent: !!o.byAgent, actions: !!o.actions,
|
|
142
|
+
mark: !!o.icon, icon: o.icon || '', markText: o.markText || '',
|
|
143
|
+
markStyle: o.warn ? mark('', '#f4c542', 'rgba(244,197,66,0.14)') : o.muted ? mark('', '#8ea3bd', '#13243b') : mark('', V, VA)
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
var key = [
|
|
147
|
+
k({ name: 'In context — pinned by you', desc: 'Blue border, tinted header, pin badge.', title: 'Raise Pro to $24?', meta: 'question', pin: true }),
|
|
148
|
+
k({ name: 'In context — pinned by the agent', desc: 'Same blue, with a violet dot on the pin; hover says why.', title: 'Churn by plan', meta: 'pinned by Claude · 14:04', pin: true, byAgent: true }),
|
|
149
|
+
k({ name: 'Read by the agent', desc: 'It loaded this into its context, pinned or not.', title: 'Competitor pricing', meta: 'read 14:11', icon: i.eye, markText: 'read' }),
|
|
150
|
+
k({ name: 'Pinned, not read yet', desc: 'In context, but the agent hasn’t loaded it since you pinned it.', title: 'Pricing notes', meta: 'pinned 14:18', pin: true, icon: i.eyeOff, markText: 'not read', muted: true }),
|
|
151
|
+
k({ name: 'Created by the agent', desc: 'Its byline stays until you edit the node.', title: 'Churn flat after last raise', meta: 'created 14:06', icon: i.spark, markText: 'by Claude' }),
|
|
152
|
+
k({ name: 'Edited by the agent', desc: 'Violet bar for the session; “see change” opens the diff and undo.', title: 'SMB is price-sensitive', meta: 'edited 14:12 · see change', bar: true, icon: i.pen, markText: 'edited' }),
|
|
153
|
+
k({ name: 'Suggested by the agent', desc: 'A node, link or pin it proposes. Nothing changes until you accept.', title: 'Summary: case for $24', meta: '', dashed: true, icon: i.spark, markText: 'suggested', actions: true }),
|
|
154
|
+
k({ name: 'Agent’s copy is out of date', desc: 'Pinned and read, then changed. Amber, because it’s a real warning.', title: 'SMB interviews', meta: 'you added 2 calls · 14:15', pin: true, icon: i.warn, markText: 'changed since read', warn: true })
|
|
155
|
+
];
|
|
156
|
+
var lens = [
|
|
157
|
+
{ name: 'read', n: 4, icon: i.eye }, { name: 'created', n: 1, icon: i.spark }, { name: 'edited', n: 1, icon: i.pen },
|
|
158
|
+
{ name: 'suggested', n: 2, icon: i.link }, { name: 'pinned', n: 1, icon: i.pin }
|
|
159
|
+
];
|
|
160
|
+
var activity = [
|
|
161
|
+
{ name: 'Read', n: '4', icon: i.eye, items: 'Raise Pro to $24?, Competitor pricing, Churn by plan, SMB interviews', action: '' },
|
|
162
|
+
{ name: 'Pinned', n: '1', icon: i.pin, items: 'Churn by plan — “the chart the churn finding rests on”', action: 'Unpin' },
|
|
163
|
+
{ name: 'Created', n: '1', icon: i.spark, items: 'Churn flat after last raise', action: '' },
|
|
164
|
+
{ name: 'Edited', n: '1', icon: i.pen, items: 'SMB is price-sensitive — rewrote the second paragraph', action: 'Undo' },
|
|
165
|
+
{ name: 'Suggested', n: '2', icon: i.link, items: 'Node “Summary: case for $24”; link Competitor pricing → Raise Pro to $24? (supports)', action: 'Review' }
|
|
166
|
+
];
|
|
167
|
+
var s = {
|
|
168
|
+
rule: 'display:flex;align-items:flex-start;gap:10px;width:230px;box-sizing:border-box;padding:10px 12px;border-radius:10px;border:1px solid;background:#0f1d31;font-size:12px;line-height:1.45;',
|
|
169
|
+
ruleDot: 'width:12px;height:12px;border-radius:999px;flex-shrink:0;margin-top:3px;',
|
|
170
|
+
mini: 'height:20px;padding:0 8px;border-radius:6px;font-size:11px;font-weight:500;line-height:20px;'
|
|
171
|
+
};
|
|
172
|
+
var sc = {
|
|
173
|
+
node: 'position:absolute;width:250px;height:84px;box-sizing:border-box;overflow:hidden;border-radius:10px;border:1px solid #1b2c44;background:#0f1d31;box-shadow:0 1px 2px rgba(0,0,0,0.4),0 6px 20px rgba(0,0,0,0.24);',
|
|
174
|
+
head: 'display:flex;align-items:center;gap:6px;height:36px;padding:0 8px 0 10px;border-bottom:1px solid #1b2c44;',
|
|
175
|
+
title: 'flex:1;min-width:0;font-size:12px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;',
|
|
176
|
+
read: 'display:flex;align-items:center;gap:4px;height:20px;padding:0 7px;border-radius:999px;font-size:11px;font-weight:500;flex-shrink:0;color:' + V + ';background:' + VA + ';',
|
|
177
|
+
ic: 'fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;',
|
|
178
|
+
pin: 'width:18px;height:18px;border-radius:999px;background:#4BBCFF;color:#081524;display:flex;align-items:center;justify-content:center;flex-shrink:0;',
|
|
179
|
+
body: 'padding:8px 10px;font-size:11px;color:#8ea3bd;'
|
|
180
|
+
};
|
|
181
|
+
return { key: key, lens: lens, activity: activity, s: s, sc: sc, i: i };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
</script>
|
|
185
|
+
</body>
|
|
186
|
+
</html>
|