ccdeck 3.29.10 → 3.30.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 +1 -1
- package/bin/agent-dag.js +67 -118
- package/bin/cli/help.js +67 -0
- package/bin/cli/login-item.js +182 -0
- package/bin/cli/one-shot.js +254 -0
- package/bin/cli/package.js +39 -0
- package/bin/cli/pulse.js +98 -0
- package/bin/cli/restart.js +179 -0
- package/bin/cli/screen.js +166 -0
- package/bin/cli/second-start.js +120 -0
- package/bin/cli/startup.js +459 -0
- package/bin/cli/uninstall.js +169 -0
- package/bin/deck.js +112 -1559
- package/dist/web/assets/BrowserWatchModal-DP3YMtEi.js +1 -0
- package/dist/web/assets/UsageHistoryModal-CcdPVXAw.js +1 -0
- package/dist/web/assets/index-3vS6A0vt.css +1 -0
- package/dist/web/assets/index-BVTWHDta.js +298 -0
- package/dist/web/index.html +2 -2
- package/hook/hook.js +15 -14
- package/package.json +1 -1
- package/release-notes.json +28 -0
- package/src/server/account-projects.mjs +25 -11
- package/src/server/account-routes.mjs +254 -0
- package/src/server/activity.mjs +3 -3
- package/src/server/append-budget.mjs +185 -0
- package/src/server/append-failures.mjs +147 -0
- package/src/server/args.mjs +37 -5
- package/src/server/atomic-write.mjs +300 -0
- package/src/server/block-notify.mjs +0 -5
- package/src/server/boot-lock.mjs +1 -1
- package/src/server/brand.mjs +7 -6
- package/src/server/browser-react.mjs +10 -2
- package/src/server/browser-watch-decks.mjs +146 -0
- package/src/server/browser-watch-feed.mjs +69 -0
- package/src/server/browser-watch-log.mjs +173 -0
- package/src/server/browser-watch-mtime.mjs +18 -0
- package/src/server/browser-watch-relay.mjs +112 -0
- package/src/server/browser-watch-routes.mjs +172 -0
- package/src/server/browser-watch-seen.mjs +127 -0
- package/src/server/browser-watch-store.mjs +14 -143
- package/src/server/browser-watch.mjs +278 -626
- package/src/server/canonical-path.mjs +150 -0
- package/src/server/ccusage-failure.mjs +64 -0
- package/src/server/ccusage-install.mjs +459 -0
- package/src/server/ccusage-runner.mjs +271 -0
- package/src/server/ccusage.mjs +21 -756
- package/src/server/claude-accounts.mjs +220 -464
- package/src/server/claude-collector.mjs +189 -0
- package/src/server/claude-dir.mjs +2 -2
- package/src/server/claude-identity.mjs +5 -4
- package/src/server/claude-reset-credits.mjs +130 -0
- package/src/server/claude-verdicts.mjs +174 -0
- package/src/server/clear-route.mjs +191 -0
- package/src/server/codex-auth.mjs +4 -4
- package/src/server/codex-dir.mjs +52 -8
- package/src/server/codex-enrichment.mjs +310 -0
- package/src/server/codex-quota.mjs +5 -3
- package/src/server/codex-translate.mjs +407 -0
- package/src/server/codex-usage.mjs +8 -5
- package/src/server/codex-watch.mjs +496 -0
- package/src/server/cswap-auto-loop.mjs +342 -0
- package/src/server/cswap-auto-readers.mjs +303 -0
- package/src/server/cswap-auto.mjs +51 -609
- package/src/server/cswap-install.mjs +69 -265
- package/src/server/cswap-layout.mjs +242 -0
- package/src/server/deck-home.mjs +1 -1
- package/src/server/deck-prefs.mjs +51 -184
- package/src/server/deck-scope.mjs +52 -0
- package/src/server/desktop-update-routes.mjs +75 -0
- package/src/server/detach.mjs +78 -0
- package/src/server/discovery.mjs +298 -0
- package/src/server/event-log.mjs +328 -0
- package/src/server/event-pipeline.mjs +235 -0
- package/src/server/event-ring.mjs +214 -0
- package/src/server/event-routes.mjs +352 -0
- package/src/server/event-sink.mjs +26 -0
- package/src/server/exec-children.mjs +128 -0
- package/src/server/exec-not-found.mjs +213 -0
- package/src/server/exec-output.mjs +23 -0
- package/src/server/exec-spec.mjs +341 -0
- package/src/server/exec.mjs +74 -661
- package/src/server/health-route.mjs +42 -0
- package/src/server/hook-challenge.mjs +37 -0
- package/src/server/http-io.mjs +104 -0
- package/src/server/index.mjs +172 -7620
- package/src/server/install-layout.mjs +506 -0
- package/src/server/installer.mjs +79 -608
- package/src/server/jsonl-chunks.mjs +139 -0
- package/src/server/lan-accounts.mjs +27 -0
- package/src/server/lan-beacon.mjs +457 -0
- package/src/server/lan-call.mjs +239 -0
- package/src/server/lan-copies.mjs +270 -0
- package/src/server/lan-deck.mjs +583 -0
- package/src/server/lan-dials.mjs +161 -0
- package/src/server/lan-engine.mjs +475 -1024
- package/src/server/lan-hearing.mjs +49 -0
- package/src/server/lan-inbound.mjs +100 -0
- package/src/server/lan-invite-offer.mjs +77 -0
- package/src/server/lan-invite.mjs +207 -0
- package/src/server/lan-lines.mjs +73 -0
- package/src/server/lan-manifest.mjs +74 -0
- package/src/server/lan-reach.mjs +82 -69
- package/src/server/lan-requests.mjs +249 -0
- package/src/server/lan-round-record.mjs +45 -0
- package/src/server/lan-round-timer.mjs +62 -0
- package/src/server/lan-routes.mjs +143 -0
- package/src/server/lan-serve.mjs +112 -0
- package/src/server/lan-socket.mjs +243 -925
- package/src/server/lan-sync.mjs +58 -1026
- package/src/server/lan-tailnet-poll.mjs +57 -0
- package/src/server/lan-turns.mjs +80 -0
- package/src/server/lan-wire.mjs +620 -0
- package/src/server/lifecycle.mjs +421 -0
- package/src/server/listen.mjs +110 -0
- package/src/server/live-decks.mjs +138 -0
- package/src/server/load-average.mjs +32 -0
- package/src/server/log-election.mjs +235 -0
- package/src/server/log-replay.mjs +374 -0
- package/src/server/log-writer.mjs +72 -557
- package/src/server/login-service.mjs +3 -2
- package/src/server/macmon.mjs +1 -1
- package/src/server/memory-files.mjs +163 -0
- package/src/server/memory-metrics.mjs +178 -0
- package/src/server/metrics-history.mjs +94 -0
- package/src/server/metrics-run.mjs +100 -0
- package/src/server/music-routes.mjs +134 -0
- package/src/server/network-metrics.mjs +5 -3
- package/src/server/network-sampler.mjs +256 -0
- package/src/server/npm-latest.mjs +385 -0
- package/src/server/npm-upgrade.mjs +352 -0
- package/src/server/npx.mjs +41 -7
- package/src/server/output-watch.mjs +5 -4
- package/src/server/pinned-build.mjs +108 -0
- package/src/server/prefs-path.mjs +14 -0
- package/src/server/prefs-refusal.mjs +77 -0
- package/src/server/prefs-routes.mjs +76 -0
- package/src/server/prefs-set-aside.mjs +86 -0
- package/src/server/prefs-state.mjs +51 -0
- package/src/server/process-command.mjs +104 -0
- package/src/server/process-list.mjs +547 -0
- package/src/server/pulse-line.mjs +132 -0
- package/src/server/purge-key.mjs +7 -7
- package/src/server/quota-cli.mjs +174 -0
- package/src/server/quota-oauth.mjs +190 -0
- package/src/server/quota-shape.mjs +229 -0
- package/src/server/quota-store-resets.mjs +206 -0
- package/src/server/quota.mjs +123 -509
- package/src/server/relay-guard.mjs +3 -3
- package/src/server/request-gates.mjs +441 -0
- package/src/server/restart-note.mjs +180 -0
- package/src/server/retire-sound-hook.mjs +3 -3
- package/src/server/ring-bounds.mjs +215 -0
- package/src/server/running-deck.mjs +1 -1
- package/src/server/running-version.mjs +24 -0
- package/src/server/self-update.mjs +39 -1371
- package/src/server/session-enrichment.mjs +622 -0
- package/src/server/session-read-gate.mjs +49 -0
- package/src/server/session-tracking.mjs +242 -0
- package/src/server/sse-clients.mjs +222 -0
- package/src/server/stale-discovery.mjs +30 -0
- package/src/server/static-serve.mjs +81 -0
- package/src/server/supervisor.mjs +73 -12
- package/src/server/system-metrics.mjs +169 -1935
- package/src/server/term.mjs +11 -249
- package/src/server/thermal-metrics.mjs +520 -0
- package/src/server/thermal-sampler.mjs +204 -0
- package/src/server/token-redact.mjs +123 -0
- package/src/server/transcript-gate.mjs +107 -0
- package/src/server/transcript-scan.mjs +563 -0
- package/src/server/usage-routes.mjs +93 -0
- package/src/server/uv-bootstrap.mjs +1 -1
- package/src/server/wordmark.mjs +127 -0
- package/dist/web/assets/BrowserWatchModal-CMn28FHb.js +0 -1
- package/dist/web/assets/UsageHistoryModal-C-sPhsKT.js +0 -1
- package/dist/web/assets/index-C1YFI9f4.js +0 -298
- package/dist/web/assets/index-Ck2RAla3.css +0 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// The addresses this deck dials that the beacon did not hand it — typed in,
|
|
2
|
+
// pressed accept on, joined by invite, asked from a beacon, or learned from a
|
|
3
|
+
// paired deck that called in — and what answered at each: lifted out of
|
|
4
|
+
// createEngine in lan-engine.mjs with the three collections only they used.
|
|
5
|
+
// Nothing here dials; a round in the engine walks rows() and reports back
|
|
6
|
+
// through answered() and failed().
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The most addresses `autoAsk` may put on the dial list on its own.
|
|
10
|
+
*
|
|
11
|
+
* Measured, because the shape of it is not the obvious one: the dial list is
|
|
12
|
+
* keyed `host:port`, not by fingerprint, so five hundred beacons from one
|
|
13
|
+
* address on one port make one row. Five hundred beacons from one address on
|
|
14
|
+
* five hundred PORTS make five hundred rows, and a round dials them one at a
|
|
15
|
+
* time with a ROUND_MS bell on each — so a list that size is eighty minutes of
|
|
16
|
+
* round, and the decks somebody actually paired with sit at the end of it
|
|
17
|
+
* waiting their turn. The ceiling on that without this number is 65,535 rows
|
|
18
|
+
* from a single host.
|
|
19
|
+
*
|
|
20
|
+
* It bounds only what the deck added BY ITSELF. Addresses a person typed are
|
|
21
|
+
* not capped: a list of those is somebody's own decision and the deck is in no
|
|
22
|
+
* position to tell them they have too many machines.
|
|
23
|
+
*/
|
|
24
|
+
export const MAX_AUTO_PEERS = 32;
|
|
25
|
+
|
|
26
|
+
export function createDials() {
|
|
27
|
+
/** Peers the user typed in, which the beacon will never find.
|
|
28
|
+
*
|
|
29
|
+
* Broadcast dies at the first router and is dropped by a switch that
|
|
30
|
+
* filters it, so a deck across a VPN or on another subnet is unreachable by
|
|
31
|
+
* discovery and perfectly reachable by address. Typing one is a decision to
|
|
32
|
+
* trust whatever answers there the first time, and to pin it: an address is
|
|
33
|
+
* a way to reach a deck, and the accept on the other machine is what lets
|
|
34
|
+
* anything move.
|
|
35
|
+
*
|
|
36
|
+
* Keyed by `host:port` rather than by fingerprint, because a fingerprint is
|
|
37
|
+
* what a deck says about itself after the handshake and this list has to
|
|
38
|
+
* exist before there has been one.
|
|
39
|
+
*
|
|
40
|
+
* EVERY ROW SAYS WHERE IT CAME FROM, in `typed`, and the difference decides
|
|
41
|
+
* whether reaching it may pin a key sight unseen. A row somebody put in the
|
|
42
|
+
* address field — or pressed accept on, or joined by invite — is a person
|
|
43
|
+
* naming a machine. A row `autoAsk` added from a beacon is this deck
|
|
44
|
+
* answering a shout, which is not the same claim and must not read as one.
|
|
45
|
+
* See roundWith in lan-engine.mjs, where the difference is the whole of the
|
|
46
|
+
* trust rule. */
|
|
47
|
+
const manual = new Map();
|
|
48
|
+
/** What answered at a typed address, once something has. Keyed the same way
|
|
49
|
+
* `manual` is, because until a connection succeeds an address is all there
|
|
50
|
+
* is to key on. */
|
|
51
|
+
const learned = new Map();
|
|
52
|
+
/** Addresses this deck added because a paired deck called in from them and
|
|
53
|
+
* nothing here dialled it — see learnCaller in lan-engine.mjs. Kept until a
|
|
54
|
+
* round proves the address answers: one that does is an ordinary dialled
|
|
55
|
+
* peer from then on and leaves this set; one that does not is a caller this
|
|
56
|
+
* deck cannot reach back (a strict NAT, a one-way path), and its row is
|
|
57
|
+
* taken away again so it reverts to "calls in" rather than failing every
|
|
58
|
+
* round. A person naming the address ends its trial too, and so does a
|
|
59
|
+
* settings write that takes its row away (#1674). */
|
|
60
|
+
const calledBack = new Set();
|
|
61
|
+
|
|
62
|
+
/** Dial this address on every round from now on. Returns false for an
|
|
63
|
+
* address that is not one, rather than storing a row that can never
|
|
64
|
+
* connect and reports an error every minute forever. */
|
|
65
|
+
const add = (addr, port, { typed = true } = {}) => {
|
|
66
|
+
const p = Number(port);
|
|
67
|
+
if (typeof addr !== "string" || !addr.trim() || !Number.isInteger(p) || p < 1 || p > 65_535) return false;
|
|
68
|
+
const host = addr.trim();
|
|
69
|
+
const at = `${host}:${p}`;
|
|
70
|
+
// MAKING ROOM RATHER THAN REFUSING, and only among rows the deck added
|
|
71
|
+
// itself. A hard refusal at the cap would let whoever got there first
|
|
72
|
+
// keep the whole budget, so a real deck starting later would never be
|
|
73
|
+
// asked — which turns a cap meant to protect the round into a way to
|
|
74
|
+
// silence it. Evicted first is the oldest auto row that has never
|
|
75
|
+
// answered: `learned` holds an entry only for an address that completed a
|
|
76
|
+
// handshake, so a row with no entry there has cost a round and returned
|
|
77
|
+
// nothing. When every auto row has answered, the new one waits.
|
|
78
|
+
if (!typed && !manual.has(at)) {
|
|
79
|
+
const auto = [...manual.entries()].filter(([, v]) => !v.typed);
|
|
80
|
+
if (auto.length >= MAX_AUTO_PEERS) {
|
|
81
|
+
const stale = auto.find(([k]) => !learned.has(k));
|
|
82
|
+
if (!stale) return false;
|
|
83
|
+
manual.delete(stale[0]);
|
|
84
|
+
learned.delete(stale[0]);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// A row somebody typed outranks one the deck added: the same address
|
|
88
|
+
// arriving by hand after a beacon put it there is a person vouching for
|
|
89
|
+
// it, and nothing about that should be undone by the next beacon.
|
|
90
|
+
const was = manual.get(at);
|
|
91
|
+
manual.set(at, {
|
|
92
|
+
fp: `manual:${at}`, name: host, addr: host, port: p, manual: true,
|
|
93
|
+
typed: typed || was?.typed === true,
|
|
94
|
+
});
|
|
95
|
+
// AND A PERSON NAMING IT ENDS ITS TRIAL (#1674). A dial-back is taken away
|
|
96
|
+
// when a round cannot reach it, and a row somebody typed is not the deck's
|
|
97
|
+
// to take away: it stays, failing, and says why.
|
|
98
|
+
if (typed) calledBack.delete(at);
|
|
99
|
+
return true;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
add,
|
|
104
|
+
remove(addr, port) { return manual.delete(`${String(addr).trim()}:${Number(port)}`); },
|
|
105
|
+
/** Replace the typed list wholesale, which is what a settings write means.
|
|
106
|
+
* Adding one at a time would leave a removed address still being dialled
|
|
107
|
+
* every minute until the next restart — the row would vanish from the
|
|
108
|
+
* panel while the socket kept opening, which is the worst of both. The
|
|
109
|
+
* size of the list it leaves. */
|
|
110
|
+
replace(entries) {
|
|
111
|
+
manual.clear();
|
|
112
|
+
// The trials go with the rows they were for (#1674). One left behind
|
|
113
|
+
// outlived its row, and the next round that failed at that address took
|
|
114
|
+
// away whatever was dialled there by then.
|
|
115
|
+
calledBack.clear();
|
|
116
|
+
for (const entry of Array.isArray(entries) ? entries : []) {
|
|
117
|
+
const at = String(entry).lastIndexOf(":");
|
|
118
|
+
if (at > 0) add(String(entry).slice(0, at), Number(String(entry).slice(at + 1)));
|
|
119
|
+
}
|
|
120
|
+
return manual.size;
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
/** Every row on the list, oldest first. */
|
|
124
|
+
rows: () => [...manual.values()],
|
|
125
|
+
/** What answered at `host:port`, once something has. */
|
|
126
|
+
metAt: at => learned.get(at),
|
|
127
|
+
/** Say what answered at `host:port` — a handshake that just finished said
|
|
128
|
+
* so, before any round has. */
|
|
129
|
+
meet(at, met) { learned.set(at, met); },
|
|
130
|
+
/** Whether a row on the list answered as `fp` — one of the two ways this
|
|
131
|
+
* deck already dials a deck; the other is a beacon it still hears. */
|
|
132
|
+
answersAs(fp) {
|
|
133
|
+
for (const [at, met] of learned) if (met?.fp === fp && manual.has(at)) return true;
|
|
134
|
+
return false;
|
|
135
|
+
},
|
|
136
|
+
/** The row whose answer was `fp`, or undefined. */
|
|
137
|
+
rowAnswering: fp => [...manual.values()].find(p => learned.get(`${p.addr}:${p.port}`)?.fp === fp),
|
|
138
|
+
|
|
139
|
+
/** A row put on for a paired deck that called in from it, on trial until a
|
|
140
|
+
* round proves the address answers — see calledBack. */
|
|
141
|
+
trial(at, met) {
|
|
142
|
+
learned.set(at, met);
|
|
143
|
+
calledBack.add(at);
|
|
144
|
+
},
|
|
145
|
+
/** A round reached `host:port` and `met` is who answered there. A
|
|
146
|
+
* dial-back that answered is an ordinary row from now on. */
|
|
147
|
+
answered(at, met) {
|
|
148
|
+
learned.set(at, met);
|
|
149
|
+
calledBack.delete(at);
|
|
150
|
+
},
|
|
151
|
+
/** A round did not reach `host:port`. A dial-back on trial is taken away
|
|
152
|
+
* again, and true says one was; any other row stays and fails again. */
|
|
153
|
+
failed(at) {
|
|
154
|
+
if (!calledBack.has(at)) return false;
|
|
155
|
+
calledBack.delete(at);
|
|
156
|
+
manual.delete(at);
|
|
157
|
+
learned.delete(at);
|
|
158
|
+
return true;
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|