ghostrail 0.0.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 +201 -0
- package/NOTICE +16 -0
- package/README.md +56 -0
- package/dist/agent/claude-code.d.ts +37 -0
- package/dist/agent/claude-code.d.ts.map +1 -0
- package/dist/agent/claude-code.js +74 -0
- package/dist/agent/claude-code.js.map +1 -0
- package/dist/agent/index.d.ts +4 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +4 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/prompt.d.ts +9 -0
- package/dist/agent/prompt.d.ts.map +1 -0
- package/dist/agent/prompt.js +15 -0
- package/dist/agent/prompt.js.map +1 -0
- package/dist/agent/result.d.ts +16 -0
- package/dist/agent/result.d.ts.map +1 -0
- package/dist/agent/result.js +56 -0
- package/dist/agent/result.js.map +1 -0
- package/dist/args.d.ts +27 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +25 -0
- package/dist/args.js.map +1 -0
- package/dist/backend/container.d.ts +18 -0
- package/dist/backend/container.d.ts.map +1 -0
- package/dist/backend/container.js +70 -0
- package/dist/backend/container.js.map +1 -0
- package/dist/backend/docker.d.ts +22 -0
- package/dist/backend/docker.d.ts.map +1 -0
- package/dist/backend/docker.js +38 -0
- package/dist/backend/docker.js.map +1 -0
- package/dist/backend/fs.d.ts +9 -0
- package/dist/backend/fs.d.ts.map +1 -0
- package/dist/backend/fs.js +21 -0
- package/dist/backend/fs.js.map +1 -0
- package/dist/backend/index.d.ts +7 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +6 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/local-worktree.d.ts +17 -0
- package/dist/backend/local-worktree.d.ts.map +1 -0
- package/dist/backend/local-worktree.js +51 -0
- package/dist/backend/local-worktree.js.map +1 -0
- package/dist/backend/proc.d.ts +24 -0
- package/dist/backend/proc.d.ts.map +1 -0
- package/dist/backend/proc.js +103 -0
- package/dist/backend/proc.js.map +1 -0
- package/dist/backend/types.d.ts +75 -0
- package/dist/backend/types.d.ts.map +1 -0
- package/dist/backend/types.js +12 -0
- package/dist/backend/types.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +10 -0
- package/dist/bin.js.map +1 -0
- package/dist/board/index.d.ts +4 -0
- package/dist/board/index.d.ts.map +1 -0
- package/dist/board/index.js +4 -0
- package/dist/board/index.js.map +1 -0
- package/dist/board/page.d.ts +3 -0
- package/dist/board/page.d.ts.map +1 -0
- package/dist/board/page.js +55 -0
- package/dist/board/page.js.map +1 -0
- package/dist/board/server.d.ts +36 -0
- package/dist/board/server.d.ts.map +1 -0
- package/dist/board/server.js +110 -0
- package/dist/board/server.js.map +1 -0
- package/dist/board/stats.d.ts +26 -0
- package/dist/board/stats.d.ts.map +1 -0
- package/dist/board/stats.js +57 -0
- package/dist/board/stats.js.map +1 -0
- package/dist/cli/commands.d.ts +39 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +224 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +45 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/help.d.ts +6 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +29 -0
- package/dist/commands/help.js.map +1 -0
- package/dist/config/duration.d.ts +14 -0
- package/dist/config/duration.d.ts.map +1 -0
- package/dist/config/duration.js +25 -0
- package/dist/config/duration.js.map +1 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +4 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/load.d.ts +26 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +306 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/result.d.ts +18 -0
- package/dist/config/result.d.ts.map +1 -0
- package/dist/config/result.js +7 -0
- package/dist/config/result.js.map +1 -0
- package/dist/config/schema.d.ts +77 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +35 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/factory/build.d.ts +39 -0
- package/dist/factory/build.d.ts.map +1 -0
- package/dist/factory/build.js +85 -0
- package/dist/factory/build.js.map +1 -0
- package/dist/gate/gate.d.ts +12 -0
- package/dist/gate/gate.d.ts.map +1 -0
- package/dist/gate/gate.js +22 -0
- package/dist/gate/gate.js.map +1 -0
- package/dist/gate/index.d.ts +2 -0
- package/dist/gate/index.d.ts.map +1 -0
- package/dist/gate/index.js +2 -0
- package/dist/gate/index.js.map +1 -0
- package/dist/global/index.d.ts +3 -0
- package/dist/global/index.d.ts.map +1 -0
- package/dist/global/index.js +3 -0
- package/dist/global/index.js.map +1 -0
- package/dist/global/stage.d.ts +13 -0
- package/dist/global/stage.d.ts.map +1 -0
- package/dist/global/stage.js +24 -0
- package/dist/global/stage.js.map +1 -0
- package/dist/global/store.d.ts +30 -0
- package/dist/global/store.d.ts.map +1 -0
- package/dist/global/store.js +65 -0
- package/dist/global/store.js.map +1 -0
- package/dist/lock/file-lock.d.ts +16 -0
- package/dist/lock/file-lock.d.ts.map +1 -0
- package/dist/lock/file-lock.js +51 -0
- package/dist/lock/file-lock.js.map +1 -0
- package/dist/loop/branch.d.ts +14 -0
- package/dist/loop/branch.d.ts.map +1 -0
- package/dist/loop/branch.js +24 -0
- package/dist/loop/branch.js.map +1 -0
- package/dist/loop/engine.d.ts +37 -0
- package/dist/loop/engine.d.ts.map +1 -0
- package/dist/loop/engine.js +204 -0
- package/dist/loop/engine.js.map +1 -0
- package/dist/loop/index.d.ts +6 -0
- package/dist/loop/index.d.ts.map +1 -0
- package/dist/loop/index.js +3 -0
- package/dist/loop/index.js.map +1 -0
- package/dist/loop/ports.d.ts +97 -0
- package/dist/loop/ports.d.ts.map +1 -0
- package/dist/loop/ports.js +2 -0
- package/dist/loop/ports.js.map +1 -0
- package/dist/loop/record.d.ts +26 -0
- package/dist/loop/record.d.ts.map +1 -0
- package/dist/loop/record.js +2 -0
- package/dist/loop/record.js.map +1 -0
- package/dist/publish/gh.d.ts +24 -0
- package/dist/publish/gh.d.ts.map +1 -0
- package/dist/publish/gh.js +109 -0
- package/dist/publish/gh.js.map +1 -0
- package/dist/publish/githost.d.ts +54 -0
- package/dist/publish/githost.d.ts.map +1 -0
- package/dist/publish/githost.js +33 -0
- package/dist/publish/githost.js.map +1 -0
- package/dist/publish/github-publisher.d.ts +30 -0
- package/dist/publish/github-publisher.d.ts.map +1 -0
- package/dist/publish/github-publisher.js +51 -0
- package/dist/publish/github-publisher.js.map +1 -0
- package/dist/publish/index.d.ts +4 -0
- package/dist/publish/index.d.ts.map +1 -0
- package/dist/publish/index.js +4 -0
- package/dist/publish/index.js.map +1 -0
- package/dist/respond/index.d.ts +4 -0
- package/dist/respond/index.d.ts.map +1 -0
- package/dist/respond/index.js +4 -0
- package/dist/respond/index.js.map +1 -0
- package/dist/respond/respond.d.ts +42 -0
- package/dist/respond/respond.d.ts.map +1 -0
- package/dist/respond/respond.js +128 -0
- package/dist/respond/respond.js.map +1 -0
- package/dist/respond/select.d.ts +22 -0
- package/dist/respond/select.d.ts.map +1 -0
- package/dist/respond/select.js +31 -0
- package/dist/respond/select.js.map +1 -0
- package/dist/respond/store.d.ts +25 -0
- package/dist/respond/store.d.ts.map +1 -0
- package/dist/respond/store.js +49 -0
- package/dist/respond/store.js.map +1 -0
- package/dist/secrets/redact.d.ts +11 -0
- package/dist/secrets/redact.d.ts.map +1 -0
- package/dist/secrets/redact.js +21 -0
- package/dist/secrets/redact.js.map +1 -0
- package/dist/source/index.d.ts +2 -0
- package/dist/source/index.d.ts.map +1 -0
- package/dist/source/index.js +2 -0
- package/dist/source/index.js.map +1 -0
- package/dist/source/linear.d.ts +61 -0
- package/dist/source/linear.d.ts.map +1 -0
- package/dist/source/linear.js +166 -0
- package/dist/source/linear.js.map +1 -0
- package/dist/store/events.d.ts +105 -0
- package/dist/store/events.d.ts.map +1 -0
- package/dist/store/events.js +64 -0
- package/dist/store/events.js.map +1 -0
- package/dist/store/file-store.d.ts +49 -0
- package/dist/store/file-store.d.ts.map +1 -0
- package/dist/store/file-store.js +188 -0
- package/dist/store/file-store.js.map +1 -0
- package/dist/store/index.d.ts +3 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +3 -0
- package/dist/store/index.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +21 -0
- package/dist/version.js.map +1 -0
- package/package.json +52 -0
- package/templates/content-loop/README.md +23 -0
- package/templates/content-loop/ghostrail.toml +36 -0
- package/templates/content-loop/prompts/draft.md +29 -0
- package/templates/fix-bugs-local/README.md +23 -0
- package/templates/fix-bugs-local/ghostrail.toml +37 -0
- package/templates/fix-bugs-local/prompts/fix-bug.md +27 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
export const LINEAR_ENDPOINT = "https://api.linear.app/graphql";
|
|
2
|
+
/**
|
|
3
|
+
* A default requester over `fetch`, authenticating with a Linear personal API
|
|
4
|
+
* key (sent verbatim in the Authorization header, per Linear's API).
|
|
5
|
+
*/
|
|
6
|
+
export function createFetchRequester(apiKey, endpoint = LINEAR_ENDPOINT, fetchImpl = fetch) {
|
|
7
|
+
return async (query, variables) => {
|
|
8
|
+
const response = await fetchImpl(endpoint, {
|
|
9
|
+
method: "POST",
|
|
10
|
+
headers: { "Content-Type": "application/json", Authorization: apiKey },
|
|
11
|
+
body: JSON.stringify({ query, variables }),
|
|
12
|
+
});
|
|
13
|
+
if (!response.ok) {
|
|
14
|
+
throw new Error(`Linear HTTP ${response.status}`);
|
|
15
|
+
}
|
|
16
|
+
const body = (await response.json());
|
|
17
|
+
if (body.errors !== undefined) {
|
|
18
|
+
throw new Error(`Linear GraphQL error: ${JSON.stringify(body.errors)}`);
|
|
19
|
+
}
|
|
20
|
+
return (body.data ?? {});
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export const ELIGIBLE_ISSUES_QUERY = `
|
|
24
|
+
query EligibleIssues($filter: IssueFilter!, $first: Int!) {
|
|
25
|
+
issues(filter: $filter, first: $first, orderBy: updatedAt) {
|
|
26
|
+
nodes { id identifier title url }
|
|
27
|
+
}
|
|
28
|
+
}`;
|
|
29
|
+
/**
|
|
30
|
+
* Build the Linear `IssueFilter` for an eligibility spec: state name, each label
|
|
31
|
+
* (via `and`), unassigned, and optionally scoped to a team key. Only the
|
|
32
|
+
* provided fields are included.
|
|
33
|
+
*/
|
|
34
|
+
export function buildIssueFilter(eligible, teamKey) {
|
|
35
|
+
const filter = {};
|
|
36
|
+
if (teamKey !== undefined)
|
|
37
|
+
filter.team = { key: { eq: teamKey } };
|
|
38
|
+
if (eligible.state !== undefined)
|
|
39
|
+
filter.state = { name: { eq: eligible.state } };
|
|
40
|
+
if (eligible.unassigned)
|
|
41
|
+
filter.assignee = { null: true };
|
|
42
|
+
if (eligible.labels.length > 0) {
|
|
43
|
+
filter.and = eligible.labels.map((name) => ({ labels: { some: { name: { eq: name } } } }));
|
|
44
|
+
}
|
|
45
|
+
return filter;
|
|
46
|
+
}
|
|
47
|
+
/** Extract issue nodes from an `issues` query payload, ignoring malformed nodes. */
|
|
48
|
+
export function parseIssueNodes(data) {
|
|
49
|
+
const issues = data.issues;
|
|
50
|
+
const nodes = Array.isArray(issues?.nodes) ? issues.nodes : [];
|
|
51
|
+
const parsed = [];
|
|
52
|
+
for (const node of nodes) {
|
|
53
|
+
if (node === null || typeof node !== "object")
|
|
54
|
+
continue;
|
|
55
|
+
const record = node;
|
|
56
|
+
const { id, identifier, title, url } = record;
|
|
57
|
+
if (typeof id === "string" &&
|
|
58
|
+
typeof identifier === "string" &&
|
|
59
|
+
typeof title === "string" &&
|
|
60
|
+
typeof url === "string") {
|
|
61
|
+
parsed.push({ id, identifier, title, url });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return parsed;
|
|
65
|
+
}
|
|
66
|
+
const BOOTSTRAP_QUERY = `
|
|
67
|
+
query Bootstrap($teamKey: String!) {
|
|
68
|
+
viewer { id }
|
|
69
|
+
workflowStates(filter: { team: { key: { eq: $teamKey } } }) {
|
|
70
|
+
nodes { id name }
|
|
71
|
+
}
|
|
72
|
+
}`;
|
|
73
|
+
const ISSUE_UPDATE = `
|
|
74
|
+
mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {
|
|
75
|
+
issueUpdate(id: $id, input: $input) { success }
|
|
76
|
+
}`;
|
|
77
|
+
const COMMENT_CREATE = `
|
|
78
|
+
mutation CommentCreate($input: CommentCreateInput!) {
|
|
79
|
+
commentCreate(input: $input) { success }
|
|
80
|
+
}`;
|
|
81
|
+
/**
|
|
82
|
+
* The Linear implementation of the {@link Source} port, over the GraphQL API
|
|
83
|
+
* (a headless `claude -p` has no Linear MCP). Claiming an item moves it to the
|
|
84
|
+
* in-progress state and assigns it to the acting user, which removes it from the
|
|
85
|
+
* eligible pool; reset returns it to the reset state, unassigned.
|
|
86
|
+
*/
|
|
87
|
+
export class LinearSource {
|
|
88
|
+
request;
|
|
89
|
+
opts;
|
|
90
|
+
bootstrap;
|
|
91
|
+
uuidByIdentifier = new Map();
|
|
92
|
+
constructor(request, opts) {
|
|
93
|
+
this.request = request;
|
|
94
|
+
this.opts = {
|
|
95
|
+
teamKey: opts.teamKey,
|
|
96
|
+
eligible: opts.eligible,
|
|
97
|
+
inProgressState: opts.inProgressState ?? "In Progress",
|
|
98
|
+
resetState: opts.resetState ?? opts.eligible.state ?? "Todo",
|
|
99
|
+
maxItems: opts.maxItems ?? 50,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async listEligible() {
|
|
103
|
+
const data = await this.request(ELIGIBLE_ISSUES_QUERY, {
|
|
104
|
+
filter: buildIssueFilter(this.opts.eligible, this.opts.teamKey),
|
|
105
|
+
first: this.opts.maxItems,
|
|
106
|
+
});
|
|
107
|
+
const nodes = parseIssueNodes(data);
|
|
108
|
+
for (const node of nodes)
|
|
109
|
+
this.uuidByIdentifier.set(node.identifier, node.id);
|
|
110
|
+
return nodes.map((node) => ({ id: node.identifier, title: node.title, url: node.url }));
|
|
111
|
+
}
|
|
112
|
+
async claim(item) {
|
|
113
|
+
const { viewerId, stateIdByName } = await this.ensureBootstrap();
|
|
114
|
+
const stateId = stateIdByName.get(this.opts.inProgressState);
|
|
115
|
+
await this.request(ISSUE_UPDATE, {
|
|
116
|
+
id: await this.uuidFor(item),
|
|
117
|
+
input: stateId === undefined ? { assigneeId: viewerId } : { stateId, assigneeId: viewerId },
|
|
118
|
+
});
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
async comment(item, body) {
|
|
122
|
+
await this.request(COMMENT_CREATE, { input: { issueId: await this.uuidFor(item), body } });
|
|
123
|
+
}
|
|
124
|
+
async reassignToHuman(item) {
|
|
125
|
+
const { viewerId } = await this.ensureBootstrap();
|
|
126
|
+
await this.request(ISSUE_UPDATE, {
|
|
127
|
+
id: await this.uuidFor(item),
|
|
128
|
+
input: { assigneeId: viewerId },
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async reset(item) {
|
|
132
|
+
const { stateIdByName } = await this.ensureBootstrap();
|
|
133
|
+
const stateId = stateIdByName.get(this.opts.resetState);
|
|
134
|
+
await this.request(ISSUE_UPDATE, {
|
|
135
|
+
id: await this.uuidFor(item),
|
|
136
|
+
input: stateId === undefined ? { assigneeId: null } : { stateId, assigneeId: null },
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
async ensureBootstrap() {
|
|
140
|
+
if (this.bootstrap !== undefined)
|
|
141
|
+
return this.bootstrap;
|
|
142
|
+
const data = await this.request(BOOTSTRAP_QUERY, { teamKey: this.opts.teamKey });
|
|
143
|
+
const viewer = data.viewer;
|
|
144
|
+
const states = data.workflowStates?.nodes;
|
|
145
|
+
const stateIdByName = new Map();
|
|
146
|
+
if (Array.isArray(states)) {
|
|
147
|
+
for (const node of states) {
|
|
148
|
+
const record = node;
|
|
149
|
+
if (typeof record.id === "string" && typeof record.name === "string") {
|
|
150
|
+
stateIdByName.set(record.name, record.id);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (typeof viewer?.id !== "string")
|
|
155
|
+
throw new Error("Linear bootstrap: no viewer id");
|
|
156
|
+
this.bootstrap = { viewerId: viewer.id, stateIdByName };
|
|
157
|
+
return this.bootstrap;
|
|
158
|
+
}
|
|
159
|
+
async uuidFor(item) {
|
|
160
|
+
const cached = this.uuidByIdentifier.get(item.id);
|
|
161
|
+
if (cached !== undefined)
|
|
162
|
+
return cached;
|
|
163
|
+
throw new Error(`Linear: unknown issue ${item.id} (list eligible before acting on it)`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=linear.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear.js","sourceRoot":"","sources":["../../src/source/linear.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The append-only event is the source of truth (research Appendix C). A run row
|
|
3
|
+
* is a fold over its events, so a crashed mid-stage run still leaves a trail and
|
|
4
|
+
* the row is always rebuildable. `ts` is an epoch-millis timestamp stamped by
|
|
5
|
+
* the emitter.
|
|
6
|
+
*/
|
|
7
|
+
export type RunEvent = {
|
|
8
|
+
type: "claimed";
|
|
9
|
+
runId: string;
|
|
10
|
+
ts: number;
|
|
11
|
+
itemId: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
kind?: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: "provisioned";
|
|
16
|
+
runId: string;
|
|
17
|
+
ts: number;
|
|
18
|
+
backend: string;
|
|
19
|
+
branch: string;
|
|
20
|
+
} | {
|
|
21
|
+
type: "agent_finished";
|
|
22
|
+
runId: string;
|
|
23
|
+
ts: number;
|
|
24
|
+
status: string;
|
|
25
|
+
costUsd?: number;
|
|
26
|
+
tokensIn?: number;
|
|
27
|
+
tokensOut?: number;
|
|
28
|
+
} | {
|
|
29
|
+
type: "gate_step";
|
|
30
|
+
runId: string;
|
|
31
|
+
ts: number;
|
|
32
|
+
name: string;
|
|
33
|
+
exitCode: number;
|
|
34
|
+
durationMs: number;
|
|
35
|
+
} | {
|
|
36
|
+
type: "pr_opened";
|
|
37
|
+
runId: string;
|
|
38
|
+
ts: number;
|
|
39
|
+
prNumber: number;
|
|
40
|
+
prUrl: string;
|
|
41
|
+
} | {
|
|
42
|
+
type: "artifact";
|
|
43
|
+
runId: string;
|
|
44
|
+
ts: number;
|
|
45
|
+
name: string;
|
|
46
|
+
hash: string;
|
|
47
|
+
} | {
|
|
48
|
+
type: "outcome";
|
|
49
|
+
runId: string;
|
|
50
|
+
ts: number;
|
|
51
|
+
state: string;
|
|
52
|
+
error?: string;
|
|
53
|
+
};
|
|
54
|
+
/** A sink the loop emits run events to. A no-op sink means "don't record". */
|
|
55
|
+
export interface EventSink {
|
|
56
|
+
emit(event: RunEvent): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
export interface GateStepRow {
|
|
59
|
+
name: string;
|
|
60
|
+
exitCode: number;
|
|
61
|
+
durationMs: number;
|
|
62
|
+
}
|
|
63
|
+
export interface ArtifactRef {
|
|
64
|
+
name: string;
|
|
65
|
+
hash: string;
|
|
66
|
+
}
|
|
67
|
+
/** The current run-row schema version, so stored rows can be migrated later. */
|
|
68
|
+
export declare const ROW_SCHEMA_VERSION = 1;
|
|
69
|
+
/** A run row: the folded, board-renderable view of one run's events. */
|
|
70
|
+
export interface RunRow {
|
|
71
|
+
schemaVersion: number;
|
|
72
|
+
runId: string;
|
|
73
|
+
itemId?: string;
|
|
74
|
+
title?: string;
|
|
75
|
+
kind?: string;
|
|
76
|
+
backend?: string;
|
|
77
|
+
branch?: string;
|
|
78
|
+
/** Final outcome state (done/blocked/failed/noop/skipped), once known. */
|
|
79
|
+
state?: string;
|
|
80
|
+
costUsd?: number;
|
|
81
|
+
tokensIn?: number;
|
|
82
|
+
tokensOut?: number;
|
|
83
|
+
gate: GateStepRow[];
|
|
84
|
+
prNumber?: number;
|
|
85
|
+
prUrl?: string;
|
|
86
|
+
error?: string;
|
|
87
|
+
artifacts: ArtifactRef[];
|
|
88
|
+
/** Epoch millis of the first and last events seen. */
|
|
89
|
+
startedAt?: number;
|
|
90
|
+
finishedAt?: number;
|
|
91
|
+
/** Number of events folded into this row. */
|
|
92
|
+
events: number;
|
|
93
|
+
}
|
|
94
|
+
/** An empty row for a run id, before any event is applied. */
|
|
95
|
+
export declare function emptyRow(runId: string): RunRow;
|
|
96
|
+
/**
|
|
97
|
+
* Apply one event to a run row, returning the updated row (does not mutate the
|
|
98
|
+
* input). `startedAt` tracks the earliest `ts`, `finishedAt` the latest, and
|
|
99
|
+
* `events` counts applications. Later same-kind fields overwrite earlier ones;
|
|
100
|
+
* gate steps and artifacts accumulate in arrival order.
|
|
101
|
+
*/
|
|
102
|
+
export declare function applyEvent(row: RunRow, event: RunEvent): RunRow;
|
|
103
|
+
/** Fold a run's events (in order) into its row. */
|
|
104
|
+
export declare function foldRun(runId: string, events: readonly RunEvent[]): RunRow;
|
|
105
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/store/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** The current run-row schema version, so stored rows can be migrated later. */
|
|
2
|
+
export const ROW_SCHEMA_VERSION = 1;
|
|
3
|
+
/** An empty row for a run id, before any event is applied. */
|
|
4
|
+
export function emptyRow(runId) {
|
|
5
|
+
return { schemaVersion: ROW_SCHEMA_VERSION, runId, gate: [], artifacts: [], events: 0 };
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Apply one event to a run row, returning the updated row (does not mutate the
|
|
9
|
+
* input). `startedAt` tracks the earliest `ts`, `finishedAt` the latest, and
|
|
10
|
+
* `events` counts applications. Later same-kind fields overwrite earlier ones;
|
|
11
|
+
* gate steps and artifacts accumulate in arrival order.
|
|
12
|
+
*/
|
|
13
|
+
export function applyEvent(row, event) {
|
|
14
|
+
const next = {
|
|
15
|
+
...row,
|
|
16
|
+
events: row.events + 1,
|
|
17
|
+
startedAt: row.startedAt === undefined ? event.ts : Math.min(row.startedAt, event.ts),
|
|
18
|
+
finishedAt: row.finishedAt === undefined ? event.ts : Math.max(row.finishedAt, event.ts),
|
|
19
|
+
gate: [...row.gate],
|
|
20
|
+
artifacts: [...row.artifacts],
|
|
21
|
+
};
|
|
22
|
+
switch (event.type) {
|
|
23
|
+
case "claimed":
|
|
24
|
+
next.itemId = event.itemId;
|
|
25
|
+
if (event.title !== undefined)
|
|
26
|
+
next.title = event.title;
|
|
27
|
+
if (event.kind !== undefined)
|
|
28
|
+
next.kind = event.kind;
|
|
29
|
+
break;
|
|
30
|
+
case "provisioned":
|
|
31
|
+
next.backend = event.backend;
|
|
32
|
+
next.branch = event.branch;
|
|
33
|
+
break;
|
|
34
|
+
case "agent_finished":
|
|
35
|
+
if (event.costUsd !== undefined)
|
|
36
|
+
next.costUsd = event.costUsd;
|
|
37
|
+
if (event.tokensIn !== undefined)
|
|
38
|
+
next.tokensIn = event.tokensIn;
|
|
39
|
+
if (event.tokensOut !== undefined)
|
|
40
|
+
next.tokensOut = event.tokensOut;
|
|
41
|
+
break;
|
|
42
|
+
case "gate_step":
|
|
43
|
+
next.gate.push({ name: event.name, exitCode: event.exitCode, durationMs: event.durationMs });
|
|
44
|
+
break;
|
|
45
|
+
case "pr_opened":
|
|
46
|
+
next.prNumber = event.prNumber;
|
|
47
|
+
next.prUrl = event.prUrl;
|
|
48
|
+
break;
|
|
49
|
+
case "artifact":
|
|
50
|
+
next.artifacts.push({ name: event.name, hash: event.hash });
|
|
51
|
+
break;
|
|
52
|
+
case "outcome":
|
|
53
|
+
next.state = event.state;
|
|
54
|
+
if (event.error !== undefined)
|
|
55
|
+
next.error = event.error;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
return next;
|
|
59
|
+
}
|
|
60
|
+
/** Fold a run's events (in order) into its row. */
|
|
61
|
+
export function foldRun(runId, events) {
|
|
62
|
+
return events.reduce(applyEvent, emptyRow(runId));
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/store/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type EventSink, type RunEvent, type RunRow } from "./events.js";
|
|
2
|
+
export interface RunFilter {
|
|
3
|
+
state?: string;
|
|
4
|
+
/** Only runs whose startedAt is at or after this epoch-millis timestamp. */
|
|
5
|
+
since?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface RetentionPolicy {
|
|
8
|
+
/** Drop run rows older than this many ms (by startedAt). */
|
|
9
|
+
retainRunsMs?: number;
|
|
10
|
+
/** Drop events older than this many ms (by ts). */
|
|
11
|
+
retainEventsMs?: number;
|
|
12
|
+
/** Drop artifacts older than this many ms (by mtime). */
|
|
13
|
+
retainArtifactsMs?: number;
|
|
14
|
+
/** Cap total artifact bytes; oldest are removed first when over. */
|
|
15
|
+
maxArtifactBytes?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The local-by-default run store (research Appendix C). `events.ndjson` is the
|
|
19
|
+
* append-only source of truth; each run's row (`runs/<id>.json`) is the fold
|
|
20
|
+
* over its events, updated on every append; artifacts are content-addressed
|
|
21
|
+
* blobs under `artifacts/<sha256>`. Rows are rebuildable from the events, so a
|
|
22
|
+
* lost row is a re-fold, not an incident. Retention is tuned per tier.
|
|
23
|
+
*
|
|
24
|
+
* A derived SQLite index for O(1) history queries is a drop-in optimization over
|
|
25
|
+
* this same event log (Appendix C) and is deferred to a later phase.
|
|
26
|
+
*/
|
|
27
|
+
export declare class FileStore implements EventSink {
|
|
28
|
+
private readonly eventsPath;
|
|
29
|
+
private readonly runsDir;
|
|
30
|
+
private readonly artifactsDir;
|
|
31
|
+
constructor(dir: string);
|
|
32
|
+
emit(event: RunEvent): Promise<void>;
|
|
33
|
+
/** Append an event and fold it into the run's row. */
|
|
34
|
+
append(event: RunEvent): Promise<void>;
|
|
35
|
+
getRun(runId: string): Promise<RunRow | undefined>;
|
|
36
|
+
/** Rows matching the filter, newest first. */
|
|
37
|
+
listRuns(filter?: RunFilter): Promise<RunRow[]>;
|
|
38
|
+
/** The events for one run, in order (read from the source-of-truth log). */
|
|
39
|
+
getEvents(runId: string): Promise<RunEvent[]>;
|
|
40
|
+
/** Store a blob by content hash and return the sha256 hex id. */
|
|
41
|
+
putArtifact(content: string | Buffer): Promise<string>;
|
|
42
|
+
getArtifact(hash: string): Promise<Buffer | undefined>;
|
|
43
|
+
/** Apply retention: drop old rows, old events, and old/oversized artifacts. */
|
|
44
|
+
prune(policy: RetentionPolicy, now: number): Promise<void>;
|
|
45
|
+
private pruneEvents;
|
|
46
|
+
private pruneArtifacts;
|
|
47
|
+
private rowPath;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=file-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../src/store/file-store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAwB,MAAM,aAAa,CAAC;AAE/F,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,qBAAa,SAAU,YAAW,SAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,GAAG,EAAE,MAAM;IAMvB,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpC,sDAAsD;IAChD,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAWtC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAQxD,8CAA8C;IACxC,QAAQ,CAAC,MAAM,GAAE,SAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAyBzD,4EAA4E;IACtE,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAoBnD,iEAAiE;IAC3D,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQtD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAQ5D,+EAA+E;IACzE,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAalD,WAAW;YAqBX,cAAc;IAsC5B,OAAO,CAAC,OAAO;CAGhB"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { appendFile, mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { applyEvent, emptyRow } from "./events.js";
|
|
5
|
+
/**
|
|
6
|
+
* The local-by-default run store (research Appendix C). `events.ndjson` is the
|
|
7
|
+
* append-only source of truth; each run's row (`runs/<id>.json`) is the fold
|
|
8
|
+
* over its events, updated on every append; artifacts are content-addressed
|
|
9
|
+
* blobs under `artifacts/<sha256>`. Rows are rebuildable from the events, so a
|
|
10
|
+
* lost row is a re-fold, not an incident. Retention is tuned per tier.
|
|
11
|
+
*
|
|
12
|
+
* A derived SQLite index for O(1) history queries is a drop-in optimization over
|
|
13
|
+
* this same event log (Appendix C) and is deferred to a later phase.
|
|
14
|
+
*/
|
|
15
|
+
export class FileStore {
|
|
16
|
+
eventsPath;
|
|
17
|
+
runsDir;
|
|
18
|
+
artifactsDir;
|
|
19
|
+
constructor(dir) {
|
|
20
|
+
this.eventsPath = join(dir, "events.ndjson");
|
|
21
|
+
this.runsDir = join(dir, "runs");
|
|
22
|
+
this.artifactsDir = join(dir, "artifacts");
|
|
23
|
+
}
|
|
24
|
+
emit(event) {
|
|
25
|
+
return this.append(event);
|
|
26
|
+
}
|
|
27
|
+
/** Append an event and fold it into the run's row. */
|
|
28
|
+
async append(event) {
|
|
29
|
+
await mkdir(this.runsDir, { recursive: true });
|
|
30
|
+
await appendFile(this.eventsPath, `${JSON.stringify(event)}\n`, "utf8");
|
|
31
|
+
const current = (await this.getRun(event.runId)) ?? emptyRow(event.runId);
|
|
32
|
+
await writeFile(this.rowPath(event.runId), `${JSON.stringify(applyEvent(current, event))}\n`, "utf8");
|
|
33
|
+
}
|
|
34
|
+
async getRun(runId) {
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(await readFile(this.rowPath(runId), "utf8"));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Rows matching the filter, newest first. */
|
|
43
|
+
async listRuns(filter = {}) {
|
|
44
|
+
let names;
|
|
45
|
+
try {
|
|
46
|
+
names = await readdir(this.runsDir);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
const rows = [];
|
|
52
|
+
for (const name of names) {
|
|
53
|
+
if (!name.endsWith(".json"))
|
|
54
|
+
continue;
|
|
55
|
+
try {
|
|
56
|
+
rows.push(JSON.parse(await readFile(join(this.runsDir, name), "utf8")));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// skip an unreadable row
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const filtered = rows.filter((row) => (filter.state === undefined || row.state === filter.state) &&
|
|
63
|
+
(filter.since === undefined || (row.startedAt ?? 0) >= filter.since));
|
|
64
|
+
filtered.sort((a, b) => (b.startedAt ?? 0) - (a.startedAt ?? 0));
|
|
65
|
+
return filtered;
|
|
66
|
+
}
|
|
67
|
+
/** The events for one run, in order (read from the source-of-truth log). */
|
|
68
|
+
async getEvents(runId) {
|
|
69
|
+
let raw;
|
|
70
|
+
try {
|
|
71
|
+
raw = await readFile(this.eventsPath, "utf8");
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
const events = [];
|
|
77
|
+
for (const line of raw.split("\n")) {
|
|
78
|
+
if (line.length === 0)
|
|
79
|
+
continue;
|
|
80
|
+
try {
|
|
81
|
+
const event = JSON.parse(line);
|
|
82
|
+
if (event.runId === runId)
|
|
83
|
+
events.push(event);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// skip a corrupt line
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return events;
|
|
90
|
+
}
|
|
91
|
+
/** Store a blob by content hash and return the sha256 hex id. */
|
|
92
|
+
async putArtifact(content) {
|
|
93
|
+
const buffer = typeof content === "string" ? Buffer.from(content, "utf8") : content;
|
|
94
|
+
const hash = createHash("sha256").update(buffer).digest("hex");
|
|
95
|
+
await mkdir(this.artifactsDir, { recursive: true });
|
|
96
|
+
await writeFile(join(this.artifactsDir, hash), buffer);
|
|
97
|
+
return hash;
|
|
98
|
+
}
|
|
99
|
+
async getArtifact(hash) {
|
|
100
|
+
try {
|
|
101
|
+
return await readFile(join(this.artifactsDir, hash));
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** Apply retention: drop old rows, old events, and old/oversized artifacts. */
|
|
108
|
+
async prune(policy, now) {
|
|
109
|
+
if (policy.retainRunsMs !== undefined) {
|
|
110
|
+
const cutoff = now - policy.retainRunsMs;
|
|
111
|
+
for (const row of await this.listRuns()) {
|
|
112
|
+
if ((row.startedAt ?? 0) < cutoff)
|
|
113
|
+
await rm(this.rowPath(row.runId), { force: true });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (policy.retainEventsMs !== undefined) {
|
|
117
|
+
await this.pruneEvents(now - policy.retainEventsMs);
|
|
118
|
+
}
|
|
119
|
+
await this.pruneArtifacts(policy, now);
|
|
120
|
+
}
|
|
121
|
+
async pruneEvents(cutoff) {
|
|
122
|
+
let raw;
|
|
123
|
+
try {
|
|
124
|
+
raw = await readFile(this.eventsPath, "utf8");
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const kept = raw
|
|
130
|
+
.split("\n")
|
|
131
|
+
.filter((line) => {
|
|
132
|
+
if (line.length === 0)
|
|
133
|
+
return false;
|
|
134
|
+
try {
|
|
135
|
+
return JSON.parse(line).ts >= cutoff;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
.join("\n");
|
|
142
|
+
await writeFile(this.eventsPath, kept.length > 0 ? `${kept}\n` : "", "utf8");
|
|
143
|
+
}
|
|
144
|
+
async pruneArtifacts(policy, now) {
|
|
145
|
+
let names;
|
|
146
|
+
try {
|
|
147
|
+
names = await readdir(this.artifactsDir);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const entries = [];
|
|
153
|
+
for (const hash of names) {
|
|
154
|
+
try {
|
|
155
|
+
const info = await stat(join(this.artifactsDir, hash));
|
|
156
|
+
entries.push({ hash, mtimeMs: info.mtimeMs, size: info.size });
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// skip
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
let survivors = entries;
|
|
163
|
+
if (policy.retainArtifactsMs !== undefined) {
|
|
164
|
+
const cutoff = now - policy.retainArtifactsMs;
|
|
165
|
+
survivors = [];
|
|
166
|
+
for (const entry of entries) {
|
|
167
|
+
if (entry.mtimeMs < cutoff)
|
|
168
|
+
await rm(join(this.artifactsDir, entry.hash), { force: true });
|
|
169
|
+
else
|
|
170
|
+
survivors.push(entry);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (policy.maxArtifactBytes !== undefined) {
|
|
174
|
+
survivors.sort((a, b) => a.mtimeMs - b.mtimeMs); // oldest first
|
|
175
|
+
let total = survivors.reduce((sum, e) => sum + e.size, 0);
|
|
176
|
+
for (const entry of survivors) {
|
|
177
|
+
if (total <= policy.maxArtifactBytes)
|
|
178
|
+
break;
|
|
179
|
+
await rm(join(this.artifactsDir, entry.hash), { force: true });
|
|
180
|
+
total -= entry.size;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
rowPath(runId) {
|
|
185
|
+
return join(this.runsDir, `${encodeURIComponent(runId)}.json`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=file-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-store.js","sourceRoot":"","sources":["../../src/store/file-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { applyEvent, type ArtifactRef, emptyRow, type EventSink, foldRun, type GateStepRow, ROW_SCHEMA_VERSION, type RunEvent, type RunRow, } from "./events.js";
|
|
2
|
+
export { FileStore, type RetentionPolicy, type RunFilter } from "./file-store.js";
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,WAAW,EAChB,QAAQ,EACR,KAAK,SAAS,EACd,OAAO,EACP,KAAK,WAAW,EAChB,kBAAkB,EAClB,KAAK,QAAQ,EACb,KAAK,MAAM,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAEV,QAAQ,EAER,OAAO,EAEP,kBAAkB,GAGnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAwC,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAmBA,6CAA6C;AAC7C,eAAO,MAAM,OAAO,EAAE,MAAsB,CAAC"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
/**
|
|
4
|
+
* Read the ghostrail version from the package manifest at runtime so the CLI
|
|
5
|
+
* output and the published package can never drift. Falls back to "0.0.0" if
|
|
6
|
+
* the manifest cannot be read (e.g. an unusual install layout).
|
|
7
|
+
*/
|
|
8
|
+
function readVersion() {
|
|
9
|
+
try {
|
|
10
|
+
const pkgUrl = new URL("../package.json", import.meta.url);
|
|
11
|
+
const raw = readFileSync(fileURLToPath(pkgUrl), "utf8");
|
|
12
|
+
const pkg = JSON.parse(raw);
|
|
13
|
+
return typeof pkg.version === "string" ? pkg.version : "0.0.0";
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return "0.0.0";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** The resolved ghostrail version string. */
|
|
20
|
+
export const VERSION = readVersion();
|
|
21
|
+
//# sourceMappingURL=version.js.map
|