@rubytech/create-realagent-code 0.1.30 → 0.1.32
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/dist/index.js +37 -39
- package/package.json +1 -1
- package/payload/platform/lib/graph-trash/dist/index.d.ts +1 -1
- package/payload/platform/lib/graph-trash/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-trash/dist/index.js +1 -2
- package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-trash/src/index.ts +1 -2
- package/payload/platform/lib/persistent-components/dist/index.d.ts +11 -12
- package/payload/platform/lib/persistent-components/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/persistent-components/dist/index.js +11 -12
- package/payload/platform/lib/persistent-components/dist/index.js.map +1 -1
- package/payload/platform/lib/persistent-components/src/index.ts +11 -12
- package/payload/platform/neo4j/schema.cypher +10 -19
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +1 -7
- package/payload/platform/plugins/admin/mcp/dist/index.js +15 -582
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/access-manager/references/operations.md +7 -7
- package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +1 -1
- package/payload/platform/plugins/admin/skills/stream-log-review/references/analysis-patterns.md +2 -2
- package/payload/platform/plugins/anthropic/skills/get-api-key/SKILL.md +2 -4
- package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +0 -47
- package/payload/platform/plugins/docs/references/cloudflare.md +0 -1
- package/payload/platform/plugins/docs/references/deployment.md +9 -18
- package/payload/platform/plugins/docs/references/internals.md +4 -4
- package/payload/platform/plugins/docs/references/platform.md +5 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +11 -7
- package/payload/platform/plugins/email/references/email-reference.md +3 -7
- package/payload/platform/plugins/memory/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts +2 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js +2 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.d.ts +1 -1
- package/payload/platform/plugins/memory/references/graph-primitives.md +5 -5
- package/payload/platform/plugins/teaching/PLUGIN.md +2 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +1 -1
- package/payload/platform/plugins/whatsapp/skills/manage-whatsapp-config/SKILL.md +2 -8
- package/payload/platform/plugins/writer-craft/PLUGIN.md +2 -1
- package/payload/platform/scripts/component-knowledgedoc-backfill.ts +1 -1
- package/payload/platform/scripts/seed-neo4j.sh +9 -38
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +45 -44
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +11 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.d.ts +30 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js +175 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-observer.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts +4 -2
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js +15 -22
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +13 -14
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +28 -13
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-store.d.ts +9 -0
- package/payload/platform/services/claude-session-manager/dist/session-store.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-store.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +1 -25
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +3 -54
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +2 -0
- package/payload/platform/templates/agents/public/IDENTITY.md +1 -1
- package/payload/platform/templates/specialists/agents/content-producer.md +3 -3
- package/payload/platform/templates/specialists/agents/personal-assistant.md +2 -2
- package/payload/premium-plugins/teaching/PLUGIN.md +2 -1
- package/payload/premium-plugins/writer-craft/PLUGIN.md +2 -1
- package/payload/server/{chunk-NL7QLVAD.js → chunk-KVGTWNKQ.js} +1 -70
- package/payload/server/{chunk-2MRZBQMH.js → chunk-RZQMYJVY.js} +1 -1
- package/payload/server/{chunk-YPZFYTYP.js → chunk-ZGJ6CUU2.js} +1 -1
- package/payload/server/{cloudflare-task-tracker-QVOGHKWV.js → cloudflare-task-tracker-4PKOLE4H.js} +2 -2
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/assets/{Checkbox-YIF0payo.js → Checkbox-C6zXApx_.js} +1 -1
- package/payload/server/public/assets/admin-Cuu1QdAA.js +216 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Bz8mlxZZ.js → architectureDiagram-Q4EWVU46-BYXgFii5.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DwV8Z8-i.js → blockDiagram-DXYQGD6D-GIQ0eO13.js} +1 -1
- package/payload/server/public/assets/{brand-Bm671owU.js → brand-B-bNrpwc.js} +1 -1
- package/payload/server/public/assets/{brand-DqiRNMlu.css → brand-DdhkC994.css} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-DiUTejMp.js → c4Diagram-AHTNJAMY-BmyWfG-l.js} +1 -1
- package/payload/server/public/assets/channel-C76knBRO.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-4mHZpBXe.js → chunk-336JU56O-DcWl0MQo.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-Cbv0vrN9.js → chunk-426QAEUC-BIW6kq6y.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-BvLhId_2.js → chunk-4TB4RGXK-CdoHpV4X.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-bBafOTkw.js → chunk-5FUZZQ4R-bn_a4sfU.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-B0NqBKVy.js → chunk-5PVQY5BW-C_Rq8j_M.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-CFd4SqI6.js → chunk-EDXVE4YY-CWQvoVKV.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-ajf2sb6c.js → chunk-ENJZ2VHE-DBHn1kSk.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-pWg6bug7.js → chunk-ICPOFSXX-SW2Qx11O.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-OjEd-17c.js → chunk-OYMX7WX6-BvIG7tVW.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-DbEFSPoh.js → chunk-U2HBQHQK-BiBUb0cF.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-COdNwrBb.js → chunk-X2U36JSP-Y0MKZCCh.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-CHMWuY9B.js → chunk-YZCP3GAM-DKPh06GH.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-B-uDLQOB.js → chunk-ZZ45TVLE-C2WNo-fK.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-Bohexn7P.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DVsmsAu7.js +1 -0
- package/payload/server/public/assets/clone-DUrXF4sO.js +1 -0
- package/payload/server/public/assets/{dagre-bhIG_KnW.js → dagre-CrK8E9ee.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-CMEzmhIL.js → dagre-KV5264BT-_o6uXcH8.js} +1 -1
- package/payload/server/public/assets/data-j1WNhF8t.js +1 -0
- package/payload/server/public/assets/{device-url-actions-AcOyLSeF.js → device-url-actions-BcHerWqJ.js} +1 -1
- package/payload/server/public/assets/{diagram-5BDNPKRD-6RIoQhIL.js → diagram-5BDNPKRD-FFP9DKhc.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-BSp36TVv.js → diagram-G4DWMVQ6-DpwD1jBP.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-D54fo52D.js → diagram-MMDJMWI5-C3K5agdK.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-CWL8z-Pq.js → diagram-TYMM5635-CbeDipbC.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-AnnHBo3z.js → erDiagram-SMLLAGMA-XBIFndNy.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-laWmBl5o.js → flowDiagram-DWJPFMVM-BvEgySyn.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-B94ko8ie.js → ganttDiagram-T4ZO3ILL-D7gIRKJf.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DxzL1fxZ.js → gitGraphDiagram-UUTBAWPF-vJu_hcri.js} +1 -1
- package/payload/server/public/assets/graph-C_f_9L_7.js +1 -0
- package/payload/server/public/assets/graph-labels-BSQJHlgf.js +1 -0
- package/payload/server/public/assets/{graphlib-CY-zIElM.js → graphlib-Dp0mN6JW.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-BMTajIIr.js → infoDiagram-42DDH7IO-g4Dlc5Cr.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-B_QauE5O.js → ishikawaDiagram-UXIWVN3A-D_45LXOe.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DmlqSIih.js → journeyDiagram-VCZTEJTY-CggbHl6N.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-ZGDQT7xB.js → kanban-definition-6JOO6SKY-CysAe-Ab.js} +1 -1
- package/payload/server/public/assets/{line-D13opgep.js → line-BAxq_DSY.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-C650Sual.js → mermaid-parser.core-DbFuvkjL.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-BqnQoXTp.js → mermaid.core-CehvJn5b.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-BS_8y-tY.js → mindmap-definition-QFDTVHPH-DbPbBJ9h.js} +1 -1
- package/payload/server/public/assets/page-B0BPrSE3.js +1 -0
- package/payload/server/public/assets/{page-qSH972X0.js → page-Co7KCRV8.js} +2 -2
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-B5OmNvBO.js → pieDiagram-DEJITSTG-cagLL9ng.js} +1 -1
- package/payload/server/public/assets/{public-DDsYgotk.js → public-B6TEcDLx.js} +5 -5
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-DTYITdNo.js → quadrantDiagram-34T5L4WZ-Keaa1jDh.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-CRZWxH06.js → requirementDiagram-MS252O5E-BcYRyn5z.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DazRENhe.js → sankeyDiagram-XADWPNL6--fKoG9NR.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BcHTxmPy.js → sequenceDiagram-FGHM5R23-lKG36-Di.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DYU7nbqg.js → stateDiagram-FHFEXIEX-BuVsrlig.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DSt88_xL.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BKGmqkST.js → timeline-definition-GMOUNBTQ-D6X6uq17.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BXvLPmX7.js → vennDiagram-DHZGUBPP-BgvcfRVf.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BCclUa3Z.js → wardleyDiagram-NUSXRM2D-Cpd1xsrt.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-C-Xp-Eoc.js → xychartDiagram-5P7HB3ND-CDF5ZVFv.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +142 -278
- package/payload/platform/plugins/admin/hooks/onboarding-skill-drift.sh +0 -102
- package/payload/platform/plugins/admin/references/contextual-ui.md +0 -109
- package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +0 -240
- package/payload/platform/scripts/__tests__/admin-persist-audit.test.ts +0 -182
- package/payload/server/public/assets/admin-CDvF5de6.js +0 -216
- package/payload/server/public/assets/channel-PtVtoBEL.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-RVH_SEhY.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Cm3rAb93.js +0 -1
- package/payload/server/public/assets/clone-BjY0Wzht.js +0 -1
- package/payload/server/public/assets/data-K_kS__sL.js +0 -1
- package/payload/server/public/assets/graph-DeEigyO_.js +0 -1
- package/payload/server/public/assets/graph-labels-C7I5QvNv.js +0 -1
- package/payload/server/public/assets/page-B_rpjIRr.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BgljVtlp.js +0 -1
|
@@ -268,7 +268,7 @@ Invoke the agent with `[New session. Greet the visitor.]` and stream the respons
|
|
|
268
268
|
|
|
269
269
|
## Self-Contained Constraint
|
|
270
270
|
|
|
271
|
-
Public agents run
|
|
271
|
+
Public agents run on the same native Claude Code PTY surface as the admin agent. They have no filesystem access, no MCP write tools, no subagents — every tool is on a read-only or otherwise public-safe allowlist that the manager passes to the spawn as `--allowed-tools`. Everything the agent needs to say must come from its directory files or from the public-safe tool surface. The platform assembles directory files into the system prompt at invocation time.
|
|
272
272
|
|
|
273
273
|
## URL Routing
|
|
274
274
|
|
package/payload/platform/plugins/admin/skills/stream-log-review/references/analysis-patterns.md
CHANGED
|
@@ -29,7 +29,7 @@ Tags identify the event type. Key tags:
|
|
|
29
29
|
| `heartbeat` | Long-running session keepalive. |
|
|
30
30
|
| `active` / `disabled` / `unchanged` | Plugin/tool status during init. |
|
|
31
31
|
| `expanded` | Skill or slash command expanded. |
|
|
32
|
-
| `
|
|
32
|
+
| `browser-viewer` | VNC browser-viewer surface mounted on the chat. |
|
|
33
33
|
|
|
34
34
|
### Raw JSON lines
|
|
35
35
|
|
|
@@ -117,7 +117,7 @@ These indicate degraded behaviour or potential problems that didn't cause outrig
|
|
|
117
117
|
|---------|--------------|
|
|
118
118
|
| **Subagent dispatched** | `[subagent-start]` / `[agent-dispatch]` lines |
|
|
119
119
|
| **Skill expanded** | `[expanded]` line |
|
|
120
|
-
| **
|
|
120
|
+
| **VNC browser-viewer mounted** | `[browser-viewer]` lines |
|
|
121
121
|
| **Session completed successfully** | `result` JSON with `is_error: false` |
|
|
122
122
|
|
|
123
123
|
## Diagnosis Heuristics
|
|
@@ -15,9 +15,7 @@ Obtain an API key from the Anthropic Console (platform.claude.com) on behalf of
|
|
|
15
15
|
|
|
16
16
|
## Steps
|
|
17
17
|
|
|
18
|
-
1. **
|
|
19
|
-
- `name: "browser-viewer"`
|
|
20
|
-
- `data: { title: "Anthropic Console" }`
|
|
18
|
+
1. **Surface the VNC browser to the user.** Tell the user the Anthropic Console will appear in the VNC browser that is already mounted in the chat (no further tool call is needed; the chat surface mounts the VNC view automatically when a personal-assistant subagent is dispatched against `platform.claude.com`). If the VNC browser is not currently visible, ask the user to open the brand's VNC URL and confirm before proceeding.
|
|
21
19
|
|
|
22
20
|
2. **Dispatch personal-assistant for sign-in check and billing assessment.** Use the Agent tool with `specialists:personal-assistant` as the subagent type. Brief:
|
|
23
21
|
|
|
@@ -124,7 +122,7 @@ Handle the result the same as step 7.
|
|
|
124
122
|
|
|
125
123
|
## Important
|
|
126
124
|
|
|
127
|
-
-
|
|
125
|
+
- **Confirm the VNC browser is visible before dispatching the personal-assistant.** Without VNC mounted in the chat, automation runs invisibly and the user has no way to see what the specialist is doing. If the VNC view is missing, ask the user to open the brand's VNC URL in the chat and confirm it is showing the desktop before continuing.
|
|
128
126
|
- **Credits before keys.** Never create an API key before confirming that credits are loaded on the account. A key created on a zero-balance account is permanently non-functional.
|
|
129
127
|
- The browser is visible to the user via VNC. They can see everything the specialist does.
|
|
130
128
|
- The user must sign in themselves — the specialist does not fill credentials.
|
|
@@ -909,53 +909,6 @@ if [ "${SETUP_TUNNEL_DRY_RUN}" = "1" ]; then
|
|
|
909
909
|
exit 0
|
|
910
910
|
fi
|
|
911
911
|
|
|
912
|
-
# --------------------------------------------------------------------------
|
|
913
|
-
# Step 6: Persist onboarding step-7 completion BEFORE arming the restart.
|
|
914
|
-
#
|
|
915
|
-
# Task 562: the service restart below SIGTERMs the admin-agent subprocess
|
|
916
|
-
# before it can call `onboarding-complete-step 7`. Persisting the completion
|
|
917
|
-
# here — inside the shell script — removes the LLM from the decision path
|
|
918
|
-
# and closes the race. Next session's `loadOnboardingStep` / `getOnboardingState`
|
|
919
|
-
# reads the flag file and advances the graph via the same idempotent
|
|
920
|
-
# CASE-WHEN-NULL cypher as `completeOnboardingStep`.
|
|
921
|
-
#
|
|
922
|
-
# ACCOUNT_DIR is exported by claude-agent.ts::buildSpawnEnv and inherited
|
|
923
|
-
# by every Bash-tool subprocess. If it is unset, this script was invoked
|
|
924
|
-
# outside an agent session (operator-initiated reconfig via SSH) — there
|
|
925
|
-
# is no onboarding to persist, so skip loudly without error. No $PWD
|
|
926
|
-
# fallback: the Bash-tool cwd can drift across invocations, and writing
|
|
927
|
-
# the marker into a stray directory would silently detach it from any
|
|
928
|
-
# reader.
|
|
929
|
-
#
|
|
930
|
-
# The flag payload is JSON so the next session's consumer can use the
|
|
931
|
-
# real completion timestamp (not its own Date.now()) and cross-reference
|
|
932
|
-
# by tunnelId during forensic investigations.
|
|
933
|
-
# --------------------------------------------------------------------------
|
|
934
|
-
|
|
935
|
-
if [ -n "${ACCOUNT_DIR:-}" ]; then
|
|
936
|
-
ONBOARDING_DIR="${ACCOUNT_DIR}/onboarding"
|
|
937
|
-
ONBOARDING_FLAG="${ONBOARDING_DIR}/step7-complete"
|
|
938
|
-
PERSIST_NOW="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
939
|
-
if ! mkdir -p "${ONBOARDING_DIR}" 2>/dev/null; then
|
|
940
|
-
phase_line setup-tunnel step=onboarding-persist result=error \
|
|
941
|
-
reason=fs-flag-dir-failed path="${ONBOARDING_DIR}"
|
|
942
|
-
echo "WARNING: could not create ${ONBOARDING_DIR} — step-7 completion not persisted." >&2
|
|
943
|
-
echo " The next admin session will re-ask the Cloudflare question." >&2
|
|
944
|
-
elif ! printf '{"completedAt":"%s","tunnelId":"%s"}\n' "${PERSIST_NOW}" "${TUNNEL_ID}" \
|
|
945
|
-
> "${ONBOARDING_FLAG}" 2>/dev/null; then
|
|
946
|
-
phase_line setup-tunnel step=onboarding-persist result=error \
|
|
947
|
-
reason=fs-flag-write-failed path="${ONBOARDING_FLAG}"
|
|
948
|
-
echo "WARNING: could not write ${ONBOARDING_FLAG} — step-7 completion not persisted." >&2
|
|
949
|
-
echo " The next admin session will re-ask the Cloudflare question." >&2
|
|
950
|
-
else
|
|
951
|
-
phase_line setup-tunnel step=onboarding-persist result=ok \
|
|
952
|
-
path="${ONBOARDING_FLAG}" completedAt="${PERSIST_NOW}"
|
|
953
|
-
fi
|
|
954
|
-
else
|
|
955
|
-
phase_line setup-tunnel step=onboarding-persist result=skipped \
|
|
956
|
-
reason=no-account-dir
|
|
957
|
-
fi
|
|
958
|
-
|
|
959
912
|
# --------------------------------------------------------------------------
|
|
960
913
|
# Restart the brand's user-space service so resume-tunnel.sh (its
|
|
961
914
|
# ExecStartPre) picks up the new tunnel.state + config.yml and spawns the
|
|
@@ -30,7 +30,6 @@ When you submit, the `/api/admin/cloudflare/setup` endpoint runs — in strict o
|
|
|
30
30
|
- **Zone pre-flight** — for every non-apex hostname the script queries `1.1.1.1` for the registrable parent's NS records and refuses the whole run if they don't point at Cloudflare. Stream log: `step=zone-preflight result=ok|error zones_on_account=… missing_parent_for=…`. Catches "domain not on Cloudflare"; does not catch "domain on a different Cloudflare account than `cert.pem` is bound to" — that case surfaces later via `tunnel-status`.
|
|
31
31
|
- `cloudflared tunnel route dns` for each subdomain hostname. Apex hostnames cannot be routed this way — the script prints an **ACTION REQUIRED** block naming the exact dashboard record to add or edit. Stream log emits `step=route-dns hostname=… tunnel_id=…` before the call and `step=route-dns hostname=… result=ok|apex-skip|error` after; on error the bounded cloudflared stderr (≤400 chars) rides in the same phase line. **The script does not parse cloudflared's stdout** — exit code is the sole decision signal, so all three legitimate cloudflared output shapes (new record, overwrite, idempotent "already configured") are treated as success.
|
|
32
32
|
- `config.yml` and `tunnel.state` written under `${CFG_DIR}`.
|
|
33
|
-
- **Step-7 onboarding completion persisted** — the script writes `${ACCOUNT_DIR}/onboarding/step7-complete` (a JSON marker with the completion timestamp and tunnel ID) before arming the restart. Stream log: `step=onboarding-persist result=ok|error reason=<r>`. The marker is consumed by the next admin session's first state read and advances `OnboardingState.currentStep` to 7. Without this, the service restart below would SIGTERM the admin agent before it could persist step-7 completion, and the next session would re-ask the Cloudflare question you just finished. Both invocation surfaces (the form-driven action and the agent-via-Bash path) declare `ACCOUNT_DIR` explicitly because `systemd-run --user` does not inherit parent env — when ACCOUNT_DIR isn't reaching the script you'll see `result=skipped reason=no-account-dir` in the stream log instead of `result=ok`.
|
|
34
33
|
- **Post-restart resume contract** — when the script exits cleanly, the form fires a client-side resume event. The chat hook ([useAdminChat.ts](../../../../platform/ui/app/useAdminChat.ts)) waits for the brand-service to come back via `/api/health` (down-then-up), re-binds the conversation to the new server process, and sends the "Cloudflare setup completed" marker as a normal hidden chat POST that re-invokes the agent in a fresh session. No relay queue, no boot-drain, no banner. Diagnostic: `grep '\[admin-resume\] reason=post-restart' ~/{configDir}/logs/server.log` (expect one line per restart cycle), `grep '\[client-event\] kind=post-restart-resume' ~/{configDir}/logs/server.log` for the operator-visible client trace. See `.docs/web-chat.md` "Post-restart resume contract" for the full client/server contract.
|
|
35
34
|
- `systemctl --user restart ${BRAND}.service` — restarts the platform service so the new tunnel spawns via the service's `ExecStartPre=resume-tunnel.sh`.
|
|
36
35
|
- Post-restart verification — `ps -ef | grep '[c]loudflared'` confirms the connector is alive, then `curl -I https://<hostname>` against each subdomain (up to 60 s per host) confirms a non-530 response.
|
|
@@ -39,29 +39,20 @@ This installs all dependencies (Node.js, Neo4j, Cloudflare tunnel, Claude Code),
|
|
|
39
39
|
6. Starts the {{productName}} web server on port 19200
|
|
40
40
|
7. Configures systemd so everything restarts automatically if the Pi reboots
|
|
41
41
|
|
|
42
|
-
## First admin session —
|
|
42
|
+
## First admin session — install-time defaults
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
There is no onboarding state machine. At install time the installer writes three defaults into `data/accounts/<accountId>/account.json` (`enabledPlugins` from the brand's default set, `outputStyle: "default"`, `thinkingView: "default"`) and stamps a minimal `agents/admin/SOUL.md`. Diagnostic lines on the Pi:
|
|
45
45
|
|
|
46
|
-
- `seed-neo4j.sh` writes the node at install time with `currentStep=0`. The installer re-reads it before exiting; a missing node or an unreachable Neo4j fails the install loudly (`[install-invariant] onboarding-state-MISSING` or `onboarding-state-UNREACHABLE`).
|
|
47
|
-
- Every admin session-create reads `currentStep`. Anything below 9 keeps `onboarding_complete=false` on `/api/health` and `/api/admin/session`, and the chat opens on the next step's component (multi-select, dropdown, etc.).
|
|
48
|
-
- Every freshly-spawned admin claude session ships the `<onboarding-state currentStep="N">` directive as a third sentinel-wrapped section in `--append-system-prompt` (alongside `<host>` and `<attachment-ceiling>`). The agent's first turn calls `skill-load skillName=onboarding`. Resumed sessions skip the section so the agent doesn't re-ask the same step. (Task 043 — pre-fix the directive was prepended to the first user message; the Claude CLI's Ink TextInput interpreted each `\n` in the block as Enter, dropping the directive bytes before they reached the agent. The system prompt is the only multi-line-safe surface for PTY-spawned Claude Code.)
|
|
49
|
-
- If Neo4j is unreachable at session-create, the section becomes a loud-fail block (`graphUnreachable="true"`) and `onboarding_complete` is reported false — never silently skipped.
|
|
50
|
-
|
|
51
|
-
Diagnostic command on the Pi (substitute the brand's Neo4j port from `~/.maxy/.env` or `~/.realagent/.env`):
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
cypher-shell -a bolt://localhost:<brand-neo4j-port> \
|
|
55
|
-
"MATCH (o:OnboardingState) RETURN o.accountId, o.currentStep"
|
|
56
46
|
```
|
|
47
|
+
[install-defaults] account-json plugins=<n> outputStyle=default thinkingView=default
|
|
48
|
+
[install-defaults] soul-md path=<path>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Grep for both in `~/.<brand>/logs/install-*.log`. Absence after a clean install is the failure signal.
|
|
57
52
|
|
|
58
|
-
|
|
53
|
+
The first user-domain write the agent attempts (e.g. recording who the operator is) hits the graph-write gate's `Write blocked (no-admin-user)` or `Write blocked (no-local-business)` error. The agent then asks the persona question, persists the answer through the `business-profile` skill or `profile-update.personFields`, and proceeds. The error itself is the signal — grep `Write blocked` in `~/.<brand>/logs/server.log` to confirm.
|
|
59
54
|
|
|
60
|
-
-
|
|
61
|
-
- `[install-invariant] onboarding-state-MISSING`
|
|
62
|
-
- `[onboarding-gate] step=null complete=true` (the pre-Task-033 bug)
|
|
63
|
-
- missing `[skill-load] name=onboarding` while `[onboarding-gate]` reports `complete=false`
|
|
64
|
-
- missing `[onboarding-prompt] step=<n|missing|graph-unreachable> bytes=<n>` for a fresh spawn whose `[pty-spawn] appendSystemPromptBytes=` is at the bare 622-byte host + ceiling size (Task 043 — the onboarding directive failed to ship in the system prompt)
|
|
55
|
+
Cloudflare, WhatsApp, Telegram, and any other dormant capability surfaces on owner request via the `<dormant-plugins>` rule in `platform/templates/agents/admin/IDENTITY.md`. Execution is the existing plugin skill (`cloudflare:setup-tunnel`, etc.) — no banner, no per-step flag.
|
|
65
56
|
|
|
66
57
|
## Service Management
|
|
67
58
|
|
|
@@ -356,7 +356,7 @@ The server-side code in `claude-agent.ts` builds the system prompt before making
|
|
|
356
356
|
- Agent sees both: curated knowledge file + fresh graph results
|
|
357
357
|
|
|
358
358
|
**Path 3 — Memory-search only** (`knowledgeBaked: false`):
|
|
359
|
-
- No KNOWLEDGE.md exists (e.g., before
|
|
359
|
+
- No KNOWLEDGE.md exists (e.g., on a fresh install before the operator has had any conversations)
|
|
360
360
|
- Classifier decides whether to search (or falls back to always-search)
|
|
361
361
|
- Results injected as `<memory>...</memory>`
|
|
362
362
|
|
|
@@ -454,7 +454,7 @@ The SDK's per-tool override is `_meta["anthropic/alwaysLoad"]: true` on each MCP
|
|
|
454
454
|
1. **In-process plugins.** Every admin-eager tool is registered via `eagerTool(server, name, description, inputSchema, handler)` from `platform/lib/mcp-eager/` instead of `server.tool(...)`. The helper calls `server.registerTool` with the `_meta` flag set.
|
|
455
455
|
2. **Upstream graph proxy.** The upstream Python `mcp-neo4j-cypher` server has no `_meta` channel, so `platform/lib/graph-mcp/src/index.ts` intercepts every `tools/list` response on the wire and injects `_meta["anthropic/alwaysLoad"]: true` into each tool entry. The `[graph-mcp] tools/list eager-flagged count=<N>` stderr line confirms the injection fired.
|
|
456
456
|
|
|
457
|
-
**Curation rule.** Every MCP tool the admin agent calls routinely should be eager. The migrated set is `ADMIN_CORE_TOOLS` in `platform/ui/app/lib/claude-agent/spawn-env.ts` — when a tool sits on that list it must be registered via `eagerTool` (or arrive through the graph-mcp interceptor). Admin-skill / specialist / public-agent tools that are NOT in `ADMIN_CORE_TOOLS` stay on `server.tool()` today; they pay the ToolSearch tax only when their caller invokes them. The allow-list is the source of truth for the eager set, not necessarily the complete set of tools admin can ever call — skills that route into Bash + plugin-toggle / agent-config
|
|
457
|
+
**Curation rule.** Every MCP tool the admin agent calls routinely should be eager. The migrated set is `ADMIN_CORE_TOOLS` in `platform/ui/app/lib/claude-agent/spawn-env.ts` — when a tool sits on that list it must be registered via `eagerTool` (or arrive through the graph-mcp interceptor). Admin-skill / specialist / public-agent tools that are NOT in `ADMIN_CORE_TOOLS` stay on `server.tool()` today; they pay the ToolSearch tax only when their caller invokes them. The allow-list is the source of truth for the eager set, not necessarily the complete set of tools admin can ever call — skills that route into Bash + plugin-toggle / agent-config tools are an existing gap to widen the allow-list against, separately from the eager-load mechanism.
|
|
458
458
|
|
|
459
459
|
**Observability.** Spawn-time emit: `[tool-surface] session=<convId> permission_allowed=N eager_intent=E eager_set_size=T`. Turn-end emit: `[admin-agent] turn-end ... toolsearch=N toolsearch_unique=U`. A non-zero `toolsearch` on a fresh turn for an eager-intended tool means a plugin reverted to `server.tool()` — fix at the plugin's MCP registration site, not the allow-list.
|
|
460
460
|
|
|
@@ -489,7 +489,7 @@ Each log entry includes the tool name and a truncated conversation ID for correl
|
|
|
489
489
|
|
|
490
490
|
## Process provenance — durable actions emit Tasks
|
|
491
491
|
|
|
492
|
-
Every durable action —
|
|
492
|
+
Every durable action — cloudflare tunnel-login, brand publish, future deterministic flows — emits a `:Task {kind:"<flow>"}` node carrying the action's lifecycle and a `:PRODUCED` edge to every entity the action created. This makes the graph traversable from the originating Conversation to every entity created during it via `(c)<-[:RAISED_DURING]-(t:Task)-[:PRODUCED]->(e)` — answering "what did this turn produce" in one Cypher hop.
|
|
493
493
|
|
|
494
494
|
The doctrine is enforced at the storage primitive: writes to `:Person`, `:UserProfile`, `:AdminUser`, `:Organization`, `:LocalBusiness`, `:CloudflareTunnel`, or `:CloudflareHostname` MUST include at least one inbound `:PRODUCED` edge whose source is one of `:Task`, `:Conversation`, or `:Message`. Subtype labels like `:AdminConversation`, `:UserMessage`, `:AssistantMessage`, `:AdminMessage` qualify because the gate checks the full `labels()` array. Bootstrap writes (PIN-setup, schema migrations, lazy first-session UserProfile creation) are exempt via `createdBy.agent === 'system'`.
|
|
495
495
|
|
|
@@ -499,7 +499,7 @@ Two surfaces feed the gate. (1) **Workflow path:** `memory-write` accepts an opt
|
|
|
499
499
|
|
|
500
500
|
Operator audit cyphers:
|
|
501
501
|
- "What entities did this conversation's actions produce?" — `MATCH (c:AdminConversation {conversationId:$id})<-[:RAISED_DURING]-(t:Task)-[:PRODUCED]->(e) RETURN labels(e), e.name, t.kind, t.status`
|
|
502
|
-
- "What cloudflare resources did this
|
|
502
|
+
- "What cloudflare resources did this tunnel-login produce?" — `MATCH (t:Task {kind:'cloudflare-tunnel-login', status:'completed'})-[:PRODUCED]->(r) RETURN t.taskId, r.tunnelId, r.hostnameValue ORDER BY t.completedAt DESC`
|
|
503
503
|
|
|
504
504
|
See `.docs/neo4j.md § Process provenance doctrine` for the full enforcement contract, observability surface, and out-of-scope deferrals.
|
|
505
505
|
|
|
@@ -69,7 +69,11 @@ The admin interface is a three-pane layout: a sidebar on the left with your bran
|
|
|
69
69
|
|
|
70
70
|
Page titles are brand-aware: the browser tab shows your product name (e.g. `Real Agent` instead of `Maxy`) on every shell — chat, graph, and data — so a non-default brand never leaks the default name in tab strips or browser history.
|
|
71
71
|
|
|
72
|
-
**
|
|
72
|
+
**Session lifecycle and reconcile model.** The sidebar Sessions list and the ConversationsModal share one fetch loop (`useAdminSessions`). Every fetch is operator-triggered: first load on mount (`ensureLoaded`), the refresh button on the sessions group head, and a single `refetch` appended to every mutation in `session-actions` (resume, end, purge, archive, unarchive). There is no idle ticker; the UI does not call `/api/admin/claude-sessions` between operator actions, so the DevTools console stays quiet while you are not clicking anything. Each fetch emits exactly one line: `[admin-ui] sessions-poll outcome=<unchanged|changed|error> count=<n> cacheKey=<8>`. The format is held from the prior polling shape so existing log greps still match; the rate just drops to one per user action. Byte-identical responses skip the `setSessions` commit (projection-equality gate) so AdminShell does not re-render when the list has not changed.
|
|
73
|
+
|
|
74
|
+
The trade-off is staleness for PTY exits that happen outside this UI: a Claude Code crash, an `ssh` kill of the brand process, or a sibling tab spawning a new session stays invisible in the current tab until you click the refresh button or perform another mutation. Two open tabs can show different lists until both refresh. The accepted view is that every lifecycle event in this dashboard originates from a click in this dashboard, so a missing ticker cannot deliver information the operator did not already cause.
|
|
75
|
+
|
|
76
|
+
The metadata pane subscribes to the same /list projection. When an operator clicks End on an alive row, the DELETE returns 200 and the post-mutation refetch decides what happens next: a session that wrote a JSONL surfaces as a dehydrated `status: 'ended'` row (the pane swaps `End session` for `Purge JSONL` plus `Resume`), and a session that never wrote a JSONL (`Turns: 0`) leaves the list entirely (the pane shows a `Session ended without a transcript. Close this pane.` banner with a Close button and no destructive action). The manager's `/list` and `/meta` are the only authorities on post-End state; the client does not pre-empt either response with an optimistic mutation.
|
|
73
77
|
|
|
74
78
|
The Data search panel ranks results by combining vector similarity with keyword (BM25) matching. Each row shows a one-line score breakdown — `vector 0.NN · bm25 0.NN · combined 0.NN` — so you can tell whether a row surfaced because of meaning, exact-keyword match, or both. A bm25 column of `0.00` across every row means your search term wasn't in the keyword index, so ranking fell back to pure vector similarity (this can produce surprising results — the breakdown tells you when to interpret with caution). Above the result list, a chip row shows the unique types in your current results — click one to filter, click again to clear. Click any row to jump straight to that node's neighbourhood in the Graph; from the artefact pane the graph opens alongside chat, from the standalone Data page it opens in place.
|
|
75
79
|
|
|
@@ -531,14 +531,18 @@ sudo systemctl --user start maxy-ui
|
|
|
531
531
|
|
|
532
532
|
**A chat turn looks broken — assistant bubble never rendered:** Open `claude-agent-stream-<sessionKey>.log` and grep for `[sse-client]`. The five phases (`connected`, `event_received`, `render_complete`, `error`, `close`) tell the story in order. Missing `connected` = the chat fetch never returned 200; missing `event_received` = the server emitted nothing or the client lost the stream before the first frame; missing `render_complete` = the reducer never committed the assistant bubble (persist_ack never arrived). The operator can also click "Report this turn" in the chat menu to append a `[failure-report]` line carrying the same sessionKey + conversationId + clientSnapshot, plus copy the payload to the clipboard.
|
|
533
533
|
|
|
534
|
-
## Admin DevTools console floods with `onboarding-banner-mount` or
|
|
534
|
+
## Admin DevTools console floods with `onboarding-banner-mount` or `sessions-poll` lines
|
|
535
535
|
|
|
536
|
-
**Symptom
|
|
536
|
+
**Symptom (pre-Task-050).** Open DevTools on the admin shell at `/` with `onboardingComplete=false`, leave the page idle for a minute, then scroll back through the console. You would see thousands of `[admin-ui] onboarding-banner-mount onboardingComplete=false` lines (one per AdminShell render, roughly 40/min driven by the 3s sessions poll) and no per-tick poll telemetry at all.
|
|
537
537
|
|
|
538
|
-
**
|
|
538
|
+
**Steady-state invariants at `/` (post-Task-067):**
|
|
539
539
|
|
|
540
|
-
- `grep -c '\[admin-ui\] onboarding-banner-mount' ~/.maxy/logs/admin-ui-console.log` equals page-load count plus onboarding-flip count, not the render count. Sustained climb at idle
|
|
541
|
-
- `grep -c '\[admin-ui\] sessions-poll' ~/.maxy/logs/admin-ui-console.log`
|
|
542
|
-
- `outcome=error` lines name a real fetch failure
|
|
540
|
+
- `grep -c '\[admin-ui\] onboarding-banner-mount' ~/.maxy/logs/admin-ui-console.log` equals page-load count plus onboarding-flip count, not the render count. Sustained climb at idle means the banner mount log regressed back into the render body (Task 050 fix).
|
|
541
|
+
- `grep -c '\[admin-ui\] sessions-poll' ~/.maxy/logs/admin-ui-console.log` over a 60-minute idle window equals zero. The hook no longer installs a `setInterval`; every `sessions-poll` line is operator-triggered (initial mount, refresh button, post-mutation refetch). One or more lines during operator idle means `setInterval` was reinstated.
|
|
542
|
+
- `outcome=error` lines name a real fetch failure on an operator-triggered refetch, set the `error` field, and surface in the sidebar.
|
|
543
543
|
|
|
544
|
-
**
|
|
544
|
+
**Reconcile signal (Task 067):**
|
|
545
|
+
|
|
546
|
+
- `grep -c '\[admin-ui\] sidebar-meta-pane-reconcile' ~/.maxy/logs/admin-ui-console.log` should equal the count of End / Resume / Purge clicks while the metadata pane was open. A `to=gone` line without a paired Close click means the pane's auto-close logic regressed.
|
|
547
|
+
|
|
548
|
+
**Why this matters.** The render-body log was misleading: it read as "the admin agent is checking onboarding state continuously", when in fact `onboardingComplete` had not changed at all. The Task 050 fix moved the log into `useEffect(…, [])`; Task 067 then dropped the per-tick poll entirely, so a quiet console is now the steady state. With both fixes in place, console output is a faithful record of what the page actually did each operator click.
|
|
@@ -4,9 +4,7 @@ Full reference for the email plugin. Load with `plugin-read` when detailed confi
|
|
|
4
4
|
|
|
5
5
|
## Setup
|
|
6
6
|
|
|
7
|
-
Collect email credentials
|
|
8
|
-
|
|
9
|
-
**Fields:**
|
|
7
|
+
Collect email credentials in plain chat, one field at a time or as a numbered checklist the operator fills in:
|
|
10
8
|
|
|
11
9
|
| name | label | type | required | placeholder |
|
|
12
10
|
|------|-------|------|----------|-------------|
|
|
@@ -22,7 +20,7 @@ Collect email credentials via a form. Render this `form` component with `render-
|
|
|
22
20
|
|
|
23
21
|
The `agentAddress` field is for catchall/alias setups where the authentication email differs from the address the agent operates as. Leave empty when they're the same.
|
|
24
22
|
|
|
25
|
-
After
|
|
23
|
+
After the operator confirms all values, pass them to `email-setup`. On success, confirm "credentials stored" and the inbox count. On failure, relay the diagnostic — the tool returns specific guidance (wrong password, connection refused, TLS mismatch).
|
|
26
24
|
|
|
27
25
|
The agent never displays stored passwords. Never name or recommend specific email providers — the form collects the standard fields every provider gives its users.
|
|
28
26
|
|
|
@@ -154,9 +152,7 @@ When enabled, a public agent replies to incoming emails. The auto-respond binary
|
|
|
154
152
|
|
|
155
153
|
### Setup
|
|
156
154
|
|
|
157
|
-
To enable auto-respond, call `email-auto-respond-config` with `enabled: true`. The tool requires an `agentSlug
|
|
158
|
-
|
|
159
|
-
When called without an `agentSlug`, the tool returns available agents. Present these as a `single-select` component for the admin to choose from, then call the tool again with the selected slug.
|
|
155
|
+
To enable auto-respond, call `email-auto-respond-config` with `enabled: true`. The tool requires an `agentSlug`. When called without a slug, the tool returns available public agents — present these as a numbered list in plain chat so the admin can choose which agent handles responses, then call the tool again with the selected slug.
|
|
160
156
|
|
|
161
157
|
### Configuration
|
|
162
158
|
|
|
@@ -118,7 +118,7 @@ Graph hygiene is **agent-directed, case by case** — no autonomous rule engine,
|
|
|
118
118
|
|
|
119
119
|
**Single-node removal.** Use `memory-delete` by `elementId`. The node is marked `:Trashed` (relationships preserved, invisible to `memory-search` and any read filtered via `notTrashed`). For `KnowledgeDocument`, the trash cascades to linked `Section` and `Chunk` children. Restore via `memory-restore` (fails loudly when an active node already holds a unique slot the trashed one needs back). Hard removal happens later via `memory-empty-trash` after the grace period (default 30 days). GDPR cascades go through `contact-erase` (per Art. 17) — that bypasses the trash primitive deliberately. There is no bulk delete-by-shape.
|
|
120
120
|
|
|
121
|
-
**Why soft-delete.** On 2026-04-20 an autonomous orphan-delete rule wiped
|
|
121
|
+
**Why soft-delete.** On 2026-04-20 an autonomous orphan-delete rule wiped 19 nodes in one `graph-prune-run` call; properties were unrecoverable (Neo4j Community has no PITR, no APOC). The cron, the `graph-prune-run` tool, and the rule engine have been removed. An earlier fix added the `:Trashed` label primitive so every soft-delete caller (`memory-delete`, `contact-delete`, the admin `/graph` page's trash button) runs the same shared `trashNode` helper — relationships preserved, unique keys snapshotted into `_trashedKeys`, audit lines `[trash:marked] by=<surface>` for cross-cut provenance.
|
|
122
122
|
|
|
123
123
|
## Conversational Memory
|
|
124
124
|
|
|
@@ -1087,7 +1087,7 @@ if (!readOnly) {
|
|
|
1087
1087
|
server.tool("memory-restore", "Undo memory-delete on a single graph node by elementId. Removes the :Trashed label and restores " +
|
|
1088
1088
|
"snapshotted unique-key properties. For KnowledgeDocument, walks HAS_SECTION/HAS_CHUNK edges to bring " +
|
|
1089
1089
|
"trashed children back too. Fails loudly when an active node already holds a unique slot the trashed " +
|
|
1090
|
-
"node needs back (e.g. a fresh
|
|
1090
|
+
"node needs back (e.g. a fresh LocalBusiness was created while the old one was in trash) — " +
|
|
1091
1091
|
"the error names the conflicting elementId so the caller can decide how to resolve.", {
|
|
1092
1092
|
elementId: z.string().describe("Neo4j elementId of the trashed node to restore."),
|
|
1093
1093
|
}, async ({ elementId }) => {
|