agent-dag 3.22.0 → 3.22.3

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 (70) hide show
  1. package/README.md +6 -477
  2. package/package.json +14 -48
  3. package/shim.js +107 -0
  4. package/LICENSE +0 -661
  5. package/LICENSING.md +0 -82
  6. package/THIRD_PARTY_NOTICES.md +0 -395
  7. package/bin/agent-dag.js +0 -626
  8. package/bin/deck.js +0 -1805
  9. package/dist/web/assets/index-3FWd7g_W.css +0 -1
  10. package/dist/web/assets/index-BOwtoP02.js +0 -266
  11. package/dist/web/index.html +0 -49
  12. package/hook/hook.js +0 -542
  13. package/release-notes.json +0 -392
  14. package/src/server/activity.mjs +0 -52
  15. package/src/server/agent-activity.mjs +0 -522
  16. package/src/server/args.mjs +0 -183
  17. package/src/server/auto-update.mjs +0 -79
  18. package/src/server/block-notify.mjs +0 -173
  19. package/src/server/boot-deadline.mjs +0 -127
  20. package/src/server/brand.mjs +0 -16
  21. package/src/server/browser-history.mjs +0 -497
  22. package/src/server/browser-presence.mjs +0 -211
  23. package/src/server/browser-profiles.mjs +0 -279
  24. package/src/server/browser-react.mjs +0 -284
  25. package/src/server/browser-watch-store.mjs +0 -350
  26. package/src/server/browser-watch.mjs +0 -905
  27. package/src/server/ccusage.mjs +0 -1168
  28. package/src/server/claude-accounts.mjs +0 -951
  29. package/src/server/claude-dir.mjs +0 -213
  30. package/src/server/codex-auth.mjs +0 -388
  31. package/src/server/codex-dir.mjs +0 -171
  32. package/src/server/codex-quota.mjs +0 -449
  33. package/src/server/codex-usage.mjs +0 -512
  34. package/src/server/cswap-admin.mjs +0 -1562
  35. package/src/server/cswap-auto.mjs +0 -658
  36. package/src/server/cswap-install.mjs +0 -641
  37. package/src/server/deck-home.mjs +0 -243
  38. package/src/server/deck-prefs.mjs +0 -301
  39. package/src/server/deck-probe.mjs +0 -111
  40. package/src/server/detach.mjs +0 -244
  41. package/src/server/exec.mjs +0 -996
  42. package/src/server/global-install.mjs +0 -67
  43. package/src/server/hwmonitor.mjs +0 -56
  44. package/src/server/index.mjs +0 -6043
  45. package/src/server/installer.mjs +0 -912
  46. package/src/server/invoked-as.mjs +0 -144
  47. package/src/server/lan-about.mjs +0 -119
  48. package/src/server/lan-engine.mjs +0 -952
  49. package/src/server/lan-reach.mjs +0 -256
  50. package/src/server/lan-socket.mjs +0 -682
  51. package/src/server/lan-sync.mjs +0 -941
  52. package/src/server/lhm-parse.mjs +0 -91
  53. package/src/server/log-tail.mjs +0 -139
  54. package/src/server/log-writer.mjs +0 -322
  55. package/src/server/login-service.mjs +0 -473
  56. package/src/server/macmon.mjs +0 -310
  57. package/src/server/npx.mjs +0 -264
  58. package/src/server/open-url.mjs +0 -242
  59. package/src/server/presence.mjs +0 -40
  60. package/src/server/quota.mjs +0 -792
  61. package/src/server/relay-guard.mjs +0 -507
  62. package/src/server/reset-label.mjs +0 -78
  63. package/src/server/retire-sound-hook.mjs +0 -349
  64. package/src/server/running-deck.mjs +0 -234
  65. package/src/server/self-update.mjs +0 -1380
  66. package/src/server/stop-deck.mjs +0 -171
  67. package/src/server/supervisor.mjs +0 -392
  68. package/src/server/system-metrics.mjs +0 -1825
  69. package/src/server/term.mjs +0 -686
  70. package/src/server/uv-bootstrap.mjs +0 -337
@@ -1,144 +0,0 @@
1
- // Which of the three published commands the user typed — and nothing else.
2
- //
3
- // The deck is on npm three times over — `ccdeck`, `agents-deck` and `agent-dag`
4
- // — and since #340 all three are literally the same tarball, published with
5
- // `name` set to each in turn. Every surface a human reads says ccdeck now, and
6
- // most of the downloads are still on the other two, so nothing closes that split
7
- // on its own. This file is the evidence behind saying so — once in the terminal,
8
- // once in the browser.
9
- //
10
- // Two rules make that safe, and they are the whole of the file.
11
- //
12
- // It is never a refusal. A build that declined to boot under an old name would
13
- // take the self-update path down with it: a user on `agents-deck` clicks
14
- // "Update & restart", the copy that arrives refuses to run, and the deck is
15
- // dead on the one machine where the deck was the thing that would have
16
- // explained why.
17
- //
18
- // And it is never asked of the PACKAGE. That was unarguable while ccdeck was a
19
- // stub — it depended on `agents-deck` and spawned its bin, so "is this build
20
- // agents-deck?" was true inside every ccdeck run, and a notice keyed on it would
21
- // have scolded exactly the people who did what we asked. #340 removed the stub
22
- // and the rule outlived it, because the three names are now ONE tarball: asking
23
- // the package what it is gets you whichever name the publish step happened to
24
- // set last, which is not evidence about the user at all. The question is which
25
- // name the USER TYPED. That is a different question, with a different answer,
26
- // and on one platform with no answer at all:
27
- //
28
- // npx, everywhere — npm writes the literal spec into
29
- // `_npx/<hash>/package.json` as `_npx.packages`, which npxRestartSpec
30
- // already reads to decide what a restart re-runs. Reused rather than
31
- // re-derived; the only difference here is that this caller has no fallback
32
- // to offer, since a guess is the one answer it must not give.
33
- //
34
- // a global install on macOS or Linux — npm links <prefix>/bin/<name> at the
35
- // package's bin/agent-dag.js, and node does not resolve that symlink for
36
- // argv[1]. All three names reach one file and only argv[1] tells them
37
- // apart, so its last segment is the command that was typed. Verified with
38
- // npm's own layout: a symlink named `ccdeck` gives argv[1] `…/bin/ccdeck`.
39
- //
40
- // a global install on Windows — nowhere. npm writes <name>.cmd, <name>.ps1
41
- // and an extensionless sh shim, each of which runs
42
- // `node "…\node_modules\<pkg>\bin\agent-dag.js" %*` (npm's cmd-shim).
43
- // The typed name is the shim's FILENAME and never becomes an argument, and
44
- // there is no other carrier — npm_config_user_agent and friends are not set
45
- // for a direct bin invocation. So Windows answers null.
46
- //
47
- // a git checkout — nothing was typed. `node bin/agent-dag.js` is not any of
48
- // the three names.
49
- //
50
- // Which leaves the callers one rule: positive identification, or silence. A
51
- // notice shown to somebody who already types `ccdeck` is worse than a notice
52
- // missed, because it is the failure that teaches everyone to ignore the next
53
- // one.
54
- import { bareSpecName, isNpxInstall, npxRestartSpec } from "./self-update.mjs";
55
-
56
- /** The command every surface promotes. Deliberately not brand.mjs's PRODUCT:
57
- * that is the name a human reads, this is an npm bin name the user types, and
58
- * the two are the same string only because the rename made them so —
59
- * invoked-as.test.ts pins them against each other rather than assuming it. */
60
- export const PREFERRED = "ccdeck";
61
-
62
- /** Every command an install of this package provides, which is every name that
63
- * can be typed. package.json's `bin` block is the other half of this list. */
64
- export const COMMANDS = [PREFERRED, "agents-deck", "agent-dag"];
65
-
66
- /** `value` when it is one of those three, and null for everything else — a shim
67
- * filename with an extension on it, a path, a spec that resolved to some other
68
- * package, an environment variable somebody set by hand. None of those are
69
- * evidence of anything, and this function is the only place that decides so. */
70
- export function knownCommand(value) {
71
- return typeof value === "string" && COMMANDS.includes(value) ? value : null;
72
- }
73
-
74
- /** The last segment of a path, split on both separators rather than `path.sep`
75
- * — the same reason isNpxInstall gives: a Windows path can reach a POSIX
76
- * process through a test or a config file, and a separator-agnostic split is
77
- * what keeps this one function on all three platforms. */
78
- function lastSegment(path) {
79
- if (typeof path !== "string") return null;
80
- const parts = path.split(/[\\/]/);
81
- return parts[parts.length - 1];
82
- }
83
-
84
- /**
85
- * The name the user typed, when we can prove it. Null means unknown, and
86
- * unknown must never produce a notice.
87
- */
88
- export function invokedAs({ pkgRoot, argv1, platform = process.platform } = {}) {
89
- // npx first, and alone: under npx argv[1] is a path inside the cache
90
- // directory, so the metadata is not the better answer, it is the only one.
91
- // The explicit null fallback is the point of the call — npxRestartSpec's
92
- // default is the package name, which is right for "what do I re-run" and
93
- // would be a guess wearing an answer's clothes here.
94
- if (isNpxInstall(pkgRoot)) return knownCommand(bareSpecName(npxRestartSpec(pkgRoot, null)));
95
- // See the header: on Windows the shim eats the name. Decided on the platform
96
- // rather than left to the extension check below, so that a Windows path that
97
- // somehow did end in a bare name still cannot become a guess.
98
- if (platform === "win32") return null;
99
- return knownCommand(lastSegment(argv1));
100
- }
101
-
102
- /**
103
- * The same question, answered for the process that is asking it.
104
- *
105
- * bin/deck.js — and the server running inside it — is spawned BY the
106
- * supervisor, so its own argv[1] is `…/bin/deck.js` every single time: the
107
- * typed name reached bin/agent-dag.js and stopped there. The supervisor answers
108
- * once and passes the answer down in AGENTS_DECK_INVOKED_AS, which is read back
109
- * through knownCommand rather than trusted, since an environment variable is
110
- * user input like any other. The fall-through still answers the npx half for a
111
- * worker started with no supervisor above it.
112
- */
113
- export function invokedName({
114
- env = process.env, pkgRoot, argv1 = process.argv[1], platform = process.platform,
115
- } = {}) {
116
- return knownCommand(env?.AGENTS_DECK_INVOKED_AS) ?? invokedAs({ pkgRoot, argv1, platform });
117
- }
118
-
119
- /**
120
- * What the terminal says about it, or null when there is nothing to say.
121
- *
122
- * Two lines, because the second one is where the value is. Someone who ran
123
- * `npm i -g agents-deck` has nothing to install and nothing to download — the
124
- * same install already put a `ccdeck` on their PATH, and all they have to do is
125
- * type it. Handing them an install command instead would be work we invented.
126
- * Under npx there is no such install, so the fix there is the command itself.
127
- *
128
- * `dash` comes from the caller's glyph tier: an em dash is as absent from a
129
- * legacy Windows console as a check mark is, and this file must not be the one
130
- * place that forgets it.
131
- */
132
- export function renameNotice({ invoked, pkgRoot, dash = "—", preferred = PREFERRED } = {}) {
133
- const name = knownCommand(invoked);
134
- if (!name || name === preferred) return null;
135
- return {
136
- // Leads with the reassurance on purpose. Nothing is breaking here, no
137
- // command is being taken away, and a line that opened with the rename would
138
- // read as one that was.
139
- said: `${name} still works ${dash} the deck is called ${preferred} now`,
140
- fix: isNpxInstall(pkgRoot)
141
- ? `next time: npx ${preferred}`
142
- : `${preferred} already works here ${dash} same install, no download`,
143
- };
144
- }
@@ -1,119 +0,0 @@
1
- // What a paired deck says about itself: the version it runs and the machine it
2
- // runs on.
3
- //
4
- // ONLY TO A DECK THAT IS PAIRED, AND SEALED. The beacon is shouted at the whole
5
- // network and the hello is sent before anybody has proved anything, so neither
6
- // carries this: which build of which operating system a machine runs is the
7
- // first thing somebody hunting for a known-broken version would want, and
8
- // nobody on the network is owed it. It rides the manifest exchange, which only
9
- // happens between two decks that have each accepted the other — and it is
10
- // sealed with that connection's key, because the frames around it are JSON in
11
- // the clear on the wire.
12
- //
13
- // BOTH WAYS. The deck that dials sends its own card with the question, and the
14
- // deck that answers sends its own with the answer. A deck that only calls in —
15
- // paired, with no address this one can reach — is never asked anything, so the
16
- // card it sends when it calls is the only way this deck ever learns what it is.
17
- //
18
- // OLDER DECKS SAY NOTHING, AND NOTHING BREAKS. The field is extra on a frame
19
- // both versions already send: a deck from before this reads the accounts and
20
- // never looks at the rest, and a card that is absent is drawn as absent.
21
- import { readFileSync } from "node:fs";
22
- import { release as osRelease } from "node:os";
23
- import { open, seal } from "./lan-sync.mjs";
24
-
25
- /**
26
- * The operating system, in the words its owner would use.
27
- *
28
- * Node reports the KERNEL — `darwin 25.5.0`, `win32 10.0.26100` — and nobody
29
- * calls their laptop Darwin 25. So the numbers are translated on the machine
30
- * they describe, where the translation is certain, rather than on the one
31
- * reading them. Every input is a parameter, so all three platforms are tested
32
- * on any one of them.
33
- */
34
- export function osLabel({ platform, release = "", prettyName = "" } = {}) {
35
- const [major, minor, build] = String(release).split(".").map(n => Number.parseInt(n, 10));
36
- const dot = Number.isInteger(minor) ? `.${minor}` : "";
37
- if (platform === "darwin") {
38
- if (!Number.isInteger(major)) return "macOS";
39
- // Darwin 20 was macOS 11 and every major after it was one more — until 25,
40
- // which Apple shipped as macOS 26 to match the year.
41
- if (major >= 25) return `macOS ${major + 1}${dot}`;
42
- if (major >= 20) return `macOS ${major - 9}${dot}`;
43
- // The 10.x years, where the kernel's major minus four is the second number.
44
- return major >= 5 ? `macOS 10.${major - 4}` : "macOS";
45
- }
46
- if (platform === "win32") {
47
- // Windows 11 kept the version 10.0 and moved only the build, and 22000 is
48
- // the first one. From here it is the only way to tell the two apart.
49
- if (major === 10 && Number.isInteger(build)) return build >= 22_000 ? "Windows 11" : "Windows 10";
50
- return "Windows";
51
- }
52
- if (platform === "linux") return prettyName || "Linux";
53
- return typeof platform === "string" && platform ? platform : "unknown";
54
- }
55
-
56
- /** The distribution's own name for itself, from the file every systemd-era
57
- * distribution ships, with the fallback path the same spec names. Only ever
58
- * read on Linux: the paths are Linux's and mean nothing anywhere else. */
59
- export function linuxPrettyName(read = readFileSync) {
60
- for (const file of ["/etc/os-release", "/usr/lib/os-release"]) {
61
- try {
62
- const line = /^PRETTY_NAME=(.*)$/m.exec(String(read(file, "utf8")))?.[1];
63
- const name = line?.trim().replace(/^(["'])(.*)\1$/, "$2").trim();
64
- if (name) return name;
65
- } catch { /* not this one */ }
66
- }
67
- return "";
68
- }
69
-
70
- /** This deck's own card. Built once, at start: nothing in it changes while the
71
- * process lives, and an upgrade is a restart. */
72
- export function aboutThisDeck({
73
- version = null, platform = process.platform, release = osRelease(), arch = process.arch, read = readFileSync,
74
- } = {}) {
75
- return readAbout({
76
- version,
77
- os: osLabel({ platform, release, prettyName: platform === "linux" ? linuxPrettyName(read) : "" }),
78
- arch,
79
- });
80
- }
81
-
82
- /** One field of a card, or null. It came off the network, so it is a string of
83
- * bounded length with no control characters — the rule cleanName applies to a
84
- * deck's name, for the same reason: it reaches a terminal as well as a page.
85
- * `\p{Cc}` is the Unicode class for exactly those, C0 and C1 both. */
86
- function field(v, max, shape = null) {
87
- if (typeof v !== "string") return null;
88
- const flat = v.replace(/\p{Cc}/gu, " ").replace(/\s+/g, " ").trim();
89
- const s = [...flat].slice(0, max).join("").trim();
90
- return s && (!shape || shape.test(s)) ? s : null;
91
- }
92
-
93
- /** A card, or null when there is nothing in it worth drawing. */
94
- export function readAbout(raw) {
95
- if (!raw || typeof raw !== "object") return null;
96
- const version = field(raw.version, 32, /^[0-9A-Za-z][0-9A-Za-z.+-]*$/);
97
- const os = field(raw.os, 48);
98
- const arch = field(raw.arch, 16, /^[0-9A-Za-z_]+$/);
99
- return version || os || arch ? { version, os, arch } : null;
100
- }
101
-
102
- /** Bound to one connection AND one direction, so a card cannot be replayed
103
- * back at the deck that sent it as if it were the other deck's. */
104
- const aboutAad = (fromFp, toFp) => `${fromFp}->${toFp}|about`;
105
-
106
- /** This deck's card, sealed for the deck on the other end of `key`. */
107
- export function sealAbout(key, about, fromFp, toFp) {
108
- if (!key || !about) return null;
109
- return seal(key, JSON.stringify(about), aboutAad(fromFp, toFp));
110
- }
111
-
112
- /** The other deck's card, or null — for a deck that sent none, and for one
113
- * whose seal does not open, which mean the same thing to the panel. */
114
- export function openAbout(key, sealed, fromFp, toFp) {
115
- if (!key || !sealed || typeof sealed !== "object") return null;
116
- const text = open(key, sealed, aboutAad(fromFp, toFp));
117
- if (text == null) return null;
118
- try { return readAbout(JSON.parse(text)); } catch { return null; }
119
- }