@remnic/connector-x 9.69.64
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/LICENSE +21 -0
- package/README.md +172 -0
- package/dist/chunk-JR2ZNAYD.js +1482 -0
- package/dist/chunk-JR2ZNAYD.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +129 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +467 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
import { ConnectorApiError } from '@remnic/core/http-retry';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared types for @remnic/connector-x.
|
|
5
|
+
*/
|
|
6
|
+
type XRecordKind = "bookmark" | "own_post";
|
|
7
|
+
/** Trust gate for extracted memories. "suggest" routes through a review queue; "store" writes directly. */
|
|
8
|
+
type XMemoryMode = "suggest" | "store";
|
|
9
|
+
type XSourceKind = "mcp" | "corpusDir" | "cli";
|
|
10
|
+
interface XAuthor {
|
|
11
|
+
id?: string;
|
|
12
|
+
username?: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
}
|
|
15
|
+
interface XProvenance {
|
|
16
|
+
sourceId: string;
|
|
17
|
+
sourceKind: XSourceKind;
|
|
18
|
+
syncRunId: string;
|
|
19
|
+
fetchedAt: string;
|
|
20
|
+
}
|
|
21
|
+
/** Normalized record, the common currency every source emits. */
|
|
22
|
+
interface XPostRecord {
|
|
23
|
+
postId: string;
|
|
24
|
+
kind: XRecordKind;
|
|
25
|
+
author?: XAuthor;
|
|
26
|
+
/** Post creation time (ISO 8601) when the source carries it. */
|
|
27
|
+
createdAt?: string;
|
|
28
|
+
/** When the bookmark act happened (ISO 8601), when known. */
|
|
29
|
+
bookmarkedAt?: string;
|
|
30
|
+
text: string;
|
|
31
|
+
urls: string[];
|
|
32
|
+
mediaCount: number;
|
|
33
|
+
/** Zero-credit enrichment (e.g. resolved URL titles from a local corpus). */
|
|
34
|
+
enrichment?: Record<string, unknown>;
|
|
35
|
+
provenance?: XProvenance;
|
|
36
|
+
}
|
|
37
|
+
/** The memory a record maps to, before trust gating. */
|
|
38
|
+
interface XMemorySuggestion {
|
|
39
|
+
record: XPostRecord;
|
|
40
|
+
tags: string[];
|
|
41
|
+
category: string;
|
|
42
|
+
entityRef?: string;
|
|
43
|
+
confidence: number;
|
|
44
|
+
postUrl: string;
|
|
45
|
+
/** Composed memory sentence. */
|
|
46
|
+
content: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Host-provided memory sink. `submitSuggestion` feeds the review queue;
|
|
50
|
+
* `storeMemory` writes directly. The connector picks per `memoryMode`.
|
|
51
|
+
*/
|
|
52
|
+
interface XMemorySink {
|
|
53
|
+
submitSuggestion(suggestion: XMemorySuggestion): Promise<void>;
|
|
54
|
+
storeMemory(suggestion: XMemorySuggestion): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
interface XSourceFetchOutcome {
|
|
57
|
+
records: XPostRecord[];
|
|
58
|
+
/** Billable reads consumed (MCP only; 0 for zero-credit sources). */
|
|
59
|
+
reads: number;
|
|
60
|
+
pages: number;
|
|
61
|
+
/** Present when the source degraded instead of erroring. */
|
|
62
|
+
skipped?: {
|
|
63
|
+
reason: string;
|
|
64
|
+
detail?: string;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
interface XSource {
|
|
68
|
+
id: string;
|
|
69
|
+
kind: XSourceKind;
|
|
70
|
+
fetch(ctx: XSourceFetchContext): Promise<XSourceFetchOutcome>;
|
|
71
|
+
}
|
|
72
|
+
interface XSourceFetchContext {
|
|
73
|
+
knownIds: ReadonlySet<string>;
|
|
74
|
+
budget: XBudgetRuntime;
|
|
75
|
+
signal?: AbortSignal;
|
|
76
|
+
}
|
|
77
|
+
/** Budget enforcement shared by the sync loop and the MCP source. */
|
|
78
|
+
interface XBudgetRuntime {
|
|
79
|
+
canRead(): {
|
|
80
|
+
ok: true;
|
|
81
|
+
} | {
|
|
82
|
+
ok: false;
|
|
83
|
+
reason: string;
|
|
84
|
+
detail?: string;
|
|
85
|
+
};
|
|
86
|
+
noteRead(): void;
|
|
87
|
+
/** Pages consumed this sync by the current source. */
|
|
88
|
+
pagesUsed: number;
|
|
89
|
+
maxPages: number;
|
|
90
|
+
}
|
|
91
|
+
interface XSourceSyncSummary {
|
|
92
|
+
sourceId: string;
|
|
93
|
+
kind: XSourceKind;
|
|
94
|
+
recordsNew: number;
|
|
95
|
+
recordsKnown: number;
|
|
96
|
+
reads: number;
|
|
97
|
+
pages: number;
|
|
98
|
+
skipped?: {
|
|
99
|
+
reason: string;
|
|
100
|
+
detail?: string;
|
|
101
|
+
};
|
|
102
|
+
error?: string;
|
|
103
|
+
}
|
|
104
|
+
interface XSyncReport {
|
|
105
|
+
runId: string;
|
|
106
|
+
startedAt: string;
|
|
107
|
+
finishedAt: string;
|
|
108
|
+
memoryMode: XMemoryMode;
|
|
109
|
+
sources: XSourceSyncSummary[];
|
|
110
|
+
suggestionsSubmitted: number;
|
|
111
|
+
memoriesStored: number;
|
|
112
|
+
sinkFailures: number;
|
|
113
|
+
monthKey: string;
|
|
114
|
+
monthSpendUsd: number;
|
|
115
|
+
}
|
|
116
|
+
interface XSourceStatus {
|
|
117
|
+
sourceId: string;
|
|
118
|
+
kind: XSourceKind;
|
|
119
|
+
priority: number;
|
|
120
|
+
lastSyncAt: string | null;
|
|
121
|
+
lastRecordsNew: number;
|
|
122
|
+
available: boolean;
|
|
123
|
+
availabilityDetail?: string;
|
|
124
|
+
}
|
|
125
|
+
interface XStatusReport {
|
|
126
|
+
enabled: boolean;
|
|
127
|
+
memoryMode: XMemoryMode;
|
|
128
|
+
syncSchedule: string;
|
|
129
|
+
sources: XSourceStatus[];
|
|
130
|
+
seenCount: number;
|
|
131
|
+
monthKey: string;
|
|
132
|
+
monthSpendUsd: number;
|
|
133
|
+
monthlyCostCapUsd: number;
|
|
134
|
+
lastSyncAt: string | null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Strict parser for the `xConnector` config block (issue #2009).
|
|
139
|
+
*
|
|
140
|
+
* Invalid values are rejected, never silently reinterpreted: unknown
|
|
141
|
+
* source kinds, duplicate source ids, priorities naming unknown sources,
|
|
142
|
+
* non-finite numbers, and unrecognized enum values all throw.
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
declare const X_SOURCE_KINDS: readonly XSourceKind[];
|
|
146
|
+
declare const X_MEMORY_MODES: readonly XMemoryMode[];
|
|
147
|
+
declare const X_SYNC_SCHEDULES: readonly string[];
|
|
148
|
+
declare const X_DEFAULT_MCP_URL = "https://api.x.com/mcp";
|
|
149
|
+
declare const X_DEFAULT_TOKEN_FILE = "~/.openclaw/secrets/x-tokens.json";
|
|
150
|
+
declare const X_DEFAULT_STATE_DIR = "~/.remnic/x-connector";
|
|
151
|
+
/** Pay-per-use reference rate: ~1 credit per read at ~$0.01/credit. */
|
|
152
|
+
declare const X_DEFAULT_COST_PER_READ_USD = 0.01;
|
|
153
|
+
interface XBudgetConfig {
|
|
154
|
+
maxPagesPerSync: number;
|
|
155
|
+
maxCostUsdPerMonth: number;
|
|
156
|
+
costPerReadUsd: number;
|
|
157
|
+
}
|
|
158
|
+
interface XMcpSourceConfig {
|
|
159
|
+
id: string;
|
|
160
|
+
kind: "mcp";
|
|
161
|
+
url: string;
|
|
162
|
+
tokenFile: string;
|
|
163
|
+
bookmarksTool: string;
|
|
164
|
+
timelineTool: string;
|
|
165
|
+
maxResults: number;
|
|
166
|
+
budget: XBudgetConfig;
|
|
167
|
+
}
|
|
168
|
+
interface XCorpusSourceConfig {
|
|
169
|
+
id: string;
|
|
170
|
+
kind: "corpusDir";
|
|
171
|
+
path: string;
|
|
172
|
+
}
|
|
173
|
+
interface XCliSourceConfig {
|
|
174
|
+
id: string;
|
|
175
|
+
kind: "cli";
|
|
176
|
+
bin: string;
|
|
177
|
+
bookmarksArgs: string[];
|
|
178
|
+
/** When unset, this source contributes bookmarks only. */
|
|
179
|
+
postsArgs?: string[];
|
|
180
|
+
}
|
|
181
|
+
type XSourceConfig = XMcpSourceConfig | XCorpusSourceConfig | XCliSourceConfig;
|
|
182
|
+
interface XConnectorConfig {
|
|
183
|
+
enabled: boolean;
|
|
184
|
+
userId?: string;
|
|
185
|
+
sources: XSourceConfig[];
|
|
186
|
+
sourcePriority: string[];
|
|
187
|
+
syncSchedule: string;
|
|
188
|
+
memoryMode: XMemoryMode;
|
|
189
|
+
stateDir: string;
|
|
190
|
+
}
|
|
191
|
+
declare class XConfigError extends Error {
|
|
192
|
+
constructor(message: string);
|
|
193
|
+
}
|
|
194
|
+
/** Coerces boolean-like strings at the config boundary; anything else is invalid. */
|
|
195
|
+
declare function coerceXBool(value: unknown, field: string): boolean;
|
|
196
|
+
declare function parseXConnectorConfig(raw: unknown): XConnectorConfig;
|
|
197
|
+
/** OAuth2 client credentials for the MCP source, with env fallbacks. */
|
|
198
|
+
declare function resolveMcpClientCredentials(source: XMcpSourceConfig, env?: NodeJS.ProcessEnv): {
|
|
199
|
+
clientId?: string;
|
|
200
|
+
clientSecret?: string;
|
|
201
|
+
tokenFile: string;
|
|
202
|
+
};
|
|
203
|
+
/** The effective monthly cost cap across all paid sources (max of per-source caps). */
|
|
204
|
+
declare function monthlyCostCapUsd(config: XConnectorConfig): number;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Canonical unknown-payload guard for @remnic/connector-x.
|
|
208
|
+
*
|
|
209
|
+
* Fields stay `unknown` after narrowing; every field read is checked at
|
|
210
|
+
* its use site with `typeof` / `in` / `Array.isArray`.
|
|
211
|
+
*/
|
|
212
|
+
declare function isXObject(value: unknown): value is Record<string, unknown>;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Official X MCP client (Streamable HTTP, protocol 2025-06-18).
|
|
216
|
+
*
|
|
217
|
+
* Contract per https://docs.x.com (MCP, launched 2026-06-30): JSON-RPC
|
|
218
|
+
* over HTTP POST; `initialize` hands back an `Mcp-Session-Id` response
|
|
219
|
+
* header; response bodies may be plain JSON or SSE (`text/event-stream`,
|
|
220
|
+
* `data:` lines). Reads bill against X API credits — `credits depleted`
|
|
221
|
+
* (HTTP 402 or a 402-in-tool-result payload) maps to
|
|
222
|
+
* XCreditsDepletedError so callers can skip the cycle cleanly instead
|
|
223
|
+
* of erroring. Session `initialize`/`tools/list` are free.
|
|
224
|
+
*
|
|
225
|
+
* The API token is never logged and never included in thrown error
|
|
226
|
+
* messages.
|
|
227
|
+
*/
|
|
228
|
+
|
|
229
|
+
declare const X_MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
230
|
+
declare const X_MCP_DEFAULT_URL = "https://api.x.com/mcp";
|
|
231
|
+
declare class XMcpError extends ConnectorApiError {
|
|
232
|
+
constructor(message: string, status?: number);
|
|
233
|
+
}
|
|
234
|
+
/** Clean-skip signal: the account's X API credits are exhausted. */
|
|
235
|
+
declare class XCreditsDepletedError extends Error {
|
|
236
|
+
constructor();
|
|
237
|
+
}
|
|
238
|
+
interface XMcpToolCallResult {
|
|
239
|
+
isError: boolean;
|
|
240
|
+
/** text blocks of result.content, in order. */
|
|
241
|
+
texts: string[];
|
|
242
|
+
raw: unknown;
|
|
243
|
+
}
|
|
244
|
+
interface XMcpClientOptions {
|
|
245
|
+
url?: string;
|
|
246
|
+
/** Lazily supplies a valid bearer token (user-context OAuth2). */
|
|
247
|
+
tokenProvider: () => Promise<string>;
|
|
248
|
+
fetchImpl?: typeof fetch;
|
|
249
|
+
timeoutMs?: number;
|
|
250
|
+
sleep?: (ms: number) => Promise<void>;
|
|
251
|
+
protocolVersion?: string;
|
|
252
|
+
clientName?: string;
|
|
253
|
+
clientVersion?: string;
|
|
254
|
+
}
|
|
255
|
+
/** Parses an SSE body into decoded `data:` JSON values, in order. */
|
|
256
|
+
declare function parseSseData(body: string): unknown[];
|
|
257
|
+
/** True when a tool-result body signals exhausted credits (docs + observed shape). */
|
|
258
|
+
declare function looksLikeCreditsDepleted(text: string): boolean;
|
|
259
|
+
/** Extracts text blocks from an MCP tool-result content array. */
|
|
260
|
+
declare function toolResultTexts(payload: Record<string, unknown>): string[];
|
|
261
|
+
declare class XMcpClient {
|
|
262
|
+
private readonly url;
|
|
263
|
+
private readonly tokenProvider;
|
|
264
|
+
private readonly fetchImpl;
|
|
265
|
+
private readonly timeoutMs;
|
|
266
|
+
private readonly sleep;
|
|
267
|
+
private readonly protocolVersion;
|
|
268
|
+
private readonly clientName;
|
|
269
|
+
private readonly clientVersion;
|
|
270
|
+
private sessionId;
|
|
271
|
+
private nextMessageId;
|
|
272
|
+
constructor(options: XMcpClientOptions);
|
|
273
|
+
/**
|
|
274
|
+
* Calls an MCP tool. Re-initializes once when the server rejects the
|
|
275
|
+
* session id (e.g. expired session), then retries the call.
|
|
276
|
+
*/
|
|
277
|
+
callTool(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<XMcpToolCallResult>;
|
|
278
|
+
/** Best-effort session shutdown (MCP `DELETE`). */
|
|
279
|
+
close(): Promise<void>;
|
|
280
|
+
private withSessionRetry;
|
|
281
|
+
private ensureSession;
|
|
282
|
+
private allocateId;
|
|
283
|
+
private rpcMessage;
|
|
284
|
+
private decodeBody;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Payload normalization for all three X sources plus the shared
|
|
289
|
+
* dedupe fingerprint and the record → memory mapping.
|
|
290
|
+
*
|
|
291
|
+
* All parsers are shape-tolerant: X MCP payloads follow the v2 API
|
|
292
|
+
* expansions shape (`data[]` + `includes.users`), local corpora and
|
|
293
|
+
* CLI tools use a variety of field aliases. Every field read is
|
|
294
|
+
* checked; unrecognized shapes yield empty results, never crashes.
|
|
295
|
+
*/
|
|
296
|
+
|
|
297
|
+
/** Sorts keys recursively so key order never changes the fingerprint. */
|
|
298
|
+
declare function stableStringify(value: unknown): string;
|
|
299
|
+
/** Identity fingerprint: same post + same content = same memory, regardless of source key order. */
|
|
300
|
+
declare function recordFingerprint(record: XPostRecord): string;
|
|
301
|
+
/**
|
|
302
|
+
* Normalizes an MCP tool-result payload (v2 expansions shape) into
|
|
303
|
+
* records. Accepts `{data: [...]}` with `includes.users`, a bare
|
|
304
|
+
* array, or `{bookmarks: [...]}`.
|
|
305
|
+
*/
|
|
306
|
+
declare function normalizeMcpPayload(payload: unknown, kind: XRecordKind, ownUsername?: string): XPostRecord[];
|
|
307
|
+
/** Normalizes one corpus/CLI entry (tolerant field aliases). */
|
|
308
|
+
declare function normalizeCorpusEntry(entry: unknown, fallbackKind: XRecordKind, ownUsername?: string): XPostRecord | null;
|
|
309
|
+
/**
|
|
310
|
+
* Record → memory mapping (issue #2009 §2):
|
|
311
|
+
* - bookmarks → tag `x/bookmark`, category `reference` (carries a URL) or `interest`
|
|
312
|
+
* - own posts → tag `x/post`, category `expression`, higher confidence
|
|
313
|
+
*/
|
|
314
|
+
declare function suggestionForRecord(record: XPostRecord): XMemorySuggestion;
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Pluggable X sources (issue #2009): official X MCP (paid, budget-
|
|
318
|
+
* capped), a local corpus directory (zero credits), and a cookie-CLI
|
|
319
|
+
* such as `bird` (zero credits). All three emit the same normalized
|
|
320
|
+
* XPostRecord currency and degrade with a `skipped` reason instead of
|
|
321
|
+
* throwing, except auth/config breakage which surfaces to the sync
|
|
322
|
+
* report's `error` field.
|
|
323
|
+
*/
|
|
324
|
+
|
|
325
|
+
type XExecFn = (bin: string, args: string[]) => Promise<{
|
|
326
|
+
stdout: string;
|
|
327
|
+
stderr: string;
|
|
328
|
+
}>;
|
|
329
|
+
interface XSourceDeps {
|
|
330
|
+
/** Owning X user id — gates the own-posts timeline reads for MCP sources. */
|
|
331
|
+
userId?: string;
|
|
332
|
+
fetchImpl?: typeof fetch;
|
|
333
|
+
sleep?: (ms: number) => Promise<void>;
|
|
334
|
+
now?: () => number;
|
|
335
|
+
env?: NodeJS.ProcessEnv;
|
|
336
|
+
execImpl?: XExecFn;
|
|
337
|
+
}
|
|
338
|
+
/** Budget enforcement for paid (MCP) sources. */
|
|
339
|
+
declare class XBudgetTracker implements XBudgetRuntime {
|
|
340
|
+
private readonly budget;
|
|
341
|
+
private readonly monthSpendUsd;
|
|
342
|
+
pagesUsed: number;
|
|
343
|
+
reads: number;
|
|
344
|
+
readonly maxPages: number;
|
|
345
|
+
constructor(budget: XBudgetConfig, monthSpendUsd: number);
|
|
346
|
+
canRead(): {
|
|
347
|
+
ok: true;
|
|
348
|
+
} | {
|
|
349
|
+
ok: false;
|
|
350
|
+
reason: string;
|
|
351
|
+
detail?: string;
|
|
352
|
+
};
|
|
353
|
+
noteRead(): void;
|
|
354
|
+
}
|
|
355
|
+
/** Zero-credit sources never consume budget. */
|
|
356
|
+
declare const unlimitedBudget: XBudgetRuntime;
|
|
357
|
+
/** Builds the source adapter for a parsed source config entry. */
|
|
358
|
+
declare function createXSource(config: XMcpSourceConfig | XCorpusSourceConfig | XCliSourceConfig, deps?: XSourceDeps): XSource;
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Sync orchestration (issue #2009): run sources in configured priority
|
|
362
|
+
* order (cheapest first is the recommended arrangement), dedupe by
|
|
363
|
+
* post_id + content fingerprint, stamp provenance, and route the mapped
|
|
364
|
+
* memory through the trust gate (`suggest` → review queue, `store` →
|
|
365
|
+
* direct write). Persisted state lives in `<stateDir>/state.json`
|
|
366
|
+
* (dedupe map, per-source last sync + new counts, monthly cost ledger);
|
|
367
|
+
* every ingested record is materialized under `<stateDir>/records/`.
|
|
368
|
+
*/
|
|
369
|
+
|
|
370
|
+
interface XSyncDeps extends XSourceDeps {
|
|
371
|
+
sink: XMemorySink;
|
|
372
|
+
}
|
|
373
|
+
/** Runs one sync cycle. Source-level degradation lands in the report, never a throw. */
|
|
374
|
+
declare function runXSync(config: XConnectorConfig, deps: XSyncDeps): Promise<XSyncReport>;
|
|
375
|
+
/**
|
|
376
|
+
* Offline status snapshot: config sources, availability, spend vs cap.
|
|
377
|
+
* No network calls, no credit use.
|
|
378
|
+
*/
|
|
379
|
+
declare function getXStatus(config: XConnectorConfig, deps?: Pick<XSyncDeps, "execImpl" | "env">): Promise<XStatusReport>;
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* OAuth2 user-token store with single-owner refresh for the X MCP
|
|
383
|
+
* source.
|
|
384
|
+
*
|
|
385
|
+
* X rotates the refresh token on EVERY refresh. Two independent
|
|
386
|
+
* refreshers fork the chain and kill one of them (observed failure:
|
|
387
|
+
* HTTP 401 on refresh after two tools both rotated the same grant).
|
|
388
|
+
* This store is therefore the single owner of the refresh chain: the
|
|
389
|
+
* refresh runs only while holding `${tokenFile}.lock`; a concurrent
|
|
390
|
+
* refresher waits, then adopts the rotated pair from the file — it
|
|
391
|
+
* never refreshes in parallel.
|
|
392
|
+
*
|
|
393
|
+
* Token files are written 0600, atomic (tmp + rename), and unknown
|
|
394
|
+
* top-level fields are preserved on rotation.
|
|
395
|
+
*/
|
|
396
|
+
declare const X_TOKEN_REFRESH_URL = "https://api.x.com/2/oauth2/token";
|
|
397
|
+
declare class XTokenError extends Error {
|
|
398
|
+
constructor(message: string);
|
|
399
|
+
}
|
|
400
|
+
/** The refresh chain forked or was revoked — re-authorization is required. */
|
|
401
|
+
declare class XRefreshChainBrokenError extends XTokenError {
|
|
402
|
+
constructor(detail: string);
|
|
403
|
+
}
|
|
404
|
+
interface XTokenPair {
|
|
405
|
+
accessToken: string;
|
|
406
|
+
refreshToken: string;
|
|
407
|
+
/** Epoch ms when the access token expires. */
|
|
408
|
+
expiresAt: number;
|
|
409
|
+
}
|
|
410
|
+
interface XTokenStoreOptions {
|
|
411
|
+
tokenFile: string;
|
|
412
|
+
clientId: string;
|
|
413
|
+
clientSecret: string;
|
|
414
|
+
/** OAuth2 token endpoint. */
|
|
415
|
+
refreshUrl?: string;
|
|
416
|
+
fetchImpl?: typeof fetch;
|
|
417
|
+
now?: () => number;
|
|
418
|
+
sleep?: (ms: number) => Promise<void>;
|
|
419
|
+
lockStaleMs?: number;
|
|
420
|
+
lockWaitMs?: number;
|
|
421
|
+
}
|
|
422
|
+
declare class XTokenStore {
|
|
423
|
+
private readonly tokenFile;
|
|
424
|
+
private readonly clientId;
|
|
425
|
+
private readonly clientSecret;
|
|
426
|
+
private readonly refreshUrl;
|
|
427
|
+
private readonly fetchImpl;
|
|
428
|
+
private readonly now;
|
|
429
|
+
private readonly sleep;
|
|
430
|
+
private readonly lockStaleMs;
|
|
431
|
+
private readonly lockWaitMs;
|
|
432
|
+
private cached;
|
|
433
|
+
constructor(options: XTokenStoreOptions);
|
|
434
|
+
/** Returns a valid access token, refreshing under the lock when expired. */
|
|
435
|
+
getAccessToken(): Promise<string>;
|
|
436
|
+
private getValidPair;
|
|
437
|
+
/**
|
|
438
|
+
* Refreshes the token pair under the file lock. When another owner
|
|
439
|
+
* holds the lock, waits for it, then adopts the pair it wrote.
|
|
440
|
+
*/
|
|
441
|
+
refresh(): Promise<XTokenPair>;
|
|
442
|
+
private refreshWithLock;
|
|
443
|
+
private waitForOtherOwner;
|
|
444
|
+
private acquireLock;
|
|
445
|
+
/** Steals the lock when its mtime is older than lockStaleMs. */
|
|
446
|
+
private stealStaleLock;
|
|
447
|
+
private requestRefresh;
|
|
448
|
+
private readTokenFile;
|
|
449
|
+
/** Atomic 0600 write; preserves unknown top-level fields from the prior file. */
|
|
450
|
+
private writeTokenFile;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Default on-disk memory sink: `suggest` mode writes review-queue
|
|
455
|
+
* files under `<stateDir>/suggestions/`, `store` mode writes directly
|
|
456
|
+
* under `<stateDir>/records/`. Hosts with a live Remnic daemon pass
|
|
457
|
+
* their own XMemorySink instead.
|
|
458
|
+
*/
|
|
459
|
+
|
|
460
|
+
interface FileSinkOptions {
|
|
461
|
+
stateDir: string;
|
|
462
|
+
mode: "suggest" | "store";
|
|
463
|
+
}
|
|
464
|
+
/** On-disk sink honoring the memoryMode trust gate by directory. */
|
|
465
|
+
declare function createFileSink(options: FileSinkOptions): XMemorySink;
|
|
466
|
+
|
|
467
|
+
export { type XAuthor, type XBudgetConfig, type XBudgetRuntime, XBudgetTracker, type XCliSourceConfig, XConfigError, type XConnectorConfig, type XCorpusSourceConfig, XCreditsDepletedError, type XExecFn, XMcpClient, type XMcpClientOptions, XMcpError, type XMcpSourceConfig, type XMcpToolCallResult, type XMemoryMode, type XMemorySink, type XMemorySuggestion, type XPostRecord, type XProvenance, type XRecordKind, XRefreshChainBrokenError, type XSource, type XSourceConfig, type XSourceDeps, type XSourceFetchContext, type XSourceFetchOutcome, type XSourceKind, type XSourceStatus, type XSourceSyncSummary, type XStatusReport, type XSyncDeps, type XSyncReport, XTokenError, type XTokenPair, XTokenStore, type XTokenStoreOptions, X_DEFAULT_COST_PER_READ_USD, X_DEFAULT_MCP_URL, X_DEFAULT_STATE_DIR, X_DEFAULT_TOKEN_FILE, X_MCP_DEFAULT_URL, X_MCP_PROTOCOL_VERSION, X_MEMORY_MODES, X_SOURCE_KINDS, X_SYNC_SCHEDULES, X_TOKEN_REFRESH_URL, coerceXBool, createFileSink, createXSource, getXStatus, isXObject, looksLikeCreditsDepleted, monthlyCostCapUsd, normalizeCorpusEntry, normalizeMcpPayload, parseSseData, parseXConnectorConfig, recordFingerprint, resolveMcpClientCredentials, runXSync, stableStringify, suggestionForRecord, toolResultTexts, unlimitedBudget };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// openclaw-engram: Local-first memory plugin
|
|
2
|
+
import {
|
|
3
|
+
XBudgetTracker,
|
|
4
|
+
XConfigError,
|
|
5
|
+
XCreditsDepletedError,
|
|
6
|
+
XMcpClient,
|
|
7
|
+
XMcpError,
|
|
8
|
+
XRefreshChainBrokenError,
|
|
9
|
+
XTokenError,
|
|
10
|
+
XTokenStore,
|
|
11
|
+
X_DEFAULT_COST_PER_READ_USD,
|
|
12
|
+
X_DEFAULT_MCP_URL,
|
|
13
|
+
X_DEFAULT_STATE_DIR,
|
|
14
|
+
X_DEFAULT_TOKEN_FILE,
|
|
15
|
+
X_MCP_DEFAULT_URL,
|
|
16
|
+
X_MCP_PROTOCOL_VERSION,
|
|
17
|
+
X_MEMORY_MODES,
|
|
18
|
+
X_SOURCE_KINDS,
|
|
19
|
+
X_SYNC_SCHEDULES,
|
|
20
|
+
X_TOKEN_REFRESH_URL,
|
|
21
|
+
coerceXBool,
|
|
22
|
+
createFileSink,
|
|
23
|
+
createXSource,
|
|
24
|
+
getXStatus,
|
|
25
|
+
isXObject,
|
|
26
|
+
looksLikeCreditsDepleted,
|
|
27
|
+
monthlyCostCapUsd,
|
|
28
|
+
normalizeCorpusEntry,
|
|
29
|
+
normalizeMcpPayload,
|
|
30
|
+
parseSseData,
|
|
31
|
+
parseXConnectorConfig,
|
|
32
|
+
recordFingerprint,
|
|
33
|
+
resolveMcpClientCredentials,
|
|
34
|
+
runXSync,
|
|
35
|
+
stableStringify,
|
|
36
|
+
suggestionForRecord,
|
|
37
|
+
toolResultTexts,
|
|
38
|
+
unlimitedBudget
|
|
39
|
+
} from "./chunk-JR2ZNAYD.js";
|
|
40
|
+
export {
|
|
41
|
+
XBudgetTracker,
|
|
42
|
+
XConfigError,
|
|
43
|
+
XCreditsDepletedError,
|
|
44
|
+
XMcpClient,
|
|
45
|
+
XMcpError,
|
|
46
|
+
XRefreshChainBrokenError,
|
|
47
|
+
XTokenError,
|
|
48
|
+
XTokenStore,
|
|
49
|
+
X_DEFAULT_COST_PER_READ_USD,
|
|
50
|
+
X_DEFAULT_MCP_URL,
|
|
51
|
+
X_DEFAULT_STATE_DIR,
|
|
52
|
+
X_DEFAULT_TOKEN_FILE,
|
|
53
|
+
X_MCP_DEFAULT_URL,
|
|
54
|
+
X_MCP_PROTOCOL_VERSION,
|
|
55
|
+
X_MEMORY_MODES,
|
|
56
|
+
X_SOURCE_KINDS,
|
|
57
|
+
X_SYNC_SCHEDULES,
|
|
58
|
+
X_TOKEN_REFRESH_URL,
|
|
59
|
+
coerceXBool,
|
|
60
|
+
createFileSink,
|
|
61
|
+
createXSource,
|
|
62
|
+
getXStatus,
|
|
63
|
+
isXObject,
|
|
64
|
+
looksLikeCreditsDepleted,
|
|
65
|
+
monthlyCostCapUsd,
|
|
66
|
+
normalizeCorpusEntry,
|
|
67
|
+
normalizeMcpPayload,
|
|
68
|
+
parseSseData,
|
|
69
|
+
parseXConnectorConfig,
|
|
70
|
+
recordFingerprint,
|
|
71
|
+
resolveMcpClientCredentials,
|
|
72
|
+
runXSync,
|
|
73
|
+
stableStringify,
|
|
74
|
+
suggestionForRecord,
|
|
75
|
+
toolResultTexts,
|
|
76
|
+
unlimitedBudget
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@remnic/connector-x",
|
|
3
|
+
"version": "9.69.64",
|
|
4
|
+
"description": "X (Twitter) connector for Remnic — remember the user's posts and bookmarks via the official X MCP, a local corpus, or a CLI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"remnic-x": "./dist/cli.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public",
|
|
22
|
+
"provenance": true
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@remnic/core": "^9.69.64"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"tsup": "^8.0.0",
|
|
29
|
+
"typescript": "^5.7.0",
|
|
30
|
+
"tsx": "^4.0.0",
|
|
31
|
+
"@remnic/core": "9.69.64"
|
|
32
|
+
},
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/joshuaswarren/remnic.git",
|
|
37
|
+
"directory": "packages/connector-x"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"remnic",
|
|
41
|
+
"memory",
|
|
42
|
+
"x",
|
|
43
|
+
"twitter",
|
|
44
|
+
"bookmarks",
|
|
45
|
+
"mcp",
|
|
46
|
+
"connector"
|
|
47
|
+
],
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsup src/index.ts src/cli.ts --format esm --dts",
|
|
50
|
+
"precheck-types": "node ../../scripts/ensure-bench-build-deps.mjs",
|
|
51
|
+
"check-types": "tsc --noEmit",
|
|
52
|
+
"test": "NODE_OPTIONS=\"${NODE_OPTIONS:+$NODE_OPTIONS }--conditions=remnic-source\" tsx --test src/config.test.ts src/mcp-client.test.ts src/token-store.test.ts src/normalize.test.ts src/sources.test.ts src/sync.test.ts"
|
|
53
|
+
}
|
|
54
|
+
}
|