@fungi.computer/truffle 0.4.0 → 0.6.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 +27 -4
- package/dist/internal/private-workerd-sandbox-worker.mjs +243 -273
- package/dist/internal/sandbox-metafile.json +35 -30
- package/dist/local-board-agents.d.ts +46 -0
- package/dist/local-board-agents.js +138 -0
- package/dist/local-board-shipping.d.ts +129 -0
- package/dist/local-board-shipping.js +325 -0
- package/dist/local-extensions.d.ts +4 -2
- package/dist/local-extensions.js +56 -22
- package/dist/local-login.js +33 -25
- package/dist/private-fungi-mcp-connection.js +6 -1
- package/dist/private-invocation-computer.d.ts +6 -2
- package/dist/private-invocation-computer.js +20 -13
- package/dist/private-local-agent-control.d.ts +5 -1
- package/dist/private-local-agent-control.js +11 -1
- package/dist/private-local-auth-rpc.d.ts +5 -0
- package/dist/private-local-auth-rpc.js +46 -4
- package/dist/private-local-client-version.js +3 -1
- package/dist/private-local-computer-processes.d.ts +7 -2
- package/dist/private-local-computer-processes.js +47 -23
- package/dist/private-local-delegation.d.ts +18 -0
- package/dist/private-local-delegation.js +84 -26
- package/dist/private-local-exec-environment.d.ts +5 -2
- package/dist/private-local-exec-environment.js +35 -1
- package/dist/private-local-exec-review.js +14 -7
- package/dist/private-local-exec-rules.d.ts +7 -0
- package/dist/private-local-exec-rules.js +23 -6
- package/dist/private-local-extension-records.d.ts +1 -1
- package/dist/private-local-runtime-host.js +54 -27
- package/dist/private-local-sandbox-policy.js +4 -0
- package/dist/private-local-sandbox.d.ts +3 -1
- package/dist/private-local-sandbox.js +2 -2
- package/dist/private-local-schedule-client.d.ts +12 -0
- package/dist/private-local-schedule-client.js +41 -0
- package/dist/private-local-schedules.d.ts +84 -0
- package/dist/private-local-schedules.js +65 -0
- package/dist/private-local-service-contract.d.ts +4 -0
- package/dist/private-local-service-discovery.d.ts +3 -3
- package/dist/private-local-service-discovery.js +1 -1
- package/dist/private-local-service-listener.js +9 -0
- package/dist/private-local-service-owner.d.ts +130 -0
- package/dist/private-local-service-owner.js +90 -2
- package/dist/private-local-service.d.ts +3 -0
- package/dist/private-local-service.js +9 -1
- package/dist/private-local-session-discovery.d.ts +10 -4
- package/dist/private-local-session-discovery.js +37 -4
- package/dist/private-provider-rejection.d.ts +1 -1
- package/dist/private-provider-rejection.js +28 -8
- package/dist/private-sqlite-owner.d.ts +7 -1
- package/dist/private-sqlite-owner.js +14 -2
- package/package.json +29 -16
|
@@ -1934,8 +1934,8 @@
|
|
|
1934
1934
|
],
|
|
1935
1935
|
"format": "esm"
|
|
1936
1936
|
},
|
|
1937
|
-
"../../packages/forage/dist/
|
|
1938
|
-
"bytes":
|
|
1937
|
+
"../../packages/forage/dist/normalization.js": {
|
|
1938
|
+
"bytes": 3520,
|
|
1939
1939
|
"imports": [
|
|
1940
1940
|
{
|
|
1941
1941
|
"path": "../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js",
|
|
@@ -1945,24 +1945,29 @@
|
|
|
1945
1945
|
],
|
|
1946
1946
|
"format": "esm"
|
|
1947
1947
|
},
|
|
1948
|
-
"../../packages/forage/dist/
|
|
1949
|
-
"bytes":
|
|
1950
|
-
"imports": [],
|
|
1951
|
-
"format": "esm"
|
|
1952
|
-
},
|
|
1953
|
-
"../../packages/forage/dist/normalization.js": {
|
|
1954
|
-
"bytes": 3477,
|
|
1948
|
+
"../../packages/forage/dist/schemas.js": {
|
|
1949
|
+
"bytes": 5698,
|
|
1955
1950
|
"imports": [
|
|
1956
1951
|
{
|
|
1957
1952
|
"path": "../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js",
|
|
1958
1953
|
"kind": "import-statement",
|
|
1959
1954
|
"original": "zod"
|
|
1955
|
+
},
|
|
1956
|
+
{
|
|
1957
|
+
"path": "../../packages/forage/dist/normalization.js",
|
|
1958
|
+
"kind": "import-statement",
|
|
1959
|
+
"original": "./normalization.js"
|
|
1960
1960
|
}
|
|
1961
1961
|
],
|
|
1962
1962
|
"format": "esm"
|
|
1963
1963
|
},
|
|
1964
|
+
"../../packages/forage/dist/errors.js": {
|
|
1965
|
+
"bytes": 396,
|
|
1966
|
+
"imports": [],
|
|
1967
|
+
"format": "esm"
|
|
1968
|
+
},
|
|
1964
1969
|
"../../packages/forage/dist/rendering.js": {
|
|
1965
|
-
"bytes":
|
|
1970
|
+
"bytes": 11613,
|
|
1966
1971
|
"imports": [
|
|
1967
1972
|
{
|
|
1968
1973
|
"path": "../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js",
|
|
@@ -1978,17 +1983,12 @@
|
|
|
1978
1983
|
"path": "../../packages/forage/dist/normalization.js",
|
|
1979
1984
|
"kind": "import-statement",
|
|
1980
1985
|
"original": "./normalization.js"
|
|
1981
|
-
},
|
|
1982
|
-
{
|
|
1983
|
-
"path": "../../packages/forage/dist/schemas.js",
|
|
1984
|
-
"kind": "import-statement",
|
|
1985
|
-
"original": "./schemas.js"
|
|
1986
1986
|
}
|
|
1987
1987
|
],
|
|
1988
1988
|
"format": "esm"
|
|
1989
1989
|
},
|
|
1990
1990
|
"../../packages/forage/dist/describe.js": {
|
|
1991
|
-
"bytes":
|
|
1991
|
+
"bytes": 3157,
|
|
1992
1992
|
"imports": [
|
|
1993
1993
|
{
|
|
1994
1994
|
"path": "../../packages/forage/dist/schemas.js",
|
|
@@ -2014,7 +2014,7 @@
|
|
|
2014
2014
|
"format": "esm"
|
|
2015
2015
|
},
|
|
2016
2016
|
"../../packages/forage/dist/search.js": {
|
|
2017
|
-
"bytes":
|
|
2017
|
+
"bytes": 9656,
|
|
2018
2018
|
"imports": [
|
|
2019
2019
|
{
|
|
2020
2020
|
"path": "../../packages/forage/dist/schemas.js",
|
|
@@ -2066,8 +2066,13 @@
|
|
|
2066
2066
|
"format": "esm"
|
|
2067
2067
|
},
|
|
2068
2068
|
"../../packages/forage/dist/catalog.js": {
|
|
2069
|
-
"bytes":
|
|
2069
|
+
"bytes": 6091,
|
|
2070
2070
|
"imports": [
|
|
2071
|
+
{
|
|
2072
|
+
"path": "../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js",
|
|
2073
|
+
"kind": "import-statement",
|
|
2074
|
+
"original": "zod"
|
|
2075
|
+
},
|
|
2071
2076
|
{
|
|
2072
2077
|
"path": "../../packages/forage/dist/errors.js",
|
|
2073
2078
|
"kind": "import-statement",
|
|
@@ -2107,7 +2112,7 @@
|
|
|
2107
2112
|
"format": "esm"
|
|
2108
2113
|
},
|
|
2109
2114
|
"../../packages/forage/dist/app-api.js": {
|
|
2110
|
-
"bytes":
|
|
2115
|
+
"bytes": 6114,
|
|
2111
2116
|
"imports": [
|
|
2112
2117
|
{
|
|
2113
2118
|
"path": "../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js",
|
|
@@ -2129,7 +2134,7 @@
|
|
|
2129
2134
|
"format": "esm"
|
|
2130
2135
|
},
|
|
2131
2136
|
"../../packages/forage/dist/index.js": {
|
|
2132
|
-
"bytes":
|
|
2137
|
+
"bytes": 996,
|
|
2133
2138
|
"imports": [
|
|
2134
2139
|
{
|
|
2135
2140
|
"path": "../../packages/forage/dist/schemas.js",
|
|
@@ -6533,8 +6538,11 @@
|
|
|
6533
6538
|
"../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js": {
|
|
6534
6539
|
"bytesInOutput": 0
|
|
6535
6540
|
},
|
|
6541
|
+
"../../packages/forage/dist/normalization.js": {
|
|
6542
|
+
"bytesInOutput": 2663
|
|
6543
|
+
},
|
|
6536
6544
|
"../../packages/forage/dist/schemas.js": {
|
|
6537
|
-
"bytesInOutput":
|
|
6545
|
+
"bytesInOutput": 5531
|
|
6538
6546
|
},
|
|
6539
6547
|
"../../packages/forage/dist/index.js": {
|
|
6540
6548
|
"bytesInOutput": 127
|
|
@@ -6542,26 +6550,23 @@
|
|
|
6542
6550
|
"../../packages/forage/dist/errors.js": {
|
|
6543
6551
|
"bytesInOutput": 299
|
|
6544
6552
|
},
|
|
6545
|
-
"../../packages/forage/dist/normalization.js": {
|
|
6546
|
-
"bytesInOutput": 2924
|
|
6547
|
-
},
|
|
6548
6553
|
"../../packages/forage/dist/rendering.js": {
|
|
6549
|
-
"bytesInOutput":
|
|
6554
|
+
"bytesInOutput": 9821
|
|
6550
6555
|
},
|
|
6551
6556
|
"../../packages/forage/dist/describe.js": {
|
|
6552
|
-
"bytesInOutput":
|
|
6557
|
+
"bytesInOutput": 2570
|
|
6553
6558
|
},
|
|
6554
6559
|
"../../packages/forage/dist/search.js": {
|
|
6555
|
-
"bytesInOutput":
|
|
6560
|
+
"bytesInOutput": 8262
|
|
6556
6561
|
},
|
|
6557
6562
|
"../../packages/forage/dist/list.js": {
|
|
6558
6563
|
"bytesInOutput": 1793
|
|
6559
6564
|
},
|
|
6560
6565
|
"../../packages/forage/dist/catalog.js": {
|
|
6561
|
-
"bytesInOutput":
|
|
6566
|
+
"bytesInOutput": 4697
|
|
6562
6567
|
},
|
|
6563
6568
|
"../../packages/forage/dist/app-api.js": {
|
|
6564
|
-
"bytesInOutput":
|
|
6569
|
+
"bytesInOutput": 1723
|
|
6565
6570
|
},
|
|
6566
6571
|
"../../packages/forage/dist/definitions.js": {
|
|
6567
6572
|
"bytesInOutput": 1100
|
|
@@ -6720,7 +6725,7 @@
|
|
|
6720
6725
|
"bytesInOutput": 4648
|
|
6721
6726
|
}
|
|
6722
6727
|
},
|
|
6723
|
-
"bytes":
|
|
6728
|
+
"bytes": 993272
|
|
6724
6729
|
}
|
|
6725
6730
|
}
|
|
6726
6731
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { SessionAttention, SessionSummaryRow } from "@fungi.computer/shiitake/client";
|
|
2
|
+
/**
|
|
3
|
+
* One Agent as the Board reads it from its store, without starting its runtime:
|
|
4
|
+
* its conversations' stored state and the open attention of those that matter.
|
|
5
|
+
*/
|
|
6
|
+
export type BoardAgent = Readonly<{
|
|
7
|
+
/** Stable identity of the Agent. */
|
|
8
|
+
agentId: string;
|
|
9
|
+
/** Display name; the id when the Agent has none. */
|
|
10
|
+
name: string;
|
|
11
|
+
/** Set when the Agent's store cannot be read, and why. */
|
|
12
|
+
unreadable?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Whether a live runtime holds the store. A conversation stored as running
|
|
15
|
+
* in a store nobody holds was left behind by a runtime that stopped.
|
|
16
|
+
*/
|
|
17
|
+
owned: boolean;
|
|
18
|
+
/** Page one of its conversations, waiting ones first, then running, then settled. */
|
|
19
|
+
sessions: readonly SessionSummaryRow[];
|
|
20
|
+
/** Open attention of the conversations `attentionWanted` names. */
|
|
21
|
+
attention: ReadonlyMap<string, readonly SessionAttention[]>;
|
|
22
|
+
}>;
|
|
23
|
+
/** Waiting conversations whose attention is read per Agent. */
|
|
24
|
+
export declare const maximumWaitingPerAgent = 4;
|
|
25
|
+
/**
|
|
26
|
+
* Which conversations' attention to load: the newest one, whose state is the
|
|
27
|
+
* Agent's lane, and the ones waiting on a person.
|
|
28
|
+
*/
|
|
29
|
+
export declare function attentionWanted(sessions: readonly SessionSummaryRow[]): readonly string[];
|
|
30
|
+
/**
|
|
31
|
+
* Whether a live runtime holds this store. A runtime holds an exclusive
|
|
32
|
+
* transaction on the store's `.owner.sqlite` sidecar for as long as its
|
|
33
|
+
* process lives, so a reader that is refused at once has found a live owner,
|
|
34
|
+
* and one that reads the sidecar has found none. Nothing is written.
|
|
35
|
+
*/
|
|
36
|
+
export declare function storeIsOwned(databasePath: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* One Agent as the Board sees it, read from its store alone: no runtime starts,
|
|
39
|
+
* so reading every Agent every few seconds costs file reads, not Agents.
|
|
40
|
+
* The run state is as the Agent's runtime last wrote it. A store that cannot
|
|
41
|
+
* be read is an unavailable Agent with the reason, never an idle one. An
|
|
42
|
+
* archived Agent is not on the board.
|
|
43
|
+
*/
|
|
44
|
+
export declare function readBoardAgent(agentId: string, databasePath: string): Promise<BoardAgent | undefined>;
|
|
45
|
+
/** Every Agent store under a project folder, as the Board reads them. */
|
|
46
|
+
export declare function readBoardAgents(root: string): Promise<readonly BoardAgent[]>;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { readStoredAttention, readStoredSessionStates, } from "@fungi.computer/shiitake/effect";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { basename, dirname } from "node:path";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { logEvent } from "./log-event.js";
|
|
7
|
+
import { listPrivateLocalAgentStores, LocalStoreSchemaError, readPrivateLocalAgentProfile, unreadableStoreReason, } from "./private-local-session-discovery.js";
|
|
8
|
+
import { createPrivateSqliteOwner, openPrivateReadOnlySqliteDatabase, } from "./private-sqlite-owner.js";
|
|
9
|
+
/** Waiting conversations whose attention is read per Agent. */
|
|
10
|
+
export const maximumWaitingPerAgent = 4;
|
|
11
|
+
/**
|
|
12
|
+
* Which conversations' attention to load: the newest one, whose state is the
|
|
13
|
+
* Agent's lane, and the ones waiting on a person.
|
|
14
|
+
*/
|
|
15
|
+
export function attentionWanted(sessions) {
|
|
16
|
+
const first = sessions[0];
|
|
17
|
+
return [
|
|
18
|
+
...new Set([
|
|
19
|
+
...(first === undefined ? [] : [first.sessionId]),
|
|
20
|
+
...sessions
|
|
21
|
+
.filter((row) => row.state === "needs_you")
|
|
22
|
+
.slice(0, maximumWaitingPerAgent)
|
|
23
|
+
.map((row) => row.sessionId),
|
|
24
|
+
]),
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
/** SQLite's "database is locked" result code, from node:sqlite or bun:sqlite. */
|
|
28
|
+
const sqliteBusy = 5;
|
|
29
|
+
/**
|
|
30
|
+
* Whether a live runtime holds this store. A runtime holds an exclusive
|
|
31
|
+
* transaction on the store's `.owner.sqlite` sidecar for as long as its
|
|
32
|
+
* process lives, so a reader that is refused at once has found a live owner,
|
|
33
|
+
* and one that reads the sidecar has found none. Nothing is written.
|
|
34
|
+
*/
|
|
35
|
+
export function storeIsOwned(databasePath) {
|
|
36
|
+
const sidecar = `${databasePath}.owner.sqlite`;
|
|
37
|
+
if (!existsSync(sidecar))
|
|
38
|
+
return false;
|
|
39
|
+
let database;
|
|
40
|
+
try {
|
|
41
|
+
database = openPrivateReadOnlySqliteDatabase(sidecar, 0);
|
|
42
|
+
}
|
|
43
|
+
catch (cause) {
|
|
44
|
+
if (busy(cause))
|
|
45
|
+
return true;
|
|
46
|
+
throw cause;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
database.prepare("SELECT count(*) FROM sqlite_master").all();
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
catch (cause) {
|
|
53
|
+
if (busy(cause))
|
|
54
|
+
return true;
|
|
55
|
+
throw cause;
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
database.close();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** node:sqlite names the result code `errcode`, bun:sqlite `errno`. */
|
|
62
|
+
const sqliteFailure = z.looseObject({
|
|
63
|
+
errcode: z.number().optional(),
|
|
64
|
+
errno: z.number().optional(),
|
|
65
|
+
});
|
|
66
|
+
function busy(cause) {
|
|
67
|
+
const failure = sqliteFailure.safeParse(cause);
|
|
68
|
+
return (failure.success &&
|
|
69
|
+
(failure.data.errcode ?? failure.data.errno) === sqliteBusy);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* One Agent as the Board sees it, read from its store alone: no runtime starts,
|
|
73
|
+
* so reading every Agent every few seconds costs file reads, not Agents.
|
|
74
|
+
* The run state is as the Agent's runtime last wrote it. A store that cannot
|
|
75
|
+
* be read is an unavailable Agent with the reason, never an idle one. An
|
|
76
|
+
* archived Agent is not on the board.
|
|
77
|
+
*/
|
|
78
|
+
export async function readBoardAgent(agentId, databasePath) {
|
|
79
|
+
const none = new Map();
|
|
80
|
+
let name;
|
|
81
|
+
let owned;
|
|
82
|
+
try {
|
|
83
|
+
const profile = readPrivateLocalAgentProfile(databasePath);
|
|
84
|
+
if (profile.archived)
|
|
85
|
+
return undefined;
|
|
86
|
+
name = profile.name ?? agentId;
|
|
87
|
+
owned = storeIsOwned(databasePath);
|
|
88
|
+
}
|
|
89
|
+
catch (cause) {
|
|
90
|
+
if (cause instanceof LocalStoreSchemaError)
|
|
91
|
+
return {
|
|
92
|
+
agentId,
|
|
93
|
+
name: agentId,
|
|
94
|
+
sessions: [],
|
|
95
|
+
attention: none,
|
|
96
|
+
owned: false,
|
|
97
|
+
unreadable: unreadableStoreReason(agentId),
|
|
98
|
+
};
|
|
99
|
+
logEvent("board-agent-profile", cause);
|
|
100
|
+
return {
|
|
101
|
+
agentId,
|
|
102
|
+
name: agentId,
|
|
103
|
+
sessions: [],
|
|
104
|
+
attention: none,
|
|
105
|
+
owned: false,
|
|
106
|
+
unreadable: "its store could not be read",
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const database = openPrivateReadOnlySqliteDatabase(databasePath);
|
|
110
|
+
try {
|
|
111
|
+
const owner = createPrivateSqliteOwner(database);
|
|
112
|
+
const sessions = (await Effect.runPromise(readStoredSessionStates(owner))).sessions;
|
|
113
|
+
const attention = new Map();
|
|
114
|
+
for (const sessionId of attentionWanted(sessions))
|
|
115
|
+
attention.set(sessionId, await Effect.runPromise(readStoredAttention(owner, sessionId)));
|
|
116
|
+
return { agentId, name, owned, sessions, attention };
|
|
117
|
+
}
|
|
118
|
+
catch (cause) {
|
|
119
|
+
logEvent("board-agent-store", cause);
|
|
120
|
+
return {
|
|
121
|
+
agentId,
|
|
122
|
+
name,
|
|
123
|
+
owned,
|
|
124
|
+
sessions: [],
|
|
125
|
+
attention: none,
|
|
126
|
+
unreadable: "its conversations could not be read",
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
database.close();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Every Agent store under a project folder, as the Board reads them. */
|
|
134
|
+
export async function readBoardAgents(root) {
|
|
135
|
+
const stores = await listPrivateLocalAgentStores(root, "all");
|
|
136
|
+
const agents = await Promise.all(stores.map((path) => readBoardAgent(basename(dirname(path)), path)));
|
|
137
|
+
return agents.flatMap((agent) => (agent === undefined ? [] : [agent]));
|
|
138
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import * as Result from "effect/Result";
|
|
2
|
+
import * as Schema from "effect/Schema";
|
|
3
|
+
/** What happened to a piece of work: it landed, shipped out, or is on its way. */
|
|
4
|
+
export declare const ShipKind: Schema.Literals<readonly ["landed", "released", "queued", "gating", "dropped"]>;
|
|
5
|
+
/** Display kind of one shipped item. */
|
|
6
|
+
export type ShipKind = typeof ShipKind.Type;
|
|
7
|
+
/** One thing a shipping source saw since local midnight. */
|
|
8
|
+
export declare const ShipItem: Schema.Struct<{
|
|
9
|
+
/** Stable within its source. */
|
|
10
|
+
readonly id: Schema.String;
|
|
11
|
+
/** What happened to it. */
|
|
12
|
+
readonly kind: Schema.Literals<readonly ["landed", "released", "queued", "gating", "dropped"]>;
|
|
13
|
+
/** A one-line title, such as a commit subject or a released version. */
|
|
14
|
+
readonly title: Schema.String;
|
|
15
|
+
/** The branch, tag or package it belongs to. */
|
|
16
|
+
readonly ref: Schema.optionalKey<Schema.String>;
|
|
17
|
+
/** When it happened. */
|
|
18
|
+
readonly at: Schema.Int;
|
|
19
|
+
/** A short note the source adds. */
|
|
20
|
+
readonly detail: Schema.optionalKey<Schema.String>;
|
|
21
|
+
}>;
|
|
22
|
+
/** Decoded shipped item. */
|
|
23
|
+
export type ShipItem = typeof ShipItem.Type;
|
|
24
|
+
/** What one read of a shipping source found; a throw is a failed source instead. */
|
|
25
|
+
export type ShippingRead = Readonly<{
|
|
26
|
+
/** `held` is paused on purpose, `stopped` is not running; neither is an error. */
|
|
27
|
+
state: "ok" | "held" | "stopped";
|
|
28
|
+
/** Why it is held or stopped, in a few words. */
|
|
29
|
+
detail?: string;
|
|
30
|
+
/** What the source saw since `sinceMs`, newest first. */
|
|
31
|
+
items: readonly ShipItem[];
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Something that ships work: a branch, a package registry, a merge train. The
|
|
35
|
+
* Board reads it on its own cadence and never trusts it to say "none" when it
|
|
36
|
+
* could not look.
|
|
37
|
+
*/
|
|
38
|
+
export type ShippingSource = Readonly<{
|
|
39
|
+
/** Stable identity of the source. */
|
|
40
|
+
id: string;
|
|
41
|
+
/** What the person calls the source. */
|
|
42
|
+
label: string;
|
|
43
|
+
/** How often the source is read again. */
|
|
44
|
+
refreshMs: number;
|
|
45
|
+
/** Read what shipped at or after `sinceMs` (local midnight); throw when it cannot be read. */
|
|
46
|
+
read: (sinceMs: number, signal: AbortSignal) => Promise<ShippingRead>;
|
|
47
|
+
}>;
|
|
48
|
+
/** The sources the Board reads, resolved afresh each cycle so settings edits apply. */
|
|
49
|
+
export type ShippingSources = (signal: AbortSignal) => Promise<readonly ShippingSource[]>;
|
|
50
|
+
/** The most shipping sources one board reads. */
|
|
51
|
+
export declare const maximumShippingSources = 6;
|
|
52
|
+
/** One configured shipping source; an unknown kind or key is refused. */
|
|
53
|
+
export declare const ShippingSourceConfig: Schema.Union<readonly [Schema.Struct<{
|
|
54
|
+
/** Reads a Git history. */
|
|
55
|
+
readonly kind: Schema.Literal<"git">;
|
|
56
|
+
/** The branch, tag or `HEAD` whose first-parent history is read. */
|
|
57
|
+
readonly ref: Schema.String;
|
|
58
|
+
/** Whether those commits landed work or released it. */
|
|
59
|
+
readonly shows: Schema.Literals<readonly ["landed", "released"]>;
|
|
60
|
+
}>, Schema.Struct<{
|
|
61
|
+
/** Reads a package registry. */
|
|
62
|
+
readonly kind: Schema.Literal<"npm">;
|
|
63
|
+
/** Package names, as `npm view` takes them. */
|
|
64
|
+
readonly packages: Schema.$Array<Schema.String>;
|
|
65
|
+
}>]>;
|
|
66
|
+
/** Decoded configured shipping source. */
|
|
67
|
+
export type ShippingSourceConfig = typeof ShippingSourceConfig.Type;
|
|
68
|
+
/** The `board` key of a `.fungi/settings.json`; excess keys are refused. */
|
|
69
|
+
export declare const BoardSettings: Schema.Struct<{
|
|
70
|
+
/** The sources the Board reads for what shipped today. */
|
|
71
|
+
readonly shipping: Schema.optionalKey<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
|
|
72
|
+
/** Reads a Git history. */
|
|
73
|
+
readonly kind: Schema.Literal<"git">;
|
|
74
|
+
/** The branch, tag or `HEAD` whose first-parent history is read. */
|
|
75
|
+
readonly ref: Schema.String;
|
|
76
|
+
/** Whether those commits landed work or released it. */
|
|
77
|
+
readonly shows: Schema.Literals<readonly ["landed", "released"]>;
|
|
78
|
+
}>, Schema.Struct<{
|
|
79
|
+
/** Reads a package registry. */
|
|
80
|
+
readonly kind: Schema.Literal<"npm">;
|
|
81
|
+
/** Package names, as `npm view` takes them. */
|
|
82
|
+
readonly packages: Schema.$Array<Schema.String>;
|
|
83
|
+
}>]>>>;
|
|
84
|
+
}>;
|
|
85
|
+
/** The sources a settings `board` value names, or each refusal with its settings path. */
|
|
86
|
+
export declare function decodeBoardSettings(board: unknown): Result.Result<readonly ShippingSourceConfig[], readonly string[]>;
|
|
87
|
+
/** Run a program with these arguments and return what it wrote to stdout. */
|
|
88
|
+
export type ShippingExec = (file: string, args: readonly string[], options: Readonly<{
|
|
89
|
+
cwd: string;
|
|
90
|
+
signal: AbortSignal;
|
|
91
|
+
}>) => Promise<string>;
|
|
92
|
+
/**
|
|
93
|
+
* The tool's ordinary interface: its own argv, no shell, a bounded environment.
|
|
94
|
+
* A program that is missing or refuses is an error with a short reason.
|
|
95
|
+
*/
|
|
96
|
+
export declare const execShipping: ShippingExec;
|
|
97
|
+
/**
|
|
98
|
+
* Commits first-parent on `ref` since local midnight, from `git log`. A merge
|
|
99
|
+
* shows the subject of the tip it merged, and any other commit its own, so a
|
|
100
|
+
* merge queue's "Merge branch ..." lines read as the work that landed.
|
|
101
|
+
*/
|
|
102
|
+
export declare function gitSource(config: Extract<ShippingSourceConfig, {
|
|
103
|
+
kind: "git";
|
|
104
|
+
}>, options: Readonly<{
|
|
105
|
+
cwd: string;
|
|
106
|
+
exec: ShippingExec;
|
|
107
|
+
label?: string;
|
|
108
|
+
}>): ShippingSource;
|
|
109
|
+
/** Versions of each package published since local midnight, from `npm view <package> time --json`. */
|
|
110
|
+
export declare function npmSource(config: Extract<ShippingSourceConfig, {
|
|
111
|
+
kind: "npm";
|
|
112
|
+
}>, options: Readonly<{
|
|
113
|
+
cwd: string;
|
|
114
|
+
exec: ShippingExec;
|
|
115
|
+
}>): ShippingSource;
|
|
116
|
+
/**
|
|
117
|
+
* The Board's shipping sources for this folder: `board.shipping` in the
|
|
118
|
+
* folder's `.fungi/settings.json`, then the person's, read afresh each cycle so
|
|
119
|
+
* an edit applies. A refused file is one failed source line naming its
|
|
120
|
+
* path, never a silent default. With nothing configured, a Git work tree
|
|
121
|
+
* shows its current branch as landed work, and a folder that is not one shows
|
|
122
|
+
* no shipping at all.
|
|
123
|
+
*/
|
|
124
|
+
export declare function createLocalShippingSources(options: Readonly<{
|
|
125
|
+
cwd: string;
|
|
126
|
+
home: string;
|
|
127
|
+
exec?: ShippingExec;
|
|
128
|
+
now?: () => number;
|
|
129
|
+
}>): ShippingSources;
|