@fnndsc/brasa 0.14.0 → 0.15.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/dist/buildinfo.json +1 -1
- package/dist/builtins/fs/ls.d.ts +2 -0
- package/dist/builtins/fs/ls.js +3 -3
- package/dist/builtins/fs/ls.js.map +1 -1
- package/dist/builtins/help.js +6 -1
- package/dist/builtins/help.js.map +1 -1
- package/dist/builtins/proc.js +57 -1
- package/dist/builtins/proc.js.map +1 -1
- package/dist/builtins/procWatch.d.ts +69 -0
- package/dist/builtins/procWatch.js +215 -0
- package/dist/builtins/procWatch.js.map +1 -0
- package/dist/builtins/res/feed.diagram.d.ts +6 -4
- package/dist/builtins/res/feed.diagram.js +91 -30
- package/dist/builtins/res/feed.diagram.js.map +1 -1
- package/dist/core/ambient.d.ts +34 -0
- package/dist/core/ambient.js +38 -0
- package/dist/core/ambient.js.map +1 -0
- package/dist/core/engine.d.ts +26 -1
- package/dist/core/engine.js +13 -0
- package/dist/core/engine.js.map +1 -1
- package/dist/lib/vfs/vfs.d.ts +40 -8
- package/dist/lib/vfs/vfs.js +68 -47
- package/dist/lib/vfs/vfs.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { ambient_publish } from '../core/ambient.js';
|
|
2
|
+
let depsLoading = null;
|
|
3
|
+
/** Loads the sampler's collaborators once, on the first watch. */
|
|
4
|
+
function deps_get() {
|
|
5
|
+
if (depsLoading === null) {
|
|
6
|
+
depsLoading = Promise.all([
|
|
7
|
+
import('@fnndsc/cumin'),
|
|
8
|
+
import('@fnndsc/salsa'),
|
|
9
|
+
import('./res/feed.diagram.js'),
|
|
10
|
+
]).then(([cumin, salsa, dag]) => ({ cumin, salsa, dag }));
|
|
11
|
+
}
|
|
12
|
+
return depsLoading;
|
|
13
|
+
}
|
|
14
|
+
/** Sampling period while a watched feed keeps changing. */
|
|
15
|
+
export const WATCH_FLOOR_MS = 3000;
|
|
16
|
+
/** Sampling period a quiet watched feed backs off to. */
|
|
17
|
+
export const WATCH_CAP_MS = 30000;
|
|
18
|
+
const watches = new Map();
|
|
19
|
+
/**
|
|
20
|
+
* Parses a watch subject into a feed id: `/proc/jobs/feed_N`, `feed_N`, or
|
|
21
|
+
* a bare number.
|
|
22
|
+
*
|
|
23
|
+
* @param subject - The subject address as a surface or operator wrote it.
|
|
24
|
+
* @returns The feed id, or null when the subject is not a feed.
|
|
25
|
+
*/
|
|
26
|
+
export function watchSubject_parse(subject) {
|
|
27
|
+
const match = /(?:^|\/)feed_(\d+)\/?$/.exec(subject.trim()) ?? /^(\d+)$/.exec(subject.trim());
|
|
28
|
+
if (!match)
|
|
29
|
+
return null;
|
|
30
|
+
const feedID = Number(match[1]);
|
|
31
|
+
return Number.isInteger(feedID) && feedID > 0 ? feedID : null;
|
|
32
|
+
}
|
|
33
|
+
/** The subject address a feed watch is reported under. */
|
|
34
|
+
function subject_of(feedID) {
|
|
35
|
+
return `/proc/jobs/feed_${feedID}`;
|
|
36
|
+
}
|
|
37
|
+
/** Records and publishes a watch's state when it changed. */
|
|
38
|
+
function state_set(watch, state) {
|
|
39
|
+
if (watch.state === state)
|
|
40
|
+
return;
|
|
41
|
+
watch.state = state;
|
|
42
|
+
ambient_publish({ kind: 'watched', subject: subject_of(watch.feedID), state });
|
|
43
|
+
}
|
|
44
|
+
/** Whether a feed can no longer change: every cached node terminal and no work pending. */
|
|
45
|
+
function feed_isSettled(cumin, salsa, cache, feedID) {
|
|
46
|
+
const feed = cache.feed_get(feedID);
|
|
47
|
+
return feed !== undefined && salsa.feedCached_isSettled(cache, feedID) && !cumin.feed_isActive(feed);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Builds and publishes the feed's current model. The build itself runs the
|
|
51
|
+
* visit delta (coalesced with any visit of the last second), so a first
|
|
52
|
+
* tick on a never-visited feed loads it here.
|
|
53
|
+
*
|
|
54
|
+
* @param watch - The watch being sampled.
|
|
55
|
+
* @returns True when a model went out.
|
|
56
|
+
*/
|
|
57
|
+
async function model_publish(dag, watch) {
|
|
58
|
+
const envelope = await dag.feedDag_handle(watch.feedID, undefined, 0, false);
|
|
59
|
+
if (envelope.status !== 'ok')
|
|
60
|
+
return false;
|
|
61
|
+
ambient_publish({ kind: 'envelope', envelope });
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* One sampler tick: visit the feed, publish a model when the visit changed
|
|
66
|
+
* anything, then either settle, back off, or re-arm at the floor.
|
|
67
|
+
*
|
|
68
|
+
* @param watch - The watch being sampled.
|
|
69
|
+
*/
|
|
70
|
+
async function watch_tick(watch) {
|
|
71
|
+
if (watch.ticking)
|
|
72
|
+
return;
|
|
73
|
+
watch.ticking = true;
|
|
74
|
+
const { cumin, salsa, dag } = await deps_get();
|
|
75
|
+
const cache = cumin.procCache_get();
|
|
76
|
+
try {
|
|
77
|
+
let changed = watch.first;
|
|
78
|
+
const listener_remove = cache.changeListener_add((change) => {
|
|
79
|
+
if (change.scope === 'all' || (change.scope === 'feed' && change.feedID === watch.feedID))
|
|
80
|
+
changed = true;
|
|
81
|
+
});
|
|
82
|
+
let synced;
|
|
83
|
+
try {
|
|
84
|
+
synced = watch.first ? true : await salsa.feedVisit_sync(watch.feedID);
|
|
85
|
+
if (changed) {
|
|
86
|
+
const published = await model_publish(dag, watch);
|
|
87
|
+
synced = synced && published;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
listener_remove();
|
|
92
|
+
}
|
|
93
|
+
watch.first = false;
|
|
94
|
+
if (!watches.has(watch.feedID))
|
|
95
|
+
return;
|
|
96
|
+
if (!synced) {
|
|
97
|
+
state_set(watch, 'stale');
|
|
98
|
+
watch.delayMs = WATCH_CAP_MS;
|
|
99
|
+
}
|
|
100
|
+
else if (feed_isSettled(cumin, salsa, cache, watch.feedID)) {
|
|
101
|
+
state_set(watch, 'settled');
|
|
102
|
+
watch_stop(watch);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
state_set(watch, 'live');
|
|
107
|
+
watch.delayMs = changed ? WATCH_FLOOR_MS : Math.min(WATCH_CAP_MS, watch.delayMs * 2);
|
|
108
|
+
}
|
|
109
|
+
watch_arm(watch, watch.delayMs);
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
watch.ticking = false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** Schedules the next tick. */
|
|
116
|
+
function watch_arm(watch, delayMs) {
|
|
117
|
+
if (watch.timer)
|
|
118
|
+
clearTimeout(watch.timer);
|
|
119
|
+
watch.timer = setTimeout(() => {
|
|
120
|
+
watch.timer = null;
|
|
121
|
+
void watch_tick(watch);
|
|
122
|
+
}, delayMs);
|
|
123
|
+
watch.timer.unref();
|
|
124
|
+
}
|
|
125
|
+
/** Ends a watch entirely: no timer, no entry. */
|
|
126
|
+
function watch_stop(watch) {
|
|
127
|
+
if (watch.timer)
|
|
128
|
+
clearTimeout(watch.timer);
|
|
129
|
+
watch.timer = null;
|
|
130
|
+
watches.delete(watch.feedID);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Opens (or joins) a watch on a feed for one owner. A new watch samples
|
|
134
|
+
* immediately; joining an existing one changes nothing but the owner set.
|
|
135
|
+
* A watch on a feed that turns out settled runs one tick, reports
|
|
136
|
+
* `settled`, and ends.
|
|
137
|
+
*
|
|
138
|
+
* @param feedID - The feed to keep live.
|
|
139
|
+
* @param owner - Who holds the watch.
|
|
140
|
+
* @returns The watch's current state.
|
|
141
|
+
*/
|
|
142
|
+
export function procWatch_add(feedID, owner) {
|
|
143
|
+
const existing = watches.get(feedID);
|
|
144
|
+
if (existing) {
|
|
145
|
+
existing.owners.add(owner);
|
|
146
|
+
return existing.state;
|
|
147
|
+
}
|
|
148
|
+
const watch = {
|
|
149
|
+
feedID,
|
|
150
|
+
owners: new Set([owner]),
|
|
151
|
+
state: 'live',
|
|
152
|
+
delayMs: WATCH_FLOOR_MS,
|
|
153
|
+
timer: null,
|
|
154
|
+
ticking: false,
|
|
155
|
+
first: true,
|
|
156
|
+
};
|
|
157
|
+
watches.set(feedID, watch);
|
|
158
|
+
void watch_tick(watch);
|
|
159
|
+
return watch.state;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Releases one owner's hold on a feed watch; the last release stops the
|
|
163
|
+
* sampler.
|
|
164
|
+
*
|
|
165
|
+
* @param feedID - The watched feed.
|
|
166
|
+
* @param owner - The owner letting go.
|
|
167
|
+
*/
|
|
168
|
+
export function procWatch_remove(feedID, owner) {
|
|
169
|
+
const watch = watches.get(feedID);
|
|
170
|
+
if (!watch)
|
|
171
|
+
return;
|
|
172
|
+
watch.owners.delete(owner);
|
|
173
|
+
if (watch.owners.size === 0)
|
|
174
|
+
watch_stop(watch);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Releases every watch one owner holds.
|
|
178
|
+
*
|
|
179
|
+
* @param owner - The owner letting go of everything.
|
|
180
|
+
*/
|
|
181
|
+
export function procWatch_release(owner) {
|
|
182
|
+
for (const watch of Array.from(watches.values()))
|
|
183
|
+
procWatch_remove(watch.feedID, owner);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Reports a feed's watch state: the sampler's last finding while watched,
|
|
187
|
+
* or `settled` once nothing watches it (a released or settled watch has
|
|
188
|
+
* nothing live to say).
|
|
189
|
+
*
|
|
190
|
+
* @param feedID - The feed in question.
|
|
191
|
+
* @returns The state.
|
|
192
|
+
*/
|
|
193
|
+
export function procWatch_state(feedID) {
|
|
194
|
+
return watches.get(feedID)?.state ?? 'settled';
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Lists the session's watches.
|
|
198
|
+
*
|
|
199
|
+
* @returns One entry per watched feed.
|
|
200
|
+
*/
|
|
201
|
+
export function procWatch_list() {
|
|
202
|
+
return Array.from(watches.values()).map((watch) => ({
|
|
203
|
+
feedID: watch.feedID,
|
|
204
|
+
owners: watch.owners.size,
|
|
205
|
+
state: watch.state,
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Ends every watch (tests, and engine teardown).
|
|
210
|
+
*/
|
|
211
|
+
export function procWatch_reset() {
|
|
212
|
+
for (const watch of Array.from(watches.values()))
|
|
213
|
+
watch_stop(watch);
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=procWatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"procWatch.js","sourceRoot":"","sources":["../../src/builtins/procWatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,10 +13,12 @@ export type DiagramDialect = 'signalflow';
|
|
|
13
13
|
*/
|
|
14
14
|
export declare function feedDiagram_handle(feedId: number, dialect: DiagramDialect): Promise<CommandEnvelope>;
|
|
15
15
|
/**
|
|
16
|
-
* Projects a built feed graph onto the wire's `feed.dag` model
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* Projects a built feed graph onto the wire's `feed.dag` model — COLLAPSED:
|
|
17
|
+
* isomorphic sibling subtrees merge into one ×N node (the terminal tree's
|
|
18
|
+
* own collapse transform), so an 88k-instance fan-out crosses the wire and
|
|
19
|
+
* reaches the scene as its shape, not its census. Each node keeps a real
|
|
20
|
+
* representative instance (id, data address), a worst-member status, summed
|
|
21
|
+
* metrics, and — for groups — a tally with jump-to-error anomalies.
|
|
20
22
|
*
|
|
21
23
|
* @param graph - The cache-first feed graph.
|
|
22
24
|
* @returns The typed model payload.
|
|
@@ -21,6 +21,7 @@ import { envelope_ok, envelope_error } from '@fnndsc/cumin';
|
|
|
21
21
|
import { feedDiagramNodes_build, feedTree_render } from './feed.tree.render.js';
|
|
22
22
|
import { signalflowDoc_build } from './feed.tree.signalflow.js';
|
|
23
23
|
import { DAG_MODEL_KINDS, dagNodeStatusSchema, } from '@fnndsc/menu';
|
|
24
|
+
import { collapse_build } from './feed.tree.collapse.js';
|
|
24
25
|
/**
|
|
25
26
|
* Handles `feed diagram --<dialect> <feedId>`. Emits the diagram document to stdout for the
|
|
26
27
|
* user to pipe into a renderer.
|
|
@@ -45,42 +46,102 @@ export async function feedDiagram_handle(feedId, dialect) {
|
|
|
45
46
|
return envelope_ok(yaml, { kind: DAG_MODEL_KINDS.feedDag, data: feedDagModel_build(graph) });
|
|
46
47
|
}
|
|
47
48
|
/**
|
|
48
|
-
* Projects a built feed graph onto the wire's `feed.dag` model
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
49
|
+
* Projects a built feed graph onto the wire's `feed.dag` model — COLLAPSED:
|
|
50
|
+
* isomorphic sibling subtrees merge into one ×N node (the terminal tree's
|
|
51
|
+
* own collapse transform), so an 88k-instance fan-out crosses the wire and
|
|
52
|
+
* reaches the scene as its shape, not its census. Each node keeps a real
|
|
53
|
+
* representative instance (id, data address), a worst-member status, summed
|
|
54
|
+
* metrics, and — for groups — a tally with jump-to-error anomalies.
|
|
52
55
|
*
|
|
53
56
|
* @param graph - The cache-first feed graph.
|
|
54
57
|
* @returns The typed model payload.
|
|
55
58
|
*/
|
|
56
59
|
export function feedDagModel_build(graph) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
: undefined;
|
|
67
|
-
const metrics = {
|
|
68
|
-
...(computeSeconds !== undefined && !Number.isNaN(computeSeconds) ? { computeSeconds } : {}),
|
|
69
|
-
...(node.outputBytes !== undefined ? { dataBytes: node.outputBytes } : {}),
|
|
70
|
-
};
|
|
71
|
-
return {
|
|
72
|
-
id: String(node.id),
|
|
73
|
-
label: node.pluginName,
|
|
74
|
-
parentIds: node.parentID === null ? [] : [String(node.parentID)],
|
|
75
|
-
joinParentIds: node.joinParentIDs.map((joinId) => String(joinId)),
|
|
76
|
-
instanceId: node.id,
|
|
77
|
-
pluginName: node.pluginName,
|
|
78
|
-
status,
|
|
79
|
-
vfsPath: `/proc/jobs/feed_${graph.feedID}/${node.pluginName}_${node.id}/data`,
|
|
80
|
-
...(Object.keys(metrics).length > 0 ? { metrics } : {}),
|
|
81
|
-
};
|
|
82
|
-
}),
|
|
60
|
+
const byId = new Map(graph.nodes.map((n) => [n.id, n]));
|
|
61
|
+
const collapsed = collapse_build(graph, graph.rootIDs);
|
|
62
|
+
// Join edges name original instance ids; a member inside a group is
|
|
63
|
+
// addressed through its representative.
|
|
64
|
+
const repOf = new Map();
|
|
65
|
+
const reps_walk = (node) => {
|
|
66
|
+
for (const member of node.memberIds)
|
|
67
|
+
repOf.set(member, node.memberIds[0]);
|
|
68
|
+
node.children.forEach(reps_walk);
|
|
83
69
|
};
|
|
70
|
+
collapsed.forEach(reps_walk);
|
|
71
|
+
const nodes = [];
|
|
72
|
+
const emit = (node, parentRep) => {
|
|
73
|
+
const rep = node.memberIds[0];
|
|
74
|
+
const members = node.memberIds.map((id) => byId.get(id));
|
|
75
|
+
// Group metrics are sums: total compute spent and total bytes produced
|
|
76
|
+
// are the honest figures for an ×N — and the molecule scales by them.
|
|
77
|
+
let computeSeconds = 0;
|
|
78
|
+
let seenSeconds = false;
|
|
79
|
+
let dataBytes = 0;
|
|
80
|
+
let seenBytes = false;
|
|
81
|
+
for (const member of members) {
|
|
82
|
+
if (member.startedAt !== undefined && member.finishedAt !== undefined) {
|
|
83
|
+
const seconds = (Date.parse(member.finishedAt) - Date.parse(member.startedAt)) / 1000;
|
|
84
|
+
if (!Number.isNaN(seconds)) {
|
|
85
|
+
computeSeconds += Math.max(0, seconds);
|
|
86
|
+
seenSeconds = true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (member.outputBytes !== undefined) {
|
|
90
|
+
dataBytes += member.outputBytes;
|
|
91
|
+
seenBytes = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const metrics = {
|
|
95
|
+
...(seenSeconds ? { computeSeconds } : {}),
|
|
96
|
+
...(seenBytes ? { dataBytes } : {}),
|
|
97
|
+
};
|
|
98
|
+
// A group's status is its worst member's class — an error anywhere in
|
|
99
|
+
// the set must be visible on the one node that stands for it.
|
|
100
|
+
const status = node.count === 1
|
|
101
|
+
? dagNodeStatusSchema.parse(members[0].status ?? 'unknown')
|
|
102
|
+
: node.tally.error > 0
|
|
103
|
+
? 'finishedWithError'
|
|
104
|
+
: node.tally.running > 0
|
|
105
|
+
? 'started'
|
|
106
|
+
: node.tally.other > 0
|
|
107
|
+
? 'unknown'
|
|
108
|
+
: 'finishedSuccessfully';
|
|
109
|
+
nodes.push({
|
|
110
|
+
id: String(rep),
|
|
111
|
+
label: node.count === 1 ? node.pluginName : `${node.pluginName} \u00d7${node.count}`,
|
|
112
|
+
parentIds: parentRep === null ? [] : [String(parentRep)],
|
|
113
|
+
joinParentIds: node.joinParentIDs.map((joinId) => String(repOf.get(joinId) ?? joinId)),
|
|
114
|
+
instanceId: rep,
|
|
115
|
+
pluginName: node.pluginName,
|
|
116
|
+
status,
|
|
117
|
+
vfsPath: `/proc/jobs/feed_${graph.feedID}/${node.pluginName}_${rep}/data`,
|
|
118
|
+
...(Object.keys(metrics).length > 0 ? { metrics } : {}),
|
|
119
|
+
...(node.count > 1
|
|
120
|
+
? {
|
|
121
|
+
tally: {
|
|
122
|
+
count: node.count,
|
|
123
|
+
done: node.tally.done,
|
|
124
|
+
error: node.tally.error,
|
|
125
|
+
running: node.tally.running,
|
|
126
|
+
other: node.tally.other,
|
|
127
|
+
...(node.anomalies.length > 0
|
|
128
|
+
? {
|
|
129
|
+
anomalies: node.anomalies.slice(0, 12).map((a) => ({
|
|
130
|
+
id: String(a.id),
|
|
131
|
+
status: dagNodeStatusSchema.parse(a.status ?? 'unknown'),
|
|
132
|
+
})),
|
|
133
|
+
}
|
|
134
|
+
: {}),
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
: {}),
|
|
138
|
+
});
|
|
139
|
+
for (const child of node.children)
|
|
140
|
+
emit(child, rep);
|
|
141
|
+
};
|
|
142
|
+
for (const root of collapsed)
|
|
143
|
+
emit(root, null);
|
|
144
|
+
return { feedId: graph.feedID, feedName: graph.title, nodes };
|
|
84
145
|
}
|
|
85
146
|
/**
|
|
86
147
|
* Handles plain `feed diagram <feed>`: the rendered tree a terminal shows,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feed.diagram.js","sourceRoot":"","sources":["../../../src/builtins/res/feed.diagram.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAa,MAAM,eAAe,CAAC;AACjF,OAAO,EAAwB,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAuB,MAAM,uBAAuB,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EACL,eAAe,EACf,mBAAmB,GAGpB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"feed.diagram.js","sourceRoot":"","sources":["../../../src/builtins/res/feed.diagram.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The ambient bus: events the engine originates on its own.
|
|
3
|
+
*
|
|
4
|
+
* A command answers with envelopes; a sampler that keeps a watched feed
|
|
5
|
+
* live has no command to answer. Its refreshed models, and the watch state
|
|
6
|
+
* changes around them, travel here. A host (the daemon) subscribes once and
|
|
7
|
+
* relays each event to every surface; a host that never subscribes simply
|
|
8
|
+
* never hears them — the engine does not care.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import type { AmbientEvent } from '@fnndsc/menu';
|
|
13
|
+
/**
|
|
14
|
+
* Subscribes to ambient events.
|
|
15
|
+
*
|
|
16
|
+
* @param listener - Receives each event as it is published.
|
|
17
|
+
* @returns Function that unsubscribes.
|
|
18
|
+
*/
|
|
19
|
+
export declare function ambient_listen(listener: (event: AmbientEvent) => void): () => void;
|
|
20
|
+
/**
|
|
21
|
+
* Publishes one ambient event to every subscriber. A subscriber that throws
|
|
22
|
+
* does not stop the others.
|
|
23
|
+
*
|
|
24
|
+
* @param event - The event to publish.
|
|
25
|
+
*/
|
|
26
|
+
export declare function ambient_publish(event: AmbientEvent): void;
|
|
27
|
+
/**
|
|
28
|
+
* Whether any host is listening. A producer with nobody to carry its
|
|
29
|
+
* event can choose the synchronous path instead (a console `ls` waits for
|
|
30
|
+
* a fresh listing rather than being handed a stale one nobody will refresh).
|
|
31
|
+
*
|
|
32
|
+
* @returns True when at least one subscriber exists.
|
|
33
|
+
*/
|
|
34
|
+
export declare function ambient_hasListeners(): boolean;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const listeners = new Set();
|
|
2
|
+
/**
|
|
3
|
+
* Subscribes to ambient events.
|
|
4
|
+
*
|
|
5
|
+
* @param listener - Receives each event as it is published.
|
|
6
|
+
* @returns Function that unsubscribes.
|
|
7
|
+
*/
|
|
8
|
+
export function ambient_listen(listener) {
|
|
9
|
+
listeners.add(listener);
|
|
10
|
+
return () => { listeners.delete(listener); };
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Publishes one ambient event to every subscriber. A subscriber that throws
|
|
14
|
+
* does not stop the others.
|
|
15
|
+
*
|
|
16
|
+
* @param event - The event to publish.
|
|
17
|
+
*/
|
|
18
|
+
export function ambient_publish(event) {
|
|
19
|
+
for (const listener of listeners) {
|
|
20
|
+
try {
|
|
21
|
+
listener(event);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// One host's failure is not another's.
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Whether any host is listening. A producer with nobody to carry its
|
|
30
|
+
* event can choose the synchronous path instead (a console `ls` waits for
|
|
31
|
+
* a fresh listing rather than being handed a stale one nobody will refresh).
|
|
32
|
+
*
|
|
33
|
+
* @returns True when at least one subscriber exists.
|
|
34
|
+
*/
|
|
35
|
+
export function ambient_hasListeners() {
|
|
36
|
+
return listeners.size > 0;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=ambient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ambient.js","sourceRoot":"","sources":["../../src/core/ambient.ts"],"names":[],"mappings":"AAaA,MAAM,SAAS,GAAuC,IAAI,GAAG,EAAE,CAAC;AAEhE;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAuC;IACpE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,GAAS,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAmB;IACjD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,uCAAuC;QACzC,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC;AAC5B,CAAC"}
|
package/dist/core/engine.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CommandEnvelope } from '@fnndsc/cumin';
|
|
2
|
-
import type { Regard } from '@fnndsc/menu';
|
|
2
|
+
import type { Regard, WatchState, AmbientEvent } from '@fnndsc/menu';
|
|
3
3
|
/**
|
|
4
4
|
* Result of a completion request: the candidates and the prefix they
|
|
5
5
|
* complete, matching what a readline completer consumes.
|
|
@@ -66,6 +66,31 @@ export interface BrasaEngine {
|
|
|
66
66
|
* @returns The retained regard, or null.
|
|
67
67
|
*/
|
|
68
68
|
regard_get?(): Regard | null;
|
|
69
|
+
/**
|
|
70
|
+
* Opens or closes a liveness watch on a subject for one owner (a surface
|
|
71
|
+
* id, or the operator at a console). While any owner watches a subject,
|
|
72
|
+
* the engine samples it and publishes refreshed models as ambient events.
|
|
73
|
+
*
|
|
74
|
+
* @param subject - The subject address (`/proc/jobs/feed_N`).
|
|
75
|
+
* @param owner - Who holds the watch.
|
|
76
|
+
* @param on - True to watch, false to release.
|
|
77
|
+
* @returns The subject's watch state, or null when the subject is not watchable.
|
|
78
|
+
*/
|
|
79
|
+
watch_set?(subject: string, owner: string, on: boolean): WatchState | null;
|
|
80
|
+
/**
|
|
81
|
+
* Releases every watch one owner holds (a surface detached).
|
|
82
|
+
*
|
|
83
|
+
* @param owner - The owner whose watches end.
|
|
84
|
+
*/
|
|
85
|
+
watch_release?(owner: string): void;
|
|
86
|
+
/**
|
|
87
|
+
* Subscribes to events the engine originates on its own: a sampler's
|
|
88
|
+
* refreshed model, a watch changing state.
|
|
89
|
+
*
|
|
90
|
+
* @param listener - Receives each ambient event.
|
|
91
|
+
* @returns Function that unsubscribes.
|
|
92
|
+
*/
|
|
93
|
+
ambient_listen?(listener: (event: AmbientEvent) => void): () => void;
|
|
69
94
|
}
|
|
70
95
|
/**
|
|
71
96
|
* Sets the shared stop-on-error flag. Exposed so the boot layer (which owns
|
package/dist/core/engine.js
CHANGED
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
* @module
|
|
26
26
|
*/
|
|
27
27
|
import chalk from 'chalk';
|
|
28
|
+
import { ambient_listen } from './ambient.js';
|
|
29
|
+
import { procWatch_add, procWatch_remove, procWatch_release, procWatch_state, watchSubject_parse } from '../builtins/procWatch.js';
|
|
28
30
|
import { session } from '../session/index.js';
|
|
29
31
|
import { semicolons_parse } from '../lib/semicolonParser.js';
|
|
30
32
|
import { pipes_parse, redirect_parse, command_shellEscape_detect, } from './preprocess.js';
|
|
@@ -253,6 +255,17 @@ export async function engine_create() {
|
|
|
253
255
|
file_read,
|
|
254
256
|
regard_note: (regard) => session.regard_set(regard),
|
|
255
257
|
regard_get: () => session.regard_get(),
|
|
258
|
+
watch_set: (subject, owner, on) => {
|
|
259
|
+
const feedID = watchSubject_parse(subject);
|
|
260
|
+
if (feedID === null)
|
|
261
|
+
return null;
|
|
262
|
+
if (on)
|
|
263
|
+
return procWatch_add(feedID, owner);
|
|
264
|
+
procWatch_remove(feedID, owner);
|
|
265
|
+
return procWatch_state(feedID);
|
|
266
|
+
},
|
|
267
|
+
watch_release: (owner) => procWatch_release(owner),
|
|
268
|
+
ambient_listen,
|
|
256
269
|
};
|
|
257
270
|
}
|
|
258
271
|
/**
|
package/dist/core/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/core/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EACL,WAAW,EACX,cAAc,EACd,0BAA0B,GAE3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/core/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/vfs/vfs.d.ts
CHANGED
|
@@ -4,6 +4,19 @@ import { Result, type CommandEnvelope } from '@fnndsc/cumin';
|
|
|
4
4
|
* Virtual File System Router.
|
|
5
5
|
* Dispatches operations to Virtual or Native providers.
|
|
6
6
|
*/
|
|
7
|
+
/**
|
|
8
|
+
* A resolved directory listing with its freshness.
|
|
9
|
+
*
|
|
10
|
+
* @property path - The absolute path listed.
|
|
11
|
+
* @property items - The entries.
|
|
12
|
+
* @property fresh - True when current; false when served stale with a
|
|
13
|
+
* revalidation running behind it.
|
|
14
|
+
*/
|
|
15
|
+
export interface VfsListing {
|
|
16
|
+
path: string;
|
|
17
|
+
items: ListingItem[];
|
|
18
|
+
fresh: boolean;
|
|
19
|
+
}
|
|
7
20
|
export declare class VFS {
|
|
8
21
|
/**
|
|
9
22
|
* Gets data for a directory (Virtual or Native).
|
|
@@ -18,6 +31,33 @@ export declare class VFS {
|
|
|
18
31
|
reverse?: boolean;
|
|
19
32
|
directory?: boolean;
|
|
20
33
|
}): Promise<Result<ListingItem[]>>;
|
|
34
|
+
/** Background revalidations in flight, one per path. */
|
|
35
|
+
private revalidating;
|
|
36
|
+
/**
|
|
37
|
+
* Re-fetches one listing behind a stale serve and publishes the fresh
|
|
38
|
+
* result as an ambient `fs.listing` envelope, so every surface showing
|
|
39
|
+
* that path repaints. One fetch per path at a time.
|
|
40
|
+
*
|
|
41
|
+
* @param effectivePath - The absolute path to refresh.
|
|
42
|
+
*/
|
|
43
|
+
private listing_revalidate;
|
|
44
|
+
/**
|
|
45
|
+
* Resolves a directory listing with its freshness. A fresh cached
|
|
46
|
+
* listing is served as is. A stale one is served at once only when a
|
|
47
|
+
* host can carry the refresh (an ambient listener exists — the daemon),
|
|
48
|
+
* with the revalidation running behind it; at a plain console the stale
|
|
49
|
+
* entry is refetched in line, because nobody would deliver the refresh.
|
|
50
|
+
* `/proc` paths never touch this cache.
|
|
51
|
+
*
|
|
52
|
+
* @param targetPath - The path to list; the working directory when empty.
|
|
53
|
+
* @param options - Sort and `-d` options.
|
|
54
|
+
* @returns The listing, its absolute path, and whether it is current.
|
|
55
|
+
*/
|
|
56
|
+
listing_get(targetPath?: string, options?: {
|
|
57
|
+
sort?: 'name' | 'size' | 'date' | 'owner';
|
|
58
|
+
reverse?: boolean;
|
|
59
|
+
directory?: boolean;
|
|
60
|
+
}): Promise<Result<VfsListing>>;
|
|
21
61
|
/**
|
|
22
62
|
* Returns the directory entry for `absolutePath` itself (not its contents).
|
|
23
63
|
* Looks up the entry in the parent's listing — used to implement `ls -d`.
|
|
@@ -51,14 +91,6 @@ export declare class VFS {
|
|
|
51
91
|
reverse?: boolean;
|
|
52
92
|
directory?: boolean;
|
|
53
93
|
}): Promise<CommandEnvelope>;
|
|
54
|
-
/**
|
|
55
|
-
* Refreshes cache in the background without blocking or updating display.
|
|
56
|
-
* Used for optimistic rendering - fetch fresh data after serving stale cache.
|
|
57
|
-
*
|
|
58
|
-
* @param targetPath - The path to refresh.
|
|
59
|
-
* @param options - Options including sort and reverse.
|
|
60
|
-
*/
|
|
61
|
-
private refreshInBackground;
|
|
62
94
|
}
|
|
63
95
|
/**
|
|
64
96
|
* Shared VFS singleton.
|