@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.
- package/README.md +236 -230
- package/blun-codex.ps1 +140 -140
- package/package.json +40 -40
- package/start-codex-agent.ps1 +727 -727
- package/telegram-doctor.ps1 +214 -214
- package/telegram-plugin/lib/bridge.js +1 -1
- package/telegram-plugin/lib/storage.js +25 -25
- package/telegram-setup.ps1 +145 -144
- package/telegram-status.ps1 +256 -256
- package/telegram-title-embed.ps1 +120 -107
- package/telegram-title-watcher.ps1 +110 -103
package/telegram-title-embed.ps1
CHANGED
|
@@ -7,15 +7,15 @@ param(
|
|
|
7
7
|
|
|
8
8
|
[string]$LogFile = ""
|
|
9
9
|
)
|
|
10
|
-
|
|
11
|
-
$ErrorActionPreference = "SilentlyContinue"
|
|
12
|
-
|
|
13
|
-
if (-not ("BlunEmbeddedQueueTitleWatcher" -as [type])) {
|
|
14
|
-
Add-Type -ReferencedAssemblies "System.Web.Extensions" -TypeDefinition @"
|
|
15
|
-
using System;
|
|
16
|
-
using System.Collections;
|
|
17
|
-
using System.Collections.Generic;
|
|
18
|
-
using System.IO;
|
|
10
|
+
|
|
11
|
+
$ErrorActionPreference = "SilentlyContinue"
|
|
12
|
+
|
|
13
|
+
if (-not ("BlunEmbeddedQueueTitleWatcher" -as [type])) {
|
|
14
|
+
Add-Type -ReferencedAssemblies "System.Web.Extensions" -TypeDefinition @"
|
|
15
|
+
using System;
|
|
16
|
+
using System.Collections;
|
|
17
|
+
using System.Collections.Generic;
|
|
18
|
+
using System.IO;
|
|
19
19
|
using System.Threading;
|
|
20
20
|
using System.Web.Script.Serialization;
|
|
21
21
|
|
|
@@ -48,14 +48,14 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
48
48
|
TrySetTitle(_baseTitle);
|
|
49
49
|
if (_timer != null)
|
|
50
50
|
{
|
|
51
|
-
_timer.Dispose();
|
|
52
|
-
}
|
|
53
|
-
_timer = new Timer(_ => Tick(), null, 0, 900);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
private static void Tick()
|
|
58
|
-
{
|
|
51
|
+
_timer.Dispose();
|
|
52
|
+
}
|
|
53
|
+
_timer = new Timer(_ => Tick(), null, 0, 900);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private static void Tick()
|
|
58
|
+
{
|
|
59
59
|
try
|
|
60
60
|
{
|
|
61
61
|
string title;
|
|
@@ -91,15 +91,15 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
91
91
|
WriteLog("TITLE_ERROR");
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
private static void TryWriteNotice(string notice)
|
|
96
|
-
{
|
|
97
|
-
var normalized = notice ?? "";
|
|
98
|
-
if (string.Equals(normalized, _lastNotice, StringComparison.Ordinal))
|
|
99
|
-
{
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
94
|
+
|
|
95
|
+
private static void TryWriteNotice(string notice)
|
|
96
|
+
{
|
|
97
|
+
var normalized = notice ?? "";
|
|
98
|
+
if (string.Equals(normalized, _lastNotice, StringComparison.Ordinal))
|
|
99
|
+
{
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
103
|
try
|
|
104
104
|
{
|
|
105
105
|
// Do not write background queue notices into the interactive Codex
|
|
@@ -131,8 +131,21 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
131
131
|
|
|
132
132
|
try
|
|
133
133
|
{
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
var mode = Environment.GetEnvironmentVariable("BLUN_TELEGRAM_CONSOLE_UI_NOTICES") ?? "";
|
|
135
|
+
var disabled = string.Equals(mode, "0", StringComparison.OrdinalIgnoreCase)
|
|
136
|
+
|| string.Equals(mode, "false", StringComparison.OrdinalIgnoreCase)
|
|
137
|
+
|| string.Equals(mode, "no", StringComparison.OrdinalIgnoreCase)
|
|
138
|
+
|| string.Equals(mode, "off", StringComparison.OrdinalIgnoreCase);
|
|
139
|
+
var allowAll = string.Equals(mode, "all", StringComparison.OrdinalIgnoreCase)
|
|
140
|
+
|| string.Equals(mode, "1", StringComparison.OrdinalIgnoreCase)
|
|
141
|
+
|| string.Equals(mode, "true", StringComparison.OrdinalIgnoreCase)
|
|
142
|
+
|| string.Equals(mode, "yes", StringComparison.OrdinalIgnoreCase)
|
|
143
|
+
|| string.Equals(mode, "on", StringComparison.OrdinalIgnoreCase);
|
|
144
|
+
if (!disabled && (allowAll || string.Equals(normalizedKind, "inbound", StringComparison.OrdinalIgnoreCase)))
|
|
145
|
+
{
|
|
146
|
+
Console.WriteLine("");
|
|
147
|
+
Console.WriteLine("[Telegram] " + normalized);
|
|
148
|
+
}
|
|
136
149
|
}
|
|
137
150
|
catch
|
|
138
151
|
{
|
|
@@ -154,13 +167,13 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
154
167
|
{
|
|
155
168
|
return;
|
|
156
169
|
}
|
|
157
|
-
|
|
158
|
-
var raw = File.ReadAllText(_stateFile);
|
|
159
|
-
if (string.IsNullOrWhiteSpace(raw))
|
|
160
|
-
{
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
|
|
170
|
+
|
|
171
|
+
var raw = File.ReadAllText(_stateFile);
|
|
172
|
+
if (string.IsNullOrWhiteSpace(raw))
|
|
173
|
+
{
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
164
177
|
var serializer = new JavaScriptSerializer();
|
|
165
178
|
var root = serializer.DeserializeObject(raw) as Dictionary<string, object>;
|
|
166
179
|
if (root == null || !root.ContainsKey("queue"))
|
|
@@ -210,20 +223,20 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
210
223
|
var entry = item as Dictionary<string, object>;
|
|
211
224
|
if (entry == null)
|
|
212
225
|
{
|
|
213
|
-
continue;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
var status = GetString(entry, "status");
|
|
217
|
-
if (!string.Equals(status, "queued", StringComparison.OrdinalIgnoreCase))
|
|
218
|
-
{
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
var relevance = GetString(entry, "relevance");
|
|
223
|
-
if (string.Equals(relevance, "ambient", StringComparison.OrdinalIgnoreCase) && IsOlderThan(entry, _ambientTtlMs))
|
|
224
|
-
{
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
var status = GetString(entry, "status");
|
|
230
|
+
if (!string.Equals(status, "queued", StringComparison.OrdinalIgnoreCase))
|
|
231
|
+
{
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
var relevance = GetString(entry, "relevance");
|
|
236
|
+
if (string.Equals(relevance, "ambient", StringComparison.OrdinalIgnoreCase) && IsOlderThan(entry, _ambientTtlMs))
|
|
237
|
+
{
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
227
240
|
|
|
228
241
|
total += 1;
|
|
229
242
|
CountRelevance(entry, ref direct, ref ambient, ref escalation);
|
|
@@ -236,8 +249,8 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
236
249
|
|
|
237
250
|
if (total == 0)
|
|
238
251
|
{
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
241
254
|
|
|
242
255
|
var parts = new List<string> { "Q:" + total.ToString() };
|
|
243
256
|
if (pending > 0) parts.Add("P:" + pending.ToString());
|
|
@@ -252,15 +265,15 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
252
265
|
if (direct > 0) noticeParts.Add("direct " + direct.ToString());
|
|
253
266
|
if (ambient > 0) noticeParts.Add("group " + ambient.ToString());
|
|
254
267
|
if (escalation > 0) noticeParts.Add("escalation " + escalation.ToString());
|
|
255
|
-
notice = string.Join(" | ", noticeParts.ToArray());
|
|
256
|
-
if (string.IsNullOrWhiteSpace(preview))
|
|
257
|
-
{
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
title = title + " | " + preview;
|
|
261
|
-
notice = notice + " | " + preview;
|
|
262
|
-
}
|
|
263
|
-
|
|
268
|
+
notice = string.Join(" | ", noticeParts.ToArray());
|
|
269
|
+
if (string.IsNullOrWhiteSpace(preview))
|
|
270
|
+
{
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
title = title + " | " + preview;
|
|
274
|
+
notice = notice + " | " + preview;
|
|
275
|
+
}
|
|
276
|
+
|
|
264
277
|
private static object[] AsObjects(object value)
|
|
265
278
|
{
|
|
266
279
|
var arr = value as object[];
|
|
@@ -273,16 +286,16 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
273
286
|
{
|
|
274
287
|
return list.ToArray();
|
|
275
288
|
}
|
|
276
|
-
return new object[0];
|
|
277
|
-
}
|
|
278
|
-
|
|
289
|
+
return new object[0];
|
|
290
|
+
}
|
|
291
|
+
|
|
279
292
|
private static string GetString(Dictionary<string, object> entry, string key)
|
|
280
293
|
{
|
|
281
|
-
if (!entry.ContainsKey(key) || entry[key] == null)
|
|
282
|
-
{
|
|
283
|
-
return "";
|
|
284
|
-
}
|
|
285
|
-
return Convert.ToString(entry[key]) ?? "";
|
|
294
|
+
if (!entry.ContainsKey(key) || entry[key] == null)
|
|
295
|
+
{
|
|
296
|
+
return "";
|
|
297
|
+
}
|
|
298
|
+
return Convert.ToString(entry[key]) ?? "";
|
|
286
299
|
}
|
|
287
300
|
|
|
288
301
|
private static void CountRelevance(Dictionary<string, object> entry, ref int direct, ref int ambient, ref int escalation)
|
|
@@ -337,7 +350,7 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
337
350
|
}
|
|
338
351
|
return state + text;
|
|
339
352
|
}
|
|
340
|
-
|
|
353
|
+
|
|
341
354
|
private static string Normalize(string value, int maxLength)
|
|
342
355
|
{
|
|
343
356
|
if (string.IsNullOrWhiteSpace(value))
|
|
@@ -350,11 +363,11 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
350
363
|
{
|
|
351
364
|
compact = compact.Replace(" ", " ");
|
|
352
365
|
}
|
|
353
|
-
|
|
354
|
-
if (compact.Length <= maxLength)
|
|
355
|
-
{
|
|
356
|
-
return compact;
|
|
357
|
-
}
|
|
366
|
+
|
|
367
|
+
if (compact.Length <= maxLength)
|
|
368
|
+
{
|
|
369
|
+
return compact;
|
|
370
|
+
}
|
|
358
371
|
|
|
359
372
|
return compact.Substring(0, Math.Max(0, maxLength - 3)).TrimEnd() + "...";
|
|
360
373
|
}
|
|
@@ -384,21 +397,21 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
384
397
|
.Replace("ü", "ü")
|
|
385
398
|
.Replace("ß", "ß");
|
|
386
399
|
}
|
|
387
|
-
|
|
400
|
+
|
|
388
401
|
private static bool IsOlderThan(Dictionary<string, object> entry, long ttlMs)
|
|
389
402
|
{
|
|
390
|
-
if (!entry.ContainsKey("ts") || entry["ts"] == null)
|
|
391
|
-
{
|
|
392
|
-
return true;
|
|
393
|
-
}
|
|
394
|
-
try
|
|
395
|
-
{
|
|
396
|
-
var parsed = DateTimeOffset.Parse(Convert.ToString(entry["ts"]) ?? "");
|
|
397
|
-
return (DateTimeOffset.UtcNow - parsed.ToUniversalTime()).TotalMilliseconds >= ttlMs;
|
|
398
|
-
}
|
|
399
|
-
catch
|
|
400
|
-
{
|
|
401
|
-
return true;
|
|
403
|
+
if (!entry.ContainsKey("ts") || entry["ts"] == null)
|
|
404
|
+
{
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
try
|
|
408
|
+
{
|
|
409
|
+
var parsed = DateTimeOffset.Parse(Convert.ToString(entry["ts"]) ?? "");
|
|
410
|
+
return (DateTimeOffset.UtcNow - parsed.ToUniversalTime()).TotalMilliseconds >= ttlMs;
|
|
411
|
+
}
|
|
412
|
+
catch
|
|
413
|
+
{
|
|
414
|
+
return true;
|
|
402
415
|
}
|
|
403
416
|
}
|
|
404
417
|
|
|
@@ -419,24 +432,24 @@ public static class BlunEmbeddedQueueTitleWatcher
|
|
|
419
432
|
}
|
|
420
433
|
"@
|
|
421
434
|
}
|
|
422
|
-
|
|
423
|
-
$ambientTtlMs = 600000
|
|
424
|
-
try {
|
|
425
|
-
$stateDir = Split-Path -Parent $StateFile
|
|
426
|
-
$envPath = Join-Path $stateDir ".env"
|
|
427
|
-
if (Test-Path $envPath) {
|
|
428
|
-
foreach ($line in (Get-Content -Path $envPath)) {
|
|
429
|
-
if (-not $line) { continue }
|
|
430
|
-
if ($line.Trim().StartsWith("#")) { continue }
|
|
431
|
-
$parts = $line -split "=", 2
|
|
432
|
-
if ($parts.Count -ne 2) { continue }
|
|
433
|
-
if ($parts[0].Trim() -eq "BLUN_TELEGRAM_AMBIENT_QUEUE_TTL_MS") {
|
|
434
|
-
$ambientTtlMs = [int64]$parts[1].Trim()
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
} catch {
|
|
439
|
-
$ambientTtlMs = 600000
|
|
440
|
-
}
|
|
441
|
-
|
|
435
|
+
|
|
436
|
+
$ambientTtlMs = 600000
|
|
437
|
+
try {
|
|
438
|
+
$stateDir = Split-Path -Parent $StateFile
|
|
439
|
+
$envPath = Join-Path $stateDir ".env"
|
|
440
|
+
if (Test-Path $envPath) {
|
|
441
|
+
foreach ($line in (Get-Content -Path $envPath)) {
|
|
442
|
+
if (-not $line) { continue }
|
|
443
|
+
if ($line.Trim().StartsWith("#")) { continue }
|
|
444
|
+
$parts = $line -split "=", 2
|
|
445
|
+
if ($parts.Count -ne 2) { continue }
|
|
446
|
+
if ($parts[0].Trim() -eq "BLUN_TELEGRAM_AMBIENT_QUEUE_TTL_MS") {
|
|
447
|
+
$ambientTtlMs = [int64]$parts[1].Trim()
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
} catch {
|
|
452
|
+
$ambientTtlMs = 600000
|
|
453
|
+
}
|
|
454
|
+
|
|
442
455
|
[BlunEmbeddedQueueTitleWatcher]::Start($StateFile, $BaseTitle, $ambientTtlMs, $LogFile)
|
|
@@ -6,18 +6,18 @@ param(
|
|
|
6
6
|
|
|
7
7
|
[Parameter(Mandatory = $true)]
|
|
8
8
|
[string]$RuntimeFile,
|
|
9
|
-
|
|
10
|
-
[Parameter(Mandatory = $true)]
|
|
11
|
-
[string]$StateFile,
|
|
12
|
-
|
|
13
|
-
[Parameter(Mandatory = $true)]
|
|
14
|
-
[string]$BaseTitle,
|
|
15
|
-
|
|
16
|
-
[string]$LogFile = ""
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
$ErrorActionPreference = "SilentlyContinue"
|
|
20
|
-
|
|
9
|
+
|
|
10
|
+
[Parameter(Mandatory = $true)]
|
|
11
|
+
[string]$StateFile,
|
|
12
|
+
|
|
13
|
+
[Parameter(Mandatory = $true)]
|
|
14
|
+
[string]$BaseTitle,
|
|
15
|
+
|
|
16
|
+
[string]$LogFile = ""
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
$ErrorActionPreference = "SilentlyContinue"
|
|
20
|
+
|
|
21
21
|
if (-not ("CodexLink.NativeMethods" -as [type])) {
|
|
22
22
|
Add-Type -TypeDefinition @"
|
|
23
23
|
using System;
|
|
@@ -45,28 +45,28 @@ namespace CodexLink
|
|
|
45
45
|
}
|
|
46
46
|
"@
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
function Try-ReadJson {
|
|
50
|
-
param([string]$Path)
|
|
51
|
-
if (-not (Test-Path $Path)) { return $null }
|
|
52
|
-
try {
|
|
53
|
-
$raw = Get-Content -Raw -Path $Path
|
|
54
|
-
if ($null -eq $raw) { return $null }
|
|
55
|
-
return ($raw -replace "^\uFEFF", "") | ConvertFrom-Json
|
|
56
|
-
} catch {
|
|
57
|
-
return $null
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function Write-WatcherLog {
|
|
62
|
-
param([string]$Message)
|
|
63
|
-
if (-not $LogFile) { return }
|
|
64
|
-
try {
|
|
65
|
-
Add-Content -Path $LogFile -Value (((Get-Date).ToUniversalTime().ToString("o")) + " " + $Message) -Encoding UTF8
|
|
66
|
-
} catch {
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
48
|
+
|
|
49
|
+
function Try-ReadJson {
|
|
50
|
+
param([string]$Path)
|
|
51
|
+
if (-not (Test-Path $Path)) { return $null }
|
|
52
|
+
try {
|
|
53
|
+
$raw = Get-Content -Raw -Path $Path
|
|
54
|
+
if ($null -eq $raw) { return $null }
|
|
55
|
+
return ($raw -replace "^\uFEFF", "") | ConvertFrom-Json
|
|
56
|
+
} catch {
|
|
57
|
+
return $null
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function Write-WatcherLog {
|
|
62
|
+
param([string]$Message)
|
|
63
|
+
if (-not $LogFile) { return }
|
|
64
|
+
try {
|
|
65
|
+
Add-Content -Path $LogFile -Value (((Get-Date).ToUniversalTime().ToString("o")) + " " + $Message) -Encoding UTF8
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
70
|
function Test-PidAlive {
|
|
71
71
|
param([int]$ProcId)
|
|
72
72
|
if ($ProcId -le 0) { return $false }
|
|
@@ -103,14 +103,14 @@ function Get-EffectiveAttachPid {
|
|
|
103
103
|
|
|
104
104
|
return 0
|
|
105
105
|
}
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
function Normalize-Preview {
|
|
108
108
|
param([string]$Value, [int]$MaxLength = 44)
|
|
109
|
-
$text = [string]$Value
|
|
110
|
-
$text = $text -replace "\s+", " "
|
|
111
|
-
$text = $text.Trim()
|
|
112
|
-
if (-not $text) { return "" }
|
|
113
|
-
if ($text.Length -le $MaxLength) { return $text }
|
|
109
|
+
$text = [string]$Value
|
|
110
|
+
$text = $text -replace "\s+", " "
|
|
111
|
+
$text = $text.Trim()
|
|
112
|
+
if (-not $text) { return "" }
|
|
113
|
+
if ($text.Length -le $MaxLength) { return $text }
|
|
114
114
|
return ($text.Substring(0, [Math]::Max(0, $MaxLength - 3)).TrimEnd() + "...")
|
|
115
115
|
}
|
|
116
116
|
|
|
@@ -178,18 +178,18 @@ function Format-QueuePreview {
|
|
|
178
178
|
}
|
|
179
179
|
return "${prefix}${text}"
|
|
180
180
|
}
|
|
181
|
-
|
|
181
|
+
|
|
182
182
|
function Get-QueueTitle {
|
|
183
183
|
param(
|
|
184
184
|
[object]$State,
|
|
185
185
|
[string]$FallbackTitle,
|
|
186
186
|
[int]$IdleCooldownMs = 15000
|
|
187
187
|
)
|
|
188
|
-
|
|
189
|
-
if ($null -eq $State -or $null -eq $State.queue) {
|
|
190
|
-
return $FallbackTitle
|
|
191
|
-
}
|
|
192
|
-
|
|
188
|
+
|
|
189
|
+
if ($null -eq $State -or $null -eq $State.queue) {
|
|
190
|
+
return $FallbackTitle
|
|
191
|
+
}
|
|
192
|
+
|
|
193
193
|
$queued = @($State.queue | Where-Object { $_.status -eq "queued" })
|
|
194
194
|
$pendingReplies = @(Get-OpenPendingReplies -State $State)
|
|
195
195
|
$totalWaiting = $queued.Count + $pendingReplies.Count
|
|
@@ -212,8 +212,8 @@ function Get-QueueTitle {
|
|
|
212
212
|
if ($pendingCount -gt 0) { $parts += "P:$pendingCount" }
|
|
213
213
|
if ($directCount -gt 0) { $parts += "D:$directCount" }
|
|
214
214
|
if ($ambientCount -gt 0) { $parts += "G:$ambientCount" }
|
|
215
|
-
if ($escalationCount -gt 0) { $parts += "E:$escalationCount" }
|
|
216
|
-
|
|
215
|
+
if ($escalationCount -gt 0) { $parts += "E:$escalationCount" }
|
|
216
|
+
|
|
217
217
|
$summary = ($parts -join " ")
|
|
218
218
|
$waitReason = Get-QueueWaitReason -State $State -IdleCooldownMs $IdleCooldownMs
|
|
219
219
|
if ($preview) {
|
|
@@ -221,7 +221,7 @@ function Get-QueueTitle {
|
|
|
221
221
|
}
|
|
222
222
|
return "$FallbackTitle | $summary | $waitReason"
|
|
223
223
|
}
|
|
224
|
-
|
|
224
|
+
|
|
225
225
|
function Update-ConsoleTitle {
|
|
226
226
|
param([string]$Title)
|
|
227
227
|
try {
|
|
@@ -235,11 +235,11 @@ function Update-ConsoleTitle {
|
|
|
235
235
|
$updated = [CodexLink.NativeMethods]::SetConsoleTitle($Title)
|
|
236
236
|
[void][CodexLink.NativeMethods]::FreeConsole()
|
|
237
237
|
return $updated
|
|
238
|
-
} catch {
|
|
239
|
-
return $false
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
238
|
+
} catch {
|
|
239
|
+
return $false
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
243
|
function Write-ConsoleNotice {
|
|
244
244
|
param([string]$Notice)
|
|
245
245
|
if ($env:BLUN_TELEGRAM_CONSOLE_NOTICES -ne "1") {
|
|
@@ -253,15 +253,15 @@ function Write-ConsoleNotice {
|
|
|
253
253
|
Write-WatcherLog ("WAIT attach_console_failed_notice target=" + $targetPid)
|
|
254
254
|
return $false
|
|
255
255
|
}
|
|
256
|
-
$handle = [CodexLink.NativeMethods]::GetStdHandle(-11)
|
|
257
|
-
if ($handle -eq [IntPtr]::Zero -or $handle -eq [IntPtr](-1)) {
|
|
258
|
-
[void][CodexLink.NativeMethods]::FreeConsole()
|
|
259
|
-
return $false
|
|
260
|
-
}
|
|
261
|
-
$line = "[CodexLink Queue] $Notice`r`n"
|
|
262
|
-
[uint32]$written = 0
|
|
263
|
-
$ok = [CodexLink.NativeMethods]::WriteConsole($handle, $line, [uint32]$line.Length, [ref]$written, [IntPtr]::Zero)
|
|
264
|
-
[void][CodexLink.NativeMethods]::FreeConsole()
|
|
256
|
+
$handle = [CodexLink.NativeMethods]::GetStdHandle(-11)
|
|
257
|
+
if ($handle -eq [IntPtr]::Zero -or $handle -eq [IntPtr](-1)) {
|
|
258
|
+
[void][CodexLink.NativeMethods]::FreeConsole()
|
|
259
|
+
return $false
|
|
260
|
+
}
|
|
261
|
+
$line = "[CodexLink Queue] $Notice`r`n"
|
|
262
|
+
[uint32]$written = 0
|
|
263
|
+
$ok = [CodexLink.NativeMethods]::WriteConsole($handle, $line, [uint32]$line.Length, [ref]$written, [IntPtr]::Zero)
|
|
264
|
+
[void][CodexLink.NativeMethods]::FreeConsole()
|
|
265
265
|
return $ok
|
|
266
266
|
} catch {
|
|
267
267
|
return $false
|
|
@@ -273,6 +273,13 @@ function Write-ConsoleUiNotice {
|
|
|
273
273
|
[string]$Kind,
|
|
274
274
|
[string]$Notice
|
|
275
275
|
)
|
|
276
|
+
$mode = [string]$env:BLUN_TELEGRAM_CONSOLE_UI_NOTICES
|
|
277
|
+
$disabled = $mode -eq "0" -or $mode -ieq "false" -or $mode -ieq "no" -or $mode -ieq "off"
|
|
278
|
+
$allowAll = $mode -ieq "all" -or $mode -eq "1" -or $mode -ieq "true" -or $mode -ieq "yes" -or $mode -ieq "on"
|
|
279
|
+
$isInbound = [string]::Equals($Kind, "inbound", [System.StringComparison]::OrdinalIgnoreCase)
|
|
280
|
+
if ($disabled -or (-not $allowAll -and -not $isInbound)) {
|
|
281
|
+
return $false
|
|
282
|
+
}
|
|
276
283
|
try {
|
|
277
284
|
[void][CodexLink.NativeMethods]::FreeConsole()
|
|
278
285
|
$targetPid = Get-EffectiveAttachPid
|
|
@@ -318,17 +325,17 @@ function Get-UiNoticeSnapshot {
|
|
|
318
325
|
text = $text
|
|
319
326
|
}
|
|
320
327
|
}
|
|
321
|
-
|
|
328
|
+
|
|
322
329
|
function Get-QueueNotice {
|
|
323
330
|
param(
|
|
324
331
|
[object]$State,
|
|
325
332
|
[int]$IdleCooldownMs = 15000
|
|
326
333
|
)
|
|
327
|
-
|
|
328
|
-
if ($null -eq $State -or $null -eq $State.queue) {
|
|
329
|
-
return ""
|
|
330
|
-
}
|
|
331
|
-
|
|
334
|
+
|
|
335
|
+
if ($null -eq $State -or $null -eq $State.queue) {
|
|
336
|
+
return ""
|
|
337
|
+
}
|
|
338
|
+
|
|
332
339
|
$queued = @($State.queue | Where-Object { $_.status -eq "queued" })
|
|
333
340
|
$pendingReplies = @(Get-OpenPendingReplies -State $State)
|
|
334
341
|
$totalWaiting = $queued.Count + $pendingReplies.Count
|
|
@@ -365,7 +372,7 @@ function Get-QueueNotice {
|
|
|
365
372
|
$parts += $preview
|
|
366
373
|
}
|
|
367
374
|
}
|
|
368
|
-
|
|
375
|
+
|
|
369
376
|
return ($parts -join " | ")
|
|
370
377
|
}
|
|
371
378
|
|
|
@@ -396,48 +403,48 @@ $lastNotice = ""
|
|
|
396
403
|
$lastUiKind = ""
|
|
397
404
|
$lastUiNotice = ""
|
|
398
405
|
Write-WatcherLog "START"
|
|
399
|
-
|
|
400
|
-
while ($true) {
|
|
401
|
-
if (-not (Test-PidAlive -ProcId $FrontendPid)) {
|
|
402
|
-
Write-WatcherLog "EXIT frontend_dead"
|
|
403
|
-
break
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
$runtime = Try-ReadJson -Path $RuntimeFile
|
|
407
|
-
if ($null -eq $runtime) {
|
|
408
|
-
Write-WatcherLog "WAIT runtime_missing"
|
|
409
|
-
Start-Sleep -Milliseconds 300
|
|
410
|
-
continue
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
$runtimeOwnerPid = 0
|
|
414
|
-
try { $runtimeOwnerPid = [int]$runtime.frontend_host_pid } catch { $runtimeOwnerPid = 0 }
|
|
415
|
-
if ($runtimeOwnerPid -ne $FrontendPid) {
|
|
416
|
-
Write-WatcherLog ("EXIT owner_changed owner=" + $runtimeOwnerPid)
|
|
417
|
-
break
|
|
418
|
-
}
|
|
419
|
-
|
|
406
|
+
|
|
407
|
+
while ($true) {
|
|
408
|
+
if (-not (Test-PidAlive -ProcId $FrontendPid)) {
|
|
409
|
+
Write-WatcherLog "EXIT frontend_dead"
|
|
410
|
+
break
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
$runtime = Try-ReadJson -Path $RuntimeFile
|
|
414
|
+
if ($null -eq $runtime) {
|
|
415
|
+
Write-WatcherLog "WAIT runtime_missing"
|
|
416
|
+
Start-Sleep -Milliseconds 300
|
|
417
|
+
continue
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
$runtimeOwnerPid = 0
|
|
421
|
+
try { $runtimeOwnerPid = [int]$runtime.frontend_host_pid } catch { $runtimeOwnerPid = 0 }
|
|
422
|
+
if ($runtimeOwnerPid -ne $FrontendPid) {
|
|
423
|
+
Write-WatcherLog ("EXIT owner_changed owner=" + $runtimeOwnerPid)
|
|
424
|
+
break
|
|
425
|
+
}
|
|
426
|
+
|
|
420
427
|
$state = Try-ReadJson -Path $StateFile
|
|
421
428
|
if ($null -eq $state) {
|
|
422
429
|
Write-WatcherLog "WAIT state_missing"
|
|
423
|
-
Start-Sleep -Milliseconds 700
|
|
424
|
-
continue
|
|
425
|
-
}
|
|
426
|
-
|
|
430
|
+
Start-Sleep -Milliseconds 700
|
|
431
|
+
continue
|
|
432
|
+
}
|
|
433
|
+
|
|
427
434
|
$title = Get-QueueTitle -State $state -FallbackTitle $BaseTitle -IdleCooldownMs $idleCooldownMs
|
|
428
435
|
$notice = Get-QueueNotice -State $state -IdleCooldownMs $idleCooldownMs
|
|
429
436
|
$ui = Get-UiNoticeSnapshot -State $state
|
|
430
437
|
if ($title -ne $lastTitle) {
|
|
431
438
|
$updated = Update-ConsoleTitle -Title $title
|
|
432
439
|
Write-WatcherLog ("TITLE updated=" + $updated + " text=" + $title)
|
|
433
|
-
$lastTitle = $title
|
|
434
|
-
}
|
|
435
|
-
if ($notice -ne $lastNotice) {
|
|
436
|
-
if ($notice) {
|
|
437
|
-
$noticeUpdated = Write-ConsoleNotice -Notice $notice
|
|
438
|
-
Write-WatcherLog ("NOTICE updated=" + $noticeUpdated + " text=" + $notice)
|
|
439
|
-
} else {
|
|
440
|
-
Write-WatcherLog "NOTICE clear"
|
|
440
|
+
$lastTitle = $title
|
|
441
|
+
}
|
|
442
|
+
if ($notice -ne $lastNotice) {
|
|
443
|
+
if ($notice) {
|
|
444
|
+
$noticeUpdated = Write-ConsoleNotice -Notice $notice
|
|
445
|
+
Write-WatcherLog ("NOTICE updated=" + $noticeUpdated + " text=" + $notice)
|
|
446
|
+
} else {
|
|
447
|
+
Write-WatcherLog "NOTICE clear"
|
|
441
448
|
}
|
|
442
449
|
$lastNotice = $notice
|
|
443
450
|
}
|