@rubytech/create-realagent-code 0.1.600 → 0.1.601

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.
Files changed (24) hide show
  1. package/dist/__tests__/email-sampler-unit.test.js +31 -0
  2. package/dist/index.js +18 -2
  3. package/dist/port-resolution.js +24 -0
  4. package/package.json +1 -1
  5. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +4 -0
  6. package/payload/platform/plugins/email/PLUGIN.md +7 -1
  7. package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts +27 -0
  8. package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts.map +1 -1
  9. package/payload/platform/plugins/email/mcp/dist/lib/credentials.js +78 -0
  10. package/payload/platform/plugins/email/mcp/dist/lib/credentials.js.map +1 -1
  11. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.d.ts +2 -0
  12. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.d.ts.map +1 -0
  13. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js +96 -0
  14. package/payload/platform/plugins/email/mcp/dist/sampler/__tests__/sample-mailbox.test.js.map +1 -0
  15. package/payload/platform/plugins/email/mcp/dist/sampler/main.d.ts +2 -0
  16. package/payload/platform/plugins/email/mcp/dist/sampler/main.d.ts.map +1 -0
  17. package/payload/platform/plugins/email/mcp/dist/sampler/main.js +75 -0
  18. package/payload/platform/plugins/email/mcp/dist/sampler/main.js.map +1 -0
  19. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts +48 -0
  20. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.d.ts.map +1 -0
  21. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js +77 -0
  22. package/payload/platform/plugins/email/mcp/dist/sampler/sample-mailbox.js.map +1 -0
  23. package/payload/platform/scripts/logs-read.sh +18 -3
  24. package/payload/server/public/operator.html +1 -1
@@ -0,0 +1,31 @@
1
+ // Acceptance gate for the email-sampler systemd unit (Task 2682).
2
+ //
3
+ // The sampler runs the plugin's compiled entrypoint as its own per-brand user
4
+ // unit. Two invariants:
5
+ // (a) it runs `node dist/sampler/main.js` from the email plugin's mcp dir, so
6
+ // its relative imports of the plugin's lib resolve;
7
+ // (b) it carries the same runtime env the email MCP server needs —
8
+ // PLATFORM_ROOT, ACCOUNT_ID, the sampler log path — plus the brand .env
9
+ // (which supplies NEO4J_URI and the neo4j password source).
10
+ import test from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { buildEmailSamplerUnitFile } from "../port-resolution.js";
13
+ const unit = buildEmailSamplerUnitFile({
14
+ productName: "Maxy",
15
+ installDir: "/home/x/maxy-code",
16
+ persistDir: "/home/x/.maxy",
17
+ accountId: "acc-1",
18
+ logPath: "/home/x/.maxy/logs/email-sampler.log",
19
+ intervalSec: 60,
20
+ });
21
+ test("runs the compiled sampler from the plugin dir", () => {
22
+ assert.match(unit, /^WorkingDirectory=\/home\/x\/maxy-code\/platform\/plugins\/email\/mcp$/m);
23
+ assert.match(unit, /^ExecStart=\/usr\/bin\/node dist\/sampler\/main\.js$/m);
24
+ });
25
+ test("carries the plugin runtime env and the brand .env", () => {
26
+ assert.match(unit, /^Environment=PLATFORM_ROOT=\/home\/x\/maxy-code\/platform$/m);
27
+ assert.match(unit, /^Environment=ACCOUNT_ID=acc-1$/m);
28
+ assert.match(unit, /^Environment=EMAIL_SAMPLER_LOG_PATH=\/home\/x\/\.maxy\/logs\/email-sampler\.log$/m);
29
+ assert.match(unit, /^Environment=EMAIL_SAMPLER_INTERVAL_SEC=60$/m);
30
+ assert.match(unit, /^EnvironmentFile=-\/home\/x\/\.maxy\/\.env$/m);
31
+ });
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { clearBrandAgentRoot } from "./brand-agent-root.js";
5
5
  import { seedBypassPermissionsSettings, assertBypassPermissionsSeed } from "./permissions-seed.js";
6
6
  import { resolve, join, dirname } from "node:path";
7
7
  import { randomBytes } from "node:crypto";
8
- import { resolveInstallPortFromFs, buildMaxyUnitFile, buildClaudeSessionManagerUnitFile, buildClaudePtysSliceUnitFile, buildCloudflaredSliceUnitFile, buildDarwinServiceEnvPath } from "./port-resolution.js";
8
+ import { resolveInstallPortFromFs, buildMaxyUnitFile, buildClaudeSessionManagerUnitFile, buildEmailSamplerUnitFile, buildClaudePtysSliceUnitFile, buildCloudflaredSliceUnitFile, buildDarwinServiceEnvPath } from "./port-resolution.js";
9
9
  import { buildBrandCronBlock, mergeBrandCronBlock } from "./cron-registration.js";
10
10
  import { validateTierFlag, validateEntitlementBase64, applyTierToAccountConfig, entitlementPath } from "./tier-flag.js";
11
11
  import { parseOsRelease, isUbuntuLike as isUbuntuLikePure, parseAptCacheCandidate, decideAptResolution, } from "./apt-resolve.js";
@@ -4571,6 +4571,20 @@ WantedBy=default.target
4571
4571
  `;
4572
4572
  writeFileSync(join(serviceDir, rssSamplerUnitName), rssSamplerUnit);
4573
4573
  logFile(` rss-sampler installed: ${rssSamplerUnitName} LOG_PATH=${rssSamplerLogPath} BRAND_SERVICE=${memBrandService} EDGE_SERVICE=${memEdgeService} NEO4J_UNIT=${memNeo4jUnit} MEM_PRESSURE_PCT=${memPressurePct}`);
4574
+ // Task 2682 — the email-sampler unit: an always-on user service that writes
4575
+ // every inbound IMAP message to the graph, independent of any agent turn. It
4576
+ // runs the email plugin's compiled sampler entrypoint from the plugin dir.
4577
+ const emailSamplerUnitName = `${BRAND.hostname}-email-sampler.service`;
4578
+ const emailSamplerLogPath = join(persistDir, "logs", "email-sampler.log");
4579
+ const emailSamplerUnit = buildEmailSamplerUnitFile({
4580
+ productName: BRAND.productName,
4581
+ installDir: INSTALL_DIR,
4582
+ persistDir,
4583
+ accountId: installAccountId,
4584
+ logPath: emailSamplerLogPath,
4585
+ });
4586
+ writeFileSync(join(serviceDir, emailSamplerUnitName), emailSamplerUnit);
4587
+ logFile(` email-sampler installed: ${emailSamplerUnitName} LOG_PATH=${emailSamplerLogPath}`);
4574
4588
  // the edge service: always-on front door that owns the public
4575
4589
  // port (PORT) and the VNC stack (Xtigervnc + websockify). Its lifecycle is
4576
4590
  // independent of the main brand service, so an in-place upgrade triggered
@@ -4791,13 +4805,15 @@ WantedBy=multi-user.target
4791
4805
  spawnSync("systemctl", ["--user", "enable", claudeSessionManagerUnitShort], { stdio: "inherit" });
4792
4806
  spawnSync("systemctl", ["--user", "enable", unitName], { stdio: "inherit" });
4793
4807
  spawnSync("systemctl", ["--user", "enable", `${BRAND.hostname}-rss-sampler`], { stdio: "inherit" });
4808
+ spawnSync("systemctl", ["--user", "enable", `${BRAND.hostname}-email-sampler`], { stdio: "inherit" });
4794
4809
  // edge first: binds public port + starts VNC stack. Then claude-session-manager
4795
4810
  // (so the main brand unit's Requires= is satisfied). Then main brand service.
4796
- // rss-sampler is independent — start last, failure is non-blocking.
4811
+ // rss-sampler and email-sampler are independent — start last, failure is non-blocking.
4797
4812
  spawnSync("systemctl", ["--user", "restart", edgeUnitShort], { stdio: "inherit" });
4798
4813
  spawnSync("systemctl", ["--user", "restart", claudeSessionManagerUnitShort], { stdio: "inherit" });
4799
4814
  spawnSync("systemctl", ["--user", "restart", unitName], { stdio: "inherit" });
4800
4815
  spawnSync("systemctl", ["--user", "restart", `${BRAND.hostname}-rss-sampler`], { stdio: "inherit" });
4816
+ spawnSync("systemctl", ["--user", "restart", `${BRAND.hostname}-email-sampler`], { stdio: "inherit" });
4801
4817
  // Session manager runs in its own systemd user unit and can boot-fail silently
4802
4818
  // (e.g. mcp-block-missing). The web server below comes up regardless, so the
4803
4819
  // install terminal would otherwise report success while every API call 503s.
@@ -167,6 +167,30 @@ EnvironmentFile=-${o.persistDir}/.env
167
167
  StandardOutput=append:${o.persistDir}/logs/server.log
168
168
  StandardError=append:${o.persistDir}/logs/server.log
169
169
 
170
+ [Install]
171
+ WantedBy=default.target
172
+ `;
173
+ }
174
+ export function buildEmailSamplerUnitFile(o) {
175
+ return `[Unit]
176
+ Description=${o.productName} Email Sampler
177
+ After=network.target
178
+
179
+ [Service]
180
+ Type=simple
181
+ WorkingDirectory=${o.installDir}/platform/plugins/email/mcp
182
+ ExecStart=/usr/bin/node dist/sampler/main.js
183
+ Restart=on-failure
184
+ RestartSec=10
185
+ Environment=NODE_ENV=production
186
+ Environment=ACCOUNT_ID=${o.accountId}
187
+ Environment=PLATFORM_ROOT=${o.installDir}/platform
188
+ Environment=EMAIL_SAMPLER_LOG_PATH=${o.logPath}
189
+ Environment=EMAIL_SAMPLER_INTERVAL_SEC=${o.intervalSec ?? 60}
190
+ EnvironmentFile=-${o.persistDir}/.env
191
+ StandardOutput=append:${o.persistDir}/logs/server.log
192
+ StandardError=append:${o.persistDir}/logs/server.log
193
+
170
194
  [Install]
171
195
  WantedBy=default.target
172
196
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-realagent-code",
3
- "version": "0.1.600",
3
+ "version": "0.1.601",
4
4
  "description": "Install Real Agent — Built for agents. By agents.",
5
5
  "bin": {
6
6
  "create-realagent-code": "./dist/index.js"
@@ -9,6 +9,10 @@ Invoked by the admin agent directly.
9
9
 
10
10
  This is the platform's release timeline, newest first. Each entry shows the date it shipped and the version it shipped in, so you can tell the operator how current their install is. To compare, read the installed version from `capabilities-here` and match it against the versions below. Keep answers high level and in plain English; this is a summary, not a full commit log.
11
11
 
12
+ ## 2026-08-13 (0.1.601)
13
+
14
+ - Your incoming email is now recorded automatically. A background service checks each connected mailbox on its own and saves every new message so the assistant can recall it later, without you having to say "check my email" first.
15
+
12
16
  ## 2026-08-13 (0.1.600)
13
17
 
14
18
  - The routine that keeps your diary and the app's view of it in step now also wakes when an appointment changes in the app, not only when your provider calendar changes. It stays quiet on a check where neither side moved.
@@ -143,7 +143,13 @@ Manages the agent's own dedicated email account — IMAP for reading, SMTP for s
143
143
 
144
144
  ## Ingestion model
145
145
 
146
- Email ingestion is **operator-initiated and human-in-the-loop**. There is no background poll, cron, or auto-classifier. New messages enter the graph only when the operator says "check my emails" and approves each one. See `skills/email-ingest/SKILL.md` for the conversation flow and `skills/email-composition/SKILL.md` for drafting replies once a thread is stored.
146
+ There are two independent paths into the graph, both writing `:ConversationArchive {source:'email'}`:
147
+
148
+ - **Deterministic ingest — the `email-sampler` service.** A per-brand, always-on systemd user unit (`<brand>-email-sampler.service`) runs the plugin's compiled `dist/sampler/main.js`. Each cycle it enumerates every connected IMAP mailbox on the install and writes every inbound message above its own cursor, with no agent turn and no approval step. Its cursor is `:EmailAccount.samplerCursorUid` + `samplerUidValidity`, written only by the sampler and kept strictly independent of `lastFetchedUid` (which `email-fetch` owns). This is the foundation a gate that reads email-in-graph can trust: every inbound message lands within one cycle. Observability: one `op=sample mailbox=<addr> fetched=<n> cursor=<uid>` line per mailbox per cycle (`op=sample-error` on failure, cursor unadvanced), read with `logs-read.sh --tail email-sampler`. Attachment archival by the sampler is deferred (see the task follow-up).
149
+
150
+ - **Operator-initiated ingest — human-in-the-loop.** When the operator says "check my emails", `email-fetch` lists new messages and the operator approves each one; only the approved subset is written via `email-ingest`, which also fetches and archives attachment bytes. See `skills/email-ingest/SKILL.md` for the conversation flow and `skills/email-composition/SKILL.md` for drafting replies once a thread is stored.
151
+
152
+ The two watermarks are independent by design, so a message may be seen by both; `dispatch` uses MERGE, so a double write is idempotent and never duplicates a node.
147
153
 
148
154
  ## Retrieval paths
149
155
 
@@ -61,6 +61,33 @@ export declare function readConfig(accountId: string, email: string): Promise<Em
61
61
  * own :EmailAccount node keyed by (accountId, email).
62
62
  */
63
63
  export declare function listConfigs(accountId: string): Promise<EmailConfig[]>;
64
+ /** The sampler's own high-water mark for one mailbox, keyed by uidValidity. */
65
+ export interface SamplerCursor {
66
+ cursorUid: number;
67
+ uidValidity: number | null;
68
+ }
69
+ /**
70
+ * Every configured IMAP mailbox across every account on the install, with its
71
+ * password resolved. An account whose password cannot be read is skipped (with
72
+ * a stderr note) rather than failing the whole enumeration, so one broken
73
+ * credential never stops the sampler from servicing the others.
74
+ */
75
+ export declare function listAllImapAccounts(): Promise<Array<{
76
+ accountId: string;
77
+ config: EmailConfig;
78
+ password: string;
79
+ }>>;
80
+ /**
81
+ * Read the sampler's cursor for one mailbox. Returns null when the node is
82
+ * absent or the sampler has never written a cursor for it — the caller treats
83
+ * that as "start from a fresh backfill".
84
+ */
85
+ export declare function readSamplerCursor(accountId: string, email: string): Promise<SamplerCursor | null>;
86
+ /**
87
+ * Advance the sampler's cursor for one mailbox. Written only by the sampler,
88
+ * never touching `lastFetchedUid`. Integer-typed to match `lastFetchedUid`.
89
+ */
90
+ export declare function advanceSamplerCursor(accountId: string, email: string, cursorUid: number, uidValidity: number): Promise<void>;
64
91
  /**
65
92
  * Resolve which configured mailbox a call targets.
66
93
  * Resolution order:
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"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"}
@@ -144,6 +144,84 @@ export async function listConfigs(accountId) {
144
144
  await session.close();
145
145
  }
146
146
  }
147
+ /**
148
+ * Every configured IMAP mailbox across every account on the install, with its
149
+ * password resolved. An account whose password cannot be read is skipped (with
150
+ * a stderr note) rather than failing the whole enumeration, so one broken
151
+ * credential never stops the sampler from servicing the others.
152
+ */
153
+ export async function listAllImapAccounts() {
154
+ const session = getSession();
155
+ let propRows;
156
+ try {
157
+ const result = await session.run(`MATCH (e:EmailAccount) RETURN e ORDER BY e.accountId, e.email`);
158
+ propRows = result.records.map((r) => r.get("e").properties);
159
+ }
160
+ finally {
161
+ await session.close();
162
+ }
163
+ // Map + resolve the password per row, skipping any row that throws (a
164
+ // malformed node whose nodeToConfig fails, or a missing password) rather than
165
+ // letting one bad node blank the whole enumeration — the sampler runs
166
+ // unattended, so a single bad row must never stop it servicing the others.
167
+ const out = [];
168
+ for (const props of propRows) {
169
+ const accountId = props.accountId;
170
+ try {
171
+ const config = nodeToConfig(props);
172
+ out.push({ accountId, config, password: readPassword(config.email) });
173
+ }
174
+ catch (err) {
175
+ process.stderr.write(`[email-sampler] WARN skip account=${(accountId ?? "").slice(0, 8)} mailbox=${props.email ?? "?"} ` +
176
+ `reason=${err instanceof Error ? err.message : String(err)}\n`);
177
+ }
178
+ }
179
+ return out;
180
+ }
181
+ /**
182
+ * Read the sampler's cursor for one mailbox. Returns null when the node is
183
+ * absent or the sampler has never written a cursor for it — the caller treats
184
+ * that as "start from a fresh backfill".
185
+ */
186
+ export async function readSamplerCursor(accountId, email) {
187
+ const session = getSession();
188
+ try {
189
+ const result = await session.run(`MATCH (e:EmailAccount {accountId: $accountId, email: $email})
190
+ RETURN e.samplerCursorUid AS uid, e.samplerUidValidity AS v LIMIT 1`, { accountId, email });
191
+ if (result.records.length === 0)
192
+ return null;
193
+ const uid = result.records[0].get("uid");
194
+ if (uid === null || uid === undefined)
195
+ return null;
196
+ const v = result.records[0].get("v");
197
+ return {
198
+ cursorUid: neo4j.integer.toNumber(uid),
199
+ uidValidity: v === null || v === undefined ? null : neo4j.integer.toNumber(v),
200
+ };
201
+ }
202
+ finally {
203
+ await session.close();
204
+ }
205
+ }
206
+ /**
207
+ * Advance the sampler's cursor for one mailbox. Written only by the sampler,
208
+ * never touching `lastFetchedUid`. Integer-typed to match `lastFetchedUid`.
209
+ */
210
+ export async function advanceSamplerCursor(accountId, email, cursorUid, uidValidity) {
211
+ const session = getSession();
212
+ try {
213
+ await session.run(`MATCH (e:EmailAccount {accountId: $accountId, email: $email})
214
+ SET e.samplerCursorUid = $cursorUid, e.samplerUidValidity = $uidValidity`, {
215
+ accountId,
216
+ email,
217
+ cursorUid: neo4j.int(cursorUid),
218
+ uidValidity: neo4j.int(uidValidity),
219
+ });
220
+ }
221
+ finally {
222
+ await session.close();
223
+ }
224
+ }
147
225
  /**
148
226
  * The one line that makes an outbound mailbox choice attributable: which
149
227
  * address was picked, and which of the three routes picked it (Task 2194).
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sample-mailbox.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sample-mailbox.test.d.ts","sourceRoot":"","sources":["../../../src/sampler/__tests__/sample-mailbox.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,96 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { sampleMailbox } from "../sample-mailbox.js";
3
+ const config = { email: "box@x.com", agentAddress: "box@x.com" };
4
+ const account = { accountId: "acc-1", config, password: "pw" };
5
+ const email = (uid) => ({
6
+ uid,
7
+ messageId: `<m${uid}@x>`,
8
+ inReplyTo: null,
9
+ toAddresses: ["box@x.com"],
10
+ ccAddresses: [],
11
+ fromAddress: "s@y.com",
12
+ fromName: "S",
13
+ subject: `s${uid}`,
14
+ date: "2026-08-13T00:00:00Z",
15
+ bodyPreview: "b",
16
+ attachments: [],
17
+ });
18
+ function deps(over = {}) {
19
+ return {
20
+ fetchSince: vi.fn(async () => ({ uidValidity: 100, emails: [], maxUid: 0 })),
21
+ write: vi.fn(async () => ({
22
+ threadsDispatched: 1,
23
+ threadsSkipped: 0,
24
+ unresolvedAddresses: [],
25
+ attachmentsAttached: 0,
26
+ attachmentsFailed: 0,
27
+ })),
28
+ readCursor: vi.fn(async () => null),
29
+ advanceCursor: vi.fn(async () => { }),
30
+ recipients: () => ["box@x.com"],
31
+ log: vi.fn(),
32
+ ...over,
33
+ };
34
+ }
35
+ describe("sampleMailbox", () => {
36
+ it("writes above-cursor messages once and advances the cursor to maxUid", async () => {
37
+ const d = deps({
38
+ readCursor: vi.fn(async () => ({ cursorUid: 10, uidValidity: 100 })),
39
+ fetchSince: vi.fn(async () => ({ uidValidity: 100, emails: [email(11), email(12)], maxUid: 12 })),
40
+ });
41
+ const r = await sampleMailbox(d, account);
42
+ expect(d.write).toHaveBeenCalledTimes(1);
43
+ expect(d.write.mock.calls[0][0]).toHaveLength(2);
44
+ expect(d.advanceCursor).toHaveBeenCalledWith("acc-1", "box@x.com", 12, 100);
45
+ expect(r).toMatchObject({ fetched: 2, cursor: 12 });
46
+ });
47
+ it("leaves the cursor unadvanced when the write fails", async () => {
48
+ const d = deps({
49
+ readCursor: vi.fn(async () => ({ cursorUid: 10, uidValidity: 100 })),
50
+ fetchSince: vi.fn(async () => ({ uidValidity: 100, emails: [email(11)], maxUid: 11 })),
51
+ write: vi.fn(async () => {
52
+ throw new Error("neo4j down");
53
+ }),
54
+ });
55
+ const r = await sampleMailbox(d, account);
56
+ expect(d.advanceCursor).not.toHaveBeenCalled();
57
+ expect(r.error).toContain("neo4j down");
58
+ expect(d.log.mock.calls.some((c) => String(c[0]).includes("op=sample-error"))).toBe(true);
59
+ });
60
+ it("is a no-op when nothing is above the cursor", async () => {
61
+ const d = deps({
62
+ readCursor: vi.fn(async () => ({ cursorUid: 10, uidValidity: 100 })),
63
+ fetchSince: vi.fn(async () => ({ uidValidity: 100, emails: [], maxUid: 0 })),
64
+ });
65
+ const r = await sampleMailbox(d, account);
66
+ expect(d.write).not.toHaveBeenCalled();
67
+ expect(d.advanceCursor).not.toHaveBeenCalled();
68
+ expect(r).toMatchObject({ fetched: 0, cursor: 10 });
69
+ });
70
+ it("a second cycle over a persistent store does not re-ingest", async () => {
71
+ let stored = null;
72
+ const d = deps({
73
+ readCursor: vi.fn(async () => stored),
74
+ advanceCursor: vi.fn(async (_a, _e, uid, v) => {
75
+ stored = { cursorUid: uid, uidValidity: v };
76
+ }),
77
+ fetchSince: vi.fn(async (_c, _p, sinceUid) => sinceUid < 12
78
+ ? { uidValidity: 100, emails: [email(11), email(12)], maxUid: 12 }
79
+ : { uidValidity: 100, emails: [], maxUid: 0 }),
80
+ });
81
+ await sampleMailbox(d, account);
82
+ await sampleMailbox(d, account);
83
+ expect(d.write).toHaveBeenCalledTimes(1);
84
+ });
85
+ it("resets the cursor to a backfill when uidValidity changed", async () => {
86
+ const d = deps({
87
+ readCursor: vi.fn(async () => ({ cursorUid: 5000, uidValidity: 100 })),
88
+ fetchSince: vi.fn(async () => ({ uidValidity: 200, emails: [email(1)], maxUid: 1 })),
89
+ });
90
+ const r = await sampleMailbox(d, account);
91
+ expect(d.write).not.toHaveBeenCalled();
92
+ expect(d.advanceCursor).toHaveBeenCalledWith("acc-1", "box@x.com", 0, 200);
93
+ expect(r).toMatchObject({ fetched: 0, cursor: 0 });
94
+ });
95
+ });
96
+ //# sourceMappingURL=sample-mailbox.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sample-mailbox.test.js","sourceRoot":"","sources":["../../../src/sampler/__tests__/sample-mailbox.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/sampler/main.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { appendFileSync, statSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import { fetchSinceUid, resolveDefaultRecipients } from "../lib/imap.js";
4
+ import { dispatchEmailMessagesToConversationArchive } from "../lib/conversation-archive-dispatch.js";
5
+ import { listAllImapAccounts, readSamplerCursor, advanceSamplerCursor } from "../lib/credentials.js";
6
+ import { sampleMailbox } from "./sample-mailbox.js";
7
+ // The standing email-sampler (Task 2682): a per-brand systemd user unit that
8
+ // each cycle enumerates every IMAP mailbox on the install and writes new
9
+ // inbound messages to the graph via the plugin's own dispatch, independent of
10
+ // any agent turn. The cursor is the only state; it advances only on a
11
+ // successful write, so the loop is restart-safe by construction.
12
+ const LOG_PATH = process.env.EMAIL_SAMPLER_LOG_PATH ?? "/tmp/email-sampler.log";
13
+ const INTERVAL_MS = (Number(process.env.EMAIL_SAMPLER_INTERVAL_SEC ?? "60") || 60) * 1000;
14
+ const LOG_MAX = Number(process.env.EMAIL_SAMPLER_LOG_MAX_BYTES ?? "10485760") || 10485760;
15
+ /** Append one structured line, capping the file at LOG_MAX by keeping the tail
16
+ * (mirrors rss-sampler's self-cap). Logging must never kill the loop. */
17
+ function logLine(line) {
18
+ const stamped = `${new Date().toISOString()} [email-sampler] ${line}\n`;
19
+ try {
20
+ mkdirSync(dirname(LOG_PATH), { recursive: true });
21
+ appendFileSync(LOG_PATH, stamped);
22
+ if (statSync(LOG_PATH).size > LOG_MAX) {
23
+ const buf = readFileSync(LOG_PATH);
24
+ // Keep roughly the last half, but start at the next line boundary so the
25
+ // first retained line is whole, not a mid-line fragment a tail reader
26
+ // would show as garbage.
27
+ const approx = buf.length - Math.floor(LOG_MAX / 2);
28
+ const nl = buf.indexOf(0x0a, approx);
29
+ const start = nl === -1 ? approx : nl + 1;
30
+ writeFileSync(LOG_PATH, buf.subarray(start));
31
+ }
32
+ }
33
+ catch {
34
+ /* a logging failure is never fatal to ingest */
35
+ }
36
+ }
37
+ const deps = {
38
+ fetchSince: fetchSinceUid,
39
+ write: (m) => dispatchEmailMessagesToConversationArchive(m),
40
+ readCursor: readSamplerCursor,
41
+ advanceCursor: advanceSamplerCursor,
42
+ recipients: (c) => resolveDefaultRecipients(c),
43
+ log: logLine,
44
+ };
45
+ async function cycle() {
46
+ let accounts;
47
+ try {
48
+ accounts = await listAllImapAccounts();
49
+ }
50
+ catch (e) {
51
+ logLine(`op=sample-error mailbox=<enumeration> detail=${e instanceof Error ? e.message : String(e)}`);
52
+ return;
53
+ }
54
+ for (const account of accounts) {
55
+ try {
56
+ await sampleMailbox(deps, account);
57
+ }
58
+ catch (e) {
59
+ logLine(`op=sample-error mailbox=${account.config.email} detail=${e instanceof Error ? e.message : String(e)}`);
60
+ }
61
+ }
62
+ }
63
+ async function main() {
64
+ logLine(`boot interval_sec=${INTERVAL_MS / 1000} log=${LOG_PATH}`);
65
+ // eslint-disable-next-line no-constant-condition
66
+ while (true) {
67
+ await cycle();
68
+ await new Promise((r) => setTimeout(r, INTERVAL_MS));
69
+ }
70
+ }
71
+ main().catch((e) => {
72
+ logLine(`op=sample-error mailbox=<fatal> detail=${e instanceof Error ? e.message : String(e)}`);
73
+ process.exit(1);
74
+ });
75
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/sampler/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { EmailConfig, SamplerCursor } from "../lib/credentials.js";
2
+ import type { FetchedEmail } from "../lib/imap.js";
3
+ import type { EmailData } from "../lib/graph.js";
4
+ import type { DispatchResult } from "../lib/conversation-archive-dispatch.js";
5
+ /**
6
+ * The email-sampler's single ingest step, isolated as a pure function with
7
+ * injected fetch / writer / cursor so the loop and the systemd unit stay thin
8
+ * and every branch is testable without IMAP, Neo4j, or a clock (Task 2682).
9
+ */
10
+ export interface SamplerDeps {
11
+ fetchSince: (config: EmailConfig, password: string, sinceUid: number, recipients: string[] | undefined) => Promise<{
12
+ uidValidity: number;
13
+ emails: FetchedEmail[];
14
+ maxUid: number;
15
+ }>;
16
+ write: (messages: EmailData[]) => Promise<DispatchResult>;
17
+ readCursor: (accountId: string, email: string) => Promise<SamplerCursor | null>;
18
+ advanceCursor: (accountId: string, email: string, cursorUid: number, uidValidity: number) => Promise<void>;
19
+ recipients: (config: EmailConfig) => string[] | undefined;
20
+ log: (line: string) => void;
21
+ }
22
+ export interface SamplerAccount {
23
+ accountId: string;
24
+ config: EmailConfig;
25
+ password: string;
26
+ }
27
+ export interface SampleResult {
28
+ mailbox: string;
29
+ fetched: number;
30
+ cursor: number;
31
+ error?: string;
32
+ }
33
+ /**
34
+ * Sample one mailbox: fetch inbound UIDs above the sampler's own cursor, write
35
+ * them to the graph, and advance the cursor — but only after a successful write.
36
+ *
37
+ * Cases, in order:
38
+ * - fetch throws → log op=sample-error, cursor unchanged, retried next cycle.
39
+ * - the mailbox's live uidValidity differs from the stored one → the stored UID
40
+ * is void (the server renumbered), so reset the cursor to 0 for the new
41
+ * uidValidity and let the next cycle backfill cleanly. This cycle writes
42
+ * nothing, because `UID > oldCursor` against a new sequence is unreliable.
43
+ * - no messages above the cursor → no-op, cursor unchanged.
44
+ * - write throws → log op=sample-error, cursor unchanged, retried next cycle.
45
+ * - otherwise → advance the cursor to the fetched maxUid.
46
+ */
47
+ export declare function sampleMailbox(deps: SamplerDeps, account: SamplerAccount): Promise<SampleResult>;
48
+ //# sourceMappingURL=sample-mailbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sample-mailbox.d.ts","sourceRoot":"","sources":["../../src/sampler/sample-mailbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAE9E;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,CACV,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,KAC7B,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9E,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1D,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAChF,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3G,UAAU,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,MAAM,EAAE,GAAG,SAAS,CAAC;IAC1D,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgCD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAoCrG"}
@@ -0,0 +1,77 @@
1
+ function msg(e) {
2
+ return e instanceof Error ? e.message : String(e);
3
+ }
4
+ /** Map a fetched IMAP message to the archive-writer's record shape. The mapping
5
+ * matches what email-ingest builds, EXCEPT the screening label: email-ingest
6
+ * stamps "clean" because an operator approved the message, whereas the sampler
7
+ * runs no screen and has no operator, so it stamps "unscreened" — the honest
8
+ * value a later gate needs to tell auto-sampled mail from operator-vetted mail. */
9
+ function toEmailData(e, accountId, config, uidValidity) {
10
+ return {
11
+ messageId: e.messageId,
12
+ inReplyTo: e.inReplyTo,
13
+ toAddresses: e.toAddresses,
14
+ ccAddresses: e.ccAddresses,
15
+ uid: e.uid,
16
+ uidValidity,
17
+ mailbox: "INBOX",
18
+ recipientAddress: config.email,
19
+ fromAddress: e.fromAddress,
20
+ fromName: e.fromName,
21
+ subject: e.subject,
22
+ bodyPreview: e.bodyPreview,
23
+ receivedAt: e.date,
24
+ accountId,
25
+ screening: "unscreened",
26
+ screeningReason: "sampler-ingest",
27
+ };
28
+ }
29
+ /**
30
+ * Sample one mailbox: fetch inbound UIDs above the sampler's own cursor, write
31
+ * them to the graph, and advance the cursor — but only after a successful write.
32
+ *
33
+ * Cases, in order:
34
+ * - fetch throws → log op=sample-error, cursor unchanged, retried next cycle.
35
+ * - the mailbox's live uidValidity differs from the stored one → the stored UID
36
+ * is void (the server renumbered), so reset the cursor to 0 for the new
37
+ * uidValidity and let the next cycle backfill cleanly. This cycle writes
38
+ * nothing, because `UID > oldCursor` against a new sequence is unreliable.
39
+ * - no messages above the cursor → no-op, cursor unchanged.
40
+ * - write throws → log op=sample-error, cursor unchanged, retried next cycle.
41
+ * - otherwise → advance the cursor to the fetched maxUid.
42
+ */
43
+ export async function sampleMailbox(deps, account) {
44
+ const { accountId, config, password } = account;
45
+ const box = config.email;
46
+ const stored = await deps.readCursor(accountId, box);
47
+ const sinceUid = stored?.cursorUid ?? 0;
48
+ let result;
49
+ try {
50
+ result = await deps.fetchSince(config, password, sinceUid, deps.recipients(config));
51
+ }
52
+ catch (e) {
53
+ deps.log(`op=sample-error mailbox=${box} detail=${msg(e)}`);
54
+ return { mailbox: box, fetched: 0, cursor: sinceUid, error: msg(e) };
55
+ }
56
+ if (stored?.uidValidity != null && stored.uidValidity !== result.uidValidity) {
57
+ await deps.advanceCursor(accountId, box, 0, result.uidValidity);
58
+ deps.log(`op=sample mailbox=${box} fetched=0 cursor=0 note=uidvalidity-reset`);
59
+ return { mailbox: box, fetched: 0, cursor: 0 };
60
+ }
61
+ if (result.emails.length === 0) {
62
+ deps.log(`op=sample mailbox=${box} fetched=0 cursor=${sinceUid}`);
63
+ return { mailbox: box, fetched: 0, cursor: sinceUid };
64
+ }
65
+ const messages = result.emails.map((e) => toEmailData(e, accountId, config, result.uidValidity));
66
+ try {
67
+ await deps.write(messages);
68
+ }
69
+ catch (e) {
70
+ deps.log(`op=sample-error mailbox=${box} detail=${msg(e)}`);
71
+ return { mailbox: box, fetched: messages.length, cursor: sinceUid, error: msg(e) };
72
+ }
73
+ await deps.advanceCursor(accountId, box, result.maxUid, result.uidValidity);
74
+ deps.log(`op=sample mailbox=${box} fetched=${messages.length} cursor=${result.maxUid}`);
75
+ return { mailbox: box, fetched: messages.length, cursor: result.maxUid };
76
+ }
77
+ //# sourceMappingURL=sample-mailbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sample-mailbox.js","sourceRoot":"","sources":["../../src/sampler/sample-mailbox.ts"],"names":[],"mappings":"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"}
@@ -61,6 +61,10 @@ VNC_LOG="$CONFIG_DIR/logs/vnc-boot.log"
61
61
  # log directly under the configDir (persistDir == CONFIG_DIR), NOT under logs/.
62
62
  # `--tail mem` surfaces it so the approach-to-OOM diagnostic is one SSH command.
63
63
  MEM_LOG="$CONFIG_DIR/rss-sampler.log"
64
+ # Task 2682 — the standing email-sampler service writes its per-cycle op=sample
65
+ # lines here (persistDir/logs/email-sampler.log). `--tail email-sampler`
66
+ # surfaces the ingest cursor and per-mailbox fetch counts in one SSH command.
67
+ EMAIL_SAMPLER_LOG="$CONFIG_DIR/logs/email-sampler.log"
64
68
 
65
69
  # --- Resolve the Claude Code state tree (Task 585) ---
66
70
  # rc-spawn per-session evidence is NOT under data/accounts/<id>/logs/ — it is
@@ -152,7 +156,7 @@ is_per_conversation_type() {
152
156
  }
153
157
 
154
158
  SEARCH_TYPES="agent-stream error session public server mcp vnc"
155
- VALID_TYPES="agent-stream, system, session, error, heartbeat, public, server, mcp, vnc, mem, chat-attempts"
159
+ VALID_TYPES="agent-stream, system, session, error, heartbeat, public, server, mcp, vnc, mem, email-sampler, chat-attempts"
156
160
 
157
161
  # chat-attempts cross-grep prefixes. Four checkpoint patterns across
158
162
  # edge.log + server.log: edge-side inbound/outcome, admin-auth gate verdict,
@@ -216,7 +220,7 @@ EOF
216
220
  validate_type() {
217
221
  local t="$1"
218
222
  case "$t" in
219
- agent-stream|system|session|error|heartbeat|public|server|mcp|vnc|mem|chat-attempts) return 0 ;;
223
+ agent-stream|system|session|error|heartbeat|public|server|mcp|vnc|mem|email-sampler|chat-attempts) return 0 ;;
220
224
  *) echo "Error: invalid type '$t'. Valid types: $VALID_TYPES" >&2; exit 2 ;;
221
225
  esac
222
226
  }
@@ -444,7 +448,7 @@ per_conversation_mode() {
444
448
 
445
449
  # Platform-scoped types shortcut to their fixed files regardless of id.
446
450
  case "$filter_type" in
447
- server|vnc|heartbeat|mcp|mem)
451
+ server|vnc|heartbeat|mcp|mem|email-sampler)
448
452
  echo "# note: type=$filter_type is platform-scoped; sessionKey ignored — showing fixed file" >&2
449
453
  tail_mode "$filter_type" "50"
450
454
  return
@@ -688,6 +692,17 @@ tail_mode() {
688
692
  exit 0
689
693
  fi
690
694
 
695
+ if [[ "$log_type" == "email-sampler" ]]; then
696
+ if [[ ! -f "$EMAIL_SAMPLER_LOG" ]]; then
697
+ echo "No email-sampler log found at $EMAIL_SAMPLER_LOG"
698
+ exit 1
699
+ fi
700
+ echo "# email-sampler.log"
701
+ echo ""
702
+ tail -n "$lines" "$EMAIL_SAMPLER_LOG"
703
+ exit 0
704
+ fi
705
+
691
706
  # Reached only for per-session stream-log types (agent-stream/error/session/
692
707
  # public/mcp); these live under the per-account log dirs.
693
708
  require_account_logs
@@ -22,8 +22,8 @@
22
22
  <link rel="modulepreload" crossorigin href="/assets/wrench-DL1pbaCs.js">
23
23
  <link rel="modulepreload" crossorigin href="/assets/page-DSsEpl8J.js">
24
24
  <link rel="stylesheet" crossorigin href="/assets/jsx-runtime-lfcjzaWi.css">
25
- <link rel="stylesheet" crossorigin href="/assets/AdminLoginScreens-CWMpccrR.css">
26
25
  <link rel="stylesheet" crossorigin href="/assets/useMediaQuery-DXAuc8G-.css">
26
+ <link rel="stylesheet" crossorigin href="/assets/AdminLoginScreens-CWMpccrR.css">
27
27
  <link rel="stylesheet" href="/brand-defaults.css">
28
28
  </head>
29
29
  <body>