@blunking/codexlink 0.1.12 → 0.1.15

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.
@@ -1,135 +1,135 @@
1
- param(
2
- [string]$Profile = "default",
3
- [switch]$Json
4
- )
5
-
6
- $ErrorActionPreference = "Stop"
7
-
8
- function Read-DotEnvFile {
9
- param([string]$Path)
10
- $values = @{}
11
- if (-not (Test-Path $Path)) { return $values }
12
- foreach ($line in (Get-Content -Path $Path)) {
13
- if (-not $line) { continue }
14
- if ($line.Trim().StartsWith("#")) { continue }
15
- $parts = $line -split "=", 2
16
- if ($parts.Count -ne 2) { continue }
17
- $values[$parts[0].Trim()] = $parts[1]
18
- }
19
- return $values
20
- }
21
-
22
- function Add-Check {
23
- param(
24
- [System.Collections.Generic.List[object]]$List,
25
- [string]$Name,
26
- [string]$Status,
27
- [string]$Detail
28
- )
29
- $List.Add([pscustomobject]@{
30
- name = $Name
31
- status = $Status
32
- detail = $Detail
33
- }) | Out-Null
34
- }
35
-
36
- function Test-TelegramTokenFormat {
37
- param([string]$Value)
38
- if (-not $Value) { return $false }
39
- return $Value -match '^\d{6,}:[A-Za-z0-9_-]{20,}$'
40
- }
41
-
42
- function Test-AllowedChatIdsFormat {
43
- param([string]$Value)
44
- if (-not $Value) { return $false }
45
- $parts = @($Value -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ })
46
- if ($parts.Count -eq 0) { return $false }
47
- foreach ($part in $parts) {
48
- if ($part -notmatch '^-?\d+$') {
49
- return $false
50
- }
51
- }
52
- return $true
53
- }
54
-
55
- function Get-OverallStatus {
56
- param([System.Collections.Generic.List[object]]$Checks)
57
- if (@($Checks | Where-Object { $_.status -eq "fail" }).Count -gt 0) {
58
- return "fail"
59
- }
60
- if (@($Checks | Where-Object { $_.status -eq "warn" }).Count -gt 0) {
61
- return "warn"
62
- }
63
- return "ok"
64
- }
65
-
1
+ param(
2
+ [string]$Profile = "default",
3
+ [switch]$Json
4
+ )
5
+
6
+ $ErrorActionPreference = "Stop"
7
+
8
+ function Read-DotEnvFile {
9
+ param([string]$Path)
10
+ $values = @{}
11
+ if (-not (Test-Path $Path)) { return $values }
12
+ foreach ($line in (Get-Content -Path $Path)) {
13
+ if (-not $line) { continue }
14
+ if ($line.Trim().StartsWith("#")) { continue }
15
+ $parts = $line -split "=", 2
16
+ if ($parts.Count -ne 2) { continue }
17
+ $values[$parts[0].Trim()] = $parts[1]
18
+ }
19
+ return $values
20
+ }
21
+
22
+ function Add-Check {
23
+ param(
24
+ [System.Collections.Generic.List[object]]$List,
25
+ [string]$Name,
26
+ [string]$Status,
27
+ [string]$Detail
28
+ )
29
+ $List.Add([pscustomobject]@{
30
+ name = $Name
31
+ status = $Status
32
+ detail = $Detail
33
+ }) | Out-Null
34
+ }
35
+
36
+ function Test-TelegramTokenFormat {
37
+ param([string]$Value)
38
+ if (-not $Value) { return $false }
39
+ return $Value -match '^\d{6,}:[A-Za-z0-9_-]{20,}$'
40
+ }
41
+
42
+ function Test-AllowedChatIdsFormat {
43
+ param([string]$Value)
44
+ if (-not $Value) { return $false }
45
+ $parts = @($Value -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ })
46
+ if ($parts.Count -eq 0) { return $false }
47
+ foreach ($part in $parts) {
48
+ if ($part -notmatch '^-?\d+$') {
49
+ return $false
50
+ }
51
+ }
52
+ return $true
53
+ }
54
+
55
+ function Get-OverallStatus {
56
+ param([System.Collections.Generic.List[object]]$Checks)
57
+ if (@($Checks | Where-Object { $_.status -eq "fail" }).Count -gt 0) {
58
+ return "fail"
59
+ }
60
+ if (@($Checks | Where-Object { $_.status -eq "warn" }).Count -gt 0) {
61
+ return "warn"
62
+ }
63
+ return "ok"
64
+ }
65
+
66
66
  function Write-DoctorReport {
67
- param(
68
- [object]$Result,
69
- [string]$TokenSource,
70
- [string]$AllowedChatSource
71
- )
72
-
73
- $emoji = switch ($Result.overall) {
74
- "ok" { "[OK]" }
75
- "warn" { "[WARN]" }
76
- default { "[FAIL]" }
77
- }
78
-
79
- Write-Host ""
80
- Write-Host "CodexLink Telegram Doctor $emoji" -ForegroundColor Cyan
81
- Write-Host "Profil: $($Result.profile)"
82
- Write-Host "State-Ordner: $($Result.state_dir)"
83
- Write-Host ""
84
-
85
- foreach ($check in $Result.checks) {
86
- $prefix = switch ($check.status) {
87
- "ok" { "[OK]" }
88
- "warn" { "[WARN]" }
89
- default { "[FAIL]" }
90
- }
91
- $color = switch ($check.status) {
92
- "ok" { "Green" }
93
- "warn" { "Yellow" }
94
- default { "Red" }
95
- }
96
- Write-Host "$prefix $($check.name): $($check.detail)" -ForegroundColor $color
97
- }
98
-
99
- Write-Host ""
100
- if ($TokenSource) {
101
- Write-Host "Bot-Token gefunden aus: $TokenSource" -ForegroundColor DarkGray
102
- }
103
- if ($AllowedChatSource) {
104
- Write-Host "Erlaubte Chat-ID(s) gefunden aus: $AllowedChatSource" -ForegroundColor DarkGray
105
- }
106
-
107
- $failed = @($Result.checks | Where-Object { $_.status -eq "fail" })
108
- if ($failed.Count -gt 0) {
109
- Write-Host ""
110
- Write-Host "Was jetzt fehlt:" -ForegroundColor Yellow
111
- foreach ($item in $failed) {
112
- switch ($item.name) {
113
- "bot_token" { Write-Host " - Telegram Bot Token fehlt. Starte: blun-codex --profile $($Result.profile) telegram-setup" }
114
- "allowed_chat_ids" { Write-Host " - Erlaubte Chat-ID(s) fehlen. Starte: blun-codex --profile $($Result.profile) telegram-setup" }
115
- "state_dir" { Write-Host " - Der lokale Telegram-State-Ordner fehlt noch. Ein Setup-Lauf legt ihn automatisch an." }
116
- "profile_file" { Write-Host " - Das angegebene Profil existiert nicht." }
117
- "node" { Write-Host " - Node.js fehlt in PATH." }
118
- "codex" { Write-Host " - Der lokale codex-Befehl fehlt in PATH." }
119
- "telegram_plugin_root" { Write-Host " - Der Telegram-Plugin-Ordner konnte nicht gefunden werden." }
120
- default { Write-Host " - $($item.detail)" }
121
- }
122
- }
123
- }
124
-
125
- if ($Result.overall -eq "ok") {
126
- Write-Host ""
127
- Write-Host "Telegram ist sauber eingerichtet." -ForegroundColor Green
128
- Write-Host "Starten: blun-codex --profile $($Result.profile) telegram-plugin"
129
- } elseif ($Result.overall -eq "warn") {
130
- Write-Host ""
131
- Write-Host "Die Grundkonfiguration steht, aber es gibt noch Laufzeit-Hinweise." -ForegroundColor Yellow
132
- Write-Host "Das ist oft normal, wenn Telegram noch nicht aktiv gestartet wurde oder noch keine Nachricht durchlief."
67
+ param(
68
+ [object]$Result,
69
+ [string]$TokenSource,
70
+ [string]$AllowedChatSource
71
+ )
72
+
73
+ $emoji = switch ($Result.overall) {
74
+ "ok" { "[OK]" }
75
+ "warn" { "[WARN]" }
76
+ default { "[FAIL]" }
77
+ }
78
+
79
+ Write-Host ""
80
+ Write-Host "CodexLink Telegram Doctor $emoji" -ForegroundColor Cyan
81
+ Write-Host "Profil: $($Result.profile)"
82
+ Write-Host "State-Ordner: $($Result.state_dir)"
83
+ Write-Host ""
84
+
85
+ foreach ($check in $Result.checks) {
86
+ $prefix = switch ($check.status) {
87
+ "ok" { "[OK]" }
88
+ "warn" { "[WARN]" }
89
+ default { "[FAIL]" }
90
+ }
91
+ $color = switch ($check.status) {
92
+ "ok" { "Green" }
93
+ "warn" { "Yellow" }
94
+ default { "Red" }
95
+ }
96
+ Write-Host "$prefix $($check.name): $($check.detail)" -ForegroundColor $color
97
+ }
98
+
99
+ Write-Host ""
100
+ if ($TokenSource) {
101
+ Write-Host "Bot-Token gefunden aus: $TokenSource" -ForegroundColor DarkGray
102
+ }
103
+ if ($AllowedChatSource) {
104
+ Write-Host "Erlaubte Chat-ID(s) gefunden aus: $AllowedChatSource" -ForegroundColor DarkGray
105
+ }
106
+
107
+ $failed = @($Result.checks | Where-Object { $_.status -eq "fail" })
108
+ if ($failed.Count -gt 0) {
109
+ Write-Host ""
110
+ Write-Host "Was jetzt fehlt:" -ForegroundColor Yellow
111
+ foreach ($item in $failed) {
112
+ switch ($item.name) {
113
+ "bot_token" { Write-Host " - Telegram Bot Token fehlt. Starte: blun-codex --profile $($Result.profile) telegram-setup" }
114
+ "allowed_chat_ids" { Write-Host " - Chat-ID ist optional. Zum automatischen Koppeln: blun-codex --profile $($Result.profile) telegram-setup" }
115
+ "state_dir" { Write-Host " - Der lokale Telegram-State-Ordner fehlt noch. Ein Setup-Lauf legt ihn automatisch an." }
116
+ "profile_file" { Write-Host " - Das angegebene Profil existiert nicht." }
117
+ "node" { Write-Host " - Node.js fehlt in PATH." }
118
+ "codex" { Write-Host " - Der lokale codex-Befehl fehlt in PATH." }
119
+ "telegram_plugin_root" { Write-Host " - Der Telegram-Plugin-Ordner konnte nicht gefunden werden." }
120
+ default { Write-Host " - $($item.detail)" }
121
+ }
122
+ }
123
+ }
124
+
125
+ if ($Result.overall -eq "ok") {
126
+ Write-Host ""
127
+ Write-Host "Telegram ist sauber eingerichtet." -ForegroundColor Green
128
+ Write-Host "Starten: blun-codex --profile $($Result.profile) telegram-plugin"
129
+ } elseif ($Result.overall -eq "warn") {
130
+ Write-Host ""
131
+ Write-Host "Die Grundkonfiguration steht, aber es gibt noch Laufzeit-Hinweise." -ForegroundColor Yellow
132
+ Write-Host "Das ist oft normal, wenn Telegram noch nicht aktiv gestartet wurde oder noch keine Nachricht durchlief."
133
133
  }
134
134
  }
135
135
 
@@ -161,40 +161,40 @@ function Get-ProfilePath {
161
161
  $runtimeRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
162
162
  $profilePath = Get-ProfilePath -RuntimeRoot $runtimeRoot -ProfileName $Profile
163
163
  $checks = New-Object 'System.Collections.Generic.List[object]'
164
-
165
- if (Test-Path $profilePath) {
166
- Add-Check -List $checks -Name "profile_file" -Status "ok" -Detail $profilePath
167
- } else {
168
- Add-Check -List $checks -Name "profile_file" -Status "fail" -Detail ("Missing profile: " + $profilePath)
169
- }
170
-
171
- $statusRaw = & powershell -ExecutionPolicy Bypass -File (Join-Path $runtimeRoot "telegram-status.ps1") -Profile $Profile
172
- $status = $statusRaw | ConvertFrom-Json
173
-
174
- $nodeCommand = Get-Command node -ErrorAction SilentlyContinue
175
- $codexCommand = Get-Command codex -ErrorAction SilentlyContinue
176
- Add-Check -List $checks -Name "node" -Status $(if ($nodeCommand) { "ok" } else { "fail" }) -Detail $(if ($nodeCommand) { $nodeCommand.Source } else { "node not found in PATH" })
177
- Add-Check -List $checks -Name "codex" -Status $(if ($codexCommand) { "ok" } else { "fail" }) -Detail $(if ($codexCommand) { $codexCommand.Source } else { "codex not found in PATH" })
178
-
179
- if ($status.plugin_root) {
180
- Add-Check -List $checks -Name "telegram_plugin_root" -Status "ok" -Detail $status.plugin_root
181
- } else {
182
- Add-Check -List $checks -Name "telegram_plugin_root" -Status "fail" -Detail "Telegram plugin root could not be resolved."
183
- }
184
-
185
- if ($status.state_dir -and (Test-Path $status.state_dir)) {
186
- Add-Check -List $checks -Name "state_dir" -Status "ok" -Detail $status.state_dir
187
- } else {
188
- Add-Check -List $checks -Name "state_dir" -Status "fail" -Detail ("Missing state dir: " + $status.state_dir)
189
- }
190
-
191
- $activeEnvPath = Join-Path $status.state_dir ".env"
192
- $activeEnv = Read-DotEnvFile -Path $activeEnvPath
193
- $legacyEnvPath = Join-Path $env:USERPROFILE ".codex\channels\codexlink-telegram\.env"
194
- $legacyEnv = Read-DotEnvFile -Path $legacyEnvPath
195
-
196
- $tokenValue = ""
197
- $tokenSource = ""
164
+
165
+ if (Test-Path $profilePath) {
166
+ Add-Check -List $checks -Name "profile_file" -Status "ok" -Detail $profilePath
167
+ } else {
168
+ Add-Check -List $checks -Name "profile_file" -Status "fail" -Detail ("Missing profile: " + $profilePath)
169
+ }
170
+
171
+ $statusRaw = & powershell -ExecutionPolicy Bypass -File (Join-Path $runtimeRoot "telegram-status.ps1") -Profile $Profile
172
+ $status = $statusRaw | ConvertFrom-Json
173
+
174
+ $nodeCommand = Get-Command node -ErrorAction SilentlyContinue
175
+ $codexCommand = Get-Command codex -ErrorAction SilentlyContinue
176
+ Add-Check -List $checks -Name "node" -Status $(if ($nodeCommand) { "ok" } else { "fail" }) -Detail $(if ($nodeCommand) { $nodeCommand.Source } else { "node not found in PATH" })
177
+ Add-Check -List $checks -Name "codex" -Status $(if ($codexCommand) { "ok" } else { "fail" }) -Detail $(if ($codexCommand) { $codexCommand.Source } else { "codex not found in PATH" })
178
+
179
+ if ($status.plugin_root) {
180
+ Add-Check -List $checks -Name "telegram_plugin_root" -Status "ok" -Detail $status.plugin_root
181
+ } else {
182
+ Add-Check -List $checks -Name "telegram_plugin_root" -Status "fail" -Detail "Telegram plugin root could not be resolved."
183
+ }
184
+
185
+ if ($status.state_dir -and (Test-Path $status.state_dir)) {
186
+ Add-Check -List $checks -Name "state_dir" -Status "ok" -Detail $status.state_dir
187
+ } else {
188
+ Add-Check -List $checks -Name "state_dir" -Status "fail" -Detail ("Missing state dir: " + $status.state_dir)
189
+ }
190
+
191
+ $activeEnvPath = Join-Path $status.state_dir ".env"
192
+ $activeEnv = Read-DotEnvFile -Path $activeEnvPath
193
+ $legacyEnvPath = Join-Path $env:USERPROFILE ".codex\channels\codexlink-telegram\.env"
194
+ $legacyEnv = Read-DotEnvFile -Path $legacyEnvPath
195
+
196
+ $tokenValue = ""
197
+ $tokenSource = ""
198
198
  if (Test-TelegramTokenFormat -Value $activeEnv["BLUN_TELEGRAM_BOT_TOKEN"]) {
199
199
  $tokenValue = [string]$activeEnv["BLUN_TELEGRAM_BOT_TOKEN"]
200
200
  $tokenSource = "state env"
@@ -208,10 +208,10 @@ if (Test-TelegramTokenFormat -Value $activeEnv["BLUN_TELEGRAM_BOT_TOKEN"]) {
208
208
  $tokenValue = [string]$legacyEnv["TELEGRAM_BOT_TOKEN"]
209
209
  $tokenSource = "legacy env fallback legacy key"
210
210
  }
211
- Add-Check -List $checks -Name "bot_token" -Status $(if ($tokenValue) { "ok" } else { "fail" }) -Detail $(if ($tokenValue) { $tokenSource } else { "No valid BLUN_TELEGRAM_BOT_TOKEN found." })
212
-
213
- $allowedChatIds = ""
214
- $allowedChatSource = ""
211
+ Add-Check -List $checks -Name "bot_token" -Status $(if ($tokenValue) { "ok" } else { "fail" }) -Detail $(if ($tokenValue) { $tokenSource } else { "No valid BLUN_TELEGRAM_BOT_TOKEN found." })
212
+
213
+ $allowedChatIds = ""
214
+ $allowedChatSource = ""
215
215
  if (Test-AllowedChatIdsFormat -Value $activeEnv["BLUN_TELEGRAM_ALLOWED_CHAT_ID"]) {
216
216
  $allowedChatIds = [string]$activeEnv["BLUN_TELEGRAM_ALLOWED_CHAT_ID"]
217
217
  $allowedChatSource = "state env"
@@ -226,7 +226,7 @@ if (Test-AllowedChatIdsFormat -Value $activeEnv["BLUN_TELEGRAM_ALLOWED_CHAT_ID"]
226
226
  $allowedChatSource = "legacy env fallback legacy key"
227
227
  }
228
228
  Add-Check -List $checks -Name "allowed_chat_ids" -Status $(if ($allowedChatIds) { "ok" } else { "warn" }) -Detail $(if ($allowedChatIds) { $allowedChatIds } else { "No allowlist set. Telegram currently accepts any chat the bot can see." })
229
-
229
+
230
230
  Add-Check -List $checks -Name "app_server_ws" -Status $(if ($status.active_ws) { "ok" } else { "warn" }) -Detail $(if ($status.active_ws) { $status.active_ws } else { "No active websocket recorded." })
231
231
  Add-Check -List $checks -Name "dispatch_mode" -Status $(if ($status.dispatch_mode -eq "deferred") { "ok" } else { "warn" }) -Detail ("mode=" + [string]$status.dispatch_mode + " cooldown_ms=" + [string]$status.idle_cooldown_ms + " pending_reply_timeout_ms=" + [string]$status.pending_reply_timeout_ms)
232
232
  Add-Check -List $checks -Name "bound_thread" -Status $(if ($status.active_thread_id) { "ok" } else { "warn" }) -Detail $(if ($status.active_thread_id) { $status.active_thread_id } else { "No active thread bound yet." })
@@ -235,48 +235,48 @@ Add-Check -List $checks -Name "queue_notifier" -Status $(if (($null -eq $status.
235
235
  Add-Check -List $checks -Name "poller" -Status $(if ($status.poller_alive) { "ok" } else { "warn" }) -Detail ("pid=" + [string]$status.poller_pid + " alive=" + [string]$status.poller_alive)
236
236
  Add-Check -List $checks -Name "dispatcher" -Status $(if ($status.dispatcher_alive) { "ok" } else { "warn" }) -Detail ("pid=" + [string]$status.dispatcher_pid + " alive=" + [string]$status.dispatcher_alive)
237
237
  Add-Check -List $checks -Name "responder" -Status $(if ($status.responder_alive) { "ok" } else { "warn" }) -Detail ("pid=" + [string]$status.responder_pid + " alive=" + [string]$status.responder_alive)
238
-
239
- if ($status.last_inbound) {
240
- $lastInboundSummary = [string]::Format(
241
- "chat={0} message={1} type={2} thread={3}",
242
- $status.last_inbound.chatId,
243
- $status.last_inbound.messageId,
244
- $status.last_inbound.chatType,
245
- $(if ($status.last_inbound.telegramThreadId) { $status.last_inbound.telegramThreadId } else { "-" })
246
- )
247
- Add-Check -List $checks -Name "last_inbound" -Status "ok" -Detail $lastInboundSummary
248
- } else {
249
- Add-Check -List $checks -Name "last_inbound" -Status "warn" -Detail "No inbound Telegram message recorded yet."
250
- }
251
-
252
- if ($status.last_outbound) {
253
- $lastOutboundSummary = [string]::Format(
254
- "chat={0} message={1} reply_to={2} thread={3}",
255
- $status.last_outbound.chatId,
256
- $status.last_outbound.messageId,
257
- $(if ($status.last_outbound.replyToMessageId) { $status.last_outbound.replyToMessageId } else { "-" }),
258
- $(if ($status.last_outbound.telegramThreadId) { $status.last_outbound.telegramThreadId } else { "-" })
259
- )
260
- Add-Check -List $checks -Name "last_outbound" -Status "ok" -Detail $lastOutboundSummary
261
- } else {
262
- Add-Check -List $checks -Name "last_outbound" -Status "warn" -Detail "No outbound Telegram message recorded yet."
263
- }
264
-
238
+
239
+ if ($status.last_inbound) {
240
+ $lastInboundSummary = [string]::Format(
241
+ "chat={0} message={1} type={2} thread={3}",
242
+ $status.last_inbound.chatId,
243
+ $status.last_inbound.messageId,
244
+ $status.last_inbound.chatType,
245
+ $(if ($status.last_inbound.telegramThreadId) { $status.last_inbound.telegramThreadId } else { "-" })
246
+ )
247
+ Add-Check -List $checks -Name "last_inbound" -Status "ok" -Detail $lastInboundSummary
248
+ } else {
249
+ Add-Check -List $checks -Name "last_inbound" -Status "warn" -Detail "No inbound Telegram message recorded yet."
250
+ }
251
+
252
+ if ($status.last_outbound) {
253
+ $lastOutboundSummary = [string]::Format(
254
+ "chat={0} message={1} reply_to={2} thread={3}",
255
+ $status.last_outbound.chatId,
256
+ $status.last_outbound.messageId,
257
+ $(if ($status.last_outbound.replyToMessageId) { $status.last_outbound.replyToMessageId } else { "-" }),
258
+ $(if ($status.last_outbound.telegramThreadId) { $status.last_outbound.telegramThreadId } else { "-" })
259
+ )
260
+ Add-Check -List $checks -Name "last_outbound" -Status "ok" -Detail $lastOutboundSummary
261
+ } else {
262
+ Add-Check -List $checks -Name "last_outbound" -Status "warn" -Detail "No outbound Telegram message recorded yet."
263
+ }
264
+
265
265
  Add-Check -List $checks -Name "queue" -Status $(if (([int]$status.queue_depth -eq 0) -and ([int]$status.pending_reply_depth -eq 0)) { "ok" } else { "warn" }) -Detail ("queued=" + $status.queue_depth + " ambient=" + $status.ambient_queue_depth + " parked=" + $status.parked_queue_depth + " submitted=" + $status.submitted_depth + " pending_replies=" + $status.pending_reply_depth + " expired_pending_replies=" + $status.expired_pending_reply_depth)
266
-
267
- $result = [ordered]@{
268
- profile = $status.profile
269
- overall = Get-OverallStatus -Checks $checks
270
- runtime_root = $runtimeRoot
271
- state_dir = $status.state_dir
272
- plugin_root = $status.plugin_root
273
- checks = $checks
274
- status = $status
275
- }
276
-
277
- if ($Json) {
278
- $result | ConvertTo-Json -Depth 8
279
- exit 0
280
- }
281
-
282
- Write-DoctorReport -Result $result -TokenSource $tokenSource -AllowedChatSource $allowedChatSource
266
+
267
+ $result = [ordered]@{
268
+ profile = $status.profile
269
+ overall = Get-OverallStatus -Checks $checks
270
+ runtime_root = $runtimeRoot
271
+ state_dir = $status.state_dir
272
+ plugin_root = $status.plugin_root
273
+ checks = $checks
274
+ status = $status
275
+ }
276
+
277
+ if ($Json) {
278
+ $result | ConvertTo-Json -Depth 8
279
+ exit 0
280
+ }
281
+
282
+ Write-DoctorReport -Result $result -TokenSource $tokenSource -AllowedChatSource $allowedChatSource
@@ -1906,7 +1906,7 @@ async function sendOutboundChunks(config, state, options) {
1906
1906
  } else if (chatType === "private" && user) {
1907
1907
  label = `Antwort an ${user}`;
1908
1908
  }
1909
- state.lastUiNotice = {
1909
+ state.lastOutboundUiNotice = {
1910
1910
  ts: nowIso(),
1911
1911
  kind: "outbound",
1912
1912
  text: `${label}: ${preview}`
@@ -55,31 +55,31 @@ export function saveJson(path, value) {
55
55
 
56
56
  throw lastError || new Error(`Failed to save JSON file: ${path}`);
57
57
  }
58
-
59
- export function appendJsonl(path, value) {
60
- appendFileSync(path, `${JSON.stringify(value)}\n`, "utf8");
61
- }
62
-
63
- export function appendLog(path, message) {
64
- appendFileSync(path, `${nowIso()} ${message}\n`, "utf8");
65
- }
66
-
67
- export function readTail(path, lines = 20) {
68
- if (!existsSync(path)) {
69
- return [];
70
- }
71
- const text = readFileSync(path, "utf8");
72
- return text.split(/\r?\n/).filter(Boolean).slice(-lines);
73
- }
74
-
75
- export function defaultState() {
76
- return {
77
- offset: 0,
78
- currentThreadId: "",
79
- queue: [],
80
- pendingReplies: [],
81
- replyOffsets: {},
82
- replyBuffers: {},
58
+
59
+ export function appendJsonl(path, value) {
60
+ appendFileSync(path, `${JSON.stringify(value)}\n`, "utf8");
61
+ }
62
+
63
+ export function appendLog(path, message) {
64
+ appendFileSync(path, `${nowIso()} ${message}\n`, "utf8");
65
+ }
66
+
67
+ export function readTail(path, lines = 20) {
68
+ if (!existsSync(path)) {
69
+ return [];
70
+ }
71
+ const text = readFileSync(path, "utf8");
72
+ return text.split(/\r?\n/).filter(Boolean).slice(-lines);
73
+ }
74
+
75
+ export function defaultState() {
76
+ return {
77
+ offset: 0,
78
+ currentThreadId: "",
79
+ queue: [],
80
+ pendingReplies: [],
81
+ replyOffsets: {},
82
+ replyBuffers: {},
83
83
  lastInbound: null,
84
84
  lastOutbound: null,
85
85
  lastUiNotice: null,