@rubytech/create-realagent 1.0.806 → 1.0.808
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/neo4j/migrations/004-project-admin-agent.ts +247 -0
- package/payload/platform/neo4j/migrations/004-prune-alien-accounts.ts +134 -0
- package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +2 -0
- package/payload/platform/plugins/docs/references/cloudflare.md +1 -0
- package/payload/platform/plugins/docs/references/graph.md +42 -0
- package/payload/platform/plugins/docs/references/internals.md +3 -1
- package/payload/platform/plugins/docs/references/memory-guide.md +4 -0
- package/payload/platform/plugins/docs/references/troubleshooting.md +19 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +19 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +4 -1
- package/payload/platform/templates/agents/admin/SOUL.md +2 -0
- package/payload/server/chunk-CRWLE6BZ.js +3511 -0
- package/payload/server/chunk-LSUMH6OF.js +9993 -0
- package/payload/server/chunk-V3VLAL7N.js +10009 -0
- package/payload/server/chunk-YULDSPAC.js +3484 -0
- package/payload/server/client-pool-LXE7RIRT.js +31 -0
- package/payload/server/client-pool-N2Y57223.js +31 -0
- package/payload/server/maxy-edge.js +5 -4
- package/payload/server/neo4j-migrations-HEECOAGK.js +128 -0
- package/payload/server/public/assets/admin-MxaCgGHZ.js +352 -0
- package/payload/server/public/assets/{graph-CBu0rtrP.js → graph-CDwy6Qw1.js} +1 -1
- package/payload/server/public/assets/page-DEyK-lSN.js +50 -0
- package/payload/server/public/graph.html +2 -2
- package/payload/server/public/index.html +2 -2
- package/payload/server/server.js +658 -278
- package/payload/server/public/assets/admin-BYsaXlDv.js +0 -352
- package/payload/server/public/assets/page-BNM63zsb.js +0 -50
package/package.json
CHANGED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 004 — Project the admin agent into the graph and clean up
|
|
3
|
+
* Conversation channel data (Task 864). Numbered 004 because the 003
|
|
4
|
+
* slot is held by `003-person-name-eradicate.cypher` (boot-time apply).
|
|
5
|
+
*
|
|
6
|
+
* Three idempotent passes:
|
|
7
|
+
*
|
|
8
|
+
* 1. For every account directory under data/accounts/<accountId>/agents/admin/
|
|
9
|
+
* that carries a config.json, call projectAgent(accountId, accountDir,
|
|
10
|
+
* 'admin'). The projector is the same function migration 002 uses for
|
|
11
|
+
* public agents and is content-agnostic — it reads config.json plus any
|
|
12
|
+
* IDENTITY/SOUL/KNOWLEDGE/KNOWLEDGE-SUMMARY files present and MERGEs the
|
|
13
|
+
* :Agent node + four owned :KnowledgeDocument projections. Re-running
|
|
14
|
+
* this migration produces no duplicate nodes or edges.
|
|
15
|
+
*
|
|
16
|
+
* Migration 002 explicitly SKIPS admin (line 60: `if (entry.name ===
|
|
17
|
+
* "admin") continue`); doing the projection here keeps that skip valid
|
|
18
|
+
* and isolates admin-specific concerns to one file.
|
|
19
|
+
*
|
|
20
|
+
* 2. For every existing :AdminConversation that does NOT yet have a
|
|
21
|
+
* :HANDLED_BY edge, MATCH the freshly-projected admin :Agent and MERGE
|
|
22
|
+
* the edge. Guarded with `WHERE NOT EXISTS((c)-[:HANDLED_BY]->(:Agent))`
|
|
23
|
+
* so re-runs short-circuit per conversation.
|
|
24
|
+
*
|
|
25
|
+
* 3. Backfill `c.channel = 'webchat'` for every Conversation node where
|
|
26
|
+
* channel IS NULL. Pre-Task-863 conversations were written without the
|
|
27
|
+
* property; channel='webchat' is the correct default — only WhatsApp
|
|
28
|
+
* and Telegram sessions ever set non-webchat values, and those have
|
|
29
|
+
* always come through sessionKeys prefixed `whatsapp:` or `telegram:`
|
|
30
|
+
* (see neo4j-store.ts:171). Idempotent: subsequent runs no-op because
|
|
31
|
+
* the WHERE clause matches zero rows.
|
|
32
|
+
*
|
|
33
|
+
* Run via the platform/ui standalone runtime so it picks up the same
|
|
34
|
+
* NEO4J_URI / accounts-directory resolution as the server:
|
|
35
|
+
*
|
|
36
|
+
* cd platform/ui && \
|
|
37
|
+
* NEO4J_URI=bolt://… NEO4J_PASSWORD=… \
|
|
38
|
+
* npx tsx ../neo4j/migrations/004-project-admin-agent.ts
|
|
39
|
+
*
|
|
40
|
+
* Output: structured `[admin-agent-graph-backfill]` lines per account + a
|
|
41
|
+
* final totals line. Non-zero exit code on any per-account agent-projection
|
|
42
|
+
* failure surfaces to the operator; subsequent accounts are still attempted.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
46
|
+
import { resolve } from "node:path";
|
|
47
|
+
import { projectAgent, getSession } from "../../ui/app/lib/neo4j-store";
|
|
48
|
+
import { ACCOUNTS_DIR } from "../../ui/app/lib/claude-agent/account";
|
|
49
|
+
|
|
50
|
+
interface PerAccountStats {
|
|
51
|
+
accountId: string;
|
|
52
|
+
projected: 0 | 1;
|
|
53
|
+
failed: 0 | 1;
|
|
54
|
+
handledByCandidates: number;
|
|
55
|
+
handledByEdges: number;
|
|
56
|
+
channelBackfilled: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function projectAccountAdmin(
|
|
60
|
+
accountId: string,
|
|
61
|
+
accountDir: string,
|
|
62
|
+
): Promise<{ projected: 0 | 1; failed: 0 | 1 }> {
|
|
63
|
+
const adminDir = resolve(accountDir, "agents", "admin");
|
|
64
|
+
const configPath = resolve(adminDir, "config.json");
|
|
65
|
+
if (!existsSync(adminDir) || !existsSync(configPath)) {
|
|
66
|
+
return { projected: 0, failed: 0 };
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
await projectAgent(accountId, accountDir, "admin");
|
|
70
|
+
return { projected: 1, failed: 0 };
|
|
71
|
+
} catch (err) {
|
|
72
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
73
|
+
console.error(
|
|
74
|
+
`[admin-agent-graph-backfill] account=${accountId.slice(0, 8)} project FAILED error="${msg}"`,
|
|
75
|
+
);
|
|
76
|
+
return { projected: 0, failed: 1 };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
interface HandledByStats {
|
|
81
|
+
candidates: number;
|
|
82
|
+
edges: number;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Backfill HANDLED_BY edges from AdminConversation nodes to the admin Agent
|
|
87
|
+
* node. Guarded with NOT EXISTS so re-runs of this migration don't redo work
|
|
88
|
+
* — and so AdminConversations that already gained a HANDLED_BY edge through
|
|
89
|
+
* the forward path are skipped.
|
|
90
|
+
*
|
|
91
|
+
* `candidates` counts AdminConversations that LACK a HANDLED_BY edge; `edges`
|
|
92
|
+
* counts edges newly created. The admin :Agent must already exist (created
|
|
93
|
+
* by pass 1); if it doesn't, the OPTIONAL MATCH falls through and zero edges
|
|
94
|
+
* are written — surfaced through `candidates - edges`.
|
|
95
|
+
*/
|
|
96
|
+
async function backfillAdminHandledBy(
|
|
97
|
+
accountId: string,
|
|
98
|
+
): Promise<HandledByStats> {
|
|
99
|
+
const session = getSession();
|
|
100
|
+
try {
|
|
101
|
+
const result = await session.run(
|
|
102
|
+
`MATCH (c:AdminConversation {accountId: $accountId})
|
|
103
|
+
WHERE NOT EXISTS((c)-[:HANDLED_BY]->(:Agent))
|
|
104
|
+
OPTIONAL MATCH (a:Agent {accountId: $accountId, slug: 'admin'})
|
|
105
|
+
FOREACH (_ IN CASE WHEN a IS NULL THEN [] ELSE [1] END | MERGE (c)-[:HANDLED_BY]->(a))
|
|
106
|
+
RETURN
|
|
107
|
+
count(c) AS candidates,
|
|
108
|
+
sum(CASE WHEN a IS NULL THEN 0 ELSE 1 END) AS edges`,
|
|
109
|
+
{ accountId },
|
|
110
|
+
);
|
|
111
|
+
const toNum = (v: unknown): number => {
|
|
112
|
+
if (typeof v === "number") return v;
|
|
113
|
+
if (v && typeof (v as { toNumber: () => number }).toNumber === "function") {
|
|
114
|
+
return (v as { toNumber: () => number }).toNumber();
|
|
115
|
+
}
|
|
116
|
+
return 0;
|
|
117
|
+
};
|
|
118
|
+
return {
|
|
119
|
+
candidates: toNum(result.records[0]?.get("candidates")),
|
|
120
|
+
edges: toNum(result.records[0]?.get("edges")),
|
|
121
|
+
};
|
|
122
|
+
} finally {
|
|
123
|
+
await session.close();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Backfill `c.channel = 'webchat'` on Conversation nodes that lack the
|
|
129
|
+
* property. Hits both AdminConversation and PublicConversation — the
|
|
130
|
+
* predicate is `c.channel IS NULL`, label-agnostic.
|
|
131
|
+
*
|
|
132
|
+
* Why default to 'webchat': new writes set channel from sessionKey prefix
|
|
133
|
+
* (neo4j-store.ts:171). Only `whatsapp:` and `telegram:` prefixes produce
|
|
134
|
+
* non-webchat values, and those prefixes have always existed. So a NULL
|
|
135
|
+
* channel can only mean "Conversation written before Task 863 added the
|
|
136
|
+
* SET clause" — which by definition was a webchat session.
|
|
137
|
+
*
|
|
138
|
+
* Idempotent: WHERE clause matches zero rows on re-run.
|
|
139
|
+
*/
|
|
140
|
+
async function backfillChannel(accountId: string): Promise<number> {
|
|
141
|
+
const session = getSession();
|
|
142
|
+
try {
|
|
143
|
+
const result = await session.run(
|
|
144
|
+
`MATCH (c:Conversation {accountId: $accountId})
|
|
145
|
+
WHERE c.channel IS NULL
|
|
146
|
+
SET c.channel = 'webchat'
|
|
147
|
+
RETURN count(c) AS backfilled`,
|
|
148
|
+
{ accountId },
|
|
149
|
+
);
|
|
150
|
+
const raw = result.records[0]?.get("backfilled");
|
|
151
|
+
if (typeof raw === "number") return raw;
|
|
152
|
+
if (raw && typeof (raw as { toNumber: () => number }).toNumber === "function") {
|
|
153
|
+
return (raw as { toNumber: () => number }).toNumber();
|
|
154
|
+
}
|
|
155
|
+
return 0;
|
|
156
|
+
} finally {
|
|
157
|
+
await session.close();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function main(): Promise<void> {
|
|
162
|
+
const start = Date.now();
|
|
163
|
+
|
|
164
|
+
if (!existsSync(ACCOUNTS_DIR)) {
|
|
165
|
+
console.error(
|
|
166
|
+
`[admin-agent-graph-backfill] ACCOUNTS_DIR missing at ${ACCOUNTS_DIR} — nothing to do`,
|
|
167
|
+
);
|
|
168
|
+
process.exit(0);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const accountEntries = readdirSync(ACCOUNTS_DIR, { withFileTypes: true })
|
|
172
|
+
.filter((e) => e.isDirectory());
|
|
173
|
+
|
|
174
|
+
console.error(
|
|
175
|
+
`[admin-agent-graph-backfill] start accounts=${accountEntries.length}`,
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
let totalProjected = 0;
|
|
179
|
+
let totalFailed = 0;
|
|
180
|
+
let totalHandledByCandidates = 0;
|
|
181
|
+
let totalHandledByEdges = 0;
|
|
182
|
+
let totalChannelBackfilled = 0;
|
|
183
|
+
const perAccount: PerAccountStats[] = [];
|
|
184
|
+
|
|
185
|
+
for (const entry of accountEntries) {
|
|
186
|
+
const accountDir = resolve(ACCOUNTS_DIR, entry.name);
|
|
187
|
+
const accountId = entry.name;
|
|
188
|
+
const accountStart = Date.now();
|
|
189
|
+
|
|
190
|
+
const { projected, failed } = await projectAccountAdmin(
|
|
191
|
+
accountId,
|
|
192
|
+
accountDir,
|
|
193
|
+
);
|
|
194
|
+
totalProjected += projected;
|
|
195
|
+
totalFailed += failed;
|
|
196
|
+
|
|
197
|
+
let handledByStats: HandledByStats = { candidates: 0, edges: 0 };
|
|
198
|
+
let channelBackfilled = 0;
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
handledByStats = await backfillAdminHandledBy(accountId);
|
|
202
|
+
totalHandledByCandidates += handledByStats.candidates;
|
|
203
|
+
totalHandledByEdges += handledByStats.edges;
|
|
204
|
+
} catch (err) {
|
|
205
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
206
|
+
console.error(
|
|
207
|
+
`[admin-agent-graph-backfill] account=${accountId.slice(0, 8)} handled-by-backfill FAILED error="${msg}"`,
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
channelBackfilled = await backfillChannel(accountId);
|
|
213
|
+
totalChannelBackfilled += channelBackfilled;
|
|
214
|
+
} catch (err) {
|
|
215
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
216
|
+
console.error(
|
|
217
|
+
`[admin-agent-graph-backfill] account=${accountId.slice(0, 8)} channel-backfill FAILED error="${msg}"`,
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
perAccount.push({
|
|
222
|
+
accountId,
|
|
223
|
+
projected,
|
|
224
|
+
failed,
|
|
225
|
+
handledByCandidates: handledByStats.candidates,
|
|
226
|
+
handledByEdges: handledByStats.edges,
|
|
227
|
+
channelBackfilled,
|
|
228
|
+
});
|
|
229
|
+
const ms = Date.now() - accountStart;
|
|
230
|
+
console.error(
|
|
231
|
+
`[admin-agent-graph-backfill] account=${accountId.slice(0, 8)} projected=${projected} failed=${failed} handled-by-candidates=${handledByStats.candidates} handled-by-edges=${handledByStats.edges} channel-backfilled=${channelBackfilled} ms=${ms}`,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const ms = Date.now() - start;
|
|
236
|
+
console.error(
|
|
237
|
+
`[admin-agent-graph-backfill] done totals: projected=${totalProjected} failed=${totalFailed} handled-by-candidates=${totalHandledByCandidates} handled-by-edges=${totalHandledByEdges} channel-backfilled=${totalChannelBackfilled} ms=${ms}`,
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
process.exit(totalFailed > 0 ? 1 : 0);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
main().catch((err) => {
|
|
244
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
245
|
+
console.error(`[admin-agent-graph-backfill] fatal error="${msg}"`);
|
|
246
|
+
process.exit(2);
|
|
247
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 004 — Prune alien-account nodes (Task 847).
|
|
3
|
+
*
|
|
4
|
+
* Deletes every node whose `accountId` is not present on disk under
|
|
5
|
+
* `${DATA_ROOT}/accounts/<uuid>/account.json`. Idempotent — silent when
|
|
6
|
+
* the graph is already clean.
|
|
7
|
+
*
|
|
8
|
+
* Why a backstop, not a writer fix: the leaked nodes were written by the
|
|
9
|
+
* `review-digest-compose` writer, which has since been removed in favour
|
|
10
|
+
* of a coming gbrain rewrite. With no live writer to fix, this is the
|
|
11
|
+
* surface that catches future writer drift before the next gbrain ships.
|
|
12
|
+
*
|
|
13
|
+
* Hard guard: refuses to run when the on-disk account set is empty
|
|
14
|
+
* (corrupt-install scenario). Refusing to wipe the graph is louder than
|
|
15
|
+
* silently wiping it.
|
|
16
|
+
*
|
|
17
|
+
* Doctrine in `.docs/neo4j.md` "Account isolation invariant" requires
|
|
18
|
+
* any writer that stamps `n.accountId` to verify the value against
|
|
19
|
+
* `${DATA_ROOT}/accounts/<id>/account.json` before write. This migration
|
|
20
|
+
* is a backstop, not a license.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
24
|
+
import { resolve } from "node:path";
|
|
25
|
+
|
|
26
|
+
const UUID_RE =
|
|
27
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Structural alias for the `Driver` instance the runner passes in. We type
|
|
31
|
+
* structurally rather than importing `Driver` from `neo4j-driver` because
|
|
32
|
+
* this file lives outside `platform/ui/` — depending on the workspace's
|
|
33
|
+
* dedupe state, `neo4j-driver` resolves to a different node_modules copy
|
|
34
|
+
* here than at the runner site, and TS treats two same-shape types from
|
|
35
|
+
* different paths as nominally distinct. Structural typing sidesteps that.
|
|
36
|
+
*/
|
|
37
|
+
type Neo4jDriverLike = {
|
|
38
|
+
session(): {
|
|
39
|
+
run(
|
|
40
|
+
cypher: string,
|
|
41
|
+
params?: Record<string, unknown>,
|
|
42
|
+
): Promise<{ records: Array<{ get(key: string): unknown }> }>;
|
|
43
|
+
close(): Promise<void>;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export async function pruneAlienAccounts(
|
|
48
|
+
driver: Neo4jDriverLike,
|
|
49
|
+
platformRoot: string,
|
|
50
|
+
): Promise<void> {
|
|
51
|
+
const accountsDir = resolve(platformRoot, "..", "data", "accounts");
|
|
52
|
+
const validIds = enumerateValidAccountIds(accountsDir);
|
|
53
|
+
|
|
54
|
+
if (validIds.size === 0) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`refusing to prune: no valid accounts found under ${accountsDir} — corrupt install? not deleting anything to avoid wiping the entire graph.`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const valid = Array.from(validIds);
|
|
61
|
+
const session = driver.session();
|
|
62
|
+
try {
|
|
63
|
+
// Two-step: first query collects the alien accountIds for the log
|
|
64
|
+
// line, second query deletes. Two cheap queries beat a single query
|
|
65
|
+
// that loses either the count or the id list under DELETE semantics.
|
|
66
|
+
const peek = await session.run(
|
|
67
|
+
`MATCH (n)
|
|
68
|
+
WHERE n.accountId IS NOT NULL AND NOT n.accountId IN $valid
|
|
69
|
+
RETURN DISTINCT n.accountId AS aid`,
|
|
70
|
+
{ valid },
|
|
71
|
+
);
|
|
72
|
+
const alienIds: string[] = [];
|
|
73
|
+
for (const record of peek.records) {
|
|
74
|
+
const aid: unknown = record.get("aid");
|
|
75
|
+
if (typeof aid === "string") alienIds.push(aid);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (alienIds.length === 0) return;
|
|
79
|
+
|
|
80
|
+
const result = await session.run(
|
|
81
|
+
`MATCH (n)
|
|
82
|
+
WHERE n.accountId IS NOT NULL AND NOT n.accountId IN $valid
|
|
83
|
+
DETACH DELETE n
|
|
84
|
+
RETURN count(n) AS pruned`,
|
|
85
|
+
{ valid },
|
|
86
|
+
);
|
|
87
|
+
const prunedRaw = result.records[0]?.get("pruned");
|
|
88
|
+
const pruned =
|
|
89
|
+
typeof prunedRaw === "number"
|
|
90
|
+
? prunedRaw
|
|
91
|
+
: (prunedRaw as { toNumber?: () => number })?.toNumber?.() ?? 0;
|
|
92
|
+
console.error(
|
|
93
|
+
`[graph-invariant] alien-accounts pruned=${pruned} accountIds=${alienIds.join(",")}`,
|
|
94
|
+
);
|
|
95
|
+
} finally {
|
|
96
|
+
await session.close();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Enumerate accountIds with a parseable `account.json`. Directory name IS
|
|
102
|
+
* the canonical accountId (matches the UUID_RE.test(name) predicate at
|
|
103
|
+
* `platform/ui/server/routes/admin/files.ts`'s account-name resolver).
|
|
104
|
+
*
|
|
105
|
+
* Corruption discipline: a present-but-unparseable account.json is
|
|
106
|
+
* EXCLUDED from the valid set and emits a skip log line. Better to
|
|
107
|
+
* over-prune one suspect account than under-prune the leak it might
|
|
108
|
+
* be hiding.
|
|
109
|
+
*/
|
|
110
|
+
function enumerateValidAccountIds(accountsDir: string): Set<string> {
|
|
111
|
+
const valid = new Set<string>();
|
|
112
|
+
let names: string[];
|
|
113
|
+
try {
|
|
114
|
+
names = readdirSync(accountsDir);
|
|
115
|
+
} catch (err) {
|
|
116
|
+
if ((err as NodeJS.ErrnoException).code === "ENOENT") return valid;
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
for (const name of names) {
|
|
120
|
+
if (!UUID_RE.test(name)) continue;
|
|
121
|
+
const configPath = resolve(accountsDir, name, "account.json");
|
|
122
|
+
try {
|
|
123
|
+
JSON.parse(readFileSync(configPath, "utf-8"));
|
|
124
|
+
valid.add(name);
|
|
125
|
+
} catch (err) {
|
|
126
|
+
const code = (err as NodeJS.ErrnoException).code ?? "parse-error";
|
|
127
|
+
if (code === "ENOENT") continue;
|
|
128
|
+
console.error(
|
|
129
|
+
`[graph-invariant] account-json-skip uuid=${name} reason=${code}`,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return valid;
|
|
134
|
+
}
|
|
@@ -142,6 +142,8 @@ Then call `render-component` with `name: "cloudflare-setup-form"` and data conta
|
|
|
142
142
|
|
|
143
143
|
Wait for the user's submission. The `_componentDone` payload contains the `setup-tunnel.sh` output verbatim. Relay that output to the user — quote any `ACTION REQUIRED` block exactly. When the script exits zero, step-7 completion has already been persisted by the script itself (Task 562) — relay the output and stop. Do not call `onboarding-complete-step` with step 7; the script is the authority for step-7 completion, and any call you make after the script's restart dispatch would race the service restart and almost always lose. If the script failed (the endpoint returned `ok: false, field: "script"`), the form surfaced the error and stayed open — relay the output, cite `plugins/cloudflare/references/reset-guide.md` for recovery, and offer to re-render the form after any manual steps. Do not synthesise alternative recovery commands. If the user skipped (step 7 not reached), call `onboarding-complete-step` with step 7 so the next session resumes at step 8.
|
|
144
144
|
|
|
145
|
+
**Post-restart resume contract (Task 867).** A successful Cloudflare setup arms a brand-service restart that kills the in-flight admin agent; the operator's "Cloudflare setup completed" relay is queued by the form (write-once filesystem queue) and dispatched server-side as the first turn of the post-restart session via the boot-drain hook in `server/index.ts`. By the time a new admin session opens, `OnboardingState.currentStep` is already 7 (the script's filesystem flag was consumed by `consumeStep7FlagUI` on the way in) AND the queue's relay turn has been persisted as the most-recent user message. From your view as the admin agent, the operator just told you "Cloudflare setup completed (actionId: …)" in a fresh session at currentStep=7. Acknowledge, then proceed to step 8 — do NOT re-ask the Cloudflare question, do NOT re-render the cloudflare-setup-form, do NOT call `onboarding-complete-step` with step 7 (already done). The relay turn is your single source of truth that step 7 finished cleanly; the script's flag-consume is the orthogonal proof that the state machine advanced.
|
|
146
|
+
|
|
145
147
|
## Step 8 — Anthropic API key
|
|
146
148
|
|
|
147
149
|
*(skip if `currentStep` >= 8)*
|
|
@@ -30,6 +30,7 @@ When you submit, the `/api/admin/cloudflare/setup` endpoint runs — in strict o
|
|
|
30
30
|
- `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.
|
|
31
31
|
- `config.yml` and `tunnel.state` written under `${CFG_DIR}`.
|
|
32
32
|
- **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`.
|
|
33
|
+
- **Chat-relay queued for the operator's "Cloudflare setup completed" turn** (Task 867) — when the form's ActionLogPanel reports `code=0`, the form fires `POST /api/admin/cloudflare/relay-completion`. The route enqueues a record at `${ACCOUNT_DIR}/queue/action-completion-relay-<actionId>.json` (write-once via Node's `wx`/O_EXCL flag) BEFORE the brand restart kills the in-flight admin agent. After the restart, the brand service's boot-drain hook ([server/index.ts](../../../../platform/ui/server/index.ts)) consumes the queue once and dispatches a server-driven agent turn via a synthetic one-shot session bound to the queued conversationId; the agent's hoisted user-message persist (Task 867 `admin-agent.ts` + `public-agent.ts` write `role=user` BEFORE the SDK invoke now) captures the operator's relay even if SIGTERM hits mid-generation. The diagnostic line you grep on the working path is `[action-completion-relay] phase=consumed actionId=<id> conversationId=<cid> ageMs=<n> outcome=injected`. Failure modes are surfaced by the `cloudflare-setup-relay-not-acknowledged` review rule.
|
|
33
34
|
- `systemctl --user restart ${BRAND}.service` — restarts the platform service so the new tunnel spawns via the service's `ExecStartPre=resume-tunnel.sh`.
|
|
34
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.
|
|
35
36
|
|
|
@@ -70,6 +70,48 @@ border, with their zoom-tier labels intact. The `N msgs` count excludes
|
|
|
70
70
|
trashed Messages, so the detailed-tier label reflects only live turns in the
|
|
71
71
|
conversation.
|
|
72
72
|
|
|
73
|
+
## Filtering by channel and message kind
|
|
74
|
+
|
|
75
|
+
When you select **AdminConversation** or **PublicConversation** in the
|
|
76
|
+
filter popover, two extra rows appear underneath the chip list:
|
|
77
|
+
|
|
78
|
+
- **Channel** — Web / WhatsApp. Select one to scope the canvas to
|
|
79
|
+
conversations that came in over that channel only. Selecting both is
|
|
80
|
+
the same as selecting neither (all channels). After the migration that
|
|
81
|
+
ships with this release, every conversation carries an explicit
|
|
82
|
+
channel value — pre-existing conversations are backfilled to "Web"
|
|
83
|
+
because only the WhatsApp and Telegram intake paths ever set non-Web
|
|
84
|
+
values.
|
|
85
|
+
- **Message** — User / Assistant / WhatsApp. When you've also pivoted
|
|
86
|
+
into a conversation neighbourhood (or your search hits messages
|
|
87
|
+
directly), this row scopes the messages on canvas to the chosen kind.
|
|
88
|
+
WhatsApp messages persist with their own sublabel so you can isolate
|
|
89
|
+
the live-channel cohort from the agent-path cohort within the same
|
|
90
|
+
conversation.
|
|
91
|
+
|
|
92
|
+
These sub-facets compose with the chip selection. Searching with the
|
|
93
|
+
AdminConversation chip selected now also reaches the body text of every
|
|
94
|
+
admin message — typing a rare word like "ATM" returns every conversation
|
|
95
|
+
that mentions it, not just conversations with that word in the title.
|
|
96
|
+
|
|
97
|
+
## Sidebar conversations list
|
|
98
|
+
|
|
99
|
+
The Recents list above the chat sidebar carries a per-row marker:
|
|
100
|
+
WhatsApp conversations show a small WhatsApp glyph next to the
|
|
101
|
+
conversation name. The dropdown above the list filters Recents to a
|
|
102
|
+
specific channel — flipping it to **WhatsApp** hides web-chat
|
|
103
|
+
conversations and vice versa.
|
|
104
|
+
|
|
105
|
+
## Agents in the graph
|
|
106
|
+
|
|
107
|
+
Both admin and public agents appear as `:Agent` nodes in the graph. Open
|
|
108
|
+
the **Agents** entry from the sidebar to see them all. Each agent
|
|
109
|
+
carries a `:HANDLED_BY` edge from every conversation it has handled, so
|
|
110
|
+
you can pivot from an agent to the conversations it ran. The admin
|
|
111
|
+
agent's IDENTITY, SOUL, KNOWLEDGE, and KNOWLEDGE-SUMMARY documents
|
|
112
|
+
appear as :KnowledgeDocument nodes connected via `HAS_*` edges, the same
|
|
113
|
+
projection shape used for public agents.
|
|
114
|
+
|
|
73
115
|
## Agent-execution telemetry
|
|
74
116
|
|
|
75
117
|
`ToolCall`, `StepResult`, `WorkflowStep`, and `WorkflowRun` nodes are
|
|
@@ -140,6 +140,8 @@ WHERE node.accountId = $accountId
|
|
|
140
140
|
|
|
141
141
|
Multi-tenancy boundary. Every query is scoped to the requesting account. The `ACCOUNT_ID` environment variable is set at MCP server startup — it is not a tool parameter and cannot be overridden by the agent.
|
|
142
142
|
|
|
143
|
+
The read filter alone is not sufficient — it correctly *hides* alien-account nodes from every UI but does not prevent them existing. A writer that misresolves `accountId` (literal, undefined, or inferred-from-the-wrong-context) leaks nodes into the graph with no downstream symptom; the read filter then keeps them invisible indefinitely. The write-side doctrine is documented in `.docs/neo4j.md` "Account isolation invariant" — every writer that stamps `n.accountId` must verify the value against `${DATA_ROOT}/accounts/<id>/account.json` before write, and migration `004-prune-alien-accounts.ts` runs at every server boot as a backstop, deleting any node whose accountId is not on disk. Hard guard: refuses to prune when the on-disk account set is empty (corrupt-install scenario), surfaced as `[migration] failed prune-alien-accounts error="refusing to prune: …"`. Boot does not block on the failure.
|
|
144
|
+
|
|
143
145
|
---
|
|
144
146
|
|
|
145
147
|
## Query Classification
|
|
@@ -313,7 +315,7 @@ This tool is read-only and available to both public and admin agents.
|
|
|
313
315
|
|
|
314
316
|
### When conversations are created
|
|
315
317
|
|
|
316
|
-
`:Conversation` nodes on webchat (admin login, "New conversation" in the burger, a new public visitor) are created lazily. Opening the chat or logging in does not write anything to the graph — {{productName}} only records the conversation once the user sends a second message. This keeps `conversation-search` and the Conversations modal free of one-turn abandoned threads. WhatsApp and Telegram take the opposite posture:
|
|
318
|
+
`:Conversation` nodes on webchat (admin login, "New conversation" in the burger, a new public visitor) are created lazily. Opening the chat or logging in does not write anything to the graph — {{productName}} only records the conversation once the user sends a second message. This keeps `conversation-search` and the Conversations modal free of one-turn abandoned threads. WhatsApp and Telegram take the opposite posture: every inbound — DM or group, allowed or activation-off, agent-invoked or gated — MERGEs the `:Conversation` and writes a forensic `:Message:WhatsAppMessage` row before any access-control decision (Task 863). The graph is the durable record of every message the device received, not just the ones the agent replied to. See `.docs/web-chat.md` "Deferred conversation persistence (Task 650)" and `.docs/whatsapp.md` "Session continuity" for the full contract.
|
|
317
319
|
|
|
318
320
|
Each row in the Conversations modal exposes a `View logs` row-action that opens a popover with three links — **Stream**, **Errors**, **SSE** — each of which targets `/api/admin/logs?type={stream|error|sse}&conversationId={full-id}` in a new tab. The row's 8-char id chip is click-to-copy; hover reveals the full `conversationId` as a tooltip. See `.docs/web-chat.md` "In-chat retrieval" for the route contract and `console.debug` observability (Task 686).
|
|
319
321
|
|
|
@@ -29,6 +29,10 @@ Just say it naturally:
|
|
|
29
29
|
|
|
30
30
|
{{productName}} will confirm and store it.
|
|
31
31
|
|
|
32
|
+
## How {{productName}} learns how you work
|
|
33
|
+
|
|
34
|
+
{{productName}} also learns how you work without you having to teach it deliberately. Six broad areas cover the way most operators run a business — communication, scheduling, decisions, workflow, content, and interaction. {{productName}} tracks which of these you have spoken into and which are still empty. While any are empty, it folds one organic question per turn into the conversation aimed at the next gap — never a list, never a form, never the same question twice. Once every area carries at least one preference above the confidence threshold, the proactive questions stop and {{productName}} answers what you ask without volunteering more. This is why session 300 should feel sharper than session 3: the longer you work together, the less {{productName}} needs to ask.
|
|
35
|
+
|
|
32
36
|
## Telling {{productName}} to Forget Something
|
|
33
37
|
|
|
34
38
|
Be direct:
|
|
@@ -192,7 +192,25 @@ The transient unit was auto-collected by systemd before the client subscribed. R
|
|
|
192
192
|
|
|
193
193
|
**Cloudflare-setup auto-relays "completed" but the next chat turn 502s.**
|
|
194
194
|
|
|
195
|
-
Pre-Task-860, `CloudflareSetupForm` dispatched the post-success chat message immediately on `exit{code:0}`. The relay POST hit the admin server inside the brand-restart bounce window (`~3 s` after `step=service-restart-armed`) and returned `Error: Request failed (502)`.
|
|
195
|
+
Pre-Task-860, `CloudflareSetupForm` dispatched the post-success chat message immediately on `exit{code:0}`. The relay POST hit the admin server inside the brand-restart bounce window (`~3 s` after `step=service-restart-armed`) and returned `Error: Request failed (502)`. Task 860 added an `awaitAdminReachable` holdback that polled `/api/admin/version` before dispatch. **Task 867 deleted the holdback** — `/api/admin/version` is on `maxy-edge.service` (Task 666 peer surface) which never restarts, so the probe always returned 200 immediately and never actually waited.
|
|
196
|
+
|
|
197
|
+
The replacement is a write-once filesystem queue + boot-drain. The form fires `POST /api/admin/cloudflare/relay-completion`, the route enqueues to `${accountDir}/queue/action-completion-relay-<actionId>.json`, and the brand-service boot-drain hook in `server/index.ts` consumes the queue on the next process-init via a synthetic one-shot session that calls `invokeAgent` directly. The agent's user-message persist is hoisted to BEFORE SDK invoke (Task 867) so even if SIGTERM hits mid-generation, the user message survives.
|
|
198
|
+
|
|
199
|
+
Diagnostic recipe:
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
ls ${ACCOUNT_DIR}/queue/ # any *.json present = consumer not running
|
|
203
|
+
grep '\[action-relay-queue\] phase=enqueued' ~/.maxy/logs/server.log | tail
|
|
204
|
+
grep '\[action-completion-relay\] phase=consumed' ~/.maxy/logs/server.log | tail
|
|
205
|
+
grep '\[persist\] .* role=user .* Cloudflare setup completed' ~/.maxy/logs/server.log | tail
|
|
206
|
+
grep '\[client-event\] source=cloudflare-setup-form' ~/.maxy/logs/server.log | tail
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Failure modes:
|
|
210
|
+
- `phase=enqueued` absent: form's POST never landed (check `[client-event]` for the dispatch line).
|
|
211
|
+
- `phase=enqueued` present, `phase=consumed` absent within 60s of the next brand restart: boot-drain hook regressed.
|
|
212
|
+
- Both present, `[persist] role=user` absent: persist hoist regressed (admin-agent.ts).
|
|
213
|
+
- Review-detector rule `cloudflare-setup-relay-not-acknowledged` is the consolidated alarm — fires if any of the above is missing within 60s of `[script:setup-tunnel] step=done`.
|
|
196
214
|
|
|
197
215
|
---
|
|
198
216
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-read.d.ts","sourceRoot":"","sources":["../../src/tools/profile-read.ts"],"names":[],"mappings":"AAOA,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,gBAAgB;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,cAAc;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,wBAAyB,SAAQ,gBAAgB;IACzD,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,uBAAuB;IAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,wBAAwB,EAAE,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QACL,gBAAgB,EAAE,MAAM,CAAC;QACzB,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,iBAAiB,GAAG,uBAAuB,CAAC,CA8GtD;
|
|
1
|
+
{"version":3,"file":"profile-read.d.ts","sourceRoot":"","sources":["../../src/tools/profile-read.ts"],"names":[],"mappings":"AAOA,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,gBAAgB;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,cAAc;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,wBAAyB,SAAQ,gBAAgB;IACzD,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,uBAAuB;IAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,wBAAwB,EAAE,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QACL,gBAAgB,EAAE,MAAM,CAAC;QACzB,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,iBAAiB,GAAG,uBAAuB,CAAC,CA8GtD;AAwBD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,WAAW,EAAE,gBAAgB,EAAE,GAC9B,MAAM,CA2DR"}
|
|
@@ -104,6 +104,16 @@ const CATEGORY_LABELS = {
|
|
|
104
104
|
content: "Content",
|
|
105
105
|
interaction: "Interaction patterns",
|
|
106
106
|
};
|
|
107
|
+
// Canonical six. Mutating this list is a schema change — keep aligned with
|
|
108
|
+
// PROFILE_CATEGORIES in neo4j-store.ts.
|
|
109
|
+
const PROFILE_CATEGORIES = [
|
|
110
|
+
"communication",
|
|
111
|
+
"scheduling",
|
|
112
|
+
"decision",
|
|
113
|
+
"workflow",
|
|
114
|
+
"content",
|
|
115
|
+
"interaction",
|
|
116
|
+
];
|
|
107
117
|
// Profile summary format — also implemented in neo4j-store.ts (loadUserProfile).
|
|
108
118
|
// Changes here must be reflected there and vice versa.
|
|
109
119
|
export function formatProfileSummary(profile, preferences) {
|
|
@@ -148,6 +158,15 @@ export function formatProfileSummary(profile, preferences) {
|
|
|
148
158
|
}
|
|
149
159
|
lines.push("");
|
|
150
160
|
}
|
|
161
|
+
// Coverage block — names absent canonical categories so the agent can bias
|
|
162
|
+
// one elicitation per turn toward expanding sparse coverage. Silent when
|
|
163
|
+
// every category carries ≥1 Preference above threshold.
|
|
164
|
+
const absent = PROFILE_CATEGORIES.filter((c) => !categories[c]);
|
|
165
|
+
if (absent.length > 0) {
|
|
166
|
+
lines.push(`### Coverage`);
|
|
167
|
+
lines.push(`Missing: ${absent.join(", ")}`);
|
|
168
|
+
lines.push("");
|
|
169
|
+
}
|
|
151
170
|
return lines.join("\n");
|
|
152
171
|
}
|
|
153
172
|
// Detailed summary for "what do you know about me?" — includes confidence,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-read.js","sourceRoot":"","sources":["../../src/tools/profile-read.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"profile-read.js","sourceRoot":"","sources":["../../src/tools/profile-read.ts"],"names":[],"mappings":"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"}
|
|
@@ -108,12 +108,14 @@ Load `plugins/cloudflare/skills/setup-tunnel/SKILL.md` via `plugin-read` on the
|
|
|
108
108
|
|
|
109
109
|
## Questions
|
|
110
110
|
|
|
111
|
-
Operationalises the CONCISE prerogative for clarification.
|
|
111
|
+
Operationalises the CONCISE prerogative for clarification. Three rules:
|
|
112
112
|
|
|
113
113
|
1. **One-sided questions only.** Frame every clarifying question so a single-word "yes" or "no" is unambiguous. Never pose two opposing framings joined by "or" — "Should I proceed, or stop?", "Want me to do X, or not?", "Shall I run this, or do you want to?". "Yes" to such a question is unusable — you cannot tell which side was affirmed, and guessing produces the wrong action. Pick one side, ask it plainly: "Proceed?" or "Stop?" — not both.
|
|
114
114
|
|
|
115
115
|
2. **No choice-fork when the signal is deterministic.** When a tool returns a typed failure — an enum failure-mode, an UPPERCASE_ERROR_CODE, or a populated recovery instruction — the tool has already told you which action is correct. Relay that action to the owner and take it. Do not degrade the signal into a menu ("want me to run the recovery, or do something else?"). The menu invites the wrong branch. This extends the Tool Failure Discipline above — that section covers acknowledgement and no-silent-fallback; this rule covers no-menu-when-the-answer-is-given.
|
|
116
116
|
|
|
117
|
+
3. **One question, last sentence.** Every response contains at most one question, and that question is the final sentence. Describe the situation, context, trade-offs, and any alternatives in declarative sentences first; close with the single question that asks for the owner's decision. Never open with the question and append caveats, never scatter mini-questions through the body, never end with two questions. The only exception is when the *intent* of the response is to offer enumerated choices — in that case, present the options as a numbered list, then close with one question ("Which would you like?"). A response that informs but does not require a decision ends without a question at all. *Failure symptoms:* a question in the first paragraph, a question followed by further explanation, two question marks in one response, "Would you like X, or shall I Y?" framings.
|
|
118
|
+
|
|
117
119
|
## Tool Routing
|
|
118
120
|
|
|
119
121
|
Plugins provide domain-specific tools that query their own data stores directly. `memory-search` is a general-purpose semantic search across the entire knowledge graph — it finds nodes by vector similarity, which means results are ranked by semantic closeness to the query, not by domain relevance. A query containing the word "email" will surface product documentation *about* email features before it surfaces actual Email nodes whose content is unrelated to the query wording.
|
|
@@ -182,6 +184,7 @@ You learn about the owner through conversation — never through questionnaires
|
|
|
182
184
|
- When the owner says "remember this" or "forget that", use `profile-update` or `profile-delete` accordingly and confirm what you did.
|
|
183
185
|
- When the owner asks "what do you know about me?", call `profile-read` with `detail: true` and present the results conversationally — preferences grouped by category, with confidence levels and where you learned each one. Offer to correct or remove anything.
|
|
184
186
|
- Memory informs but does not override. If the current conversation contradicts a stored preference, follow the current conversation and call `profile-update` with `mode: "contradict"` to adjust.
|
|
187
|
+
- The `## About the Owner` block in your system prompt is the per-turn signal source. Its `### Coverage` sub-block, when present, lists the canonical Preference categories that are absent (`communication`, `scheduling`, `decision`, `workflow`, `content`, `interaction`). While ≥1 category is absent, bias one organic question per turn toward an absent category — never a questionnaire, never more than one elicitation per turn, never a category already covered. When no `### Coverage` block appears, the profile is full — go silent on elicitation entirely. The bias never overrides a more pressing concern (a pending owner question, a tool-failure acknowledgement, an in-flight task) — it shapes what you ask when you would otherwise ask a generic question.
|
|
185
188
|
|
|
186
189
|
## Premium Plugin Delivery
|
|
187
190
|
|