instar 0.28.82 → 0.28.84
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/dashboard/index.html +239 -0
- package/dist/cli.js +10 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/memoryBackfillEvidence.d.ts +69 -0
- package/dist/commands/memoryBackfillEvidence.d.ts.map +1 -0
- package/dist/commands/memoryBackfillEvidence.js +220 -0
- package/dist/commands/memoryBackfillEvidence.js.map +1 -0
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +72 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/EvolutionManager.d.ts +73 -0
- package/dist/core/EvolutionManager.d.ts.map +1 -1
- package/dist/core/EvolutionManager.js +376 -0
- package/dist/core/EvolutionManager.js.map +1 -1
- package/dist/core/SharedStateLedger.d.ts.map +1 -1
- package/dist/core/SharedStateLedger.js +4 -0
- package/dist/core/SharedStateLedger.js.map +1 -1
- package/dist/core/types.d.ts +90 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +8 -0
- package/dist/core/types.js.map +1 -1
- package/dist/memory/EvidenceRenderer.d.ts +64 -0
- package/dist/memory/EvidenceRenderer.d.ts.map +1 -0
- package/dist/memory/EvidenceRenderer.js +119 -0
- package/dist/memory/EvidenceRenderer.js.map +1 -0
- package/dist/memory/SemanticMemory.d.ts +61 -1
- package/dist/memory/SemanticMemory.d.ts.map +1 -1
- package/dist/memory/SemanticMemory.js +381 -11
- package/dist/memory/SemanticMemory.js.map +1 -1
- package/dist/server/AgentServer.d.ts +4 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +2 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +8 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +493 -3
- package/dist/server/routes.js.map +1 -1
- package/dist/tasks/DivergenceChecker.d.ts +89 -0
- package/dist/tasks/DivergenceChecker.d.ts.map +1 -0
- package/dist/tasks/DivergenceChecker.js +255 -0
- package/dist/tasks/DivergenceChecker.js.map +1 -0
- package/dist/tasks/LruCache.d.ts +33 -0
- package/dist/tasks/LruCache.d.ts.map +1 -0
- package/dist/tasks/LruCache.js +88 -0
- package/dist/tasks/LruCache.js.map +1 -0
- package/dist/tasks/RateLimiter.d.ts +61 -0
- package/dist/tasks/RateLimiter.d.ts.map +1 -0
- package/dist/tasks/RateLimiter.js +108 -0
- package/dist/tasks/RateLimiter.js.map +1 -0
- package/dist/tasks/TaskFlowDueWaker.d.ts +29 -0
- package/dist/tasks/TaskFlowDueWaker.d.ts.map +1 -0
- package/dist/tasks/TaskFlowDueWaker.js +73 -0
- package/dist/tasks/TaskFlowDueWaker.js.map +1 -0
- package/dist/tasks/TaskFlowMaintenanceSweeper.d.ts +40 -0
- package/dist/tasks/TaskFlowMaintenanceSweeper.d.ts.map +1 -0
- package/dist/tasks/TaskFlowMaintenanceSweeper.js +131 -0
- package/dist/tasks/TaskFlowMaintenanceSweeper.js.map +1 -0
- package/dist/tasks/TaskFlowRegistry.d.ts +180 -0
- package/dist/tasks/TaskFlowRegistry.d.ts.map +1 -0
- package/dist/tasks/TaskFlowRegistry.js +791 -0
- package/dist/tasks/TaskFlowRegistry.js.map +1 -0
- package/dist/tasks/ThreadlineFlowBridge.d.ts +54 -0
- package/dist/tasks/ThreadlineFlowBridge.d.ts.map +1 -0
- package/dist/tasks/ThreadlineFlowBridge.js +129 -0
- package/dist/tasks/ThreadlineFlowBridge.js.map +1 -0
- package/dist/tasks/task-flow-registry.store.sqlite.d.ts +77 -0
- package/dist/tasks/task-flow-registry.store.sqlite.d.ts.map +1 -0
- package/dist/tasks/task-flow-registry.store.sqlite.js +350 -0
- package/dist/tasks/task-flow-registry.store.sqlite.js.map +1 -0
- package/dist/tasks/task-flow-types.d.ts +229 -0
- package/dist/tasks/task-flow-types.d.ts.map +1 -0
- package/dist/tasks/task-flow-types.js +128 -0
- package/dist/tasks/task-flow-types.js.map +1 -0
- package/dist/threadline/ThreadlineNicknames.d.ts +88 -0
- package/dist/threadline/ThreadlineNicknames.d.ts.map +1 -0
- package/dist/threadline/ThreadlineNicknames.js +195 -0
- package/dist/threadline/ThreadlineNicknames.js.map +1 -0
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +78 -78
- package/upgrades/0.28.83.md +45 -0
- package/upgrades/0.28.84.md +89 -0
- package/upgrades/side-effects/taskflow-phase1.md +130 -0
- package/upgrades/side-effects/taskflow-phase2.md +110 -0
- package/upgrades/side-effects/taskflow-phase3a.md +138 -0
- package/upgrades/side-effects/taskflow-phase5.md +234 -0
- package/upgrades/side-effects/threadline-nickname-resolver-authority.md +81 -0
- package/upgrades/side-effects/wikiclaim-evidence-phase1.md +138 -0
- package/upgrades/side-effects/wikiclaim-evidence-phase4.md +129 -0
- package/upgrades/side-effects/wikiclaim-evidence-phase5.md +285 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaskFlow — types and constants.
|
|
3
|
+
*
|
|
4
|
+
* Imported from OpenClaw's task-flow-registry shape, trimmed for Instar v1
|
|
5
|
+
* (single-writer; managed-only; no `blocked` status).
|
|
6
|
+
*
|
|
7
|
+
* See docs/specs/OPENCLAW-IMPORT-TASKFLOW-SPEC.md for full design.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
export const TERMINAL_STATUSES = new Set([
|
|
11
|
+
'succeeded',
|
|
12
|
+
'failed',
|
|
13
|
+
'cancelled',
|
|
14
|
+
'lost',
|
|
15
|
+
]);
|
|
16
|
+
// ---------- size limits ----------
|
|
17
|
+
export const MAX_OWNER_KEY_CHARS = 256;
|
|
18
|
+
export const MAX_GOAL_CHARS = 1024;
|
|
19
|
+
export const MAX_CURRENT_STEP_CHARS = 128;
|
|
20
|
+
export const MAX_STATE_JSON_BYTES = 64 * 1024;
|
|
21
|
+
export const MAX_WAIT_JSON_BYTES = 8 * 1024;
|
|
22
|
+
// ---------- defaults ----------
|
|
23
|
+
export const DEFAULT_THRESHOLDS = {
|
|
24
|
+
RUNNING_LOST_MS: 6 * 60 * 60 * 1000, // 6h
|
|
25
|
+
REPLY_LOST_MS: 7 * 24 * 60 * 60 * 1000, // 7d
|
|
26
|
+
HUMAN_REVIEW_LOST_MS: 30 * 24 * 60 * 60 * 1000, // 30d
|
|
27
|
+
EXTERNAL_LOST_MS: 7 * 24 * 60 * 60 * 1000, // 7d
|
|
28
|
+
EXTERNAL_GRACE_MS: 60 * 60 * 1000, // 1h
|
|
29
|
+
XAGENT_LOST_MS: 7 * 24 * 60 * 60 * 1000, // 7d
|
|
30
|
+
};
|
|
31
|
+
export const HEARTBEAT_INTERVAL_MS = 60 * 1000;
|
|
32
|
+
export const SWEEPER_INTERVAL_MS = 60 * 60 * 1000; // hourly
|
|
33
|
+
export const DUE_WAKER_INTERVAL_MS = 60 * 1000; // every minute
|
|
34
|
+
export const MAX_CACHE_ENTRIES = 1000;
|
|
35
|
+
export const MAX_BUSY_RETRIES = 5;
|
|
36
|
+
export const BUSY_BASE_DELAY_MS = 50;
|
|
37
|
+
export const BUSY_CAP_DELAY_MS = 5000;
|
|
38
|
+
export const RESERVED_MAINTENANCE_CONTROLLER = 'TaskFlowMaintenance';
|
|
39
|
+
// ---------- Phase 5: rate limits + cache cap defaults ----------
|
|
40
|
+
// Spec § Threat Model lines 679, 685; § Phase 5 line 650-653.
|
|
41
|
+
export const DEFAULT_CREATE_PER_SEC_PER_CONTROLLER = 10;
|
|
42
|
+
export const DEFAULT_MAX_ACTIVE_PER_CONTROLLER = 50;
|
|
43
|
+
export const DEFAULT_PING_PER_MIN_PER_FLOW = 60;
|
|
44
|
+
export const DEFAULT_CACHE_MAX_ENTRIES = MAX_CACHE_ENTRIES;
|
|
45
|
+
export const DEFAULT_RATE_LIMITS = {
|
|
46
|
+
createPerSecPerController: DEFAULT_CREATE_PER_SEC_PER_CONTROLLER,
|
|
47
|
+
maxActivePerController: DEFAULT_MAX_ACTIVE_PER_CONTROLLER,
|
|
48
|
+
pingPerMinPerFlow: DEFAULT_PING_PER_MIN_PER_FLOW,
|
|
49
|
+
};
|
|
50
|
+
export const DEFAULT_CACHE_CONFIG = {
|
|
51
|
+
maxEntries: DEFAULT_CACHE_MAX_ENTRIES,
|
|
52
|
+
};
|
|
53
|
+
/** Active (non-terminal) flow statuses for max-active-per-controller bookkeeping. */
|
|
54
|
+
export const ACTIVE_STATUSES = ['queued', 'running', 'waiting'];
|
|
55
|
+
export class TaskFlowError extends Error {
|
|
56
|
+
code;
|
|
57
|
+
detail;
|
|
58
|
+
constructor(code, message, detail = {}) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = 'TaskFlowError';
|
|
61
|
+
this.code = code;
|
|
62
|
+
this.detail = detail;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// ---------- zod schemas ----------
|
|
66
|
+
const requesterOriginSchema = z.object({
|
|
67
|
+
kind: z.enum(['user', 'agent', 'system', 'job']),
|
|
68
|
+
id: z.string().min(1).max(256),
|
|
69
|
+
channel: z.string().max(256).optional(),
|
|
70
|
+
});
|
|
71
|
+
const notifyPolicySchema = z.discriminatedUnion('kind', [
|
|
72
|
+
z.object({ kind: z.literal('silent') }),
|
|
73
|
+
z.object({ kind: z.literal('on-wait'), topicId: z.number().int() }),
|
|
74
|
+
z.object({ kind: z.literal('on-terminal'), topicId: z.number().int() }),
|
|
75
|
+
z.object({ kind: z.literal('on-wait-and-terminal'), topicId: z.number().int() }),
|
|
76
|
+
]);
|
|
77
|
+
export const waitJsonSchema = z.discriminatedUnion('kind', [
|
|
78
|
+
z.object({
|
|
79
|
+
kind: z.literal('reply'),
|
|
80
|
+
channel: z.string().min(1).max(256),
|
|
81
|
+
threadId: z.string().min(1).max(256),
|
|
82
|
+
peer: z.string().min(1).max(256),
|
|
83
|
+
}),
|
|
84
|
+
z.object({
|
|
85
|
+
kind: z.literal('human-review'),
|
|
86
|
+
question: z.string().min(1).max(2000),
|
|
87
|
+
topicId: z.number().int().optional(),
|
|
88
|
+
reviewerId: z.string().max(256).optional(),
|
|
89
|
+
}),
|
|
90
|
+
z.object({
|
|
91
|
+
kind: z.literal('external-call'),
|
|
92
|
+
serviceId: z.string().min(1).max(256),
|
|
93
|
+
correlationId: z.string().min(16).max(256),
|
|
94
|
+
deadline: z.number().int().optional(),
|
|
95
|
+
}),
|
|
96
|
+
z.object({
|
|
97
|
+
kind: z.literal('scheduled-tick'),
|
|
98
|
+
dueAt: z.number().int(),
|
|
99
|
+
jobSlug: z.string().max(256).optional(),
|
|
100
|
+
}),
|
|
101
|
+
z.object({
|
|
102
|
+
kind: z.literal('cross-agent-callback'),
|
|
103
|
+
threadId: z.string().min(1).max(256),
|
|
104
|
+
correlationId: z.string().min(16).max(256),
|
|
105
|
+
expectedAgentId: z.string().min(1).max(256),
|
|
106
|
+
}),
|
|
107
|
+
]);
|
|
108
|
+
export const createFlowInputSchema = z.object({
|
|
109
|
+
ownerKey: z.string().min(1).max(MAX_OWNER_KEY_CHARS),
|
|
110
|
+
controllerId: z.string().min(1).max(256),
|
|
111
|
+
controllerInstanceId: z.string().min(1).max(256),
|
|
112
|
+
idempotencyKey: z.string().min(8).max(256),
|
|
113
|
+
goal: z.string().min(1).max(MAX_GOAL_CHARS),
|
|
114
|
+
currentStep: z.string().max(MAX_CURRENT_STEP_CHARS).optional(),
|
|
115
|
+
stateJson: z.unknown().optional(),
|
|
116
|
+
notifyPolicy: notifyPolicySchema.optional(),
|
|
117
|
+
requesterOrigin: requesterOriginSchema.optional(),
|
|
118
|
+
privacyScope: z.enum(['private', 'shared-topic', 'shared-project']).optional(),
|
|
119
|
+
});
|
|
120
|
+
export function jsonByteLength(value) {
|
|
121
|
+
if (value === undefined)
|
|
122
|
+
return 0;
|
|
123
|
+
return Buffer.byteLength(JSON.stringify(value), 'utf8');
|
|
124
|
+
}
|
|
125
|
+
export function isTerminalStatus(status) {
|
|
126
|
+
return TERMINAL_STATUSES.has(status);
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=task-flow-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-flow-types.js","sourceRoot":"","sources":["../../src/tasks/task-flow-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreadlineNicknames — user-editable display names for threadline agents,
|
|
3
|
+
* keyed by fingerprint (or any stable id).
|
|
4
|
+
*
|
|
5
|
+
* Storage: .instar/threadline/nicknames.json
|
|
6
|
+
* {
|
|
7
|
+
* "version": 1,
|
|
8
|
+
* "nicknames": {
|
|
9
|
+
* "8c7928aa9f04fbda...": {
|
|
10
|
+
* "nickname": "Dawn",
|
|
11
|
+
* "source": "user" | "haiku" | "import",
|
|
12
|
+
* "updatedAt": "2026-05-06T17:00:00.000Z"
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
* }
|
|
16
|
+
*/
|
|
17
|
+
export type NicknameSource = 'user' | 'haiku' | 'import';
|
|
18
|
+
export interface NicknameEntry {
|
|
19
|
+
nickname: string;
|
|
20
|
+
source: NicknameSource;
|
|
21
|
+
updatedAt: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ThreadlineNicknamesOptions {
|
|
24
|
+
stateDir: string;
|
|
25
|
+
}
|
|
26
|
+
export declare class ThreadlineNicknames {
|
|
27
|
+
private readonly stateDir;
|
|
28
|
+
private cache;
|
|
29
|
+
private cacheReadAt;
|
|
30
|
+
private static readonly CACHE_TTL_MS;
|
|
31
|
+
constructor(opts: ThreadlineNicknamesOptions);
|
|
32
|
+
/** Path to the nicknames JSON file. */
|
|
33
|
+
filePath(): string;
|
|
34
|
+
/** Returns the nickname for a fingerprint, or null if none set. */
|
|
35
|
+
get(fingerprint: string): NicknameEntry | null;
|
|
36
|
+
/** Returns all nicknames as a plain map. */
|
|
37
|
+
all(): Record<string, NicknameEntry>;
|
|
38
|
+
/**
|
|
39
|
+
* Canonicalize a name for authority-grade comparison.
|
|
40
|
+
*
|
|
41
|
+
* Applies Unicode NFC normalization, trims surrounding whitespace,
|
|
42
|
+
* collapses internal whitespace runs to a single space, and lowercases.
|
|
43
|
+
* This is what makes two visually-identical names compare equal even
|
|
44
|
+
* when one was hand-edited with stray whitespace, mixed case, or
|
|
45
|
+
* combining-character forms.
|
|
46
|
+
*
|
|
47
|
+
* Used by `resolveByName()` on BOTH the lookup key AND each stored
|
|
48
|
+
* entry's nickname at compare time — so we never mutate the user's
|
|
49
|
+
* chosen display string on disk (preserving their preferred casing
|
|
50
|
+
* and spacing for the dashboard), but lookups still match across
|
|
51
|
+
* cosmetic differences. `set()` does NOT pre-canonicalize on store
|
|
52
|
+
* for the same reason: the stored string is user-presentation; the
|
|
53
|
+
* canonical form is comparison-only.
|
|
54
|
+
*/
|
|
55
|
+
static canonicalizeName(name: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Reverse-lookup: nickname → fingerprint. Canonicalized exact match
|
|
58
|
+
* (NFC-normalized, internal-whitespace-collapsed, case-insensitive).
|
|
59
|
+
*
|
|
60
|
+
* Returns null if no nickname matches. If multiple fingerprints share
|
|
61
|
+
* the same nickname (rare; user shouldn't do this but the file allows it),
|
|
62
|
+
* returns { ambiguous: true, candidates: [...] } so callers can fail
|
|
63
|
+
* loudly instead of silently picking one.
|
|
64
|
+
*
|
|
65
|
+
* The send-path resolver consults this BEFORE relay discovery so that
|
|
66
|
+
* user-curated names take authority over potentially-stale or imposter
|
|
67
|
+
* presence entries. See routes.ts /threadline/relay-send.
|
|
68
|
+
*/
|
|
69
|
+
resolveByName(name: string): {
|
|
70
|
+
fingerprint: string;
|
|
71
|
+
entry: NicknameEntry;
|
|
72
|
+
} | {
|
|
73
|
+
ambiguous: true;
|
|
74
|
+
candidates: Array<{
|
|
75
|
+
fingerprint: string;
|
|
76
|
+
entry: NicknameEntry;
|
|
77
|
+
}>;
|
|
78
|
+
} | null;
|
|
79
|
+
/** Set a nickname for a fingerprint. Empty/whitespace nickname clears it. */
|
|
80
|
+
set(fingerprint: string, nickname: string, source?: NicknameSource): NicknameEntry | null;
|
|
81
|
+
/** Delete a nickname mapping. Returns true if one existed. */
|
|
82
|
+
delete(fingerprint: string): boolean;
|
|
83
|
+
/** Force-reload on next get(). */
|
|
84
|
+
invalidate(): void;
|
|
85
|
+
private load;
|
|
86
|
+
private persist;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=ThreadlineNicknames.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThreadlineNicknames.d.ts","sourceRoot":"","sources":["../../src/threadline/ThreadlineNicknames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAOD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAU;gBAElC,IAAI,EAAE,0BAA0B;IAI5C,uCAAuC;IACvC,QAAQ,IAAI,MAAM;IAIlB,mEAAmE;IACnE,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAM9C,4CAA4C;IAC5C,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAOpC;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAS7C;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,aAAa,CAAA;KAAE,GAAG;QAAE,SAAS,EAAE,IAAI,CAAC;QAAC,UAAU,EAAE,KAAK,CAAC;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,aAAa,CAAA;SAAE,CAAC,CAAA;KAAE,GAAG,IAAI;IAezK,6EAA6E;IAC7E,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAE,cAAuB,GAAG,aAAa,GAAG,IAAI;IAsBjG,8DAA8D;IAC9D,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAQpC,kCAAkC;IAClC,UAAU,IAAI,IAAI;IAOlB,OAAO,CAAC,IAAI;IAqCZ,OAAO,CAAC,OAAO;CAiBhB"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreadlineNicknames — user-editable display names for threadline agents,
|
|
3
|
+
* keyed by fingerprint (or any stable id).
|
|
4
|
+
*
|
|
5
|
+
* Storage: .instar/threadline/nicknames.json
|
|
6
|
+
* {
|
|
7
|
+
* "version": 1,
|
|
8
|
+
* "nicknames": {
|
|
9
|
+
* "8c7928aa9f04fbda...": {
|
|
10
|
+
* "nickname": "Dawn",
|
|
11
|
+
* "source": "user" | "haiku" | "import",
|
|
12
|
+
* "updatedAt": "2026-05-06T17:00:00.000Z"
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
* }
|
|
16
|
+
*/
|
|
17
|
+
import fs from 'node:fs';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
const FILE_VERSION = 1;
|
|
20
|
+
export class ThreadlineNicknames {
|
|
21
|
+
stateDir;
|
|
22
|
+
cache = null;
|
|
23
|
+
cacheReadAt = 0;
|
|
24
|
+
static CACHE_TTL_MS = 30_000;
|
|
25
|
+
constructor(opts) {
|
|
26
|
+
this.stateDir = opts.stateDir;
|
|
27
|
+
}
|
|
28
|
+
/** Path to the nicknames JSON file. */
|
|
29
|
+
filePath() {
|
|
30
|
+
return path.join(this.stateDir, 'threadline', 'nicknames.json');
|
|
31
|
+
}
|
|
32
|
+
/** Returns the nickname for a fingerprint, or null if none set. */
|
|
33
|
+
get(fingerprint) {
|
|
34
|
+
if (!fingerprint)
|
|
35
|
+
return null;
|
|
36
|
+
const map = this.load();
|
|
37
|
+
return map.get(fingerprint) ?? null;
|
|
38
|
+
}
|
|
39
|
+
/** Returns all nicknames as a plain map. */
|
|
40
|
+
all() {
|
|
41
|
+
const map = this.load();
|
|
42
|
+
const out = {};
|
|
43
|
+
for (const [k, v] of map)
|
|
44
|
+
out[k] = v;
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Canonicalize a name for authority-grade comparison.
|
|
49
|
+
*
|
|
50
|
+
* Applies Unicode NFC normalization, trims surrounding whitespace,
|
|
51
|
+
* collapses internal whitespace runs to a single space, and lowercases.
|
|
52
|
+
* This is what makes two visually-identical names compare equal even
|
|
53
|
+
* when one was hand-edited with stray whitespace, mixed case, or
|
|
54
|
+
* combining-character forms.
|
|
55
|
+
*
|
|
56
|
+
* Used by `resolveByName()` on BOTH the lookup key AND each stored
|
|
57
|
+
* entry's nickname at compare time — so we never mutate the user's
|
|
58
|
+
* chosen display string on disk (preserving their preferred casing
|
|
59
|
+
* and spacing for the dashboard), but lookups still match across
|
|
60
|
+
* cosmetic differences. `set()` does NOT pre-canonicalize on store
|
|
61
|
+
* for the same reason: the stored string is user-presentation; the
|
|
62
|
+
* canonical form is comparison-only.
|
|
63
|
+
*/
|
|
64
|
+
static canonicalizeName(name) {
|
|
65
|
+
if (!name)
|
|
66
|
+
return '';
|
|
67
|
+
return name
|
|
68
|
+
.normalize('NFC')
|
|
69
|
+
.trim()
|
|
70
|
+
.replace(/\s+/g, ' ')
|
|
71
|
+
.toLowerCase();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Reverse-lookup: nickname → fingerprint. Canonicalized exact match
|
|
75
|
+
* (NFC-normalized, internal-whitespace-collapsed, case-insensitive).
|
|
76
|
+
*
|
|
77
|
+
* Returns null if no nickname matches. If multiple fingerprints share
|
|
78
|
+
* the same nickname (rare; user shouldn't do this but the file allows it),
|
|
79
|
+
* returns { ambiguous: true, candidates: [...] } so callers can fail
|
|
80
|
+
* loudly instead of silently picking one.
|
|
81
|
+
*
|
|
82
|
+
* The send-path resolver consults this BEFORE relay discovery so that
|
|
83
|
+
* user-curated names take authority over potentially-stale or imposter
|
|
84
|
+
* presence entries. See routes.ts /threadline/relay-send.
|
|
85
|
+
*/
|
|
86
|
+
resolveByName(name) {
|
|
87
|
+
const canonical = ThreadlineNicknames.canonicalizeName(name);
|
|
88
|
+
if (!canonical)
|
|
89
|
+
return null;
|
|
90
|
+
const map = this.load();
|
|
91
|
+
const matches = [];
|
|
92
|
+
for (const [fp, entry] of map) {
|
|
93
|
+
if (ThreadlineNicknames.canonicalizeName(entry.nickname) === canonical) {
|
|
94
|
+
matches.push({ fingerprint: fp, entry });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (matches.length === 0)
|
|
98
|
+
return null;
|
|
99
|
+
if (matches.length === 1)
|
|
100
|
+
return matches[0];
|
|
101
|
+
return { ambiguous: true, candidates: matches };
|
|
102
|
+
}
|
|
103
|
+
/** Set a nickname for a fingerprint. Empty/whitespace nickname clears it. */
|
|
104
|
+
set(fingerprint, nickname, source = 'user') {
|
|
105
|
+
if (!fingerprint)
|
|
106
|
+
throw new Error('fingerprint required');
|
|
107
|
+
const trimmed = nickname.trim();
|
|
108
|
+
const map = this.load();
|
|
109
|
+
if (trimmed.length === 0) {
|
|
110
|
+
map.delete(fingerprint);
|
|
111
|
+
this.persist(map);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
if (trimmed.length > 64) {
|
|
115
|
+
throw new Error('nickname too long (max 64 chars)');
|
|
116
|
+
}
|
|
117
|
+
const entry = {
|
|
118
|
+
nickname: trimmed,
|
|
119
|
+
source,
|
|
120
|
+
updatedAt: new Date().toISOString(),
|
|
121
|
+
};
|
|
122
|
+
map.set(fingerprint, entry);
|
|
123
|
+
this.persist(map);
|
|
124
|
+
return entry;
|
|
125
|
+
}
|
|
126
|
+
/** Delete a nickname mapping. Returns true if one existed. */
|
|
127
|
+
delete(fingerprint) {
|
|
128
|
+
const map = this.load();
|
|
129
|
+
if (!map.has(fingerprint))
|
|
130
|
+
return false;
|
|
131
|
+
map.delete(fingerprint);
|
|
132
|
+
this.persist(map);
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
/** Force-reload on next get(). */
|
|
136
|
+
invalidate() {
|
|
137
|
+
this.cache = null;
|
|
138
|
+
this.cacheReadAt = 0;
|
|
139
|
+
}
|
|
140
|
+
// ── internal ───────────────────────────────────────────────────
|
|
141
|
+
load() {
|
|
142
|
+
const fresh = Date.now() - this.cacheReadAt < ThreadlineNicknames.CACHE_TTL_MS;
|
|
143
|
+
if (this.cache && fresh)
|
|
144
|
+
return this.cache;
|
|
145
|
+
const map = new Map();
|
|
146
|
+
const file = this.filePath();
|
|
147
|
+
if (fs.existsSync(file)) {
|
|
148
|
+
try {
|
|
149
|
+
const raw = fs.readFileSync(file, 'utf-8');
|
|
150
|
+
const parsed = JSON.parse(raw);
|
|
151
|
+
const items = parsed?.nicknames ?? {};
|
|
152
|
+
for (const [k, v] of Object.entries(items)) {
|
|
153
|
+
if (v && typeof v.nickname === 'string') {
|
|
154
|
+
map.set(k, {
|
|
155
|
+
nickname: v.nickname,
|
|
156
|
+
source: v.source ?? 'user',
|
|
157
|
+
updatedAt: v.updatedAt ?? new Date().toISOString(),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
// Corrupt file — degrade to empty map (sends still flow via
|
|
164
|
+
// relay-discovery fallback) but make the silent authority loss
|
|
165
|
+
// visible. One log per cache cycle (every 30s at most), so a
|
|
166
|
+
// persistently-corrupt file doesn't spam logs but is observable.
|
|
167
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
168
|
+
console.warn(`[ThreadlineNicknames] nicknames.json parse failed at ${file}: ${msg}. ` +
|
|
169
|
+
`Treating as empty (no user-curated authority for this load cycle). ` +
|
|
170
|
+
`Outbound sends will fall back to relay-discovery for nicknamed names.`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
this.cache = map;
|
|
174
|
+
this.cacheReadAt = Date.now();
|
|
175
|
+
return map;
|
|
176
|
+
}
|
|
177
|
+
persist(map) {
|
|
178
|
+
const file = this.filePath();
|
|
179
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
180
|
+
const obj = {
|
|
181
|
+
version: FILE_VERSION,
|
|
182
|
+
nicknames: Object.fromEntries(map),
|
|
183
|
+
};
|
|
184
|
+
// Atomic write: temp + rename. Prevents a concurrent reader from
|
|
185
|
+
// observing a half-written file (which would parse-fail and degrade
|
|
186
|
+
// to "no nicknames" — silent authority loss). rename(2) is atomic on
|
|
187
|
+
// POSIX when source and destination live on the same filesystem.
|
|
188
|
+
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
189
|
+
fs.writeFileSync(tmp, JSON.stringify(obj, null, 2), 'utf-8');
|
|
190
|
+
fs.renameSync(tmp, file);
|
|
191
|
+
this.cache = map;
|
|
192
|
+
this.cacheReadAt = Date.now();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=ThreadlineNicknames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThreadlineNicknames.js","sourceRoot":"","sources":["../../src/threadline/ThreadlineNicknames.ts"],"names":[],"mappings":"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"}
|