instar 0.9.0 → 0.9.2

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 (59) hide show
  1. package/dist/cli.js +0 -0
  2. package/dist/commands/server.d.ts.map +1 -1
  3. package/dist/commands/server.js +202 -71
  4. package/dist/commands/server.js.map +1 -1
  5. package/dist/commands/setup.d.ts.map +1 -1
  6. package/dist/commands/setup.js +38 -4
  7. package/dist/commands/setup.js.map +1 -1
  8. package/dist/core/AgentConnector.d.ts +76 -0
  9. package/dist/core/AgentConnector.d.ts.map +1 -0
  10. package/dist/core/AgentConnector.js +323 -0
  11. package/dist/core/AgentConnector.js.map +1 -0
  12. package/dist/core/AutoUpdater.d.ts +7 -0
  13. package/dist/core/AutoUpdater.d.ts.map +1 -1
  14. package/dist/core/AutoUpdater.js +31 -3
  15. package/dist/core/AutoUpdater.js.map +1 -1
  16. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  17. package/dist/core/PostUpdateMigrator.js +86 -5
  18. package/dist/core/PostUpdateMigrator.js.map +1 -1
  19. package/dist/core/StateWriteAuthority.d.ts +101 -0
  20. package/dist/core/StateWriteAuthority.d.ts.map +1 -0
  21. package/dist/core/StateWriteAuthority.js +167 -0
  22. package/dist/core/StateWriteAuthority.js.map +1 -0
  23. package/dist/core/types.d.ts +104 -0
  24. package/dist/core/types.d.ts.map +1 -1
  25. package/dist/index.d.ts +2 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +1 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/memory/TopicMemory.d.ts +167 -0
  30. package/dist/memory/TopicMemory.d.ts.map +1 -0
  31. package/dist/memory/TopicMemory.js +494 -0
  32. package/dist/memory/TopicMemory.js.map +1 -0
  33. package/dist/memory/TopicSummarizer.d.ts +58 -0
  34. package/dist/memory/TopicSummarizer.d.ts.map +1 -0
  35. package/dist/memory/TopicSummarizer.js +140 -0
  36. package/dist/memory/TopicSummarizer.js.map +1 -0
  37. package/dist/messaging/TelegramAdapter.d.ts +35 -0
  38. package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
  39. package/dist/messaging/TelegramAdapter.js +136 -2
  40. package/dist/messaging/TelegramAdapter.js.map +1 -1
  41. package/dist/server/AgentServer.d.ts +2 -0
  42. package/dist/server/AgentServer.d.ts.map +1 -1
  43. package/dist/server/AgentServer.js +1 -0
  44. package/dist/server/AgentServer.js.map +1 -1
  45. package/dist/server/routes.d.ts +2 -0
  46. package/dist/server/routes.d.ts.map +1 -1
  47. package/dist/server/routes.js +340 -1
  48. package/dist/server/routes.js.map +1 -1
  49. package/dist/users/UserManager.d.ts +21 -0
  50. package/dist/users/UserManager.d.ts.map +1 -1
  51. package/dist/users/UserManager.js +32 -0
  52. package/dist/users/UserManager.js.map +1 -1
  53. package/dist/users/UserOnboarding.d.ts +116 -0
  54. package/dist/users/UserOnboarding.d.ts.map +1 -0
  55. package/dist/users/UserOnboarding.js +365 -0
  56. package/dist/users/UserOnboarding.js.map +1 -0
  57. package/package.json +2 -1
  58. package/upgrades/0.8.23.md +106 -0
  59. package/upgrades/0.9.1.md +91 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * TopicSummarizer — LLM-powered rolling summary generation for topic conversations.
3
+ *
4
+ * Generates and maintains rolling summaries for each Telegram topic thread.
5
+ * Summaries compress the full conversation history into a concise context
6
+ * that new sessions can load instantly — no need to replay hundreds of messages.
7
+ *
8
+ * Summary strategy:
9
+ * - First summary: Generated from all messages when topic exceeds threshold
10
+ * - Incremental updates: Previous summary + new messages → updated summary
11
+ * - Triggered: On session end (if threshold exceeded) or on-demand via API
12
+ *
13
+ * Uses IntelligenceProvider (Claude CLI by default) for LLM calls.
14
+ * Haiku tier for cost efficiency — summaries don't need deep reasoning.
15
+ */
16
+ import type { IntelligenceProvider } from '../core/types.js';
17
+ import type { TopicMemory, TopicMessage } from './TopicMemory.js';
18
+ export interface TopicSummarizerConfig {
19
+ /** Minimum new messages before triggering a summary update */
20
+ messageThreshold: number;
21
+ /** Maximum messages to include in a single summarization prompt */
22
+ maxMessagesPerPrompt: number;
23
+ /** Maximum tokens for the summary response */
24
+ maxSummaryTokens: number;
25
+ }
26
+ export interface SummarizeResult {
27
+ topicId: number;
28
+ summary: string;
29
+ messagesProcessed: number;
30
+ isUpdate: boolean;
31
+ durationMs: number;
32
+ }
33
+ /**
34
+ * Build the prompt for generating a topic summary.
35
+ */
36
+ declare function buildSummaryPrompt(messages: TopicMessage[], existingSummary: string | null, topicName: string | null): string;
37
+ export declare class TopicSummarizer {
38
+ private intelligence;
39
+ private topicMemory;
40
+ private config;
41
+ constructor(intelligence: IntelligenceProvider, topicMemory: TopicMemory, config?: Partial<TopicSummarizerConfig>);
42
+ /**
43
+ * Generate or update the summary for a topic.
44
+ * Returns null if the topic doesn't need a summary update.
45
+ */
46
+ summarize(topicId: number, force?: boolean): Promise<SummarizeResult | null>;
47
+ /**
48
+ * Check all topics and summarize those that need it.
49
+ * Returns results for topics that were summarized.
50
+ */
51
+ summarizeAll(): Promise<SummarizeResult[]>;
52
+ /**
53
+ * Check if a specific topic needs a summary update.
54
+ */
55
+ needsUpdate(topicId: number): boolean;
56
+ }
57
+ export { buildSummaryPrompt };
58
+ //# sourceMappingURL=TopicSummarizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TopicSummarizer.d.ts","sourceRoot":"","sources":["../../src/memory/TopicSummarizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,gBAAgB,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAQD;;GAEG;AACH,iBAAS,kBAAkB,CACzB,QAAQ,EAAE,YAAY,EAAE,EACxB,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,GACvB,MAAM,CA8CR;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,MAAM,CAAwB;gBAGpC,YAAY,EAAE,oBAAoB,EAClC,WAAW,EAAE,WAAW,EACxB,MAAM,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAOzC;;;OAGG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAqDlF;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAgBhD;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;CAGtC;AAGD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * TopicSummarizer — LLM-powered rolling summary generation for topic conversations.
3
+ *
4
+ * Generates and maintains rolling summaries for each Telegram topic thread.
5
+ * Summaries compress the full conversation history into a concise context
6
+ * that new sessions can load instantly — no need to replay hundreds of messages.
7
+ *
8
+ * Summary strategy:
9
+ * - First summary: Generated from all messages when topic exceeds threshold
10
+ * - Incremental updates: Previous summary + new messages → updated summary
11
+ * - Triggered: On session end (if threshold exceeded) or on-demand via API
12
+ *
13
+ * Uses IntelligenceProvider (Claude CLI by default) for LLM calls.
14
+ * Haiku tier for cost efficiency — summaries don't need deep reasoning.
15
+ */
16
+ const DEFAULT_CONFIG = {
17
+ messageThreshold: 20,
18
+ maxMessagesPerPrompt: 200,
19
+ maxSummaryTokens: 1024,
20
+ };
21
+ /**
22
+ * Build the prompt for generating a topic summary.
23
+ */
24
+ function buildSummaryPrompt(messages, existingSummary, topicName) {
25
+ const lines = [];
26
+ lines.push('You are summarizing a conversation between a user and their AI agent.');
27
+ lines.push('Your summary will be loaded as context for future sessions so the agent can continue the conversation seamlessly.');
28
+ lines.push('');
29
+ if (topicName) {
30
+ lines.push(`Topic: ${topicName}`);
31
+ lines.push('');
32
+ }
33
+ lines.push('RULES:');
34
+ lines.push('- Capture what was discussed, decisions made, current state, and any pending items');
35
+ lines.push('- Preserve specific details: names, file paths, version numbers, URLs, technical decisions');
36
+ lines.push('- Note the emotional tone and relationship dynamics if relevant');
37
+ lines.push('- Keep it under 500 words — concise but complete');
38
+ lines.push('- Write in present tense for current state, past tense for completed work');
39
+ lines.push('- DO NOT include meta-commentary about the summarization itself');
40
+ lines.push('');
41
+ if (existingSummary) {
42
+ lines.push('EXISTING SUMMARY (update this with the new messages below):');
43
+ lines.push('---');
44
+ lines.push(existingSummary);
45
+ lines.push('---');
46
+ lines.push('');
47
+ lines.push('NEW MESSAGES SINCE LAST SUMMARY:');
48
+ }
49
+ else {
50
+ lines.push('CONVERSATION TO SUMMARIZE:');
51
+ }
52
+ lines.push('');
53
+ for (const m of messages) {
54
+ const sender = m.fromUser ? 'User' : 'Agent';
55
+ const ts = m.timestamp ? new Date(m.timestamp).toISOString().slice(0, 16).replace('T', ' ') : '';
56
+ // Truncate very long messages to keep prompt manageable
57
+ const text = m.text.length > 1000 ? m.text.slice(0, 1000) + '...' : m.text;
58
+ lines.push(`[${ts}] ${sender}: ${text}`);
59
+ }
60
+ lines.push('');
61
+ lines.push('Write the updated conversation summary:');
62
+ return lines.join('\n');
63
+ }
64
+ export class TopicSummarizer {
65
+ intelligence;
66
+ topicMemory;
67
+ config;
68
+ constructor(intelligence, topicMemory, config) {
69
+ this.intelligence = intelligence;
70
+ this.topicMemory = topicMemory;
71
+ this.config = { ...DEFAULT_CONFIG, ...config };
72
+ }
73
+ /**
74
+ * Generate or update the summary for a topic.
75
+ * Returns null if the topic doesn't need a summary update.
76
+ */
77
+ async summarize(topicId, force) {
78
+ const needsUpdate = force || this.topicMemory.needsSummaryUpdate(topicId, this.config.messageThreshold);
79
+ if (!needsUpdate)
80
+ return null;
81
+ const startTime = Date.now();
82
+ // Get existing summary and new messages
83
+ const existingSummary = this.topicMemory.getTopicSummary(topicId);
84
+ const newMessages = this.topicMemory.getMessagesSinceSummary(topicId);
85
+ if (newMessages.length === 0 && !force)
86
+ return null;
87
+ // Limit messages to prevent prompt explosion
88
+ const messagesToProcess = newMessages.slice(-this.config.maxMessagesPerPrompt);
89
+ const meta = this.topicMemory.getTopicMeta(topicId);
90
+ const prompt = buildSummaryPrompt(messagesToProcess, existingSummary?.summary ?? null, meta?.topicName ?? null);
91
+ // Generate summary via LLM (Haiku for cost efficiency)
92
+ const summary = await this.intelligence.evaluate(prompt, {
93
+ model: 'fast',
94
+ maxTokens: this.config.maxSummaryTokens,
95
+ });
96
+ if (!summary || summary.trim().length < 10) {
97
+ throw new Error(`Summary generation returned empty/invalid result for topic ${topicId}`);
98
+ }
99
+ // Get the last message ID for tracking what's been summarized
100
+ const lastMessage = newMessages[newMessages.length - 1];
101
+ const totalMessages = this.topicMemory.getMessageCount(topicId);
102
+ // Save the summary
103
+ this.topicMemory.saveTopicSummary(topicId, summary.trim(), totalMessages, lastMessage?.messageId ?? existingSummary?.lastMessageId ?? 0);
104
+ return {
105
+ topicId,
106
+ summary: summary.trim(),
107
+ messagesProcessed: messagesToProcess.length,
108
+ isUpdate: !!existingSummary,
109
+ durationMs: Date.now() - startTime,
110
+ };
111
+ }
112
+ /**
113
+ * Check all topics and summarize those that need it.
114
+ * Returns results for topics that were summarized.
115
+ */
116
+ async summarizeAll() {
117
+ const topics = this.topicMemory.listTopics();
118
+ const results = [];
119
+ for (const topic of topics) {
120
+ try {
121
+ const result = await this.summarize(topic.topicId);
122
+ if (result)
123
+ results.push(result);
124
+ }
125
+ catch (err) {
126
+ console.error(`[TopicSummarizer] Failed to summarize topic ${topic.topicId}: ${err}`);
127
+ }
128
+ }
129
+ return results;
130
+ }
131
+ /**
132
+ * Check if a specific topic needs a summary update.
133
+ */
134
+ needsUpdate(topicId) {
135
+ return this.topicMemory.needsSummaryUpdate(topicId, this.config.messageThreshold);
136
+ }
137
+ }
138
+ // Export the prompt builder for testing
139
+ export { buildSummaryPrompt };
140
+ //# sourceMappingURL=TopicSummarizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TopicSummarizer.js","sourceRoot":"","sources":["../../src/memory/TopicSummarizer.ts"],"names":[],"mappings":"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"}
@@ -85,6 +85,14 @@ export declare class TelegramAdapter implements MessagingAdapter {
85
85
  }>) | null;
86
86
  onIsSessionAlive: ((tmuxSession: string) => boolean) | null;
87
87
  onIsSessionActive: ((tmuxSession: string) => Promise<boolean>) | null;
88
+ onMessageLogged: ((entry: {
89
+ messageId: number;
90
+ topicId: number | null;
91
+ text: string;
92
+ fromUser: boolean;
93
+ timestamp: string;
94
+ sessionName: string | null;
95
+ }) => void) | null;
88
96
  onAttentionStatusChange: ((itemId: string, status: string) => Promise<void>) | null;
89
97
  onSwitchAccountRequest: ((target: string, replyTopicId: number) => Promise<void>) | null;
90
98
  onQuotaStatusRequest: ((replyTopicId: number) => Promise<void>) | null;
@@ -93,6 +101,23 @@ export declare class TelegramAdapter implements MessagingAdapter {
93
101
  cause: string;
94
102
  detail: string;
95
103
  } | null>) | null;
104
+ onGetRegistrationPolicy: (() => {
105
+ policy: string;
106
+ contactHint?: string;
107
+ agentName?: string;
108
+ }) | null;
109
+ onNotifyAdminJoinRequest: ((request: {
110
+ name: string;
111
+ username?: string;
112
+ telegramUserId: number;
113
+ }) => Promise<void>) | null;
114
+ onValidateInviteCode: ((code: string, telegramUserId: number) => Promise<{
115
+ valid: boolean;
116
+ error?: string;
117
+ }>) | null;
118
+ onStartMiniOnboarding: ((telegramUserId: number, firstName: string, username?: string) => Promise<void>) | null;
119
+ private unknownUserRateLimit;
120
+ private static readonly UNKNOWN_USER_COOLDOWN_MS;
96
121
  constructor(config: TelegramConfig, stateDir: string);
97
122
  start(): Promise<void>;
98
123
  stop(): Promise<void>;
@@ -133,6 +158,16 @@ export declare class TelegramAdapter implements MessagingAdapter {
133
158
  * If no authorizedUserIds configured, all messages are accepted.
134
159
  */
135
160
  private isAuthorized;
161
+ /**
162
+ * Handle a message from an unknown/unauthorized Telegram user.
163
+ * Checks the registration policy and responds appropriately:
164
+ * - admin-only: Gated message + notify admin
165
+ * - invite-only: Ask for invite code
166
+ * - open: Start mini-onboarding (rate limited)
167
+ *
168
+ * Rate-limited to prevent spam from the same unknown user.
169
+ */
170
+ private handleUnknownUser;
136
171
  registerTopicSession(topicId: number, sessionName: string): void;
137
172
  unregisterTopic(topicId: number): void;
138
173
  getSessionForTopic(topicId: number): string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"TelegramAdapter.d.ts","sourceRoot":"","sources":["../../src/messaging/TelegramAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TelegramAdapter.d.ts","sourceRoot":"","sources":["../../src/messaging/TelegramAdapter.ts"],"names":[],"mappings":"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"}
@@ -68,6 +68,9 @@ export class TelegramAdapter {
68
68
  onListSessions = null;
69
69
  onIsSessionAlive = null;
70
70
  onIsSessionActive = null;
71
+ // Message log callback — fires on every message logged (inbound and outbound).
72
+ // Used by TopicMemory to dual-write to SQLite for search and summarization.
73
+ onMessageLogged = null;
71
74
  // Attention queue callbacks
72
75
  onAttentionStatusChange = null;
73
76
  // Quota management callbacks
@@ -75,6 +78,18 @@ export class TelegramAdapter {
75
78
  onQuotaStatusRequest = null;
76
79
  onLoginRequest = null;
77
80
  onClassifySessionDeath = null;
81
+ // Unknown user handling callbacks (Multi-User Setup Wizard Phase 4.5)
82
+ // Returns the registration policy and optional contact hint for the gated message
83
+ onGetRegistrationPolicy = null;
84
+ // Called when an admin-only join request is created (notify admin via lifeline/admin topic)
85
+ onNotifyAdminJoinRequest = null;
86
+ // Called to validate an invite code for invite-only policy
87
+ onValidateInviteCode = null;
88
+ // Called to start mini-onboarding for open policy
89
+ onStartMiniOnboarding = null;
90
+ // Rate limiting for unknown user responses (prevent spam)
91
+ unknownUserRateLimit = new Map(); // telegramUserId -> last response timestamp
92
+ static UNKNOWN_USER_COOLDOWN_MS = 60_000; // 1 minute between responses to same unknown user
78
93
  constructor(config, stateDir) {
79
94
  this.config = config;
80
95
  this.stateDir = stateDir;
@@ -310,6 +325,118 @@ export class TelegramAdapter {
310
325
  return true;
311
326
  return authorized.includes(userId);
312
327
  }
328
+ /**
329
+ * Handle a message from an unknown/unauthorized Telegram user.
330
+ * Checks the registration policy and responds appropriately:
331
+ * - admin-only: Gated message + notify admin
332
+ * - invite-only: Ask for invite code
333
+ * - open: Start mini-onboarding (rate limited)
334
+ *
335
+ * Rate-limited to prevent spam from the same unknown user.
336
+ */
337
+ async handleUnknownUser(telegramUserId, firstName, username, messageText) {
338
+ // Rate limit: don't spam responses to the same unknown user
339
+ const lastResponse = this.unknownUserRateLimit.get(telegramUserId);
340
+ if (lastResponse && (Date.now() - lastResponse) < TelegramAdapter.UNKNOWN_USER_COOLDOWN_MS) {
341
+ console.log(`[telegram] Rate-limited response to unknown user ${telegramUserId} (${username ?? firstName})`);
342
+ return;
343
+ }
344
+ // Get registration policy from callback
345
+ const policyInfo = this.onGetRegistrationPolicy?.();
346
+ if (!policyInfo) {
347
+ // No policy callback wired — fall back to silent ignore (legacy behavior)
348
+ console.log(`[telegram] Ignoring message from unauthorized user ${telegramUserId} (${username ?? firstName}) — no registration policy configured`);
349
+ return;
350
+ }
351
+ const { policy, contactHint, agentName } = policyInfo;
352
+ const displayName = agentName || 'This agent';
353
+ // Mark that we responded to this user
354
+ this.unknownUserRateLimit.set(telegramUserId, Date.now());
355
+ // Clean up old rate limit entries periodically (keep map from growing unbounded)
356
+ if (this.unknownUserRateLimit.size > 100) {
357
+ const cutoff = Date.now() - TelegramAdapter.UNKNOWN_USER_COOLDOWN_MS * 10;
358
+ for (const [uid, ts] of this.unknownUserRateLimit) {
359
+ if (ts < cutoff)
360
+ this.unknownUserRateLimit.delete(uid);
361
+ }
362
+ }
363
+ console.log(`[telegram] Unknown user ${telegramUserId} (${username ?? firstName}) — policy: ${policy}`);
364
+ try {
365
+ switch (policy) {
366
+ case 'admin-only': {
367
+ // Send gated message to the user
368
+ let gatedMessage = `Hi ${firstName}! ${displayName} is not open for public registration. Access is managed by an administrator.`;
369
+ if (contactHint) {
370
+ gatedMessage += `\n\n${contactHint}`;
371
+ }
372
+ gatedMessage += `\n\nYour request has been noted and forwarded to the admin.`;
373
+ // Reply in the group's General topic (since unknown users don't have their own topic)
374
+ await this.sendToTopic(GENERAL_TOPIC_ID, gatedMessage).catch(() => { });
375
+ // Notify admin via callback
376
+ if (this.onNotifyAdminJoinRequest) {
377
+ await this.onNotifyAdminJoinRequest({
378
+ name: firstName,
379
+ username,
380
+ telegramUserId,
381
+ }).catch(err => {
382
+ console.error(`[telegram] Failed to notify admin of join request: ${err}`);
383
+ });
384
+ }
385
+ break;
386
+ }
387
+ case 'invite-only': {
388
+ // Check if the message contains an invite code
389
+ const trimmedText = messageText?.trim();
390
+ if (trimmedText && this.onValidateInviteCode) {
391
+ const result = await this.onValidateInviteCode(trimmedText, telegramUserId);
392
+ if (result.valid) {
393
+ await this.sendToTopic(GENERAL_TOPIC_ID, `Welcome, ${firstName}! Your invite code has been accepted. Setting up your account...`).catch(() => { });
394
+ // Trigger mini-onboarding after successful invite validation
395
+ if (this.onStartMiniOnboarding) {
396
+ await this.onStartMiniOnboarding(telegramUserId, firstName, username).catch(err => {
397
+ console.error(`[telegram] Failed to start onboarding after invite: ${err}`);
398
+ });
399
+ }
400
+ return;
401
+ }
402
+ else if (result.error) {
403
+ await this.sendToTopic(GENERAL_TOPIC_ID, result.error).catch(() => { });
404
+ return;
405
+ }
406
+ }
407
+ // Default invite-only prompt
408
+ let inviteMessage = `Hi ${firstName}! ${displayName} requires an invite code to join. Please reply with your invite code.`;
409
+ if (contactHint) {
410
+ inviteMessage += `\n\n${contactHint}`;
411
+ }
412
+ await this.sendToTopic(GENERAL_TOPIC_ID, inviteMessage).catch(() => { });
413
+ break;
414
+ }
415
+ case 'open': {
416
+ // Start mini-onboarding via callback
417
+ if (this.onStartMiniOnboarding) {
418
+ await this.sendToTopic(GENERAL_TOPIC_ID, `Hi ${firstName}! Welcome! Setting up your account...`).catch(() => { });
419
+ await this.onStartMiniOnboarding(telegramUserId, firstName, username).catch(err => {
420
+ console.error(`[telegram] Failed to start mini-onboarding: ${err}`);
421
+ this.sendToTopic(GENERAL_TOPIC_ID, `Sorry ${firstName}, there was an issue setting up your account. Please try again later.`).catch(() => { });
422
+ });
423
+ }
424
+ else {
425
+ await this.sendToTopic(GENERAL_TOPIC_ID, `Hi ${firstName}! Registration is currently being set up. Please try again later.`).catch(() => { });
426
+ }
427
+ break;
428
+ }
429
+ default: {
430
+ // Unknown policy — fall back to gated message
431
+ console.warn(`[telegram] Unknown registration policy: ${policy}`);
432
+ await this.sendToTopic(GENERAL_TOPIC_ID, `Hi ${firstName}! ${displayName} is not currently accepting new users.`).catch(() => { });
433
+ }
434
+ }
435
+ }
436
+ catch (err) {
437
+ console.error(`[telegram] Error handling unknown user ${telegramUserId}: ${err}`);
438
+ }
439
+ }
313
440
  // ── Topic-Session Registry ─────────────────────────────────
314
441
  registerTopicSession(topicId, sessionName) {
315
442
  this.topicToSession.set(topicId, sessionName);
@@ -829,6 +956,13 @@ export class TelegramAdapter {
829
956
  catch (err) {
830
957
  console.error(`[telegram] Failed to append to message log: ${err}`);
831
958
  }
959
+ // Notify subscribers (TopicMemory for SQLite dual-write)
960
+ if (this.onMessageLogged) {
961
+ try {
962
+ this.onMessageLogged(entry);
963
+ }
964
+ catch { /* non-critical — don't break logging pipeline */ }
965
+ }
832
966
  }
833
967
  /** Keep only the last 75,000 lines when log exceeds 100,000 lines.
834
968
  * High limits because message history is core agent memory.
@@ -1157,9 +1291,9 @@ export class TelegramAdapter {
1157
1291
  const msg = update.message;
1158
1292
  if (!msg)
1159
1293
  return;
1160
- // Auth gating — reject messages from unauthorized users
1294
+ // Auth gating — handle messages from unauthorized/unknown users
1161
1295
  if (!this.isAuthorized(msg.from.id)) {
1162
- console.log(`[telegram] Ignoring message from unauthorized user ${msg.from.id} (${msg.from.username ?? msg.from.first_name})`);
1296
+ await this.handleUnknownUser(msg.from.id, msg.from.first_name, msg.from.username, msg.text);
1163
1297
  return;
1164
1298
  }
1165
1299
  const numericTopicId = msg.message_thread_id ?? GENERAL_TOPIC_ID;