@adhdev/mesh-shared 1.0.58-rc.6 → 1.0.58-rc.7
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/dist/index.d.ts +2 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +84 -0
- package/dist/index.mjs.map +1 -1
- package/dist/mesh-tool-names.d.ts +2 -2
- package/dist/semver-compare.d.ts +68 -0
- package/dist/ws-protocol.d.ts +35 -0
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/mesh-tool-names.ts +1 -0
- package/src/semver-compare.ts +122 -0
- package/src/ws-protocol.ts +90 -0
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* Order mirrors mcp-server `ALL_MESH_TOOLS` for easy visual diffing, but the consistency
|
|
19
19
|
* checks are set-based (order-insensitive).
|
|
20
20
|
*/
|
|
21
|
-
export declare const CANONICAL_MESH_TOOL_NAMES: readonly ["mesh_status", "mesh_list_nodes", "mesh_enqueue_batch", "mesh_enqueue_task", "mesh_view_queue", "mesh_graph_view", "mesh_graph_gate_claim", "mesh_graph_gate_release", "mesh_graph_gate_abandon", "mesh_queue_cancel", "mesh_queue_requeue", "mesh_send_task", "mesh_read_chat", "mesh_read_debug", "mesh_read_terminal", "mesh_send_keys", "mesh_launch_session", "mesh_git_status", "mesh_read_node_logs", "mesh_fast_forward_node", "mesh_restart_daemon", "mesh_checkpoint", "mesh_approve", "mesh_answer_question", "mesh_list_pending_approvals", "mesh_plan_onboarding", "mesh_create", "mesh_add_node", "mesh_clone_node", "mesh_remove_node", "mesh_cleanup_worktree_nodes", "mesh_refine_node", "mesh_refine_batch", "mesh_refine_config", "mesh_change_impact_config", "mesh_init", "mesh_reinit", "mesh_write_mesh_json_config", "mesh_refine_plan", "mesh_cleanup_sessions", "mesh_prune_stale_direct", "mesh_task_history", "mesh_ledger_query", "mesh_record_note", "mesh_forget_note", "mesh_reconcile_ledger", "mesh_requeue_held_events", "mesh_mission_upsert", "mesh_mission_list", "mesh_review_inbox", "mesh_magi_review", "mesh_magi_collect", "mesh_magi_kind_panel_set", "mesh_magi_kind_panel_list", "mesh_node_slots_set", "mesh_node_slots_list", "mesh_node_slots_propose", "mesh_coordinator_prompt_append_get", "mesh_coordinator_prompt_append_set"];
|
|
21
|
+
export declare const CANONICAL_MESH_TOOL_NAMES: readonly ["mesh_status", "mesh_route_preview", "mesh_list_nodes", "mesh_enqueue_batch", "mesh_enqueue_task", "mesh_view_queue", "mesh_graph_view", "mesh_graph_gate_claim", "mesh_graph_gate_release", "mesh_graph_gate_abandon", "mesh_queue_cancel", "mesh_queue_requeue", "mesh_send_task", "mesh_read_chat", "mesh_read_debug", "mesh_read_terminal", "mesh_send_keys", "mesh_launch_session", "mesh_git_status", "mesh_read_node_logs", "mesh_fast_forward_node", "mesh_restart_daemon", "mesh_checkpoint", "mesh_approve", "mesh_answer_question", "mesh_list_pending_approvals", "mesh_plan_onboarding", "mesh_create", "mesh_add_node", "mesh_clone_node", "mesh_remove_node", "mesh_cleanup_worktree_nodes", "mesh_refine_node", "mesh_refine_batch", "mesh_refine_config", "mesh_change_impact_config", "mesh_init", "mesh_reinit", "mesh_write_mesh_json_config", "mesh_refine_plan", "mesh_cleanup_sessions", "mesh_prune_stale_direct", "mesh_task_history", "mesh_ledger_query", "mesh_record_note", "mesh_forget_note", "mesh_reconcile_ledger", "mesh_requeue_held_events", "mesh_mission_upsert", "mesh_mission_list", "mesh_review_inbox", "mesh_magi_review", "mesh_magi_collect", "mesh_magi_kind_panel_set", "mesh_magi_kind_panel_list", "mesh_node_slots_set", "mesh_node_slots_list", "mesh_node_slots_propose", "mesh_coordinator_prompt_append_get", "mesh_coordinator_prompt_append_set"];
|
|
22
22
|
export type CanonicalMeshToolName = typeof CANONICAL_MESH_TOOL_NAMES[number];
|
|
23
23
|
/** The count the `NN tools` barrel doc comments and consistency test assert against. */
|
|
24
|
-
export declare const CANONICAL_MESH_TOOL_COUNT:
|
|
24
|
+
export declare const CANONICAL_MESH_TOOL_COUNT: 60;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semver precedence comparison — the single version-ordering primitive for the
|
|
3
|
+
* daemon's upgrade paths.
|
|
4
|
+
*
|
|
5
|
+
* Why this exists: the upgrade path used to decide "is this a no-op?" with a
|
|
6
|
+
* raw string equality check (`currentInstalled === latest`) and nothing else.
|
|
7
|
+
* Equality answers "is it the same version?" but never "which one is newer?",
|
|
8
|
+
* so any target that merely differed from the running build was installed —
|
|
9
|
+
* including one that is OLDER. That is how a node running `1.0.49-rc.2`
|
|
10
|
+
* silently got rolled back to `1.0.48`.
|
|
11
|
+
*
|
|
12
|
+
* String comparison cannot fix it either: `'1.0.49-rc.2' < '1.0.48'` is TRUE
|
|
13
|
+
* lexicographically (the '4' in "-rc.2"'s prefix never gets that far — '9' vs
|
|
14
|
+
* '8' at index 4 decides it, and even where it works `rc.10` sorts below
|
|
15
|
+
* `rc.9`). Only field-wise numeric comparison with semver §11 prerelease rules
|
|
16
|
+
* gives the right answer.
|
|
17
|
+
*
|
|
18
|
+
* This module is a PURE LEAF: zero imports, no I/O. It lives in mesh-shared
|
|
19
|
+
* (fragmentation audit) so BOTH the OSS daemon and the proprietary Workers
|
|
20
|
+
* server (`packages/server/src/utils/version-policy.ts`, previously a
|
|
21
|
+
* byte-identical independent copy) can consume ONE implementation — the two
|
|
22
|
+
* gate the same auto-update decision from opposite ends, and a drift between
|
|
23
|
+
* them can produce an unbreakable update-nag loop (server says behind, daemon
|
|
24
|
+
* gate refuses the "upgrade" as a rollback). daemon-core re-exports this from
|
|
25
|
+
* its original `version-compare.ts` path, so existing imports keep working.
|
|
26
|
+
*
|
|
27
|
+
* NOTE ON PRERELEASE SEMANTICS: this is STRICT semver §11 — `1.0.49-rc.2` is
|
|
28
|
+
* BELOW `1.0.49`, because a prerelease precedes its own release. That is the
|
|
29
|
+
* correct rule for "would installing this move me backwards?", which is the
|
|
30
|
+
* only question this module is used to answer. It deliberately differs from
|
|
31
|
+
* `oss/packages/web-core/src/utils/version-update.ts`, whose
|
|
32
|
+
* `isDaemonBehindTarget` treats an rc as up-to-date against its own base
|
|
33
|
+
* release so the dashboard does not nag preview users with an update banner.
|
|
34
|
+
* Those are two different questions; do not collapse them into one helper.
|
|
35
|
+
*/
|
|
36
|
+
/** Parsed semver fields. Build metadata (`+…`) is discarded: it never affects precedence (§10). */
|
|
37
|
+
export interface ParsedSemver {
|
|
38
|
+
readonly major: number;
|
|
39
|
+
readonly minor: number;
|
|
40
|
+
readonly patch: number;
|
|
41
|
+
/** Dot-separated prerelease identifiers; empty for a release build. */
|
|
42
|
+
readonly prerelease: readonly string[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parse a semver string, tolerating a leading `v` (npm/CLI output carries it
|
|
46
|
+
* inconsistently). Returns null for anything unparsable so callers can fail
|
|
47
|
+
* closed rather than guess.
|
|
48
|
+
*/
|
|
49
|
+
export declare function parseSemver(version: unknown): ParsedSemver | null;
|
|
50
|
+
/**
|
|
51
|
+
* Compare two versions by semver precedence.
|
|
52
|
+
*
|
|
53
|
+
* @returns -1 when `a` precedes `b`, 0 when equal, 1 when `a` succeeds `b`, and
|
|
54
|
+
* **null when either side is unparsable** — callers MUST treat null as
|
|
55
|
+
* "direction unknown" and fail closed rather than coercing it to a number
|
|
56
|
+
* (`null` compares as `0` in JS numeric contexts, which would read as "equal").
|
|
57
|
+
*/
|
|
58
|
+
export declare function compareSemver(a: unknown, b: unknown): number | null;
|
|
59
|
+
/**
|
|
60
|
+
* Would installing `target` move a daemon currently on `current` BACKWARDS?
|
|
61
|
+
*
|
|
62
|
+
* Returns false when the direction cannot be established (either version
|
|
63
|
+
* unparsable) — an unknown direction must never block an upgrade, because the
|
|
64
|
+
* cost of a false block (the whole fleet can no longer be upgraded) is far
|
|
65
|
+
* higher than the cost of a missed downgrade guard. Equal versions are NOT a
|
|
66
|
+
* downgrade, so a same-version reinstall stays allowed.
|
|
67
|
+
*/
|
|
68
|
+
export declare function isDowngrade(current: unknown, target: unknown): boolean;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ws-protocol — shared string-literal unions for the daemon↔server WS surface
|
|
3
|
+
* and the daemon↔dashboard P2P DataChannel surface.
|
|
4
|
+
*
|
|
5
|
+
* Fragmentation audit: these message types existed as a TypeScript union in
|
|
6
|
+
* exactly ONE package (the proprietary daemon-cloud's server-connection.ts),
|
|
7
|
+
* which is a leaf CONSUMER — the other two participants (the Workers server
|
|
8
|
+
* and OSS daemon-core, which is the primary `status_report` producer) matched
|
|
9
|
+
* bare string literals by hand. Renaming `auth_ok` server-side would compile
|
|
10
|
+
* everywhere and leave the daemon reconnecting forever. Pure literals, zero
|
|
11
|
+
* runtime deps — the textbook mesh-shared leaf.
|
|
12
|
+
*
|
|
13
|
+
* SCOPE HONESTY: this file declares the OSS-visible protocol surface. The
|
|
14
|
+
* proprietary repo's server-connection.ts remains the authority for the full
|
|
15
|
+
* ServerToDaemon command set; it should adopt these unions and extend them
|
|
16
|
+
* (`ServerToDaemonMsg | <proprietary extras>`) rather than re-declaring the
|
|
17
|
+
* shared members. Members here are the ones OSS daemon-core itself produces
|
|
18
|
+
* or matches.
|
|
19
|
+
*/
|
|
20
|
+
/** Messages the daemon sends UP to the Workers server over the WS bridge. */
|
|
21
|
+
export type DaemonToServerWsMsg = 'auth' | 'status_report' | 'status_heartbeat' | 'status_event' | 'command_result' | 'error' | 'agent_event' | 'log';
|
|
22
|
+
/** Server→daemon control messages the OSS engine reacts to. */
|
|
23
|
+
export type ServerToDaemonWsMsg = 'auth_ok' | 'auth_error' | 'machine_evicted' | 'force_disconnect' | 'token_revoked' | 'version_mismatch' | 'force_update_required' | 'command' | 'agent_command' | 'resolve_action';
|
|
24
|
+
/** P2P signaling relayed through the server WS. */
|
|
25
|
+
export type P2PSignalingWsMsg = 'p2p_ready' | 'offer' | 'answer' | 'ice' | 'mesh_p2p_ready' | 'mesh_p2p_offer' | 'mesh_p2p_answer' | 'mesh_p2p_ice';
|
|
26
|
+
/**
|
|
27
|
+
* Dashboard↔daemon P2P DataChannel JSON message kinds. Previously matched as
|
|
28
|
+
* hand-synced literals on both ends with NO shared symbol anywhere —
|
|
29
|
+
* `p2p_evicted` had exactly two occurrences repo-wide (emit + handle).
|
|
30
|
+
*/
|
|
31
|
+
export type DashboardP2PMessageKind = 'ping' | 'pong' | 'status_report' | 'status_event' | 'p2p_evicted' | 'command' | 'command_result' | 'command_result_chunk' | 'screenshot_start' | 'screenshot_stop' | 'pty_input' | 'pty_resize';
|
|
32
|
+
export declare const DAEMON_TO_SERVER_WS_MSGS: readonly DaemonToServerWsMsg[];
|
|
33
|
+
export declare const SERVER_TO_DAEMON_WS_MSGS: readonly ServerToDaemonWsMsg[];
|
|
34
|
+
export declare function isDaemonToServerWsMsg(value: unknown): value is DaemonToServerWsMsg;
|
|
35
|
+
export declare function isServerToDaemonWsMsg(value: unknown): value is ServerToDaemonWsMsg;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/mesh-tool-names.ts
CHANGED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semver precedence comparison — the single version-ordering primitive for the
|
|
3
|
+
* daemon's upgrade paths.
|
|
4
|
+
*
|
|
5
|
+
* Why this exists: the upgrade path used to decide "is this a no-op?" with a
|
|
6
|
+
* raw string equality check (`currentInstalled === latest`) and nothing else.
|
|
7
|
+
* Equality answers "is it the same version?" but never "which one is newer?",
|
|
8
|
+
* so any target that merely differed from the running build was installed —
|
|
9
|
+
* including one that is OLDER. That is how a node running `1.0.49-rc.2`
|
|
10
|
+
* silently got rolled back to `1.0.48`.
|
|
11
|
+
*
|
|
12
|
+
* String comparison cannot fix it either: `'1.0.49-rc.2' < '1.0.48'` is TRUE
|
|
13
|
+
* lexicographically (the '4' in "-rc.2"'s prefix never gets that far — '9' vs
|
|
14
|
+
* '8' at index 4 decides it, and even where it works `rc.10` sorts below
|
|
15
|
+
* `rc.9`). Only field-wise numeric comparison with semver §11 prerelease rules
|
|
16
|
+
* gives the right answer.
|
|
17
|
+
*
|
|
18
|
+
* This module is a PURE LEAF: zero imports, no I/O. It lives in mesh-shared
|
|
19
|
+
* (fragmentation audit) so BOTH the OSS daemon and the proprietary Workers
|
|
20
|
+
* server (`packages/server/src/utils/version-policy.ts`, previously a
|
|
21
|
+
* byte-identical independent copy) can consume ONE implementation — the two
|
|
22
|
+
* gate the same auto-update decision from opposite ends, and a drift between
|
|
23
|
+
* them can produce an unbreakable update-nag loop (server says behind, daemon
|
|
24
|
+
* gate refuses the "upgrade" as a rollback). daemon-core re-exports this from
|
|
25
|
+
* its original `version-compare.ts` path, so existing imports keep working.
|
|
26
|
+
*
|
|
27
|
+
* NOTE ON PRERELEASE SEMANTICS: this is STRICT semver §11 — `1.0.49-rc.2` is
|
|
28
|
+
* BELOW `1.0.49`, because a prerelease precedes its own release. That is the
|
|
29
|
+
* correct rule for "would installing this move me backwards?", which is the
|
|
30
|
+
* only question this module is used to answer. It deliberately differs from
|
|
31
|
+
* `oss/packages/web-core/src/utils/version-update.ts`, whose
|
|
32
|
+
* `isDaemonBehindTarget` treats an rc as up-to-date against its own base
|
|
33
|
+
* release so the dashboard does not nag preview users with an update banner.
|
|
34
|
+
* Those are two different questions; do not collapse them into one helper.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/** Parsed semver fields. Build metadata (`+…`) is discarded: it never affects precedence (§10). */
|
|
38
|
+
export interface ParsedSemver {
|
|
39
|
+
readonly major: number;
|
|
40
|
+
readonly minor: number;
|
|
41
|
+
readonly patch: number;
|
|
42
|
+
/** Dot-separated prerelease identifiers; empty for a release build. */
|
|
43
|
+
readonly prerelease: readonly string[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const SEMVER_PATTERN = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
47
|
+
const NUMERIC_IDENTIFIER = /^\d+$/;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Parse a semver string, tolerating a leading `v` (npm/CLI output carries it
|
|
51
|
+
* inconsistently). Returns null for anything unparsable so callers can fail
|
|
52
|
+
* closed rather than guess.
|
|
53
|
+
*/
|
|
54
|
+
export function parseSemver(version: unknown): ParsedSemver | null {
|
|
55
|
+
if (typeof version !== 'string') return null;
|
|
56
|
+
const match = version.trim().replace(/^v/, '').match(SEMVER_PATTERN);
|
|
57
|
+
if (!match) return null;
|
|
58
|
+
return {
|
|
59
|
+
major: Number(match[1]),
|
|
60
|
+
minor: Number(match[2]),
|
|
61
|
+
patch: Number(match[3]),
|
|
62
|
+
prerelease: match[4] ? match[4].split('.') : [],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Semver §11 prerelease precedence: a release outranks its own prereleases;
|
|
68
|
+
* numeric identifiers compare numerically (so rc.10 > rc.9) and rank below
|
|
69
|
+
* alphanumeric ones; alphanumerics compare lexically; a shorter identifier
|
|
70
|
+
* list ranks below an otherwise-equal longer one.
|
|
71
|
+
*/
|
|
72
|
+
function comparePrerelease(a: readonly string[], b: readonly string[]): number {
|
|
73
|
+
if (a.length === 0 && b.length === 0) return 0;
|
|
74
|
+
// An empty prerelease list means "release build", which outranks any prerelease.
|
|
75
|
+
if (a.length === 0) return 1;
|
|
76
|
+
if (b.length === 0) return -1;
|
|
77
|
+
for (let i = 0; i < Math.min(a.length, b.length); i += 1) {
|
|
78
|
+
const idA = a[i];
|
|
79
|
+
const idB = b[i];
|
|
80
|
+
if (idA === idB) continue;
|
|
81
|
+
const numA = NUMERIC_IDENTIFIER.test(idA);
|
|
82
|
+
const numB = NUMERIC_IDENTIFIER.test(idB);
|
|
83
|
+
if (numA && numB) return Number(idA) < Number(idB) ? -1 : 1;
|
|
84
|
+
if (numA) return -1;
|
|
85
|
+
if (numB) return 1;
|
|
86
|
+
return idA < idB ? -1 : 1;
|
|
87
|
+
}
|
|
88
|
+
return a.length === b.length ? 0 : (a.length < b.length ? -1 : 1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Compare two versions by semver precedence.
|
|
93
|
+
*
|
|
94
|
+
* @returns -1 when `a` precedes `b`, 0 when equal, 1 when `a` succeeds `b`, and
|
|
95
|
+
* **null when either side is unparsable** — callers MUST treat null as
|
|
96
|
+
* "direction unknown" and fail closed rather than coercing it to a number
|
|
97
|
+
* (`null` compares as `0` in JS numeric contexts, which would read as "equal").
|
|
98
|
+
*/
|
|
99
|
+
export function compareSemver(a: unknown, b: unknown): number | null {
|
|
100
|
+
const pa = parseSemver(a);
|
|
101
|
+
const pb = parseSemver(b);
|
|
102
|
+
if (!pa || !pb) return null;
|
|
103
|
+
if (pa.major !== pb.major) return pa.major < pb.major ? -1 : 1;
|
|
104
|
+
if (pa.minor !== pb.minor) return pa.minor < pb.minor ? -1 : 1;
|
|
105
|
+
if (pa.patch !== pb.patch) return pa.patch < pb.patch ? -1 : 1;
|
|
106
|
+
return comparePrerelease(pa.prerelease, pb.prerelease);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Would installing `target` move a daemon currently on `current` BACKWARDS?
|
|
111
|
+
*
|
|
112
|
+
* Returns false when the direction cannot be established (either version
|
|
113
|
+
* unparsable) — an unknown direction must never block an upgrade, because the
|
|
114
|
+
* cost of a false block (the whole fleet can no longer be upgraded) is far
|
|
115
|
+
* higher than the cost of a missed downgrade guard. Equal versions are NOT a
|
|
116
|
+
* downgrade, so a same-version reinstall stays allowed.
|
|
117
|
+
*/
|
|
118
|
+
export function isDowngrade(current: unknown, target: unknown): boolean {
|
|
119
|
+
const direction = compareSemver(target, current);
|
|
120
|
+
if (direction === null) return false;
|
|
121
|
+
return direction < 0;
|
|
122
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ws-protocol — shared string-literal unions for the daemon↔server WS surface
|
|
3
|
+
* and the daemon↔dashboard P2P DataChannel surface.
|
|
4
|
+
*
|
|
5
|
+
* Fragmentation audit: these message types existed as a TypeScript union in
|
|
6
|
+
* exactly ONE package (the proprietary daemon-cloud's server-connection.ts),
|
|
7
|
+
* which is a leaf CONSUMER — the other two participants (the Workers server
|
|
8
|
+
* and OSS daemon-core, which is the primary `status_report` producer) matched
|
|
9
|
+
* bare string literals by hand. Renaming `auth_ok` server-side would compile
|
|
10
|
+
* everywhere and leave the daemon reconnecting forever. Pure literals, zero
|
|
11
|
+
* runtime deps — the textbook mesh-shared leaf.
|
|
12
|
+
*
|
|
13
|
+
* SCOPE HONESTY: this file declares the OSS-visible protocol surface. The
|
|
14
|
+
* proprietary repo's server-connection.ts remains the authority for the full
|
|
15
|
+
* ServerToDaemon command set; it should adopt these unions and extend them
|
|
16
|
+
* (`ServerToDaemonMsg | <proprietary extras>`) rather than re-declaring the
|
|
17
|
+
* shared members. Members here are the ones OSS daemon-core itself produces
|
|
18
|
+
* or matches.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** Messages the daemon sends UP to the Workers server over the WS bridge. */
|
|
22
|
+
export type DaemonToServerWsMsg =
|
|
23
|
+
| 'auth'
|
|
24
|
+
| 'status_report'
|
|
25
|
+
| 'status_heartbeat'
|
|
26
|
+
| 'status_event'
|
|
27
|
+
| 'command_result'
|
|
28
|
+
| 'error'
|
|
29
|
+
| 'agent_event'
|
|
30
|
+
| 'log';
|
|
31
|
+
|
|
32
|
+
/** Server→daemon control messages the OSS engine reacts to. */
|
|
33
|
+
export type ServerToDaemonWsMsg =
|
|
34
|
+
| 'auth_ok'
|
|
35
|
+
| 'auth_error'
|
|
36
|
+
| 'machine_evicted'
|
|
37
|
+
| 'force_disconnect'
|
|
38
|
+
| 'token_revoked'
|
|
39
|
+
| 'version_mismatch'
|
|
40
|
+
| 'force_update_required'
|
|
41
|
+
| 'command'
|
|
42
|
+
| 'agent_command'
|
|
43
|
+
| 'resolve_action';
|
|
44
|
+
|
|
45
|
+
/** P2P signaling relayed through the server WS. */
|
|
46
|
+
export type P2PSignalingWsMsg =
|
|
47
|
+
| 'p2p_ready'
|
|
48
|
+
| 'offer'
|
|
49
|
+
| 'answer'
|
|
50
|
+
| 'ice'
|
|
51
|
+
| 'mesh_p2p_ready'
|
|
52
|
+
| 'mesh_p2p_offer'
|
|
53
|
+
| 'mesh_p2p_answer'
|
|
54
|
+
| 'mesh_p2p_ice';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Dashboard↔daemon P2P DataChannel JSON message kinds. Previously matched as
|
|
58
|
+
* hand-synced literals on both ends with NO shared symbol anywhere —
|
|
59
|
+
* `p2p_evicted` had exactly two occurrences repo-wide (emit + handle).
|
|
60
|
+
*/
|
|
61
|
+
export type DashboardP2PMessageKind =
|
|
62
|
+
| 'ping'
|
|
63
|
+
| 'pong'
|
|
64
|
+
| 'status_report'
|
|
65
|
+
| 'status_event'
|
|
66
|
+
| 'p2p_evicted'
|
|
67
|
+
| 'command'
|
|
68
|
+
| 'command_result'
|
|
69
|
+
| 'command_result_chunk'
|
|
70
|
+
| 'screenshot_start'
|
|
71
|
+
| 'screenshot_stop'
|
|
72
|
+
| 'pty_input'
|
|
73
|
+
| 'pty_resize';
|
|
74
|
+
|
|
75
|
+
export const DAEMON_TO_SERVER_WS_MSGS: readonly DaemonToServerWsMsg[] = [
|
|
76
|
+
'auth', 'status_report', 'status_heartbeat', 'status_event', 'command_result', 'error', 'agent_event', 'log',
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
export const SERVER_TO_DAEMON_WS_MSGS: readonly ServerToDaemonWsMsg[] = [
|
|
80
|
+
'auth_ok', 'auth_error', 'machine_evicted', 'force_disconnect', 'token_revoked',
|
|
81
|
+
'version_mismatch', 'force_update_required', 'command', 'agent_command', 'resolve_action',
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
export function isDaemonToServerWsMsg(value: unknown): value is DaemonToServerWsMsg {
|
|
85
|
+
return typeof value === 'string' && (DAEMON_TO_SERVER_WS_MSGS as readonly string[]).includes(value);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function isServerToDaemonWsMsg(value: unknown): value is ServerToDaemonWsMsg {
|
|
89
|
+
return typeof value === 'string' && (SERVER_TO_DAEMON_WS_MSGS as readonly string[]).includes(value);
|
|
90
|
+
}
|