@pelotto-tech/bellwether 0.0.0 → 0.1.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/LICENSE +202 -0
- package/README.md +228 -1
- package/dist/agents/claude.d.ts +8 -0
- package/dist/agents/claude.js +63 -0
- package/dist/agents/claude.js.map +1 -0
- package/dist/agents/copilot.d.ts +7 -0
- package/dist/agents/copilot.js +39 -0
- package/dist/agents/copilot.js.map +1 -0
- package/dist/agents/index.d.ts +5 -0
- package/dist/agents/index.js +8 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/paths.d.ts +2 -0
- package/dist/agents/paths.js +5 -0
- package/dist/agents/paths.js.map +1 -0
- package/dist/agents/types.d.ts +29 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +38 -0
- package/dist/install.js +104 -0
- package/dist/install.js.map +1 -0
- package/dist/json-file.d.ts +12 -0
- package/dist/json-file.js +33 -0
- package/dist/json-file.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +75 -0
- package/dist/main.js.map +1 -0
- package/dist/roles.d.ts +3 -0
- package/dist/roles.js +13 -0
- package/dist/roles.js.map +1 -0
- package/dist/run.d.ts +9 -0
- package/dist/run.js +41 -0
- package/dist/run.js.map +1 -0
- package/dist/skill.d.ts +9 -0
- package/dist/skill.js +65 -0
- package/dist/skill.js.map +1 -0
- package/package.json +53 -6
- package/runtime/adapter/dist/actions.d.ts +15 -0
- package/runtime/adapter/dist/actions.js +7 -0
- package/runtime/adapter/dist/actions.js.map +1 -0
- package/runtime/adapter/dist/bin.d.ts +2 -0
- package/runtime/adapter/dist/bin.js +121 -0
- package/runtime/adapter/dist/bin.js.map +1 -0
- package/runtime/adapter/dist/config.d.ts +41 -0
- package/runtime/adapter/dist/config.js +71 -0
- package/runtime/adapter/dist/config.js.map +1 -0
- package/runtime/adapter/dist/core.d.ts +8 -0
- package/runtime/adapter/dist/core.js +10 -0
- package/runtime/adapter/dist/core.js.map +1 -0
- package/runtime/adapter/dist/herdr/connection.d.ts +34 -0
- package/runtime/adapter/dist/herdr/connection.js +137 -0
- package/runtime/adapter/dist/herdr/connection.js.map +1 -0
- package/runtime/adapter/dist/herdr/index.d.ts +5 -0
- package/runtime/adapter/dist/herdr/index.js +5 -0
- package/runtime/adapter/dist/herdr/index.js.map +1 -0
- package/runtime/adapter/dist/herdr/mapper.d.ts +27 -0
- package/runtime/adapter/dist/herdr/mapper.js +141 -0
- package/runtime/adapter/dist/herdr/mapper.js.map +1 -0
- package/runtime/adapter/dist/herdr/paths.d.ts +29 -0
- package/runtime/adapter/dist/herdr/paths.js +89 -0
- package/runtime/adapter/dist/herdr/paths.js.map +1 -0
- package/runtime/adapter/dist/herdr/protocol.d.ts +102 -0
- package/runtime/adapter/dist/herdr/protocol.js +19 -0
- package/runtime/adapter/dist/herdr/protocol.js.map +1 -0
- package/runtime/adapter/dist/herdr/source.d.ts +99 -0
- package/runtime/adapter/dist/herdr/source.js +316 -0
- package/runtime/adapter/dist/herdr/source.js.map +1 -0
- package/runtime/adapter/dist/index.d.ts +6 -0
- package/runtime/adapter/dist/index.js +7 -0
- package/runtime/adapter/dist/index.js.map +1 -0
- package/runtime/adapter/dist/mock.d.ts +33 -0
- package/runtime/adapter/dist/mock.js +130 -0
- package/runtime/adapter/dist/mock.js.map +1 -0
- package/runtime/adapter/dist/random.d.ts +3 -0
- package/runtime/adapter/dist/random.js +18 -0
- package/runtime/adapter/dist/random.js.map +1 -0
- package/runtime/adapter/dist/recording.d.ts +22 -0
- package/runtime/adapter/dist/recording.js +52 -0
- package/runtime/adapter/dist/recording.js.map +1 -0
- package/runtime/adapter/dist/roles.d.ts +16 -0
- package/runtime/adapter/dist/roles.js +21 -0
- package/runtime/adapter/dist/roles.js.map +1 -0
- package/runtime/adapter/dist/rollup.d.ts +5 -0
- package/runtime/adapter/dist/rollup.js +18 -0
- package/runtime/adapter/dist/rollup.js.map +1 -0
- package/runtime/adapter/dist/scrub.d.ts +9 -0
- package/runtime/adapter/dist/scrub.js +56 -0
- package/runtime/adapter/dist/scrub.js.map +1 -0
- package/runtime/adapter/dist/server.d.ts +47 -0
- package/runtime/adapter/dist/server.js +119 -0
- package/runtime/adapter/dist/server.js.map +1 -0
- package/runtime/adapter/dist/source.d.ts +20 -0
- package/runtime/adapter/dist/source.js +14 -0
- package/runtime/adapter/dist/source.js.map +1 -0
- package/runtime/adapter/dist/types.d.ts +66 -0
- package/runtime/adapter/dist/types.js +23 -0
- package/runtime/adapter/dist/types.js.map +1 -0
- package/runtime/adapter/dist/world.d.ts +9 -0
- package/runtime/adapter/dist/world.js +64 -0
- package/runtime/adapter/dist/world.js.map +1 -0
- package/runtime/adapter/package.json +37 -0
- package/runtime/renderer/dist/assets/BitmapFont-CrMu5gVf.js +6 -0
- package/runtime/renderer/dist/assets/CanvasRenderer-BJUwGe2K.js +1 -0
- package/runtime/renderer/dist/assets/Filter-CYMWP98C.js +1 -0
- package/runtime/renderer/dist/assets/RenderTargetSystem-CUv6yCH8.js +184 -0
- package/runtime/renderer/dist/assets/WebGLRenderer-DT-aSeEc.js +156 -0
- package/runtime/renderer/dist/assets/WebGPURenderer-CV0poHB6.js +75 -0
- package/runtime/renderer/dist/assets/browserAll-BpE2Jy31.js +14 -0
- package/runtime/renderer/dist/assets/getTexelRangeRects-BCdgu8cV.js +195 -0
- package/runtime/renderer/dist/assets/index-BgIYSiaY.js +296 -0
- package/runtime/renderer/dist/assets/webworkerAll-DEtPMT-J.js +83 -0
- package/runtime/renderer/dist/index.html +36 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
3
|
+
import { createSource, loadSourceConfig } from './config.js';
|
|
4
|
+
import { MockSource } from './mock.js';
|
|
5
|
+
import { recordTo, ReplaySource } from './recording.js';
|
|
6
|
+
import { scrubDelta, scrubFile } from './scrub.js';
|
|
7
|
+
import { DEFAULT_PORT, DELTA_PATH, DeltaServer } from './server.js';
|
|
8
|
+
const USAGE = `bellwether-adapter: stream Herdr world deltas over WebSocket
|
|
9
|
+
|
|
10
|
+
Source (default from bellwether.toml / BELLWETHER_SOURCE, else mock):
|
|
11
|
+
--live read the live Herdr TUI socket API
|
|
12
|
+
--mock generate mock agents
|
|
13
|
+
--replay <file> replay a recorded .jsonl (loops)
|
|
14
|
+
--session <name> live: one named session --all live: every running session
|
|
15
|
+
--socket <path> live: explicit socket/pipe path
|
|
16
|
+
--config <file> config file (default bellwether.toml)
|
|
17
|
+
--seed <n> mock seed (default 1)
|
|
18
|
+
--interval <ms> mock delta interval (default 1500)
|
|
19
|
+
--speed <n> replay speed multiplier (default 1)
|
|
20
|
+
|
|
21
|
+
Output:
|
|
22
|
+
--port <n> WebSocket port (default ${DEFAULT_PORT}); deltas on ${DELTA_PATH}
|
|
23
|
+
--serve <dir> also serve a built renderer from <dir>
|
|
24
|
+
--record <file> append every delta to a .jsonl file
|
|
25
|
+
--scrub with --record: hash repo/branch/workspace labels, strip say text and titles
|
|
26
|
+
--scrub-file <in> <out> scrub an existing .jsonl recording and exit
|
|
27
|
+
--actions let the overlay send prompts and keys to agents (focus is always allowed)
|
|
28
|
+
--pack <name> skin pack for the served overlay (default from bellwether.toml, else neutral)
|
|
29
|
+
--print print every delta to stdout as JSON lines
|
|
30
|
+
-h, --help`;
|
|
31
|
+
const { values, positionals } = parseArgs({
|
|
32
|
+
options: {
|
|
33
|
+
live: { type: 'boolean' },
|
|
34
|
+
mock: { type: 'boolean' },
|
|
35
|
+
replay: { type: 'string' },
|
|
36
|
+
session: { type: 'string' },
|
|
37
|
+
all: { type: 'boolean' },
|
|
38
|
+
socket: { type: 'string' },
|
|
39
|
+
config: { type: 'string' },
|
|
40
|
+
seed: { type: 'string' },
|
|
41
|
+
interval: { type: 'string' },
|
|
42
|
+
speed: { type: 'string' },
|
|
43
|
+
port: { type: 'string' },
|
|
44
|
+
serve: { type: 'string' },
|
|
45
|
+
record: { type: 'string' },
|
|
46
|
+
scrub: { type: 'boolean' },
|
|
47
|
+
actions: { type: 'boolean' },
|
|
48
|
+
'scrub-file': { type: 'string' },
|
|
49
|
+
print: { type: 'boolean' },
|
|
50
|
+
pack: { type: 'string' },
|
|
51
|
+
help: { type: 'boolean', short: 'h' },
|
|
52
|
+
},
|
|
53
|
+
allowPositionals: true,
|
|
54
|
+
});
|
|
55
|
+
let scrubConfig = false;
|
|
56
|
+
let actionsConfig = false;
|
|
57
|
+
let clientPack = values.pack;
|
|
58
|
+
if (values.help) {
|
|
59
|
+
console.log(USAGE);
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}
|
|
62
|
+
if (values['scrub-file']) {
|
|
63
|
+
const out = positionals[0];
|
|
64
|
+
if (!out) {
|
|
65
|
+
process.stderr.write('usage: --scrub-file <in.jsonl> <out.jsonl>\n');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
const n = scrubFile(values['scrub-file'], out);
|
|
69
|
+
process.stderr.write(`bellwether-adapter: scrubbed ${n} deltas into ${out}\n`);
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
const log = (m) => process.stderr.write(m + '\n');
|
|
73
|
+
async function pickSource() {
|
|
74
|
+
if (values.replay) {
|
|
75
|
+
return ReplaySource.fromFile(values.replay, { speed: Number(values.speed ?? 1), loop: true });
|
|
76
|
+
}
|
|
77
|
+
const cfg = await loadSourceConfig(values.config ?? 'bellwether.toml');
|
|
78
|
+
if (values.pack)
|
|
79
|
+
cfg.pack = values.pack;
|
|
80
|
+
clientPack = cfg.pack ?? clientPack;
|
|
81
|
+
scrubConfig = cfg.scrub ?? false;
|
|
82
|
+
actionsConfig = cfg.actions ?? false;
|
|
83
|
+
if (values.live)
|
|
84
|
+
cfg.source = 'live';
|
|
85
|
+
if (values.mock)
|
|
86
|
+
cfg.source = 'mock';
|
|
87
|
+
if (values.session)
|
|
88
|
+
cfg.herdr.sessions = [values.session];
|
|
89
|
+
if (values.all)
|
|
90
|
+
cfg.herdr.sessions = 'all';
|
|
91
|
+
if (values.socket)
|
|
92
|
+
cfg.herdr.socket = values.socket;
|
|
93
|
+
log(`bellwether-adapter: source=${cfg.source}`);
|
|
94
|
+
return createSource(cfg, {
|
|
95
|
+
log,
|
|
96
|
+
mock: () => new MockSource({ seed: Number(values.seed ?? 1), intervalMs: Number(values.interval ?? 1500) }),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const source = await pickSource();
|
|
100
|
+
const server = new DeltaServer({ port: Number(values.port ?? DEFAULT_PORT), staticDir: values.serve, clientConfig: clientPack ? { pack: clientPack } : {}, actions: values.actions || actionsConfig, log });
|
|
101
|
+
server.attach(source);
|
|
102
|
+
if (values.record) {
|
|
103
|
+
const rec = recordTo(values.record);
|
|
104
|
+
const scrubOn = values.scrub || scrubConfig;
|
|
105
|
+
source.on('delta', scrubOn ? (d) => rec(scrubDelta(d)) : rec);
|
|
106
|
+
}
|
|
107
|
+
if (values.print)
|
|
108
|
+
source.on('delta', (d) => process.stdout.write(JSON.stringify(d) + '\n'));
|
|
109
|
+
const port = await server.listen();
|
|
110
|
+
await source.start();
|
|
111
|
+
log(`bellwether-adapter: deltas on ws://127.0.0.1:${port}${DELTA_PATH}`);
|
|
112
|
+
if (values.serve)
|
|
113
|
+
log(`bellwether-adapter: overlay at http://127.0.0.1:${port}/`);
|
|
114
|
+
const shutdown = async () => {
|
|
115
|
+
await source.stop();
|
|
116
|
+
await server.close();
|
|
117
|
+
process.exit(0);
|
|
118
|
+
};
|
|
119
|
+
process.on('SIGINT', shutdown);
|
|
120
|
+
process.on('SIGTERM', shutdown);
|
|
121
|
+
//# sourceMappingURL=bin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { WorldSource } from './source.js';
|
|
2
|
+
export type SourceKind = 'mock' | 'live';
|
|
3
|
+
export interface SourceConfig {
|
|
4
|
+
source: SourceKind;
|
|
5
|
+
/** Skin pack the overlay shows (a folder name under themes/). The renderer falls back to neutral if it is unknown. */
|
|
6
|
+
pack?: string;
|
|
7
|
+
/** Scrub recordings at record time (`scrub = true`). */
|
|
8
|
+
scrub?: boolean;
|
|
9
|
+
/** Let the overlay send prompts and keys to agents (`actions = true`). Focus is always allowed. */
|
|
10
|
+
actions?: boolean;
|
|
11
|
+
herdr: {
|
|
12
|
+
/** `"all"` discovers running sessions; a list names them; omitted uses HERDR_SESSION or default. */
|
|
13
|
+
sessions?: 'all' | string[];
|
|
14
|
+
socket?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export declare const DEFAULT_CONFIG: SourceConfig;
|
|
18
|
+
/**
|
|
19
|
+
* Parse the source section of `bellwether.toml`:
|
|
20
|
+
*
|
|
21
|
+
* ```toml
|
|
22
|
+
* source = "live" # or "mock"
|
|
23
|
+
* pack = "aesir" # skin pack: neutral, aesir, wayfarers, or a private theme folder
|
|
24
|
+
* scrub = true # hash labels and strip say text in recordings
|
|
25
|
+
* actions = true # let the overlay prompt and send keys to agents (focus is always on)
|
|
26
|
+
* [herdr]
|
|
27
|
+
* sessions = "all" # or ["default", "overlay-dev"]
|
|
28
|
+
* # socket = "/path/to/herdr.sock"
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseSourceConfig(text: string): SourceConfig;
|
|
32
|
+
/** Load config from a file (missing file means defaults), then apply env overrides. */
|
|
33
|
+
export declare function loadSourceConfig(file?: string, env?: NodeJS.ProcessEnv): Promise<SourceConfig>;
|
|
34
|
+
export interface CreateSourceDeps {
|
|
35
|
+
log?: (msg: string) => void;
|
|
36
|
+
/** Factories, overridable in tests. */
|
|
37
|
+
live?: (cfg: SourceConfig) => WorldSource;
|
|
38
|
+
mock?: (cfg: SourceConfig) => WorldSource;
|
|
39
|
+
}
|
|
40
|
+
/** Pick the world source named by config. */
|
|
41
|
+
export declare function createSource(cfg: SourceConfig, deps?: CreateSourceDeps): WorldSource;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { parse } from 'smol-toml';
|
|
3
|
+
import { HerdrSource } from './herdr/source.js';
|
|
4
|
+
import { MockSource } from './mock.js';
|
|
5
|
+
export const DEFAULT_CONFIG = { source: 'mock', herdr: {} };
|
|
6
|
+
/**
|
|
7
|
+
* Parse the source section of `bellwether.toml`:
|
|
8
|
+
*
|
|
9
|
+
* ```toml
|
|
10
|
+
* source = "live" # or "mock"
|
|
11
|
+
* pack = "aesir" # skin pack: neutral, aesir, wayfarers, or a private theme folder
|
|
12
|
+
* scrub = true # hash labels and strip say text in recordings
|
|
13
|
+
* actions = true # let the overlay prompt and send keys to agents (focus is always on)
|
|
14
|
+
* [herdr]
|
|
15
|
+
* sessions = "all" # or ["default", "overlay-dev"]
|
|
16
|
+
* # socket = "/path/to/herdr.sock"
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function parseSourceConfig(text) {
|
|
20
|
+
const raw = parse(text);
|
|
21
|
+
const source = raw.source ?? DEFAULT_CONFIG.source;
|
|
22
|
+
if (source !== 'mock' && source !== 'live')
|
|
23
|
+
throw new Error(`bellwether.toml: source must be "mock" or "live", got ${JSON.stringify(source)}`);
|
|
24
|
+
const h = (raw.herdr ?? {});
|
|
25
|
+
const herdr = {};
|
|
26
|
+
if (h.sessions !== undefined) {
|
|
27
|
+
if (h.sessions === 'all')
|
|
28
|
+
herdr.sessions = 'all';
|
|
29
|
+
else if (typeof h.sessions === 'string')
|
|
30
|
+
herdr.sessions = [h.sessions];
|
|
31
|
+
else if (Array.isArray(h.sessions) && h.sessions.every((s) => typeof s === 'string'))
|
|
32
|
+
herdr.sessions = h.sessions;
|
|
33
|
+
else
|
|
34
|
+
throw new Error('bellwether.toml: herdr.sessions must be "all", a name, or a list of names');
|
|
35
|
+
}
|
|
36
|
+
if (typeof h.socket === 'string')
|
|
37
|
+
herdr.socket = h.socket;
|
|
38
|
+
if (raw.pack !== undefined && (typeof raw.pack !== 'string' || !/^[a-z0-9][a-z0-9_-]*$/i.test(raw.pack))) {
|
|
39
|
+
throw new Error('bellwether.toml: pack must be a theme folder name');
|
|
40
|
+
}
|
|
41
|
+
if (raw.scrub !== undefined && typeof raw.scrub !== 'boolean')
|
|
42
|
+
throw new Error('bellwether.toml: scrub must be true or false');
|
|
43
|
+
if (raw.actions !== undefined && typeof raw.actions !== 'boolean')
|
|
44
|
+
throw new Error('bellwether.toml: actions must be true or false');
|
|
45
|
+
return { source, ...(raw.actions === true ? { actions: true } : {}), ...(raw.scrub === true ? { scrub: true } : {}), ...(typeof raw.pack === 'string' ? { pack: raw.pack } : {}), herdr };
|
|
46
|
+
}
|
|
47
|
+
/** Load config from a file (missing file means defaults), then apply env overrides. */
|
|
48
|
+
export async function loadSourceConfig(file = 'bellwether.toml', env = process.env) {
|
|
49
|
+
let cfg = { ...DEFAULT_CONFIG, herdr: {} };
|
|
50
|
+
try {
|
|
51
|
+
cfg = parseSourceConfig(await readFile(file, 'utf8'));
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
if (err.code !== 'ENOENT')
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
const override = env.BELLWETHER_SOURCE;
|
|
58
|
+
if (override === 'mock' || override === 'live')
|
|
59
|
+
cfg.source = override;
|
|
60
|
+
if (env.BELLWETHER_PACK && /^[a-z0-9][a-z0-9_-]*$/i.test(env.BELLWETHER_PACK))
|
|
61
|
+
cfg.pack = env.BELLWETHER_PACK;
|
|
62
|
+
return cfg;
|
|
63
|
+
}
|
|
64
|
+
/** Pick the world source named by config. */
|
|
65
|
+
export function createSource(cfg, deps = {}) {
|
|
66
|
+
if (cfg.source === 'live') {
|
|
67
|
+
return deps.live ? deps.live(cfg) : new HerdrSource({ sessions: cfg.herdr.sessions, socket: cfg.herdr.socket, log: deps.log });
|
|
68
|
+
}
|
|
69
|
+
return deps.mock ? deps.mock(cfg) : new MockSource();
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAoBvC,MAAM,CAAC,MAAM,cAAc,GAAiB,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAA4B,CAAC;IACnD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM,CAAC;IACnD,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC/I,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAC;IACvD,MAAM,KAAK,GAA0B,EAAE,CAAC;IACxC,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,CAAC,CAAC,QAAQ,KAAK,KAAK;YAAE,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;aAC5C,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ;YAAE,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;aAClE,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;YAAE,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAoB,CAAC;;YACzH,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;QAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1D,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACzG,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAC/H,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACrI,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;AAC5L,CAAC;AAED,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAI,GAAG,iBAAiB,EAAE,MAAyB,OAAO,CAAC,GAAG;IACnG,IAAI,GAAG,GAAiB,EAAE,GAAG,cAAc,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACzD,IAAI,CAAC;QACH,GAAG,GAAG,iBAAiB,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,GAAG,CAAC;IAClE,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,CAAC,iBAAiB,CAAC;IACvC,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,MAAM;QAAE,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC;IACtE,IAAI,GAAG,CAAC,eAAe,IAAI,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC;QAAE,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC;IAC9G,OAAO,GAAG,CAAC;AACb,CAAC;AASD,6CAA6C;AAC7C,MAAM,UAAU,YAAY,CAAC,GAAiB,EAAE,OAAyB,EAAE;IACzE,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACjI,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,EAAE,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Browser-safe entry: no Node built-ins. The renderer imports from here.
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
export * from './rollup.js';
|
|
4
|
+
export * from './roles.js';
|
|
5
|
+
export * from './world.js';
|
|
6
|
+
export * from './source.js';
|
|
7
|
+
export * from './actions.js';
|
|
8
|
+
export * from './mock.js';
|
|
9
|
+
export { createRng } from './random.js';
|
|
10
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import net from 'node:net';
|
|
3
|
+
import type { SuccessResponse } from './protocol.js';
|
|
4
|
+
export declare class HerdrError extends Error {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
constructor(code: string, message: string);
|
|
7
|
+
}
|
|
8
|
+
export type Connector = (connectPath: string) => net.Socket;
|
|
9
|
+
/**
|
|
10
|
+
* One NDJSON connection to a Herdr server socket (Unix socket or Windows named pipe).
|
|
11
|
+
*
|
|
12
|
+
* Events:
|
|
13
|
+
* - `event` (EventLine) pushed lines on a subscription connection
|
|
14
|
+
* - `error` (Error) a request-less error, e.g. `events_lost` on a subscription
|
|
15
|
+
* - `close` () the socket closed
|
|
16
|
+
*/
|
|
17
|
+
export declare class HerdrConnection extends EventEmitter {
|
|
18
|
+
private readonly socket;
|
|
19
|
+
private buf;
|
|
20
|
+
private seq;
|
|
21
|
+
private pending;
|
|
22
|
+
private closed;
|
|
23
|
+
private constructor();
|
|
24
|
+
static open(connectPath: string, connector?: Connector, timeoutMs?: number): Promise<HerdrConnection>;
|
|
25
|
+
get isClosed(): boolean;
|
|
26
|
+
request(method: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<SuccessResponse['result']>;
|
|
27
|
+
/** Start a subscription on this connection. Resolves on `subscription_started`. */
|
|
28
|
+
subscribe(subscriptions: Array<Record<string, unknown>>, timeoutMs?: number): Promise<void>;
|
|
29
|
+
close(): void;
|
|
30
|
+
private onData;
|
|
31
|
+
private onLine;
|
|
32
|
+
private failAll;
|
|
33
|
+
private onClose;
|
|
34
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import net from 'node:net';
|
|
3
|
+
import { isError, isEvent } from './protocol.js';
|
|
4
|
+
export class HerdrError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
constructor(code, message) {
|
|
7
|
+
super(`${code}: ${message}`);
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.name = 'HerdrError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const defaultConnector = (p) => net.connect(p);
|
|
13
|
+
/**
|
|
14
|
+
* One NDJSON connection to a Herdr server socket (Unix socket or Windows named pipe).
|
|
15
|
+
*
|
|
16
|
+
* Events:
|
|
17
|
+
* - `event` (EventLine) pushed lines on a subscription connection
|
|
18
|
+
* - `error` (Error) a request-less error, e.g. `events_lost` on a subscription
|
|
19
|
+
* - `close` () the socket closed
|
|
20
|
+
*/
|
|
21
|
+
export class HerdrConnection extends EventEmitter {
|
|
22
|
+
socket;
|
|
23
|
+
buf = '';
|
|
24
|
+
seq = 0;
|
|
25
|
+
pending = new Map();
|
|
26
|
+
closed = false;
|
|
27
|
+
constructor(socket) {
|
|
28
|
+
super();
|
|
29
|
+
this.socket = socket;
|
|
30
|
+
socket.setEncoding('utf8');
|
|
31
|
+
socket.on('data', (chunk) => this.onData(chunk));
|
|
32
|
+
socket.on('close', () => this.onClose());
|
|
33
|
+
socket.on('error', (err) => this.failAll(err));
|
|
34
|
+
}
|
|
35
|
+
static open(connectPath, connector = defaultConnector, timeoutMs = 5000) {
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
const socket = connector(connectPath);
|
|
38
|
+
const timer = setTimeout(() => {
|
|
39
|
+
socket.destroy();
|
|
40
|
+
reject(new HerdrError('connect_timeout', `no answer from ${connectPath}`));
|
|
41
|
+
}, timeoutMs);
|
|
42
|
+
socket.once('connect', () => {
|
|
43
|
+
clearTimeout(timer);
|
|
44
|
+
socket.removeListener('error', onErr);
|
|
45
|
+
resolve(new HerdrConnection(socket));
|
|
46
|
+
});
|
|
47
|
+
const onErr = (err) => {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
reject(err);
|
|
50
|
+
};
|
|
51
|
+
socket.once('error', onErr);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
get isClosed() {
|
|
55
|
+
return this.closed;
|
|
56
|
+
}
|
|
57
|
+
request(method, params = {}, timeoutMs = 10_000) {
|
|
58
|
+
if (this.closed)
|
|
59
|
+
return Promise.reject(new HerdrError('closed', 'connection closed'));
|
|
60
|
+
const id = `bw_${++this.seq}`;
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
const p = { resolve, reject };
|
|
63
|
+
if (timeoutMs > 0) {
|
|
64
|
+
p.timer = setTimeout(() => {
|
|
65
|
+
this.pending.delete(id);
|
|
66
|
+
reject(new HerdrError('timeout', `${method} timed out`));
|
|
67
|
+
}, timeoutMs);
|
|
68
|
+
}
|
|
69
|
+
this.pending.set(id, p);
|
|
70
|
+
this.socket.write(JSON.stringify({ id, method, params }) + '\n');
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** Start a subscription on this connection. Resolves on `subscription_started`. */
|
|
74
|
+
async subscribe(subscriptions, timeoutMs = 10_000) {
|
|
75
|
+
const res = await this.request('events.subscribe', { subscriptions }, timeoutMs);
|
|
76
|
+
if (res.type !== 'subscription_started')
|
|
77
|
+
throw new HerdrError('unexpected', `subscribe answered ${res.type}`);
|
|
78
|
+
}
|
|
79
|
+
close() {
|
|
80
|
+
if (this.closed)
|
|
81
|
+
return;
|
|
82
|
+
this.socket.destroy();
|
|
83
|
+
}
|
|
84
|
+
onData(chunk) {
|
|
85
|
+
this.buf += chunk;
|
|
86
|
+
let nl;
|
|
87
|
+
while ((nl = this.buf.indexOf('\n')) >= 0) {
|
|
88
|
+
const raw = this.buf.slice(0, nl).trim();
|
|
89
|
+
this.buf = this.buf.slice(nl + 1);
|
|
90
|
+
if (!raw)
|
|
91
|
+
continue;
|
|
92
|
+
let line;
|
|
93
|
+
try {
|
|
94
|
+
line = JSON.parse(raw);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
continue; // tolerate garbage lines
|
|
98
|
+
}
|
|
99
|
+
this.onLine(line);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
onLine(line) {
|
|
103
|
+
if (isEvent(line)) {
|
|
104
|
+
this.emit('event', line);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const p = this.pending.get(line.id);
|
|
108
|
+
if (p) {
|
|
109
|
+
this.pending.delete(line.id);
|
|
110
|
+
if (p.timer)
|
|
111
|
+
clearTimeout(p.timer);
|
|
112
|
+
if (isError(line))
|
|
113
|
+
p.reject(new HerdrError(line.error.code, line.error.message));
|
|
114
|
+
else
|
|
115
|
+
p.resolve(line.result);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (isError(line)) {
|
|
119
|
+
// e.g. events_lost, sent with the original subscription id after it started
|
|
120
|
+
this.emit('error', new HerdrError(line.error.code, line.error.message));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
failAll(err) {
|
|
124
|
+
for (const [, p] of this.pending) {
|
|
125
|
+
if (p.timer)
|
|
126
|
+
clearTimeout(p.timer);
|
|
127
|
+
p.reject(err);
|
|
128
|
+
}
|
|
129
|
+
this.pending.clear();
|
|
130
|
+
}
|
|
131
|
+
onClose() {
|
|
132
|
+
this.closed = true;
|
|
133
|
+
this.failAll(new HerdrError('closed', 'connection closed'));
|
|
134
|
+
this.emit('close');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/herdr/connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { HerdrConnection, HerdrError, type Connector } from './connection.js';
|
|
2
|
+
export * from './mapper.js';
|
|
3
|
+
export * from './paths.js';
|
|
4
|
+
export { HerdrSessionSource, HerdrSource, type LiveOptions, type SessionSourceOptions } from './source.js';
|
|
5
|
+
export type * from './protocol.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/herdr/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAkB,MAAM,iBAAiB,CAAC;AAC9E,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAA+C,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Delta, Member, Party, Status } from '../types.js';
|
|
2
|
+
import type { AgentInfo, AgentStatusChanged, PaneInfo, SessionSnapshot, WorkspaceInfo } from './protocol.js';
|
|
3
|
+
export declare function toStatus(s: unknown): Status;
|
|
4
|
+
/** Party ids are unique across sessions: `<session>/<workspace_id>`. */
|
|
5
|
+
export declare function partyId(session: string, workspaceId: string): string;
|
|
6
|
+
export interface MapContext {
|
|
7
|
+
session: string;
|
|
8
|
+
/** Branch names learned from worktree events, keyed by workspace_id. */
|
|
9
|
+
branches?: ReadonlyMap<string, string>;
|
|
10
|
+
}
|
|
11
|
+
export declare function memberFromPane(pane: PaneInfo | AgentInfo): Member | undefined;
|
|
12
|
+
export declare function partyFromWorkspace(ws: WorkspaceInfo, members: Record<string, Member>, ctx: MapContext): Party;
|
|
13
|
+
/** Build every party for one session from `session.snapshot`. Agent records win over pane records. */
|
|
14
|
+
export declare function partiesFromSnapshot(snap: SessionSnapshot, ctx: MapContext): Record<string, Party>;
|
|
15
|
+
/** Every pane id in the snapshot, for per-pane status subscriptions. */
|
|
16
|
+
export declare function paneIds(snap: SessionSnapshot): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Apply a `pane.agent_status_changed` event. Returns the updated party, or
|
|
19
|
+
* undefined when the pane is not a known member (caller should re-read).
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyStatusChange(parties: Record<string, Party>, ev: AgentStatusChanged, ctx: MapContext): {
|
|
22
|
+
party: Party;
|
|
23
|
+
member: Member;
|
|
24
|
+
rollupChanged: boolean;
|
|
25
|
+
} | undefined;
|
|
26
|
+
/** Deltas that turn `prev` into `next`. New parties and header changes send the whole party. */
|
|
27
|
+
export declare function diffParties(prev: Record<string, Party>, next: Record<string, Party>, t: number): Delta[];
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// Pure mapping from Herdr protocol records to the Bellwether world model.
|
|
2
|
+
import { resolveRole } from '../roles.js';
|
|
3
|
+
import { rollup } from '../rollup.js';
|
|
4
|
+
const STATUSES = new Set(['working', 'done', 'blocked', 'idle', 'unknown']);
|
|
5
|
+
export function toStatus(s) {
|
|
6
|
+
return typeof s === 'string' && STATUSES.has(s) ? s : 'unknown';
|
|
7
|
+
}
|
|
8
|
+
/** Party ids are unique across sessions: `<session>/<workspace_id>`. */
|
|
9
|
+
export function partyId(session, workspaceId) {
|
|
10
|
+
return `${session}/${workspaceId}`;
|
|
11
|
+
}
|
|
12
|
+
export function memberFromPane(pane) {
|
|
13
|
+
if (!pane.agent)
|
|
14
|
+
return undefined;
|
|
15
|
+
const tokens = pane.tokens ?? {};
|
|
16
|
+
const name = 'name' in pane ? pane.name : undefined;
|
|
17
|
+
const seq = 'state_change_seq' in pane ? pane.state_change_seq : undefined;
|
|
18
|
+
const m = {
|
|
19
|
+
paneId: pane.pane_id,
|
|
20
|
+
agent: pane.agent,
|
|
21
|
+
role: resolveRole({ tokens, agentName: name, title: pane.title }),
|
|
22
|
+
status: toStatus(pane.agent_status),
|
|
23
|
+
lastChange: seq ?? pane.revision ?? 0,
|
|
24
|
+
};
|
|
25
|
+
if (pane.title)
|
|
26
|
+
m.title = pane.title;
|
|
27
|
+
if (tokens.say)
|
|
28
|
+
m.say = tokens.say;
|
|
29
|
+
return m;
|
|
30
|
+
}
|
|
31
|
+
export function partyFromWorkspace(ws, members, ctx) {
|
|
32
|
+
const list = Object.values(members);
|
|
33
|
+
const p = {
|
|
34
|
+
id: partyId(ctx.session, ws.workspace_id),
|
|
35
|
+
label: ws.label,
|
|
36
|
+
session: ctx.session,
|
|
37
|
+
isWorktree: ws.worktree?.is_linked_worktree ?? false,
|
|
38
|
+
status: list.length ? rollup(list) : toStatus(ws.agent_status),
|
|
39
|
+
members,
|
|
40
|
+
tokens: { ...(ws.tokens ?? {}) },
|
|
41
|
+
};
|
|
42
|
+
if (ws.worktree?.repo_name)
|
|
43
|
+
p.repo = ws.worktree.repo_name;
|
|
44
|
+
const branch = ctx.branches?.get(ws.workspace_id);
|
|
45
|
+
if (branch)
|
|
46
|
+
p.branch = branch;
|
|
47
|
+
return p;
|
|
48
|
+
}
|
|
49
|
+
/** Build every party for one session from `session.snapshot`. Agent records win over pane records. */
|
|
50
|
+
export function partiesFromSnapshot(snap, ctx) {
|
|
51
|
+
const byWs = new Map();
|
|
52
|
+
const seen = new Set();
|
|
53
|
+
for (const rec of [...(snap.agents ?? []), ...(snap.panes ?? [])]) {
|
|
54
|
+
if (seen.has(rec.pane_id))
|
|
55
|
+
continue;
|
|
56
|
+
const m = memberFromPane(rec);
|
|
57
|
+
if (!m)
|
|
58
|
+
continue;
|
|
59
|
+
seen.add(rec.pane_id);
|
|
60
|
+
let ms = byWs.get(rec.workspace_id);
|
|
61
|
+
if (!ms)
|
|
62
|
+
byWs.set(rec.workspace_id, (ms = {}));
|
|
63
|
+
ms[m.paneId] = m;
|
|
64
|
+
}
|
|
65
|
+
const out = {};
|
|
66
|
+
for (const ws of snap.workspaces) {
|
|
67
|
+
// A workspace with no agents has nothing to show; it appears once an agent starts.
|
|
68
|
+
const members = byWs.get(ws.workspace_id);
|
|
69
|
+
if (!members)
|
|
70
|
+
continue;
|
|
71
|
+
const p = partyFromWorkspace(ws, members, ctx);
|
|
72
|
+
out[p.id] = p;
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
/** Every pane id in the snapshot, for per-pane status subscriptions. */
|
|
77
|
+
export function paneIds(snap) {
|
|
78
|
+
return [...new Set((snap.panes ?? []).map((p) => p.pane_id))].sort();
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Apply a `pane.agent_status_changed` event. Returns the updated party, or
|
|
82
|
+
* undefined when the pane is not a known member (caller should re-read).
|
|
83
|
+
*/
|
|
84
|
+
export function applyStatusChange(parties, ev, ctx) {
|
|
85
|
+
const party = parties[partyId(ctx.session, ev.workspace_id)];
|
|
86
|
+
const prev = party?.members[ev.pane_id];
|
|
87
|
+
if (!party || !prev)
|
|
88
|
+
return undefined;
|
|
89
|
+
const member = { ...prev, status: toStatus(ev.agent_status), lastChange: prev.lastChange + 1 };
|
|
90
|
+
if (ev.agent)
|
|
91
|
+
member.agent = ev.agent;
|
|
92
|
+
if (ev.title)
|
|
93
|
+
member.title = ev.title;
|
|
94
|
+
const members = { ...party.members, [member.paneId]: member };
|
|
95
|
+
const status = rollup(Object.values(members));
|
|
96
|
+
const next = { ...party, members, status };
|
|
97
|
+
return { party: next, member, rollupChanged: status !== party.status };
|
|
98
|
+
}
|
|
99
|
+
function sameMember(a, b) {
|
|
100
|
+
return a.agent === b.agent && a.role === b.role && a.status === b.status && a.title === b.title && a.say === b.say;
|
|
101
|
+
}
|
|
102
|
+
function samePartyHeader(a, b) {
|
|
103
|
+
return (a.label === b.label &&
|
|
104
|
+
a.repo === b.repo &&
|
|
105
|
+
a.branch === b.branch &&
|
|
106
|
+
a.isWorktree === b.isWorktree &&
|
|
107
|
+
a.status === b.status &&
|
|
108
|
+
a.session === b.session &&
|
|
109
|
+
JSON.stringify(a.tokens) === JSON.stringify(b.tokens));
|
|
110
|
+
}
|
|
111
|
+
/** Deltas that turn `prev` into `next`. New parties and header changes send the whole party. */
|
|
112
|
+
export function diffParties(prev, next, t) {
|
|
113
|
+
const out = [];
|
|
114
|
+
for (const id of Object.keys(prev))
|
|
115
|
+
if (!next[id])
|
|
116
|
+
out.push({ t, kind: 'removed', partyId: id });
|
|
117
|
+
for (const [id, np] of Object.entries(next)) {
|
|
118
|
+
const op = prev[id];
|
|
119
|
+
if (!op) {
|
|
120
|
+
out.push({ t, kind: 'party', party: np });
|
|
121
|
+
for (const m of Object.values(np.members))
|
|
122
|
+
if (m.say)
|
|
123
|
+
out.push({ t, kind: 'say', partyId: id, paneId: m.paneId, text: m.say });
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
for (const paneId of Object.keys(op.members))
|
|
127
|
+
if (!np.members[paneId])
|
|
128
|
+
out.push({ t, kind: 'removed', partyId: id, paneId });
|
|
129
|
+
for (const [paneId, nm] of Object.entries(np.members)) {
|
|
130
|
+
const om = op.members[paneId];
|
|
131
|
+
if (!om || !sameMember(om, nm))
|
|
132
|
+
out.push({ t, kind: 'member', partyId: id, member: nm });
|
|
133
|
+
if (nm.say && nm.say !== om?.say)
|
|
134
|
+
out.push({ t, kind: 'say', partyId: id, paneId, text: nm.say });
|
|
135
|
+
}
|
|
136
|
+
if (!samePartyHeader(op, np))
|
|
137
|
+
out.push({ t, kind: 'party', party: np });
|
|
138
|
+
}
|
|
139
|
+
return out;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=mapper.js.map
|