surface-cli 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/refs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"refs.js","sourceRoot":"","sources":["../src/refs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAExC,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;AAEtC,SAAS,QAAQ,CAAC,MAAc;IAC9B,OAAO,GAAG,MAAM,IAAI,UAAU,EAAE,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC"}
1
+ {"version":3,"file":"refs.js","sourceRoot":"","sources":["../src/refs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAExC,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;AAEtC,SAAS,QAAQ,CAAC,MAAc;IAC9B,OAAO,GAAG,MAAM,IAAI,UAAU,EAAE,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env node
2
+ import { createServer } from "node:net";
3
+ import { existsSync, rmSync } from "node:fs";
4
+ import { errorToEnvelope, SurfaceError } from "./lib/errors.js";
5
+ import { fetchUnreadOutlookWithSession, readOutlookMessageWithSession, refreshOutlookThreadWithSession, searchOutlookWithSession, } from "./providers/outlook/adapter.js";
6
+ import { launchOutlookSession, probeOutlookAuth } from "./providers/outlook/session.js";
7
+ import { createAccountRuntimeContext, createRuntimeContext } from "./runtime.js";
8
+ import { sessionExpiry } from "./session.js";
9
+ function parseArgs(argv) {
10
+ const values = new Map();
11
+ for (let index = 0; index < argv.length; index += 2) {
12
+ const key = argv[index];
13
+ const value = argv[index + 1];
14
+ if (!key?.startsWith("--") || value === undefined) {
15
+ throw new Error(`Invalid daemon argument near '${key ?? ""}'.`);
16
+ }
17
+ values.set(key.slice(2), value);
18
+ }
19
+ const sessionId = values.get("session-id");
20
+ const accountId = values.get("account-id");
21
+ const configPath = values.get("config-path");
22
+ const socketPath = values.get("socket-path");
23
+ const authToken = values.get("auth-token");
24
+ const idleTimeoutSeconds = Number.parseInt(values.get("idle-timeout-seconds") ?? "", 10);
25
+ const maxAgeSeconds = Number.parseInt(values.get("max-age-seconds") ?? "", 10);
26
+ if (!sessionId || !accountId || !configPath || !socketPath || !authToken) {
27
+ throw new Error("Missing required daemon arguments.");
28
+ }
29
+ if (!Number.isFinite(idleTimeoutSeconds) || idleTimeoutSeconds <= 0) {
30
+ throw new Error("idle-timeout-seconds must be a positive integer.");
31
+ }
32
+ if (!Number.isFinite(maxAgeSeconds) || maxAgeSeconds <= 0) {
33
+ throw new Error("max-age-seconds must be a positive integer.");
34
+ }
35
+ return {
36
+ sessionId,
37
+ accountId,
38
+ configPath,
39
+ socketPath,
40
+ authToken,
41
+ idleTimeoutSeconds,
42
+ maxAgeSeconds,
43
+ };
44
+ }
45
+ async function main() {
46
+ const args = parseArgs(process.argv.slice(2));
47
+ const runtime = createRuntimeContext({ configPath: args.configPath });
48
+ let closed = false;
49
+ let idleTimer;
50
+ let maxAgeTimer;
51
+ let inflight = Promise.resolve();
52
+ let session;
53
+ let server;
54
+ const record = runtime.db.getSession(args.sessionId);
55
+ if (!record) {
56
+ throw new Error(`Session '${args.sessionId}' was not found.`);
57
+ }
58
+ const account = runtime.db.findAccountById(args.accountId);
59
+ if (!account) {
60
+ throw new Error(`Account '${args.accountId}' was not found.`);
61
+ }
62
+ if (!(account.provider === "outlook" && account.transport === "outlook-web-playwright")) {
63
+ throw new SurfaceError("unsupported", "Warm sessions only support outlook-web-playwright in v1.", {
64
+ account: account.name,
65
+ });
66
+ }
67
+ const context = createAccountRuntimeContext(runtime, account);
68
+ const shutdown = async (status, errorDetail, exitCode = 0) => {
69
+ if (closed) {
70
+ return;
71
+ }
72
+ closed = true;
73
+ if (idleTimer) {
74
+ clearTimeout(idleTimer);
75
+ }
76
+ if (maxAgeTimer) {
77
+ clearTimeout(maxAgeTimer);
78
+ }
79
+ runtime.db.markSessionClosed(args.sessionId, status, {
80
+ errorDetail: errorDetail ?? null,
81
+ pid: null,
82
+ });
83
+ try {
84
+ await new Promise((resolve) => {
85
+ if (!server) {
86
+ resolve();
87
+ return;
88
+ }
89
+ server.close(() => resolve());
90
+ });
91
+ }
92
+ catch {
93
+ // Ignore close failures during shutdown.
94
+ }
95
+ if (session) {
96
+ try {
97
+ await session.context.close();
98
+ }
99
+ catch {
100
+ // Ignore close failures during shutdown.
101
+ }
102
+ session.cleanup?.();
103
+ }
104
+ if (existsSync(args.socketPath)) {
105
+ rmSync(args.socketPath, { force: true });
106
+ }
107
+ runtime.db.close();
108
+ process.exit(exitCode);
109
+ };
110
+ const resetIdleTimer = () => {
111
+ if (idleTimer) {
112
+ clearTimeout(idleTimer);
113
+ }
114
+ idleTimer = setTimeout(() => {
115
+ void shutdown("expired", "Session expired due to idle timeout.");
116
+ }, args.idleTimeoutSeconds * 1000);
117
+ };
118
+ process.on("SIGTERM", () => {
119
+ void shutdown("closed", undefined, 0);
120
+ });
121
+ process.on("SIGINT", () => {
122
+ void shutdown("closed", undefined, 0);
123
+ });
124
+ try {
125
+ if (existsSync(args.socketPath)) {
126
+ rmSync(args.socketPath, { force: true });
127
+ }
128
+ session = await launchOutlookSession(context.accountPaths.authDir + "/profile", { headless: true });
129
+ const auth = await probeOutlookAuth(session.page, { timeoutMs: context.config.providerTimeoutMs });
130
+ if (auth.status !== "authenticated") {
131
+ throw new SurfaceError("reauth_required", auth.detail ?? "Outlook session is not authenticated.", {
132
+ account: account.name,
133
+ });
134
+ }
135
+ server = createServer({ allowHalfOpen: true }, (socket) => {
136
+ let raw = "";
137
+ socket.setEncoding("utf8");
138
+ socket.on("data", (chunk) => {
139
+ raw += chunk;
140
+ });
141
+ socket.on("end", () => {
142
+ inflight = inflight.then(async () => {
143
+ try {
144
+ const request = JSON.parse(raw);
145
+ if (request.token !== args.authToken) {
146
+ throw new SurfaceError("forbidden", "Session token mismatch.");
147
+ }
148
+ const current = runtime.db.getSession(args.sessionId);
149
+ if (!current || current.status !== "running") {
150
+ throw new SurfaceError("session_invalid", `Session '${args.sessionId}' is not running.`, {
151
+ account: account.name,
152
+ });
153
+ }
154
+ const expiry = sessionExpiry(current);
155
+ if (expiry.expired) {
156
+ void shutdown("expired", `Session expired due to ${expiry.reason ?? "timeout"}.`);
157
+ throw new SurfaceError("session_invalid", `Session '${args.sessionId}' has expired.`, {
158
+ account: account.name,
159
+ });
160
+ }
161
+ runtime.db.touchSession(args.sessionId);
162
+ resetIdleTimer();
163
+ let result;
164
+ switch (request.method) {
165
+ case "ping":
166
+ result = { session_id: args.sessionId, status: "running" };
167
+ break;
168
+ case "search":
169
+ result = await searchOutlookWithSession(account, request.params?.query, context, session);
170
+ break;
171
+ case "fetch-unread":
172
+ result = await fetchUnreadOutlookWithSession(account, request.params?.query, context, session);
173
+ break;
174
+ case "refresh-thread":
175
+ await refreshOutlookThreadWithSession(account, String(request.params?.thread_ref ?? ""), context, session);
176
+ result = { ok: true };
177
+ break;
178
+ case "read-message":
179
+ result = await readOutlookMessageWithSession(account, String(request.params?.message_ref ?? ""), Boolean(request.params?.refresh), context, session);
180
+ break;
181
+ case "shutdown":
182
+ result = { ok: true };
183
+ setTimeout(() => {
184
+ void shutdown("closed", undefined, 0);
185
+ }, 0);
186
+ break;
187
+ default:
188
+ throw new SurfaceError("invalid_argument", `Unsupported session method '${request.method ?? ""}'.`, {
189
+ account: account.name,
190
+ });
191
+ }
192
+ socket.end(JSON.stringify({ ok: true, result }));
193
+ }
194
+ catch (error) {
195
+ socket.end(JSON.stringify({ ok: false, error: errorToEnvelope(error).error }));
196
+ }
197
+ });
198
+ });
199
+ });
200
+ await new Promise((resolve, reject) => {
201
+ server.once("error", reject);
202
+ server.listen(args.socketPath, () => resolve());
203
+ });
204
+ runtime.db.markSessionRunning(args.sessionId, process.pid);
205
+ resetIdleTimer();
206
+ maxAgeTimer = setTimeout(() => {
207
+ void shutdown("expired", "Session expired due to max age.");
208
+ }, args.maxAgeSeconds * 1000);
209
+ }
210
+ catch (error) {
211
+ await shutdown("failed", error instanceof Error ? error.message : String(error), 1);
212
+ }
213
+ }
214
+ main().catch((error) => {
215
+ console.error(error instanceof Error ? error.message : String(error));
216
+ process.exit(1);
217
+ });
218
+ //# sourceMappingURL=session-daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-daemon.js","sourceRoot":"","sources":["../src/session-daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,283 @@
1
+ import { spawn } from "node:child_process";
2
+ import { randomBytes } from "node:crypto";
3
+ import { existsSync, rmSync } from "node:fs";
4
+ import { connect } from "node:net";
5
+ import { dirname, join } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { SurfaceError } from "./lib/errors.js";
8
+ import { nowIsoUtc } from "./lib/time.js";
9
+ import { makeSessionId } from "./refs.js";
10
+ export const DEFAULT_SESSION_IDLE_TIMEOUT_SECONDS = 60 * 60;
11
+ export const DEFAULT_SESSION_MAX_AGE_SECONDS = 7 * 24 * 60 * 60;
12
+ const SESSION_STARTUP_TIMEOUT_MS = 20_000;
13
+ const SESSION_POLL_INTERVAL_MS = 200;
14
+ function sessionDaemonPath() {
15
+ const modulePath = fileURLToPath(import.meta.url);
16
+ const moduleDir = dirname(modulePath);
17
+ if (modulePath.endsWith(".ts")) {
18
+ return {
19
+ command: join(process.cwd(), "node_modules", ".bin", process.platform === "win32" ? "tsx.cmd" : "tsx"),
20
+ args: [join(moduleDir, "session-daemon.ts")],
21
+ };
22
+ }
23
+ return {
24
+ command: process.execPath,
25
+ args: [join(moduleDir, "session-daemon.js")],
26
+ };
27
+ }
28
+ function sessionSocketPath(context, sessionId) {
29
+ return join(context.paths.sessionsDir, `${sessionId}.sock`);
30
+ }
31
+ function makeSessionToken() {
32
+ return randomBytes(24).toString("hex");
33
+ }
34
+ function sleep(ms) {
35
+ return new Promise((resolve) => setTimeout(resolve, ms));
36
+ }
37
+ function isWarmSessionSupported(account) {
38
+ return account.provider === "outlook" && account.transport === "outlook-web-playwright";
39
+ }
40
+ function parseTimestamp(input) {
41
+ const parsed = Date.parse(input);
42
+ return Number.isFinite(parsed) ? parsed : 0;
43
+ }
44
+ export function sessionExpiry(record) {
45
+ const createdAt = parseTimestamp(record.created_at);
46
+ const lastUsedAt = parseTimestamp(record.last_used_at);
47
+ const idleExpiry = lastUsedAt + record.idle_timeout_seconds * 1000;
48
+ const maxAgeExpiry = createdAt + record.max_age_seconds * 1000;
49
+ const expiry = Math.min(idleExpiry, maxAgeExpiry);
50
+ const now = Date.now();
51
+ if (now >= maxAgeExpiry) {
52
+ return {
53
+ expired: true,
54
+ reason: "max_age",
55
+ expires_at: new Date(expiry).toISOString(),
56
+ };
57
+ }
58
+ if (now >= idleExpiry) {
59
+ return {
60
+ expired: true,
61
+ reason: "idle_timeout",
62
+ expires_at: new Date(expiry).toISOString(),
63
+ };
64
+ }
65
+ return {
66
+ expired: false,
67
+ reason: null,
68
+ expires_at: new Date(expiry).toISOString(),
69
+ };
70
+ }
71
+ function assertWarmSessionSupported(account) {
72
+ if (isWarmSessionSupported(account)) {
73
+ return;
74
+ }
75
+ throw new SurfaceError("unsupported", `Warm sessions are only supported for ${"outlook-web-playwright"} accounts in v1.`, { account: account.name });
76
+ }
77
+ async function waitForSessionReady(context, sessionId) {
78
+ const deadline = Date.now() + SESSION_STARTUP_TIMEOUT_MS;
79
+ while (Date.now() < deadline) {
80
+ const record = context.db.getSession(sessionId);
81
+ if (!record) {
82
+ throw new SurfaceError("not_found", `Session '${sessionId}' was not found after startup.`, {
83
+ account: null,
84
+ });
85
+ }
86
+ if (record.status === "running") {
87
+ return record;
88
+ }
89
+ if (record.status === "failed" || record.status === "closed" || record.status === "expired") {
90
+ throw new SurfaceError("transport_error", record.error_detail || `Session '${sessionId}' failed to start.`);
91
+ }
92
+ await sleep(SESSION_POLL_INTERVAL_MS);
93
+ }
94
+ throw new SurfaceError("transport_error", `Timed out waiting for session '${sessionId}' to start.`, {
95
+ retryable: true,
96
+ });
97
+ }
98
+ export async function startWarmSession(context, account, options) {
99
+ assertWarmSessionSupported(account);
100
+ const sessionId = makeSessionId();
101
+ const socketPath = sessionSocketPath(context, sessionId);
102
+ const authToken = makeSessionToken();
103
+ const record = context.db.createSession({
104
+ session_id: sessionId,
105
+ account_id: account.account_id,
106
+ provider: account.provider,
107
+ transport: account.transport,
108
+ socket_path: socketPath,
109
+ auth_token: authToken,
110
+ idle_timeout_seconds: options.idleTimeoutSeconds,
111
+ max_age_seconds: options.maxAgeSeconds,
112
+ });
113
+ const daemon = sessionDaemonPath();
114
+ const child = spawn(daemon.command, [
115
+ ...daemon.args,
116
+ "--session-id",
117
+ sessionId,
118
+ "--account-id",
119
+ account.account_id,
120
+ "--config-path",
121
+ context.configPath,
122
+ "--socket-path",
123
+ socketPath,
124
+ "--auth-token",
125
+ authToken,
126
+ "--idle-timeout-seconds",
127
+ String(options.idleTimeoutSeconds),
128
+ "--max-age-seconds",
129
+ String(options.maxAgeSeconds),
130
+ ], {
131
+ detached: true,
132
+ stdio: "ignore",
133
+ env: process.env,
134
+ });
135
+ child.unref();
136
+ context.db.updateSessionProcessInfo(sessionId, child.pid ?? null);
137
+ return waitForSessionReady(context, record.session_id);
138
+ }
139
+ function validateSessionForAccount(context, sessionId, account) {
140
+ const record = context.db.getSession(sessionId);
141
+ if (!record) {
142
+ throw new SurfaceError("not_found", `Session '${sessionId}' was not found.`, {
143
+ account: account.name,
144
+ });
145
+ }
146
+ if (record.account_id !== account.account_id) {
147
+ throw new SurfaceError("invalid_argument", `Session '${sessionId}' belongs to a different account.`, { account: account.name });
148
+ }
149
+ const expiry = sessionExpiry(record);
150
+ if (expiry.expired && record.status === "running") {
151
+ context.db.markSessionClosed(sessionId, "expired", {
152
+ errorDetail: `Session expired due to ${expiry.reason ?? "timeout"}.`,
153
+ });
154
+ }
155
+ const refreshed = context.db.getSession(sessionId) ?? record;
156
+ if (refreshed.status !== "running") {
157
+ throw new SurfaceError("session_invalid", refreshed.error_detail || `Session '${sessionId}' is not running.`, { account: account.name });
158
+ }
159
+ return refreshed;
160
+ }
161
+ async function callSession(record, method, params) {
162
+ if (!existsSync(record.socket_path)) {
163
+ throw new SurfaceError("session_invalid", `Session socket is missing for '${record.session_id}'.`);
164
+ }
165
+ const request = {
166
+ token: record.auth_token,
167
+ method,
168
+ params,
169
+ };
170
+ const response = await new Promise((resolve, reject) => {
171
+ const socket = connect(record.socket_path);
172
+ let raw = "";
173
+ socket.setEncoding("utf8");
174
+ socket.on("connect", () => {
175
+ socket.write(JSON.stringify(request));
176
+ socket.end();
177
+ });
178
+ socket.on("data", (chunk) => {
179
+ raw += chunk;
180
+ });
181
+ socket.on("error", (error) => {
182
+ reject(error);
183
+ });
184
+ socket.on("end", () => {
185
+ try {
186
+ resolve(JSON.parse(raw));
187
+ }
188
+ catch (error) {
189
+ reject(error);
190
+ }
191
+ });
192
+ });
193
+ if (!response.ok) {
194
+ throw new SurfaceError(response.error.code, response.error.message, {
195
+ retryable: response.error.retryable,
196
+ account: response.error.account,
197
+ messageRef: response.error.message_ref,
198
+ threadRef: response.error.thread_ref,
199
+ });
200
+ }
201
+ return response.result;
202
+ }
203
+ export function listWarmSessions(context) {
204
+ return context.db.listSessions().map((record) => ({
205
+ ...record,
206
+ account_name: context.db.findAccountById(record.account_id)?.name ?? null,
207
+ expires_at: sessionExpiry(record).expires_at,
208
+ }));
209
+ }
210
+ export async function stopWarmSession(context, sessionId) {
211
+ const record = context.db.getSession(sessionId);
212
+ if (!record) {
213
+ throw new SurfaceError("not_found", `Session '${sessionId}' was not found.`);
214
+ }
215
+ try {
216
+ if (record.status === "running" && existsSync(record.socket_path)) {
217
+ await callSession(record, "shutdown", {});
218
+ }
219
+ }
220
+ catch {
221
+ if (record.pid) {
222
+ try {
223
+ process.kill(record.pid, "SIGTERM");
224
+ }
225
+ catch {
226
+ // Ignore missing processes.
227
+ }
228
+ }
229
+ }
230
+ finally {
231
+ if (existsSync(record.socket_path)) {
232
+ rmSync(record.socket_path, { force: true });
233
+ }
234
+ context.db.markSessionClosed(sessionId, "closed", { pid: null });
235
+ }
236
+ return context.db.getSession(sessionId);
237
+ }
238
+ export async function sessionSearch(context, sessionId, query) {
239
+ const record = validateSessionForAccount(context, sessionId, context.account);
240
+ const result = await callSession(record, "search", { query });
241
+ context.db.touchSession(sessionId);
242
+ return result;
243
+ }
244
+ export async function sessionFetchUnread(context, sessionId, query) {
245
+ const record = validateSessionForAccount(context, sessionId, context.account);
246
+ const result = await callSession(record, "fetch-unread", { query });
247
+ context.db.touchSession(sessionId);
248
+ return result;
249
+ }
250
+ export async function sessionRefreshThread(context, sessionId, threadRef) {
251
+ const record = validateSessionForAccount(context, sessionId, context.account);
252
+ await callSession(record, "refresh-thread", { thread_ref: threadRef });
253
+ context.db.touchSession(sessionId);
254
+ }
255
+ export async function sessionReadMessage(context, sessionId, messageRef, refresh) {
256
+ const record = validateSessionForAccount(context, sessionId, context.account);
257
+ const result = await callSession(record, "read-message", {
258
+ message_ref: messageRef,
259
+ refresh,
260
+ });
261
+ context.db.touchSession(sessionId);
262
+ return result;
263
+ }
264
+ export function sessionStartEnvelope(record, account) {
265
+ return {
266
+ schema_version: "1",
267
+ command: "session-start",
268
+ generated_at: nowIsoUtc(),
269
+ session: {
270
+ session_id: record.session_id,
271
+ account: account.name,
272
+ provider: record.provider,
273
+ transport: record.transport,
274
+ status: record.status,
275
+ created_at: record.created_at,
276
+ last_used_at: record.last_used_at,
277
+ idle_timeout_seconds: record.idle_timeout_seconds,
278
+ max_age_seconds: record.max_age_seconds,
279
+ expires_at: sessionExpiry(record).expires_at,
280
+ },
281
+ };
282
+ }
283
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}