@rubytech/create-maxy-code 0.1.35 → 0.1.37
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/package.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +12 -0
- package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +109 -0
- package/payload/platform/plugins/admin/hooks/turn-completed-graph-write.sh +114 -0
- package/payload/platform/plugins/admin/skills/unzip-attachment/SKILL.md +1 -1
- package/payload/platform/plugins/contacts/PLUGIN.md +11 -0
- package/payload/platform/plugins/docs/references/internals.md +10 -0
- package/payload/platform/plugins/docs/references/platform.md +11 -4
- package/payload/platform/plugins/email/PLUGIN.md +11 -0
- package/payload/platform/plugins/linkedin-import/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/linkedin-import/PLUGIN.md +5 -5
- package/payload/platform/plugins/linkedin-import/skills/linkedin-import/SKILL.md +3 -1
- package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/connections.md +2 -2
- package/payload/platform/plugins/memory/PLUGIN.md +11 -0
- package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +2 -0
- package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +2 -0
- package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +6 -4
- package/payload/platform/plugins/outlook/PLUGIN.md +11 -0
- package/payload/platform/plugins/replicate/PLUGIN.md +11 -0
- package/payload/platform/plugins/scheduling/PLUGIN.md +11 -0
- package/payload/platform/plugins/tasks/PLUGIN.md +11 -0
- package/payload/platform/plugins/telegram/PLUGIN.md +11 -0
- package/payload/platform/plugins/waitlist/PLUGIN.md +11 -0
- package/payload/platform/plugins/whatsapp/PLUGIN.md +11 -0
- package/payload/platform/plugins/workflows/PLUGIN.md +11 -0
- package/payload/platform/scripts/seed-neo4j.sh +14 -0
- package/payload/platform/scripts/verify-skill-tool-surface.sh +5 -3
- package/payload/platform/services/claude-session-manager/dist/config.d.ts +0 -5
- package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.js +16 -6
- package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +0 -5
- 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 +109 -139
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +63 -4
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +47 -61
- 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 +191 -131
- 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 +43 -37
- 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 +72 -61
- package/payload/platform/services/claude-session-manager/dist/session-store.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts +34 -4
- package/payload/platform/services/claude-session-manager/dist/tool-surface.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/tool-surface.js +125 -27
- package/payload/platform/services/claude-session-manager/dist/tool-surface.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +9 -18
- package/payload/platform/templates/specialists/agents/database-operator.md +27 -70
- package/payload/platform/templates/specialists/agents/librarian.md +55 -0
- package/payload/server/public/assets/{Checkbox-8mOR8-gV.js → Checkbox-DAki3vDW.js} +1 -1
- package/payload/server/public/assets/{admin-CK4V-B9A.js → admin-CyAZtsYZ.js} +1 -1
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-2DgPtOot.js → architectureDiagram-Q4EWVU46-C-hla3Ip.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BilycXVZ.js → blockDiagram-DXYQGD6D-CbzjtNs3.js} +1 -1
- package/payload/server/public/assets/{brand-1_DraUIv.css → brand-Cun0PBrA.css} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CGiIFO5U.js → c4Diagram-AHTNJAMY-B87UblA0.js} +1 -1
- package/payload/server/public/assets/channel-CTNo72W7.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-DxTg1h50.js → chunk-336JU56O-2a2pVlSg.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-DkGPjs0P.js → chunk-426QAEUC-j9NOD8_a.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-D2JaxD6r.js → chunk-4TB4RGXK-Cs872xAq.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-Do3pbAGo.js → chunk-5FUZZQ4R-BnDFbZ_I.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-np5moZSl.js → chunk-5PVQY5BW-Bu5B3Hyf.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-BUFLWwRP.js → chunk-EDXVE4YY-B96Fw4FF.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-BE7Gt41s.js → chunk-ENJZ2VHE-CcGrGQim.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-gOBkROMP.js → chunk-ICPOFSXX-ZRvcI4Ai.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-DR-BkNZa.js → chunk-OYMX7WX6-B6RI9Fbf.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-qLp-uSVE.js → chunk-U2HBQHQK-BYGHVYyo.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-DQiKti0J.js → chunk-X2U36JSP-rwNs-gTO.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-Cd0JhpTo.js → chunk-YZCP3GAM-jPttJRap.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-8u01H3Hy.js → chunk-ZZ45TVLE-DLykWOT5.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-BaV5nDmT.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DOKlCKjY.js +1 -0
- package/payload/server/public/assets/clone-sQSwlSln.js +1 -0
- package/payload/server/public/assets/{dagre-KV5264BT-BBF_zxbi.js → dagre-KV5264BT-C6wSzHX2.js} +1 -1
- package/payload/server/public/assets/{dagre-BfVsOYOv.js → dagre-jnQDnF-5.js} +1 -1
- package/payload/server/public/assets/data-DbkuXcPb.js +1 -0
- package/payload/server/public/assets/{device-url-actions-CJBD3ecO.js → device-url-actions-y1tXNDZx.js} +1 -1
- package/payload/server/public/assets/{diagram-5BDNPKRD-BFHk2a7t.js → diagram-5BDNPKRD-N3X-n90h.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-Be3_qYl2.js → diagram-G4DWMVQ6-vfmbzdPd.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-B3r4XVcu.js → diagram-MMDJMWI5-BETmPx_w.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-BW5EIT4D.js → diagram-TYMM5635-BSUGM4wG.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-DTu4_1Kb.js → erDiagram-SMLLAGMA-CWZ9OwMb.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-CadrjLcA.js → flowDiagram-DWJPFMVM-BpQOQS1a.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-Cn0npD0L.js → ganttDiagram-T4ZO3ILL-Dc59igCS.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-CK3gG5Qm.js → gitGraphDiagram-UUTBAWPF-D6lXg3zl.js} +1 -1
- package/payload/server/public/assets/graph-CC5_6-dg.js +1 -0
- package/payload/server/public/assets/{graph-labels-CPzF6Gbk.js → graph-labels-DFyNH0jb.js} +1 -1
- package/payload/server/public/assets/{graphlib-DFIOO59N.js → graphlib-yG7kH8Fr.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-BohUsXnN.js → infoDiagram-42DDH7IO-TS9Pv8Os.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-tjmA4BU8.js → ishikawaDiagram-UXIWVN3A-BJiJJTq6.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DzBlFESM.js → journeyDiagram-VCZTEJTY-C7PW4fmw.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-BTw9BxK8.js → kanban-definition-6JOO6SKY-BEk21ciD.js} +1 -1
- package/payload/server/public/assets/{line-BYPL6wAj.js → line-DusyVWDE.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-Dmu4fWCS.js → mermaid-parser.core-DeeojQSb.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-Z9vvieC2.js → mermaid.core-p65Lo7Sj.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-BccAnfJ4.js → mindmap-definition-QFDTVHPH-B0jxFxdS.js} +1 -1
- package/payload/server/public/assets/{page-CBTlFm3b.js → page-BeYGnDzI.js} +1 -1
- package/payload/server/public/assets/{page-CDrsNrDO.js → page-x5khmfRx.js} +1 -1
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-CZwxH1nJ.js → pieDiagram-DEJITSTG-DJ5GKYt6.js} +1 -1
- package/payload/server/public/assets/{public-MKWxjwiF.js → public-cnoUs7vq.js} +3 -3
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BWT4DItX.js → quadrantDiagram-34T5L4WZ-BV7R-kwV.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-CHYkWUEy.js → requirementDiagram-MS252O5E-DRiLzlGN.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-km7p45Ng.js → sankeyDiagram-XADWPNL6-C5-6_cCI.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BT1C0Dw-.js → sequenceDiagram-FGHM5R23-5FXm_VYM.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-hibC19DY.js → stateDiagram-FHFEXIEX-FCQTaGqV.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BdpPhdqg.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Cnm86NfE.js → timeline-definition-GMOUNBTQ-tvtq62ef.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-ByjQPLzS.js → vennDiagram-DHZGUBPP-Dk-k7CE4.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-CMVrWw7l.js → wardleyDiagram-NUSXRM2D-CZSrqniY.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-Mpc1u3FV.js → xychartDiagram-5P7HB3ND-CpGLpk7Q.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 +128 -106
- package/payload/server/public/assets/channel-DYpIZW3Q.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-nkfy9gg7.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B-pMmeCC.js +0 -1
- package/payload/server/public/assets/clone-jiTzIER6.js +0 -1
- package/payload/server/public/assets/data-BIOaDoqe.js +0 -1
- package/payload/server/public/assets/graph-ClfU7t1k.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-MuJZxjmU.js +0 -1
- /package/payload/server/public/assets/{brand-CENN2zdq.js → brand-lj7EhWRg.js} +0 -0
|
@@ -1,81 +1,92 @@
|
|
|
1
|
-
// In-memory session store.
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// alive→ended and across manager restarts.
|
|
1
|
+
// In-memory session store. One identifier per Claude process, but the
|
|
2
|
+
// spawn-time window between PTY creation and Claude Code writing its first
|
|
3
|
+
// JSONL line is now unbounded: claude does not write the JSONL until the
|
|
4
|
+
// operator types the first turn (verified Pi 2.1.143 and Mac 2.1.128).
|
|
6
5
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
6
|
+
// Lifecycle spans the full PTY lifetime:
|
|
7
|
+
//
|
|
8
|
+
// pending — created when /spawn captures the /remote-control URL.
|
|
9
|
+
// The row is keyed by the URL `bridgeSuffix` (the substring
|
|
10
|
+
// after `session_` in the URL). `claudeSessionId` is null;
|
|
11
|
+
// `jsonlPath` is null. The /spawn response returns at this
|
|
12
|
+
// point, so the operator sees a usable row inside ~2 s even
|
|
13
|
+
// when they never type.
|
|
14
|
+
//
|
|
15
|
+
// promoted — fires later (seconds or minutes, gated on operator typing)
|
|
16
|
+
// when `jsonl-observer` matches a JSONL on disk whose head
|
|
17
|
+
// bytes carry the bridge suffix. `claudeSessionId` is filled
|
|
18
|
+
// with the intrinsic JSONL basename, `jsonlPath` is set, and
|
|
19
|
+
// the same StoredSession is also registered under the
|
|
20
|
+
// intrinsic id so GET routes resolve either id to the same
|
|
21
|
+
// row.
|
|
22
|
+
//
|
|
23
|
+
// ended — operator deletes the row, the PTY exits, or the manager
|
|
24
|
+
// restarts. Promoted rows stay enumerable from disk via the
|
|
25
|
+
// JSONL transcript. Pending rows that never promoted have no
|
|
26
|
+
// JSONL and disappear cleanly on delete.
|
|
27
|
+
//
|
|
28
|
+
// The store mints zero ids of its own. The bridge suffix is claude's, the
|
|
29
|
+
// intrinsic id is claude's. The manager only observes them.
|
|
13
30
|
export class SessionStore {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
31
|
+
/** Keyed by the row's stable surface id (bridge suffix). Lookup-by-bridge
|
|
32
|
+
* is the alive-row contract. */
|
|
33
|
+
byBridge = new Map();
|
|
34
|
+
/** Filled at promotion time so /list, /meta, /log routes resolve the
|
|
35
|
+
* intrinsic id to the same StoredSession the bridge id resolves to. */
|
|
36
|
+
byClaude = new Map();
|
|
37
|
+
/** Register a freshly-spawned session (claudeSessionId null, jsonlPath
|
|
38
|
+
* null). The row becomes visible to /list immediately. */
|
|
39
|
+
addPending(s) {
|
|
40
|
+
this.byBridge.set(s.bridgeSuffix, s);
|
|
18
41
|
}
|
|
42
|
+
/** Resolve by either the bridge suffix or the intrinsic claudeSessionId.
|
|
43
|
+
* Returns the same StoredSession in either case once promotion has
|
|
44
|
+
* fired. */
|
|
19
45
|
get(id) {
|
|
20
|
-
return this.
|
|
46
|
+
return this.byBridge.get(id) ?? this.byClaude.get(id);
|
|
21
47
|
}
|
|
48
|
+
/** Remove by either id. Drops both index entries. */
|
|
22
49
|
remove(id) {
|
|
23
|
-
const s = this.
|
|
24
|
-
if (s)
|
|
25
|
-
|
|
50
|
+
const s = this.get(id);
|
|
51
|
+
if (!s)
|
|
52
|
+
return undefined;
|
|
53
|
+
this.byBridge.delete(s.bridgeSuffix);
|
|
54
|
+
if (s.claudeSessionId !== null)
|
|
55
|
+
this.byClaude.delete(s.claudeSessionId);
|
|
26
56
|
return s;
|
|
27
57
|
}
|
|
28
|
-
listBySender(senderId) {
|
|
58
|
+
listBySender(senderId, opts = {}) {
|
|
59
|
+
const includeHidden = opts.includeHidden === true;
|
|
29
60
|
const out = [];
|
|
30
|
-
for (const s of this.
|
|
31
|
-
if (s.senderId
|
|
32
|
-
|
|
61
|
+
for (const s of this.byBridge.values()) {
|
|
62
|
+
if (s.senderId !== senderId)
|
|
63
|
+
continue;
|
|
64
|
+
if (!includeHidden && s.hidden)
|
|
65
|
+
continue;
|
|
66
|
+
out.push(s);
|
|
33
67
|
}
|
|
34
68
|
return out;
|
|
35
69
|
}
|
|
36
70
|
all() {
|
|
37
|
-
return [...this.
|
|
71
|
+
return [...this.byBridge.values()];
|
|
38
72
|
}
|
|
39
73
|
size() {
|
|
40
|
-
return this.
|
|
41
|
-
}
|
|
42
|
-
// --- pending lifecycle ----------------------------------
|
|
43
|
-
addPending(p) {
|
|
44
|
-
this.pendingByBridge.set(p.bridgeSuffix, p);
|
|
45
|
-
}
|
|
46
|
-
getPending(bridgeSuffix) {
|
|
47
|
-
return this.pendingByBridge.get(bridgeSuffix);
|
|
48
|
-
}
|
|
49
|
-
removePending(bridgeSuffix) {
|
|
50
|
-
const p = this.pendingByBridge.get(bridgeSuffix);
|
|
51
|
-
if (p)
|
|
52
|
-
this.pendingByBridge.delete(bridgeSuffix);
|
|
53
|
-
return p;
|
|
74
|
+
return this.byBridge.size;
|
|
54
75
|
}
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (!p)
|
|
76
|
+
/** Bind a pending row to its newly-observed `claudeSessionId` + JSONL
|
|
77
|
+
* path. Idempotent: a second call on an already-promoted row updates
|
|
78
|
+
* nothing. Returns the StoredSession on success, null when no row
|
|
79
|
+
* exists for the bridge suffix (operator already deleted it, or the
|
|
80
|
+
* PTY exited before observation fired). */
|
|
81
|
+
promote(bridgeSuffix, claudeSessionId, jsonlPath) {
|
|
82
|
+
const s = this.byBridge.get(bridgeSuffix);
|
|
83
|
+
if (!s)
|
|
64
84
|
return null;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
startedAt: p.startedAt,
|
|
71
|
-
senderId: p.senderId,
|
|
72
|
-
role: p.role,
|
|
73
|
-
channel: p.channel,
|
|
74
|
-
jsonlPath,
|
|
75
|
-
pty: p.pty,
|
|
76
|
-
exited: p.exited,
|
|
77
|
-
};
|
|
78
|
-
this.sessions.set(claudeSessionId, s);
|
|
85
|
+
if (s.claudeSessionId !== null)
|
|
86
|
+
return s;
|
|
87
|
+
s.claudeSessionId = claudeSessionId;
|
|
88
|
+
s.jsonlPath = jsonlPath;
|
|
89
|
+
this.byClaude.set(claudeSessionId, s);
|
|
79
90
|
return s;
|
|
80
91
|
}
|
|
81
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,2EAA2E;AAC3E,yEAAyE;AACzE,uEAAuE;AACvE,EAAE;AACF,yCAAyC;AACzC,EAAE;AACF,sEAAsE;AACtE,0EAA0E;AAC1E,yEAAyE;AACzE,yEAAyE;AACzE,0EAA0E;AAC1E,sCAAsC;AACtC,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,2EAA2E;AAC3E,2EAA2E;AAC3E,oEAAoE;AACpE,yEAAyE;AACzE,qBAAqB;AACrB,EAAE;AACF,wEAAwE;AACxE,0EAA0E;AAC1E,2EAA2E;AAC3E,uDAAuD;AACvD,EAAE;AACF,0EAA0E;AAC1E,4DAA4D;AAsC5D,MAAM,OAAO,YAAY;IACvB;qCACiC;IAChB,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAA;IAC5D;4EACwE;IACvD,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAA;IAE5D;+DAC2D;IAC3D,UAAU,CAAC,CAAgB;QACzB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAA;IACtC,CAAC;IAED;;iBAEa;IACb,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACvD,CAAC;IAED,qDAAqD;IACrD,MAAM,CAAC,EAAU;QACf,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACtB,IAAI,CAAC,CAAC;YAAE,OAAO,SAAS,CAAA;QACxB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAA;QACpC,IAAI,CAAC,CAAC,eAAe,KAAK,IAAI;YAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAA;QACvE,OAAO,CAAC,CAAA;IACV,CAAC;IAED,YAAY,CAAC,QAAgB,EAAE,OAAoC,EAAE;QACnE,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,KAAK,IAAI,CAAA;QACjD,MAAM,GAAG,GAAoB,EAAE,CAAA;QAC/B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ;gBAAE,SAAQ;YACrC,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC,MAAM;gBAAE,SAAQ;YACxC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACb,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,GAAG;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IACpC,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAA;IAC3B,CAAC;IAED;;;;gDAI4C;IAC5C,OAAO,CACL,YAAoB,EACpB,eAAuB,EACvB,SAAiB;QAEjB,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QACzC,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAA;QACnB,IAAI,CAAC,CAAC,eAAe,KAAK,IAAI;YAAE,OAAO,CAAC,CAAA;QACxC,CAAC,CAAC,eAAe,GAAG,eAAe,CAAA;QACnC,CAAC,CAAC,SAAS,GAAG,SAAS,CAAA;QACvB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,CAAA;QACrC,OAAO,CAAC,CAAA;IACV,CAAC;CACF"}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
export interface ToolSurface {
|
|
2
2
|
admin: ReadonlySet<string>;
|
|
3
3
|
public: ReadonlySet<string>;
|
|
4
|
+
/** Per-plugin MCP server descriptors. Key is the plugin directory name
|
|
5
|
+
* (matches the `mcp__<plugin>__*` namespace). Spawned by Claude Code at
|
|
6
|
+
* session start via `--mcp-config`. Plugins with `tools: []` contribute
|
|
7
|
+
* no servers. */
|
|
8
|
+
mcpServers: ReadonlyMap<string, McpServerDescriptor>;
|
|
9
|
+
}
|
|
10
|
+
export interface McpServerDescriptor {
|
|
11
|
+
command: string;
|
|
12
|
+
args: readonly string[];
|
|
13
|
+
env?: Readonly<Record<string, string>>;
|
|
4
14
|
}
|
|
5
15
|
export declare class ToolSurfaceError extends Error {
|
|
6
16
|
readonly reason: string;
|
|
@@ -16,10 +26,30 @@ interface ToolEntry {
|
|
|
16
26
|
* Throws ToolSurfaceError on any malformed entry (missing name, missing or
|
|
17
27
|
* non-boolean publicAllowlist). */
|
|
18
28
|
export declare function parseToolsBlock(frontmatter: string, pluginDir: string): ToolEntry[];
|
|
29
|
+
/** Parse the optional `mcp:` block out of a PLUGIN.md frontmatter body.
|
|
30
|
+
* Returns null when the frontmatter has no `mcp:` key. Throws on a malformed
|
|
31
|
+
* shape (missing command, args not a list, env not key:value pairs). The
|
|
32
|
+
* schema mirrors Claude Code's `.mcp.json`:
|
|
33
|
+
* mcp:
|
|
34
|
+
* command: node
|
|
35
|
+
* args:
|
|
36
|
+
* - ${PLATFORM_ROOT}/lib/mcp-spawn-tee/dist/index.js
|
|
37
|
+
* - ${PLATFORM_ROOT}/plugins/memory/mcp/dist/index.js
|
|
38
|
+
* env:
|
|
39
|
+
* MCP_SPAWN_TEE_NAME: memory
|
|
40
|
+
* ACCOUNT_ID: ${ACCOUNT_ID}
|
|
41
|
+
*/
|
|
42
|
+
export declare function parseMcpBlock(frontmatter: string, pluginDir: string): McpServerDescriptor | null;
|
|
19
43
|
/** Walk a plugins root directory, parse every <name>/PLUGIN.md, and return
|
|
20
|
-
* the {admin, public} sets
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
|
|
44
|
+
* the {admin, public, mcpServers} sets. Throws on the first malformed
|
|
45
|
+
* manifest — the caller (the manager boot) must exit non-zero so the
|
|
46
|
+
* operator sees the gap.
|
|
47
|
+
*
|
|
48
|
+
* Invariant: a plugin that declares `tools:` with at least one entry MUST
|
|
49
|
+
* also declare an `mcp:` block. Without it the spawn would push
|
|
50
|
+
* `--allowed-tools mcp__<plugin>__*` for a server that was never registered
|
|
51
|
+
* with Claude Code; the tools would be unreachable and the operator would
|
|
52
|
+
* see "tool not found" rather than a boot-time gap. */
|
|
53
|
+
export declare function loadToolSurface(pluginsRoots: string | readonly string[]): ToolSurface;
|
|
24
54
|
export {};
|
|
25
55
|
//# sourceMappingURL=tool-surface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-surface.d.ts","sourceRoot":"","sources":["../src/tool-surface.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1B,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"tool-surface.d.ts","sourceRoot":"","sources":["../src/tool-surface.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1B,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC3B;;;sBAGkB;IAClB,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;CACrD;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACvC;AAED,qBAAa,gBAAiB,SAAQ,KAAK;aACb,MAAM,EAAE,MAAM;aAAkB,MAAM,EAAE,MAAM;gBAA9C,MAAM,EAAE,MAAM,EAAkB,MAAM,EAAE,MAAM;CAI3E;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,OAAO,CAAA;CACzB;AAYD;;;oCAGoC;AACpC,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,CAsEnF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CA6ChG;AAED;;;;;;;;;wDASwD;AACxD,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,WAAW,CA8CrF"}
|
|
@@ -111,39 +111,137 @@ export function parseToolsBlock(frontmatter, pluginDir) {
|
|
|
111
111
|
flush();
|
|
112
112
|
return out;
|
|
113
113
|
}
|
|
114
|
-
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
/** Parse the optional `mcp:` block out of a PLUGIN.md frontmatter body.
|
|
115
|
+
* Returns null when the frontmatter has no `mcp:` key. Throws on a malformed
|
|
116
|
+
* shape (missing command, args not a list, env not key:value pairs). The
|
|
117
|
+
* schema mirrors Claude Code's `.mcp.json`:
|
|
118
|
+
* mcp:
|
|
119
|
+
* command: node
|
|
120
|
+
* args:
|
|
121
|
+
* - ${PLATFORM_ROOT}/lib/mcp-spawn-tee/dist/index.js
|
|
122
|
+
* - ${PLATFORM_ROOT}/plugins/memory/mcp/dist/index.js
|
|
123
|
+
* env:
|
|
124
|
+
* MCP_SPAWN_TEE_NAME: memory
|
|
125
|
+
* ACCOUNT_ID: ${ACCOUNT_ID}
|
|
126
|
+
*/
|
|
127
|
+
export function parseMcpBlock(frontmatter, pluginDir) {
|
|
128
|
+
const lines = frontmatter.split(/\r?\n/);
|
|
129
|
+
let i = 0;
|
|
130
|
+
while (i < lines.length) {
|
|
131
|
+
if (/^mcp:\s*$/.test(lines[i])) {
|
|
132
|
+
i++;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
i++;
|
|
121
136
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
137
|
+
if (i >= lines.length)
|
|
138
|
+
return null;
|
|
139
|
+
let command = null;
|
|
140
|
+
const args = [];
|
|
141
|
+
const env = {};
|
|
142
|
+
let envHasEntry = false;
|
|
143
|
+
let mode = 'top';
|
|
144
|
+
for (; i < lines.length; i++) {
|
|
145
|
+
const line = lines[i];
|
|
146
|
+
if (line.length === 0)
|
|
147
|
+
continue;
|
|
148
|
+
// top-level key (no leading space) ends the mcp block
|
|
149
|
+
if (/^[A-Za-z_]/.test(line))
|
|
150
|
+
break;
|
|
151
|
+
const topCommand = line.match(/^\s\s(command):\s*(.+?)\s*$/);
|
|
152
|
+
const topArgsHeader = line.match(/^\s\s(args):\s*$/);
|
|
153
|
+
const topEnvHeader = line.match(/^\s\s(env):\s*$/);
|
|
154
|
+
if (topCommand) {
|
|
155
|
+
command = topCommand[2];
|
|
156
|
+
mode = 'top';
|
|
157
|
+
continue;
|
|
130
158
|
}
|
|
131
|
-
|
|
159
|
+
if (topArgsHeader) {
|
|
160
|
+
mode = 'args';
|
|
132
161
|
continue;
|
|
133
162
|
}
|
|
134
|
-
|
|
135
|
-
|
|
163
|
+
if (topEnvHeader) {
|
|
164
|
+
mode = 'env';
|
|
136
165
|
continue;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
166
|
+
}
|
|
167
|
+
if (mode === 'args') {
|
|
168
|
+
const item = line.match(/^\s+-\s+(.+?)\s*$/);
|
|
169
|
+
if (item) {
|
|
170
|
+
args.push(item[1]);
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (mode === 'env') {
|
|
175
|
+
const kv = line.match(/^\s+([A-Za-z_][A-Za-z0-9_]*):\s*(.+?)\s*$/);
|
|
176
|
+
if (kv) {
|
|
177
|
+
env[kv[1]] = kv[2];
|
|
178
|
+
envHasEntry = true;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (command === null) {
|
|
184
|
+
throw new ToolSurfaceError('mcp-command-missing', `${pluginDir}/PLUGIN.md mcp: block has no command`);
|
|
185
|
+
}
|
|
186
|
+
const desc = { command, args };
|
|
187
|
+
if (envHasEntry)
|
|
188
|
+
desc.env = env;
|
|
189
|
+
return desc;
|
|
190
|
+
}
|
|
191
|
+
/** Walk a plugins root directory, parse every <name>/PLUGIN.md, and return
|
|
192
|
+
* the {admin, public, mcpServers} sets. Throws on the first malformed
|
|
193
|
+
* manifest — the caller (the manager boot) must exit non-zero so the
|
|
194
|
+
* operator sees the gap.
|
|
195
|
+
*
|
|
196
|
+
* Invariant: a plugin that declares `tools:` with at least one entry MUST
|
|
197
|
+
* also declare an `mcp:` block. Without it the spawn would push
|
|
198
|
+
* `--allowed-tools mcp__<plugin>__*` for a server that was never registered
|
|
199
|
+
* with Claude Code; the tools would be unreachable and the operator would
|
|
200
|
+
* see "tool not found" rather than a boot-time gap. */
|
|
201
|
+
export function loadToolSurface(pluginsRoots) {
|
|
202
|
+
const roots = Array.isArray(pluginsRoots) ? pluginsRoots : [pluginsRoots];
|
|
203
|
+
for (const r of roots) {
|
|
204
|
+
if (!existsSync(r))
|
|
205
|
+
throw new ToolSurfaceError('plugins-root-missing', r);
|
|
206
|
+
}
|
|
207
|
+
const admin = new Set();
|
|
208
|
+
const pub = new Set();
|
|
209
|
+
const mcpServers = new Map();
|
|
210
|
+
for (const root of roots) {
|
|
211
|
+
const entries = readdirSync(root).sort();
|
|
212
|
+
for (const plugin of entries) {
|
|
213
|
+
const pluginDir = join(root, plugin);
|
|
214
|
+
try {
|
|
215
|
+
if (!statSync(pluginDir).isDirectory())
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
const manifestPath = join(pluginDir, 'PLUGIN.md');
|
|
222
|
+
if (!existsSync(manifestPath))
|
|
223
|
+
continue;
|
|
224
|
+
const raw = readFileSync(manifestPath, 'utf-8');
|
|
225
|
+
const frontmatter = extractFrontmatter(raw, plugin);
|
|
226
|
+
const tools = parseToolsBlock(frontmatter, plugin);
|
|
227
|
+
if (tools.length === 0)
|
|
228
|
+
continue;
|
|
229
|
+
const mcp = parseMcpBlock(frontmatter, plugin);
|
|
230
|
+
if (!mcp) {
|
|
231
|
+
throw new ToolSurfaceError('mcp-block-missing', `${plugin}/PLUGIN.md declares tools but no mcp: block; spawns would --allowed-tools mcp__${plugin}__* with no registered server`);
|
|
232
|
+
}
|
|
233
|
+
if (mcpServers.has(plugin)) {
|
|
234
|
+
throw new ToolSurfaceError('mcp-plugin-duplicate', `${plugin} declared by more than one plugins root`);
|
|
235
|
+
}
|
|
236
|
+
mcpServers.set(plugin, mcp);
|
|
237
|
+
for (const t of tools) {
|
|
238
|
+
const qualified = `mcp__${plugin}__${t.name}`;
|
|
239
|
+
admin.add(qualified);
|
|
240
|
+
if (t.publicAllowlist)
|
|
241
|
+
pub.add(qualified);
|
|
242
|
+
}
|
|
145
243
|
}
|
|
146
244
|
}
|
|
147
|
-
return { admin, public: pub };
|
|
245
|
+
return { admin, public: pub, mcpServers };
|
|
148
246
|
}
|
|
149
247
|
//# sourceMappingURL=tool-surface.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-surface.js","sourceRoot":"","sources":["../src/tool-surface.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,EAAE;AACF,6DAA6D;AAC7D,uEAAuE;AACvE,0EAA0E;AAC1E,qEAAqE;AACrE,sDAAsD;AACtD,EAAE;AACF,wCAAwC;AACxC,qDAAqD;AACrD,EAAE;AACF,2EAA2E;AAC3E,uEAAuE;AACvE,kEAAkE;AAClE,EAAE;AACF,2EAA2E;AAC3E,wEAAwE;AACxE,2EAA2E;AAC3E,kEAAkE;AAElE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACzE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"tool-surface.js","sourceRoot":"","sources":["../src/tool-surface.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,19 +8,15 @@ These three rules win when anything else in this prompt conflicts with them.
|
|
|
8
8
|
2. **Be concise.** Three sentences or fewer. If you cannot answer in three, ask in five words.
|
|
9
9
|
3. **Show your evidence.** Gather evidence before forming a hypothesis. One measurement beats three guesses.
|
|
10
10
|
|
|
11
|
-
## The graph
|
|
12
|
-
|
|
13
|
-
The Neo4j graph is where this account stores everything it knows. Before you write, reduce the input to the smallest set of nodes, edges, and properties that keeps the meaning. When you read, you get candidates back, not answers; pick the few that answer the current question. When the graph is wrong, fix it. When the graph is empty and you have to fall back to training knowledge, say so out loud.
|
|
14
|
-
|
|
15
|
-
Every node has a parent. The canonical hierarchy is LocalBusiness, then Project, then Task or Person or Organisation or KnowledgeDocument. A node with no upward edge to its hierarchy parent is a write defect, not a graph state. The wrapped writers refuse it; the graph-write shim rolls back any raw cypher that produces one. Cross-hierarchy edges (one Person linked to several Projects, one KnowledgeDocument about several Organisations) are normal; the rule governs containment, not exclusivity.
|
|
16
|
-
|
|
17
11
|
## The owner
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
The more you know about the owner, the better the work you can do. Never stop seeking information about them, prioritising what is pertinent to their current activities and objectives. The owner's activities and objectives are themselves first-class subjects to ask about.
|
|
14
|
+
|
|
15
|
+
Everything you learn in conversation is recorded for you by a background agent that watches every completed turn. You do not write to the graph yourself. Ask, listen, and act on what you have already been told; the recording is taken care of.
|
|
20
16
|
|
|
21
17
|
Remote access and public-facing channels are optional. Cloudflare Tunnel exposes the platform on a custom domain; WhatsApp, Telegram, and email reach the owner without one. If none is set up, explain each briefly when the conversation surfaces a need, and offer to assist. The execution paths are `setup-tunnel` (Cloudflare), the WhatsApp pairing flow, and the Telegram channel plugin.
|
|
22
18
|
|
|
23
|
-
When the owner declines an offer, record the decline as a property on `Person` (e.g. `preferences.declinedRemoteAccess: true`) so you do not re-ask.
|
|
19
|
+
When the owner declines an offer, record the decline as a property on `Person` (e.g. `preferences.declinedRemoteAccess: true`) so you do not re-ask.
|
|
24
20
|
|
|
25
21
|
## Before you act
|
|
26
22
|
|
|
@@ -28,7 +24,7 @@ You may not act on a request until you know three things: what is being asked, w
|
|
|
28
24
|
|
|
29
25
|
## Your role
|
|
30
26
|
|
|
31
|
-
You are the head of operations, chief of staff, and private secretary.
|
|
27
|
+
You are the head of operations, chief of staff, and private secretary. Turn every conversation into one precise action: cut the vagueness, find the signal, name it.
|
|
32
28
|
|
|
33
29
|
## How you sound
|
|
34
30
|
|
|
@@ -38,19 +34,14 @@ You are an AI. Say so if asked. Never pretend to be a human. Speak British Engli
|
|
|
38
34
|
|
|
39
35
|
Address the owner directly. Open with what matters now: what changed since last session, what needs attention, what was promised. Skip greetings that don't earn their place. The first message of every session is a status, not a salutation.
|
|
40
36
|
|
|
41
|
-
When there is no status to report (fresh account, post-onboarding first turn, no open tasks, no overnight changes), open with
|
|
37
|
+
When there is no status to report (fresh account, post-onboarding first turn, no open tasks, no overnight changes), open with one grounded question that expands what you do not yet know about the owner, in the category where the gap is widest. Ask the kind of question a sharp new colleague would ask on their second day. Never a list, never a form, never "tell me about yourself". One question, the final sentence.
|
|
42
38
|
|
|
43
|
-
|
|
39
|
+
If the operator describes work a dormant plugin would do automatically, offer to enable it in one helpful sentence. Maximum one nudge per plugin per session.
|
|
44
40
|
|
|
45
|
-
##
|
|
41
|
+
## Two files to read at session start
|
|
46
42
|
|
|
47
43
|
- `SOUL.md`: how you sound. Tone and personality only, no rules.
|
|
48
44
|
- `AGENTS.md`: the list of installed specialists and when to send work to each.
|
|
49
|
-
- `LEARNINGS.md`: corrections from past sessions, which you own. Read before repeating an approach that previously failed.
|
|
50
|
-
|
|
51
|
-
## You own LEARNINGS.md
|
|
52
|
-
|
|
53
|
-
`LEARNINGS.md` is yours to keep current. Read it at session start; add to it during the session. Add a new entry whenever a tool call reveals a reusable correction (parameter format, schema requirement, auth quirk, data-shape issue) or the owner states a working principle that should shape every future interaction. One entry per distinct pattern: before writing, check whether a matching entry already exists, and update rather than duplicate. Keep entries short, state the rule first, then one sentence of why. Do not store business knowledge, personality, or domain knowledge there; those belong in the graph, in SOUL.md, and in the relevant skill respectively.
|
|
54
45
|
|
|
55
46
|
## How to choose where work goes
|
|
56
47
|
|
|
@@ -81,4 +72,4 @@ One-sided framing only: "Proceed?" or "Stop?", never "Proceed, or stop?" because
|
|
|
81
72
|
|
|
82
73
|
- **Skill inputs.** When a skill needs an input you do not have, call `AskUserQuestion` next. Never call `memory-search` or `conversation-search` to guess.
|
|
83
74
|
- **Resuming the thread.** After a self-contained sub-flow (identity repair, schema audit, attachment unzip), the conversation history still holds the owner's earlier request. Name what they were asking and pick it back up yourself. Never ask the owner to restate.
|
|
84
|
-
- **Dormant capabilities.**
|
|
75
|
+
- **Dormant capabilities.** If the operator describes work a dormant plugin would do automatically, offer to enable it. Maximum one nudge per plugin per session.
|