@agentdeck/bridge 1.1.0 → 1.2.0
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 +14 -6
- package/assets/fonts/NOTICE-PocketSansWorld.md +10 -0
- package/assets/fonts/OFL-PocketSansWorld.txt +93 -0
- package/assets/fonts/PocketSansWorld_12.cpfont +0 -0
- package/assets/fonts/pocket-sans-world.manifest.json +49 -0
- package/assets/learning/LICENSE-CC-BY-SA-4.0.txt +10 -0
- package/assets/learning/NOTICE.md +33 -0
- package/assets/learning/jp-n3-ko.manifest.json +27 -0
- package/assets/learning/jp-n3-ko.pdl +0 -0
- package/dist/agent-cli-diagnostics.d.ts +20 -0
- package/dist/agent-cli-diagnostics.d.ts.map +1 -0
- package/dist/agent-cli-diagnostics.js +100 -0
- package/dist/agent-cli-diagnostics.js.map +1 -0
- package/dist/apme/collector.d.ts +18 -1
- package/dist/apme/collector.d.ts.map +1 -1
- package/dist/apme/collector.js +48 -3
- package/dist/apme/collector.js.map +1 -1
- package/dist/apme/dashboard-html.d.ts.map +1 -1
- package/dist/apme/dashboard-html.js +275 -35
- package/dist/apme/dashboard-html.js.map +1 -1
- package/dist/apme/http.d.ts.map +1 -1
- package/dist/apme/http.js +33 -5
- package/dist/apme/http.js.map +1 -1
- package/dist/apme/index.d.ts.map +1 -1
- package/dist/apme/index.js +6 -2
- package/dist/apme/index.js.map +1 -1
- package/dist/apme/store.d.ts +41 -1
- package/dist/apme/store.d.ts.map +1 -1
- package/dist/apme/store.js +153 -27
- package/dist/apme/store.js.map +1 -1
- package/dist/bridge-core.d.ts +15 -0
- package/dist/bridge-core.d.ts.map +1 -1
- package/dist/bridge-core.js +30 -4
- package/dist/bridge-core.js.map +1 -1
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +55 -8
- package/dist/cli.js.map +1 -1
- package/dist/codex-rate-limits-live.d.ts +180 -10
- package/dist/codex-rate-limits-live.d.ts.map +1 -1
- package/dist/codex-rate-limits-live.js +475 -22
- package/dist/codex-rate-limits-live.js.map +1 -1
- package/dist/daemon-server.d.ts.map +1 -1
- package/dist/daemon-server.js +263 -1
- package/dist/daemon-server.js.map +1 -1
- package/dist/daemon-ws-client.d.ts +1 -0
- package/dist/daemon-ws-client.d.ts.map +1 -1
- package/dist/daemon-ws-client.js +25 -16
- package/dist/daemon-ws-client.js.map +1 -1
- package/dist/daemon.js +1 -1
- package/dist/esp32-serial.d.ts +4 -0
- package/dist/esp32-serial.d.ts.map +1 -1
- package/dist/esp32-serial.js +4 -0
- package/dist/esp32-serial.js.map +1 -1
- package/dist/font-pack.d.ts +15 -0
- package/dist/font-pack.d.ts.map +1 -0
- package/dist/font-pack.js +75 -0
- package/dist/font-pack.js.map +1 -0
- package/dist/glance-frame.d.ts.map +1 -1
- package/dist/glance-frame.js +2 -0
- package/dist/glance-frame.js.map +1 -1
- package/dist/http-auth-gate.d.ts.map +1 -1
- package/dist/http-auth-gate.js +9 -1
- package/dist/http-auth-gate.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/learning-pack.d.ts +24 -0
- package/dist/learning-pack.d.ts.map +1 -0
- package/dist/learning-pack.js +125 -0
- package/dist/learning-pack.js.map +1 -0
- package/dist/mdns.js +1 -1
- package/dist/mdns.js.map +1 -1
- package/dist/pairing-knocks.d.ts +80 -0
- package/dist/pairing-knocks.d.ts.map +1 -0
- package/dist/pairing-knocks.js +312 -0
- package/dist/pairing-knocks.js.map +1 -0
- package/dist/pixoo/micro-glyphs.d.ts +4 -0
- package/dist/pixoo/micro-glyphs.d.ts.map +1 -1
- package/dist/pixoo/micro-glyphs.js +29 -0
- package/dist/pixoo/micro-glyphs.js.map +1 -1
- package/dist/pixoo/pixoo-font.d.ts.map +1 -1
- package/dist/pixoo/pixoo-font.js +3 -1
- package/dist/pixoo/pixoo-font.js.map +1 -1
- package/dist/pixoo/pixoo-renderer.d.ts +1 -1
- package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
- package/dist/pixoo/pixoo-renderer.js +17 -2
- package/dist/pixoo/pixoo-renderer.js.map +1 -1
- package/dist/pty-manager.d.ts +9 -0
- package/dist/pty-manager.d.ts.map +1 -1
- package/dist/pty-manager.js +63 -4
- package/dist/pty-manager.js.map +1 -1
- package/dist/relayed-usage.d.ts +30 -0
- package/dist/relayed-usage.d.ts.map +1 -1
- package/dist/relayed-usage.js +25 -2
- package/dist/relayed-usage.js.map +1 -1
- package/dist/surface-protocol.d.ts.map +1 -1
- package/dist/surface-protocol.js +2 -0
- package/dist/surface-protocol.js.map +1 -1
- package/dist/tui/dashboard.d.ts.map +1 -1
- package/dist/tui/dashboard.js +8 -1
- package/dist/tui/dashboard.js.map +1 -1
- package/dist/ws-server.d.ts +18 -0
- package/dist/ws-server.d.ts.map +1 -1
- package/dist/ws-server.js +40 -2
- package/dist/ws-server.js.map +1 -1
- package/package.json +4 -3
- package/src/timebox/sync_ble.py +35 -16
package/README.md
CHANGED
|
@@ -17,17 +17,25 @@ npm install -g @agentdeck/bridge
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
agentdeck
|
|
21
|
-
|
|
22
|
-
agentdeck
|
|
23
|
-
agentdeck
|
|
24
|
-
agentdeck daemon start # start the daemon hub (port 9120)
|
|
20
|
+
agentdeck daemon install # install hooks and start the daemon on login
|
|
21
|
+
claude # or: codex / opencode
|
|
22
|
+
agentdeck dashboard # terminal dashboard
|
|
23
|
+
agentdeck daemon start # start the daemon hub manually (port 9120)
|
|
25
24
|
agentdeck devices # list connected display devices
|
|
26
25
|
agentdeck qr # pairing QR for the iOS/Android companion apps
|
|
27
26
|
agentdeck --help # full command reference
|
|
28
27
|
```
|
|
29
28
|
|
|
30
|
-
The daemon is the hub every dashboard client talks to
|
|
29
|
+
The daemon is the hub every dashboard client talks to. Normal agent commands
|
|
30
|
+
report through lifecycle hooks or native event channels and can be steered where
|
|
31
|
+
the observed session exposes a real delivery path.
|
|
32
|
+
|
|
33
|
+
The legacy `agentdeck claude|codex|opencode|monitor` per-session bridges remain
|
|
34
|
+
functional compatibility paths with no removal date. Prefer daemon-first for
|
|
35
|
+
ordinary local sessions, but keep managed-only workflows working while
|
|
36
|
+
[Discussion #278](https://github.com/puritysb/AgentDeck/discussions/278) and
|
|
37
|
+
[#273](https://github.com/puritysb/AgentDeck/issues/273) define and validate
|
|
38
|
+
replacements.
|
|
31
39
|
|
|
32
40
|
Full CLI reference: https://github.com/puritysb/AgentDeck/blob/master/docs/cli.md
|
|
33
41
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# PocketSansWorld font pack notice
|
|
2
|
+
|
|
3
|
+
PocketSansWorld is an SD-paged binary font bundle generated for Pocket Daily.
|
|
4
|
+
It combines glyphs from Noto Sans KR, Noto Sans JP, Noto Sans SC, Noto Sans
|
|
5
|
+
Hebrew, and Noto Sans. The original fonts and this redistributed derivative
|
|
6
|
+
are licensed under the SIL Open Font License 1.1. See
|
|
7
|
+
`OFL-PocketSansWorld.txt`.
|
|
8
|
+
|
|
9
|
+
The provider validates the immutable pack size, MD5, SHA-256, cpfont format,
|
|
10
|
+
source ledger, and licence before advertising it.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
https://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fontPack": {
|
|
3
|
+
"id": "pocket-sans-world",
|
|
4
|
+
"version": 1,
|
|
5
|
+
"format": 4,
|
|
6
|
+
"size": 10903872,
|
|
7
|
+
"md5": "a6844503c142be1a62e4bac8be7c7802",
|
|
8
|
+
"sha256": "a1a15a6e9cdccd114cbaf34adb29fce08ad67d3dcd52b7970a77ab89db9ee753",
|
|
9
|
+
"licenseSpdx": "OFL-1.1"
|
|
10
|
+
},
|
|
11
|
+
"attribution": "PocketSansWorld is built from Noto Sans KR, JP, SC, Hebrew, and Noto Sans under the SIL Open Font License 1.1.",
|
|
12
|
+
"sources": [
|
|
13
|
+
{
|
|
14
|
+
"name": "Noto Sans KR",
|
|
15
|
+
"url": "https://github.com/google/fonts/tree/ec626514f79f831f1ab848a82114a0ce7e2d6372/ofl/notosanskr",
|
|
16
|
+
"revision": "ec626514f79f831f1ab848a82114a0ce7e2d6372",
|
|
17
|
+
"licenseSpdx": "OFL-1.1",
|
|
18
|
+
"attribution": "Noto Sans KR contributors"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "Noto Sans SC",
|
|
22
|
+
"url": "https://github.com/google/fonts/tree/ec626514f79f831f1ab848a82114a0ce7e2d6372/ofl/notosanssc",
|
|
23
|
+
"revision": "ec626514f79f831f1ab848a82114a0ce7e2d6372",
|
|
24
|
+
"licenseSpdx": "OFL-1.1",
|
|
25
|
+
"attribution": "Noto Sans SC contributors"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "Noto Sans JP",
|
|
29
|
+
"url": "https://github.com/google/fonts/tree/295d98a7a0c17c68f1341eaeea354e7960ea70d3/ofl/notosansjp",
|
|
30
|
+
"revision": "295d98a7a0c17c68f1341eaeea354e7960ea70d3",
|
|
31
|
+
"licenseSpdx": "OFL-1.1",
|
|
32
|
+
"attribution": "Noto Sans JP contributors"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "Noto Sans",
|
|
36
|
+
"url": "https://github.com/notofonts/latin-greek-cyrillic",
|
|
37
|
+
"revision": "crosspoint-bundled-source",
|
|
38
|
+
"licenseSpdx": "OFL-1.1",
|
|
39
|
+
"attribution": "Noto Sans contributors"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "Noto Sans Hebrew",
|
|
43
|
+
"url": "https://github.com/crosspoint-reader/crosspoint-reader/tree/94c0ba466cbb225a07f653d1c27f2a7261f1fb08/lib/EpdFont/builtinFonts/source/NotoSansHebrew",
|
|
44
|
+
"revision": "94c0ba466cbb225a07f653d1c27f2a7261f1fb08",
|
|
45
|
+
"licenseSpdx": "OFL-1.1",
|
|
46
|
+
"attribution": "The Noto Project Authors"
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Pocket Daily Japanese learning content
|
|
2
|
+
Copyright (c) 2026 Pocket Daily contributors
|
|
3
|
+
|
|
4
|
+
This learning content is licensed under the Creative Commons
|
|
5
|
+
Attribution-ShareAlike 4.0 International License.
|
|
6
|
+
|
|
7
|
+
License text and terms:
|
|
8
|
+
https://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
9
|
+
|
|
10
|
+
Attribution: Original Korean study content by Pocket Daily contributors.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Pocket Daily learning data — source and modification notice
|
|
2
|
+
|
|
3
|
+
The `jp-n3-ko` dataset is an adapted subset of **OpenJLPT**, pinned at commit
|
|
4
|
+
`c42fd9fa3777bfc1775446f7c418d549dfd6e4cf`. OpenJLPT distributes its dataset
|
|
5
|
+
under **CC BY-SA 4.0** and records the following upstream sources:
|
|
6
|
+
|
|
7
|
+
- **JMdict / EDICT and KANJIDIC2**, Electronic Dictionary Research and
|
|
8
|
+
Development Group (EDRDG): vocabulary and kanji readings and English
|
|
9
|
+
glosses; CC BY-SA 4.0. <https://www.edrdg.org/>
|
|
10
|
+
- **Jonathan Waller's JLPT Resources**: unofficial N5–N1 level assignments;
|
|
11
|
+
CC BY according to the pinned OpenJLPT notice.
|
|
12
|
+
<https://www.tanos.co.uk/jlpt/>
|
|
13
|
+
- **Tatoeba**: Japanese example sentences; CC BY 2.0 FR.
|
|
14
|
+
<https://tatoeba.org/>
|
|
15
|
+
|
|
16
|
+
OpenJLPT and its full notice are available at
|
|
17
|
+
<https://github.com/evanclan/OpenJLPT/tree/c42fd9fa3777bfc1775446f7c418d549dfd6e4cf>.
|
|
18
|
+
|
|
19
|
+
Pocket Daily modifications are distributed under **CC BY-SA 4.0**:
|
|
20
|
+
|
|
21
|
+
- retained the cumulative N5, N4, and N3 kanji subset (612 unique characters);
|
|
22
|
+
- selected one compact representative word and Japanese example per character;
|
|
23
|
+
- added Korean kanji glosses, word meanings, and example translations;
|
|
24
|
+
- normalized the data into the fixed-record PDLP format for bounded SD reads.
|
|
25
|
+
|
|
26
|
+
The Korean adaptations are by Pocket Daily contributors. Automated assistance
|
|
27
|
+
was used to draft translations; field alignment, required Korean text, record
|
|
28
|
+
counts, byte bounds, source pinning, and package checksums are validated before
|
|
29
|
+
distribution. Corrections remain welcome and must be shared under CC BY-SA 4.0.
|
|
30
|
+
|
|
31
|
+
The JLPT organization does not publish an official current vocabulary or kanji
|
|
32
|
+
list. The level labels are therefore **unofficial N3-oriented study curation**,
|
|
33
|
+
not a claim about the undisclosed contents of a particular examination.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"learningPack": {
|
|
3
|
+
"id": "jp-n3-ko",
|
|
4
|
+
"version": 3,
|
|
5
|
+
"format": 1,
|
|
6
|
+
"size": 568324,
|
|
7
|
+
"md5": "34681b78b5a1d65bc787dc57e863cba7",
|
|
8
|
+
"licenseSpdx": "CC-BY-SA-4.0"
|
|
9
|
+
},
|
|
10
|
+
"attribution": "OpenJLPT/EDRDG/Waller/Tatoeba 기반; Pocket Daily 한국어 각색; CC BY-SA 4.0",
|
|
11
|
+
"sources": [
|
|
12
|
+
{
|
|
13
|
+
"name": "OpenJLPT cumulative N5-N3 dataset",
|
|
14
|
+
"url": "https://github.com/evanclan/OpenJLPT",
|
|
15
|
+
"revision": "c42fd9fa3777bfc1775446f7c418d549dfd6e4cf",
|
|
16
|
+
"licenseSpdx": "CC-BY-SA-4.0",
|
|
17
|
+
"attribution": "OpenJLPT; upstream EDRDG KANJIDIC2/JMdict, Jonathan Waller JLPT resources, and Tatoeba"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "Pocket Daily Korean adaptations",
|
|
21
|
+
"url": "https://github.com/puritysb/pocket-daily-reader",
|
|
22
|
+
"revision": "pocket-ko-2026-08-29",
|
|
23
|
+
"licenseSpdx": "CC-BY-SA-4.0",
|
|
24
|
+
"attribution": "Korean meanings and translations by Pocket Daily contributors"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type DiagnosedAgent = 'claude' | 'codex' | 'opencode';
|
|
2
|
+
export interface AgentCliDiagnosticEntry {
|
|
3
|
+
id: DiagnosedAgent;
|
|
4
|
+
label: string;
|
|
5
|
+
installed: boolean;
|
|
6
|
+
version: string | null;
|
|
7
|
+
compatibleRange: string | null;
|
|
8
|
+
compatible: boolean | null;
|
|
9
|
+
installHint?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AgentCliDiagnosticReport {
|
|
12
|
+
kind: 'agent-cli-compatibility';
|
|
13
|
+
migration: string;
|
|
14
|
+
trackingIssue: string;
|
|
15
|
+
agents: AgentCliDiagnosticEntry[];
|
|
16
|
+
}
|
|
17
|
+
export type VersionCommandRunner = (command: string) => string;
|
|
18
|
+
export declare function collectAgentCliDiagnosticReport(run?: VersionCommandRunner): AgentCliDiagnosticReport;
|
|
19
|
+
export declare function formatAgentCliDiagnosticReport(report: AgentCliDiagnosticReport): string;
|
|
20
|
+
//# sourceMappingURL=agent-cli-diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-cli-diagnostics.d.ts","sourceRoot":"","sources":["../src/agent-cli-diagnostics.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAiC7D,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,cAAc,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,yBAAyB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,uBAAuB,EAAE,CAAC;CACnC;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;AAW/D,wBAAgB,+BAA+B,CAC7C,GAAG,GAAE,oBAAwC,GAC5C,wBAAwB,CAiC1B;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAyBvF"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import { satisfiesRange } from './version-check.js';
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
const packageJson = require('../package.json');
|
|
6
|
+
const AGENTS = [
|
|
7
|
+
{
|
|
8
|
+
id: 'claude',
|
|
9
|
+
label: 'Claude Code',
|
|
10
|
+
versionCommand: 'claude --version',
|
|
11
|
+
compatibleRange: packageJson.compatibleClaudeCode,
|
|
12
|
+
installHint: 'npm install -g @anthropic-ai/claude-code',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: 'codex',
|
|
16
|
+
label: 'Codex CLI',
|
|
17
|
+
versionCommand: 'codex --version',
|
|
18
|
+
compatibleRange: packageJson.compatibleCodex,
|
|
19
|
+
installHint: 'npm install -g @openai/codex',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 'opencode',
|
|
23
|
+
label: 'OpenCode',
|
|
24
|
+
versionCommand: 'opencode --version',
|
|
25
|
+
installHint: 'brew install sst/tap/opencode (or: npm i -g opencode-ai)',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
function runVersionCommand(command) {
|
|
29
|
+
// Use the caller's PATH. A non-interactive login shell may skip interactive
|
|
30
|
+
// startup files and reorder PATH, causing diagnostics to inspect a stale
|
|
31
|
+
// installation instead of the executable `agentdeck` was launched beside.
|
|
32
|
+
return execSync(command, {
|
|
33
|
+
encoding: 'utf8', timeout: 5000, windowsHide: true,
|
|
34
|
+
}).trim();
|
|
35
|
+
}
|
|
36
|
+
export function collectAgentCliDiagnosticReport(run = runVersionCommand) {
|
|
37
|
+
return {
|
|
38
|
+
kind: 'agent-cli-compatibility',
|
|
39
|
+
migration: 'Run `agentdeck daemon install`, then start the agent normally.',
|
|
40
|
+
trackingIssue: 'https://github.com/puritysb/AgentDeck/issues/273',
|
|
41
|
+
agents: AGENTS.map((agent) => {
|
|
42
|
+
const compatibleRange = agent.compatibleRange?.trim() || null;
|
|
43
|
+
try {
|
|
44
|
+
const output = run(agent.versionCommand);
|
|
45
|
+
const version = output.match(/\b(\d+\.\d+\.\d+)\b/)?.[1] ?? null;
|
|
46
|
+
return {
|
|
47
|
+
id: agent.id,
|
|
48
|
+
label: agent.label,
|
|
49
|
+
installed: true,
|
|
50
|
+
version,
|
|
51
|
+
compatibleRange,
|
|
52
|
+
compatible: version && compatibleRange
|
|
53
|
+
? satisfiesRange(version, compatibleRange)
|
|
54
|
+
: null,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return {
|
|
59
|
+
id: agent.id,
|
|
60
|
+
label: agent.label,
|
|
61
|
+
installed: false,
|
|
62
|
+
version: null,
|
|
63
|
+
compatibleRange,
|
|
64
|
+
compatible: null,
|
|
65
|
+
installHint: agent.installHint,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function formatAgentCliDiagnosticReport(report) {
|
|
72
|
+
const lines = [
|
|
73
|
+
'Agent CLI compatibility (daemon-first)',
|
|
74
|
+
'',
|
|
75
|
+
report.migration,
|
|
76
|
+
'',
|
|
77
|
+
];
|
|
78
|
+
for (const agent of report.agents) {
|
|
79
|
+
if (!agent.installed) {
|
|
80
|
+
lines.push(`- ${agent.label}: not found — install: ${agent.installHint}`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const version = agent.version ?? 'version unknown';
|
|
84
|
+
if (!agent.compatibleRange) {
|
|
85
|
+
lines.push(`- ${agent.label}: ${version} — installed (no pinned compatibility range)`);
|
|
86
|
+
}
|
|
87
|
+
else if (agent.compatible === true) {
|
|
88
|
+
lines.push(`- ${agent.label}: ${version} — compatible (${agent.compatibleRange})`);
|
|
89
|
+
}
|
|
90
|
+
else if (agent.compatible === false) {
|
|
91
|
+
lines.push(`- ${agent.label}: ${version} — OUTSIDE supported range ${agent.compatibleRange}`);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
lines.push(`- ${agent.label}: ${version} — could not evaluate ${agent.compatibleRange}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
lines.push('', `Managed-session compatibility: ${report.trackingIssue}`);
|
|
98
|
+
return lines.join('\n');
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=agent-cli-diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-cli-diagnostics.js","sourceRoot":"","sources":["../src/agent-cli-diagnostics.ts"],"names":[],"mappings":"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"}
|
package/dist/apme/collector.d.ts
CHANGED
|
@@ -69,6 +69,10 @@ export type OnTaskOpened = (args: {
|
|
|
69
69
|
projectName: string | null;
|
|
70
70
|
taskIndex: number;
|
|
71
71
|
startedAt: number;
|
|
72
|
+
/** Display title derived from the task's first user prompt
|
|
73
|
+
* (`deriveTaskTitle` SSOT), or null when the prompt yields nothing
|
|
74
|
+
* meaningful — consumers keep their `Task N` fallback on null. */
|
|
75
|
+
title: string | null;
|
|
72
76
|
}) => void;
|
|
73
77
|
/** Callback fired when the agent declares its todos done mid-task (the
|
|
74
78
|
* TodoWrite-all-completed soft hint). Non-segmenting — the task stays open —
|
|
@@ -92,6 +96,8 @@ export declare class ApmeCollector {
|
|
|
92
96
|
* client abort, or never having run at all. Injectable for tests; the
|
|
93
97
|
* default reads the Claude transcript tail once for all three. */
|
|
94
98
|
private readonly openTurnProbe;
|
|
99
|
+
/** Injectable for tests only — production call sites take the default. */
|
|
100
|
+
private readonly idleGapMs;
|
|
95
101
|
private readonly sessionToRun;
|
|
96
102
|
private readonly sessionToAgentType;
|
|
97
103
|
private readonly sessionToTurn;
|
|
@@ -121,11 +127,17 @@ export declare class ApmeCollector {
|
|
|
121
127
|
/** Last milestone key (`taskId:turnIndex`) per session — a turn can carry
|
|
122
128
|
* several all-completed TodoWrite calls; surface only the first. */
|
|
123
129
|
private readonly sessionToLastMilestone;
|
|
130
|
+
/** Per-session idle-gap timers — armed in `closeTurn`, cleared on the next
|
|
131
|
+
* turn open / task close. See `AGENT_IDLE_GAP_MS` for the measurement the
|
|
132
|
+
* constant rests on. */
|
|
133
|
+
private readonly sessionToIdleGapTimer;
|
|
124
134
|
constructor(store: ApmeStore, hwSampler?: ApmeHwSampler | undefined,
|
|
125
135
|
/** What the transcript proves about a turn open since a timestamp — cancel,
|
|
126
136
|
* client abort, or never having run at all. Injectable for tests; the
|
|
127
137
|
* default reads the Claude transcript tail once for all three. */
|
|
128
|
-
openTurnProbe?: (transcriptPath: string, sinceMs: number) => OpenTurnEvidence | null
|
|
138
|
+
openTurnProbe?: (transcriptPath: string, sinceMs: number) => OpenTurnEvidence | null,
|
|
139
|
+
/** Injectable for tests only — production call sites take the default. */
|
|
140
|
+
idleGapMs?: number);
|
|
129
141
|
/** Start a new run and return its id. Safe to call if store disabled (returns ''). */
|
|
130
142
|
openRun(input: OpenRunInput): string;
|
|
131
143
|
/** Record a hook event as a step + manage turn lifecycle.
|
|
@@ -223,6 +235,11 @@ export declare class ApmeCollector {
|
|
|
223
235
|
* when a task proves itself "real" (second turn, or TodoWrite plan).
|
|
224
236
|
* Mirrors ApmeCollector.swift `emitDeferredTaskStartIfNeeded`. */
|
|
225
237
|
private emitDeferredTaskStartIfNeeded;
|
|
238
|
+
/** Arm the per-session idle-gap timer. Called from `closeTurn` — the turn
|
|
239
|
+
* just finished, so the gap being measured is genuine idle time, never the
|
|
240
|
+
* agent's own working time. Re-arming replaces any previous timer. */
|
|
241
|
+
private armIdleGapTimer;
|
|
242
|
+
private clearIdleGapTimer;
|
|
226
243
|
/** Public wrapper for closeTask. Used by the manual-boundary CLI /
|
|
227
244
|
* HTTP route + the macOS detail-pane button — lets the user declare
|
|
228
245
|
* "this task is done" without `/clear` (which would also split the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/apme/collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAuB,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE1H,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,EAAwB,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAE5F,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/apme/collector.ts"],"names":[],"mappings":"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"}
|
package/dist/apme/collector.js
CHANGED
|
@@ -18,7 +18,7 @@ import { mkdirSync, writeFileSync } from 'fs';
|
|
|
18
18
|
import { homedir } from 'os';
|
|
19
19
|
import { debug } from '../logger.js';
|
|
20
20
|
import { resolveProjectName } from '../utils/project-name.js';
|
|
21
|
-
import { isPricedModel, normalizeModelProvider, priceUsd } from '@agentdeck/shared';
|
|
21
|
+
import { AGENT_IDLE_GAP_MS, deriveTaskTitle, isPricedModel, normalizeModelProvider, priceUsd } from '@agentdeck/shared';
|
|
22
22
|
import { classifyRunSmart, computeSignals, classify } from './classifier.js';
|
|
23
23
|
import { readOpenTurnEvidence } from './claude-transcript-reader.js';
|
|
24
24
|
/** A turn_start with the same prompt landing on a fresh, still-empty turn
|
|
@@ -67,6 +67,7 @@ export class ApmeCollector {
|
|
|
67
67
|
store;
|
|
68
68
|
hwSampler;
|
|
69
69
|
openTurnProbe;
|
|
70
|
+
idleGapMs;
|
|
70
71
|
sessionToRun = new Map(); // sessionId → runId
|
|
71
72
|
sessionToAgentType = new Map(); // sessionId → agentType (survives closeRun for late-attributed timeline rows)
|
|
72
73
|
sessionToTurn = new Map(); // sessionId → current turn
|
|
@@ -96,14 +97,21 @@ export class ApmeCollector {
|
|
|
96
97
|
/** Last milestone key (`taskId:turnIndex`) per session — a turn can carry
|
|
97
98
|
* several all-completed TodoWrite calls; surface only the first. */
|
|
98
99
|
sessionToLastMilestone = new Map();
|
|
100
|
+
/** Per-session idle-gap timers — armed in `closeTurn`, cleared on the next
|
|
101
|
+
* turn open / task close. See `AGENT_IDLE_GAP_MS` for the measurement the
|
|
102
|
+
* constant rests on. */
|
|
103
|
+
sessionToIdleGapTimer = new Map();
|
|
99
104
|
constructor(store, hwSampler,
|
|
100
105
|
/** What the transcript proves about a turn open since a timestamp — cancel,
|
|
101
106
|
* client abort, or never having run at all. Injectable for tests; the
|
|
102
107
|
* default reads the Claude transcript tail once for all three. */
|
|
103
|
-
openTurnProbe = readOpenTurnEvidence
|
|
108
|
+
openTurnProbe = readOpenTurnEvidence,
|
|
109
|
+
/** Injectable for tests only — production call sites take the default. */
|
|
110
|
+
idleGapMs = AGENT_IDLE_GAP_MS) {
|
|
104
111
|
this.store = store;
|
|
105
112
|
this.hwSampler = hwSampler;
|
|
106
113
|
this.openTurnProbe = openTurnProbe;
|
|
114
|
+
this.idleGapMs = idleGapMs;
|
|
107
115
|
}
|
|
108
116
|
/** Start a new run and return its id. Safe to call if store disabled (returns ''). */
|
|
109
117
|
openRun(input) {
|
|
@@ -204,14 +212,18 @@ export class ApmeCollector {
|
|
|
204
212
|
prompt, hasResponse: false,
|
|
205
213
|
};
|
|
206
214
|
this.sessionToTurn.set(sessionId, turn);
|
|
215
|
+
// A new turn is the "still working" signal the idle-gap timer waits on.
|
|
216
|
+
this.clearIdleGapTimer(sessionId);
|
|
207
217
|
// Ensure an active task exists so this turn can attach to it. Tasks group
|
|
208
218
|
// consecutive turns between boundary signals (TodoWrite all-completed,
|
|
209
219
|
// /clear, session_end). First turn in a run opens task 0.
|
|
210
220
|
const task = this.openTaskIfNone(sessionId, runId);
|
|
211
221
|
if (task) {
|
|
212
222
|
const wasFirstTurn = task.firstTurnIndex === null;
|
|
213
|
-
if (wasFirstTurn)
|
|
223
|
+
if (wasFirstTurn) {
|
|
214
224
|
task.firstTurnIndex = turnIndex;
|
|
225
|
+
task.firstPrompt = prompt ?? null;
|
|
226
|
+
}
|
|
215
227
|
task.lastTurnIndex = turnIndex;
|
|
216
228
|
// Second (or later) turn on the same task proves it's a real,
|
|
217
229
|
// multi-turn work unit → promote the deferred TASK header so the
|
|
@@ -455,6 +467,9 @@ export class ApmeCollector {
|
|
|
455
467
|
catch (err) {
|
|
456
468
|
debug('APME', `closeTurn failed: ${String(err)}`);
|
|
457
469
|
}
|
|
470
|
+
// Idle starts when the turn ends. The timer is cleared by the next turn
|
|
471
|
+
// open (still working) or by closeTask (boundary reached another way).
|
|
472
|
+
this.armIdleGapTimer(sessionId);
|
|
458
473
|
}
|
|
459
474
|
/** Get the current active turn ID for a session (if any). */
|
|
460
475
|
getActiveTurnId(sessionId) {
|
|
@@ -519,6 +534,7 @@ export class ApmeCollector {
|
|
|
519
534
|
startedAt: Date.now(),
|
|
520
535
|
firstTurnIndex: null,
|
|
521
536
|
lastTurnIndex: null,
|
|
537
|
+
firstPrompt: null,
|
|
522
538
|
timelineEmitted: false,
|
|
523
539
|
};
|
|
524
540
|
this.sessionToTask.set(sessionId, task);
|
|
@@ -559,12 +575,40 @@ export class ApmeCollector {
|
|
|
559
575
|
projectName: run?.projectName ?? null,
|
|
560
576
|
taskIndex: task.index,
|
|
561
577
|
startedAt: task.startedAt,
|
|
578
|
+
title: deriveTaskTitle(task.firstPrompt),
|
|
562
579
|
});
|
|
563
580
|
}
|
|
564
581
|
catch (err) {
|
|
565
582
|
debug('APME', `onTaskOpened listener threw: ${String(err)}`);
|
|
566
583
|
}
|
|
567
584
|
}
|
|
585
|
+
/** Arm the per-session idle-gap timer. Called from `closeTurn` — the turn
|
|
586
|
+
* just finished, so the gap being measured is genuine idle time, never the
|
|
587
|
+
* agent's own working time. Re-arming replaces any previous timer. */
|
|
588
|
+
armIdleGapTimer(sessionId) {
|
|
589
|
+
this.clearIdleGapTimer(sessionId);
|
|
590
|
+
const timer = setTimeout(() => {
|
|
591
|
+
this.sessionToIdleGapTimer.delete(sessionId);
|
|
592
|
+
// A turn opened since (and its clear lost a race), or work is mid-turn:
|
|
593
|
+
// never split under an active turn.
|
|
594
|
+
if (this.sessionToTurn.has(sessionId))
|
|
595
|
+
return;
|
|
596
|
+
if (!this.sessionToTask.has(sessionId))
|
|
597
|
+
return;
|
|
598
|
+
debug('APME', `idle gap (${Math.round(this.idleGapMs / 1000)}s) → closing task for ${sessionId.slice(0, 8)}`);
|
|
599
|
+
this.closeTask(sessionId, 'idle_gap');
|
|
600
|
+
}, this.idleGapMs);
|
|
601
|
+
// Never hold the process open for an idle bookkeeping timer.
|
|
602
|
+
timer.unref?.();
|
|
603
|
+
this.sessionToIdleGapTimer.set(sessionId, timer);
|
|
604
|
+
}
|
|
605
|
+
clearIdleGapTimer(sessionId) {
|
|
606
|
+
const timer = this.sessionToIdleGapTimer.get(sessionId);
|
|
607
|
+
if (timer) {
|
|
608
|
+
clearTimeout(timer);
|
|
609
|
+
this.sessionToIdleGapTimer.delete(sessionId);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
568
612
|
/** Public wrapper for closeTask. Used by the manual-boundary CLI /
|
|
569
613
|
* HTTP route + the macOS detail-pane button — lets the user declare
|
|
570
614
|
* "this task is done" without `/clear` (which would also split the
|
|
@@ -597,6 +641,7 @@ export class ApmeCollector {
|
|
|
597
641
|
return;
|
|
598
642
|
this.sessionToTask.delete(sessionId);
|
|
599
643
|
this.sessionToLastMilestone.delete(sessionId);
|
|
644
|
+
this.clearIdleGapTimer(sessionId);
|
|
600
645
|
// Empty task: no turns ever attached. Drop the row so the dashboard
|
|
601
646
|
// doesn't show phantom entries from back-to-back boundary signals.
|
|
602
647
|
if (task.firstTurnIndex === null) {
|