@melra/cli 0.3.0-alpha.11 → 0.3.0-alpha.13
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 +14 -7
- package/dist/activity.d.ts +26 -0
- package/dist/activity.d.ts.map +1 -0
- package/dist/activity.js +404 -0
- package/dist/activity.js.map +1 -0
- package/dist/approval-screen.d.ts +35 -0
- package/dist/approval-screen.d.ts.map +1 -0
- package/dist/approval-screen.js +130 -0
- package/dist/approval-screen.js.map +1 -0
- package/dist/client-status.d.ts +24 -0
- package/dist/client-status.d.ts.map +1 -0
- package/dist/client-status.js +273 -0
- package/dist/client-status.js.map +1 -0
- package/dist/clients.d.ts +32 -0
- package/dist/clients.d.ts.map +1 -0
- package/dist/clients.js +588 -0
- package/dist/clients.js.map +1 -0
- package/dist/conformance.d.ts +7 -0
- package/dist/conformance.d.ts.map +1 -1
- package/dist/conformance.js +134 -30
- package/dist/conformance.js.map +1 -1
- package/dist/demo-workflow.d.ts +46 -0
- package/dist/demo-workflow.d.ts.map +1 -0
- package/dist/demo-workflow.js +58 -0
- package/dist/demo-workflow.js.map +1 -0
- package/dist/environment.d.ts +15 -1
- package/dist/environment.d.ts.map +1 -1
- package/dist/environment.js +30 -4
- package/dist/environment.js.map +1 -1
- package/dist/human.d.ts +67 -0
- package/dist/human.d.ts.map +1 -0
- package/dist/human.js +266 -0
- package/dist/human.js.map +1 -0
- package/dist/index.js +432 -77
- package/dist/index.js.map +1 -1
- package/dist/isolation.d.ts +35 -0
- package/dist/isolation.d.ts.map +1 -0
- package/dist/isolation.js +66 -0
- package/dist/isolation.js.map +1 -0
- package/dist/jsonc.d.ts +24 -0
- package/dist/jsonc.d.ts.map +1 -0
- package/dist/jsonc.js +238 -0
- package/dist/jsonc.js.map +1 -0
- package/dist/output.d.ts +28 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +84 -0
- package/dist/output.js.map +1 -0
- package/package.json +11 -10
package/README.md
CHANGED
|
@@ -6,10 +6,13 @@ Everything in one command, with nothing installed beforehand:
|
|
|
6
6
|
npx @melra/cli@alpha setup
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
`setup` writes a safe local policy,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
`setup` writes a safe local policy, produces an MCP client configuration, and
|
|
10
|
+
runs every readiness check (Node, workspace, SQLite, browser, computer-use
|
|
11
|
+
adapter, policy, MCP clients). In a terminal it asks which detected client to
|
|
12
|
+
set up and offers to write MELRA into that client's own config file;
|
|
13
|
+
`--client <name> --write` does the same without asking, and piped or with
|
|
14
|
+
`--json` it prints JSON. It exits non-zero if a check fails and never
|
|
15
|
+
overwrites an existing policy.
|
|
13
16
|
|
|
14
17
|
To keep a resolved copy on the machine instead of resolving on every run:
|
|
15
18
|
|
|
@@ -24,8 +27,10 @@ version that wrote the config, since an `npx` install leaves no `melra` on your
|
|
|
24
27
|
`PATH`.
|
|
25
28
|
|
|
26
29
|
Individual steps are still available: `melra doctor` checks readiness and writes
|
|
27
|
-
nothing, `melra init` writes the policy and config without checking.
|
|
28
|
-
`
|
|
30
|
+
nothing, `melra init` writes the policy and config without checking. `melra
|
|
31
|
+
serve` speaks stdio, `--http` loopback HTTP with the console, and `--socket
|
|
32
|
+
<path>` a mode-`0600` Unix socket; `melra tasks`, `watch`, and `status` show what
|
|
33
|
+
MELRA is doing without a server. Run `melra help` for the full command list.
|
|
29
34
|
|
|
30
35
|
`melra conformance` checks a running endpoint rather than a build — its own
|
|
31
36
|
stdio server by default, or `--url` for a loopback HTTP one — and reports the
|
|
@@ -34,7 +39,9 @@ The report says what the level does not prove as plainly as what it does.
|
|
|
34
39
|
|
|
35
40
|
The CLI starts with a local policy that allows reads outright and gates every
|
|
36
41
|
mutation: a consequential operation requires declared evidence and an exact,
|
|
37
|
-
task-scoped approval
|
|
42
|
+
task-scoped approval before it runs: a phrase echoed back in developer mode, or
|
|
43
|
+
an operator's `melra approve <task-id>` in enforced mode, where the agent is
|
|
44
|
+
given no phrase and one it sends is refused.
|
|
38
45
|
|
|
39
46
|
Requires Node.js 22 or newer. Full documentation:
|
|
40
47
|
[github.com/XAGI-Lab/melra](https://github.com/XAGI-Lab/melra)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type TaskRecord, type TaskStatus } from "@melra/protocol";
|
|
2
|
+
import type { CliEnvironment } from "./environment.js";
|
|
3
|
+
export declare function taskTarget(task: TaskRecord): string;
|
|
4
|
+
export interface TasksOptions {
|
|
5
|
+
limit: number;
|
|
6
|
+
status?: TaskStatus;
|
|
7
|
+
json: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function tasksCommand(env: CliEnvironment, options: TasksOptions): number;
|
|
10
|
+
/**
|
|
11
|
+
* Polls rather than subscribes: the writer may be another process (`melra
|
|
12
|
+
* serve`, a `melra run`), and SQLite has no cross-process change feed. Each poll
|
|
13
|
+
* is a short autocommit read on a read-only connection; in WAL mode a reader
|
|
14
|
+
* never blocks a writer, so a watch left open beside a server costs it nothing.
|
|
15
|
+
* Changes are found by diffing the last status seen per id, not by an
|
|
16
|
+
* `updatedAt` high-water mark, because two writes in the same millisecond would
|
|
17
|
+
* share a timestamp and a strict `>` would lose one of them.
|
|
18
|
+
*/
|
|
19
|
+
export declare function watchCommand(env: CliEnvironment, options: {
|
|
20
|
+
json: boolean;
|
|
21
|
+
}): Promise<number>;
|
|
22
|
+
export declare function statusCommand(env: CliEnvironment, options: {
|
|
23
|
+
json: boolean;
|
|
24
|
+
policyPath?: string;
|
|
25
|
+
}): Promise<number>;
|
|
26
|
+
//# sourceMappingURL=activity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAYA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,UAAU,EAEhB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAkGvD,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAenD;AAMD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,CA8C/E;AAoCD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuF7F;AAmDD,wBAAsB,aAAa,CACjC,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C,OAAO,CAAC,MAAM,CAAC,CA2FjB"}
|
package/dist/activity.js
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
// Copyright 2026 XAGI Labs Private Limited
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// `melra tasks`, `melra watch`, and `melra status`: the terminal's view of what
|
|
4
|
+
// MELRA is doing, without starting a server. Everything here reads the store
|
|
5
|
+
// read-only and prints only what the store already holds — the redacted copy —
|
|
6
|
+
// so nothing raw, and no approval phrase, can reach the screen from here.
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { stat } from "node:fs/promises";
|
|
9
|
+
import { connect } from "node:net";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { PRODUCT_VERSION, } from "@melra/protocol";
|
|
12
|
+
import { classifyOperation, loadPolicy } from "@melra/policy-core";
|
|
13
|
+
import { SqliteStore } from "@melra/storage-sqlite";
|
|
14
|
+
import { isHuman, paint, table } from "./output.js";
|
|
15
|
+
import { printable } from "./approval-screen.js";
|
|
16
|
+
const DEFAULT_HTTP_PORT = 7457;
|
|
17
|
+
const POLL_MS = 1_000;
|
|
18
|
+
const APPROVAL_HINT = "approve with `melra approve <task-id>`";
|
|
19
|
+
/**
|
|
20
|
+
* A task as an observer may see it. The approval block goes entirely, not just
|
|
21
|
+
* its `phrase`: the phrase is `APPROVE ` plus the first twelve hex digits of
|
|
22
|
+
* `actionDigest`, so leaving the digest would print the phrase by another name.
|
|
23
|
+
* Approvals belong to the governed path; the console drops the block the same way.
|
|
24
|
+
*/
|
|
25
|
+
function visible(task) {
|
|
26
|
+
const copy = { ...task };
|
|
27
|
+
delete copy.approval;
|
|
28
|
+
return copy;
|
|
29
|
+
}
|
|
30
|
+
function databasePath(env) {
|
|
31
|
+
return join(env.dataDirectory, "melra.sqlite");
|
|
32
|
+
}
|
|
33
|
+
// Read-only, and only if the database is already there: looking at MELRA must
|
|
34
|
+
// not create its state, and must never hold a lock a running server waits on.
|
|
35
|
+
function openStore(env) {
|
|
36
|
+
const path = databasePath(env);
|
|
37
|
+
return existsSync(path) ? new SqliteStore(path, { readOnly: true }) : undefined;
|
|
38
|
+
}
|
|
39
|
+
function withStore(env, empty, read) {
|
|
40
|
+
const store = openStore(env);
|
|
41
|
+
if (store === undefined)
|
|
42
|
+
return empty;
|
|
43
|
+
try {
|
|
44
|
+
return read(store);
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
store.close();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// A pipe or a script gets JSON; only a person at a terminal gets the table.
|
|
51
|
+
// The same rule as every other command, from the one place it lives.
|
|
52
|
+
function humanOutput(json) {
|
|
53
|
+
return isHuman(json ? ["--json"] : []);
|
|
54
|
+
}
|
|
55
|
+
function write(line = "") {
|
|
56
|
+
process.stdout.write(`${line}\n`);
|
|
57
|
+
}
|
|
58
|
+
// Status colours share `paint` with doctor and setup, so NO_COLOR, FORCE_COLOR,
|
|
59
|
+
// and TERM=dumb behave the same in every command.
|
|
60
|
+
const TONE = {
|
|
61
|
+
verified_success: paint.ok,
|
|
62
|
+
verified_complete: paint.ok,
|
|
63
|
+
failed: paint.fail,
|
|
64
|
+
policy_blocked: paint.fail,
|
|
65
|
+
budget_exhausted: paint.fail,
|
|
66
|
+
recovery_required: paint.fail,
|
|
67
|
+
partially_complete: paint.warn,
|
|
68
|
+
partial: paint.warn,
|
|
69
|
+
awaiting_approval: paint.warn,
|
|
70
|
+
awaiting_input: paint.warn,
|
|
71
|
+
waiting_user: paint.warn,
|
|
72
|
+
cancelled: paint.dim,
|
|
73
|
+
};
|
|
74
|
+
function tone(text, status) {
|
|
75
|
+
return (TONE[status] ?? ((plain) => plain))(text);
|
|
76
|
+
}
|
|
77
|
+
function ago(iso, now = Date.now()) {
|
|
78
|
+
const seconds = Math.max(0, Math.round((now - Date.parse(iso)) / 1000));
|
|
79
|
+
if (!Number.isFinite(seconds))
|
|
80
|
+
return "?";
|
|
81
|
+
if (seconds < 60)
|
|
82
|
+
return `${seconds}s ago`;
|
|
83
|
+
const minutes = Math.floor(seconds / 60);
|
|
84
|
+
if (minutes < 60)
|
|
85
|
+
return `${minutes}m ago`;
|
|
86
|
+
const hours = Math.floor(minutes / 60);
|
|
87
|
+
return hours < 48 ? `${hours}h ago` : `${Math.floor(hours / 24)}d ago`;
|
|
88
|
+
}
|
|
89
|
+
function truncate(text, width) {
|
|
90
|
+
return text.length <= width ? text : `${text.slice(0, width - 1)}…`;
|
|
91
|
+
}
|
|
92
|
+
function shortId(id) {
|
|
93
|
+
return id.slice(0, 8);
|
|
94
|
+
}
|
|
95
|
+
function operationName(task) {
|
|
96
|
+
const { kind, action } = task.request.operation;
|
|
97
|
+
return action === undefined ? kind : `${kind}.${action}`;
|
|
98
|
+
}
|
|
99
|
+
// From the one classifier policy uses, run over the stored (redacted) request,
|
|
100
|
+
// so the target shown is the target that was authorised. A record written by an
|
|
101
|
+
// older version may not classify; it still lists, just without a target.
|
|
102
|
+
export function taskTarget(task) {
|
|
103
|
+
// A command shows as what ran, `pnpm check`, not the classifier's
|
|
104
|
+
// `command:pnpm`: the stored arguments are already redacted (#122), and the
|
|
105
|
+
// console shows them the same way.
|
|
106
|
+
const operation = task.request.operation;
|
|
107
|
+
// Raw: the JSON emitters escape the whole payload, and the human table and
|
|
108
|
+
// `watch` escape this field at the point they print it.
|
|
109
|
+
if (operation.kind === "terminal" && operation.command !== undefined) {
|
|
110
|
+
return [operation.command, ...(operation.args ?? [])].join(" ");
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
return classifyOperation(task.request.operation).target;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function approvalHint(waiting) {
|
|
120
|
+
return `${waiting} waiting for approval — ${APPROVAL_HINT}`;
|
|
121
|
+
}
|
|
122
|
+
export function tasksCommand(env, options) {
|
|
123
|
+
const { tasks, waiting } = withStore(env, { tasks: [], waiting: 0 }, (store) => ({
|
|
124
|
+
tasks: store.listTasks(options.limit, options.status),
|
|
125
|
+
waiting: store.taskStatusCounts().awaiting_approval ?? 0,
|
|
126
|
+
}));
|
|
127
|
+
if (!humanOutput(options.json)) {
|
|
128
|
+
// The shape `/api/tasks` answers with, minus approvals.
|
|
129
|
+
write(printable(JSON.stringify({ tasks: tasks.map(visible) }, null, 2), true));
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
if (tasks.length === 0) {
|
|
133
|
+
write(options.status === undefined
|
|
134
|
+
? // Not a file under examples/: an npm install has none.
|
|
135
|
+
"No tasks yet. Try: melra demo durable-core, or melra conformance"
|
|
136
|
+
: `No ${options.status} tasks.`);
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
const header = ["ID", "STATUS", "OPERATION", "TARGET", "EFFECT", "UPDATED"];
|
|
140
|
+
const rows = tasks.map((task) => [
|
|
141
|
+
shortId(task.id),
|
|
142
|
+
task.status,
|
|
143
|
+
operationName(task),
|
|
144
|
+
truncate(printable(taskTarget(task)), 48),
|
|
145
|
+
`${task.policyDecision.effect}/${task.policyDecision.risk}`,
|
|
146
|
+
ago(task.updatedAt),
|
|
147
|
+
]);
|
|
148
|
+
// `table` measures visible width, so the status can be painted before it aligns.
|
|
149
|
+
write(table([
|
|
150
|
+
header.map((title) => paint.dim(title)),
|
|
151
|
+
...rows.map((row, index) => row.map((cell, column) => (column === 1 ? tone(cell, tasks[index]?.status ?? "") : cell))),
|
|
152
|
+
]));
|
|
153
|
+
if (waiting > 0) {
|
|
154
|
+
write();
|
|
155
|
+
write(approvalHint(waiting));
|
|
156
|
+
}
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
function describe(event) {
|
|
160
|
+
const time = new Date(event.at).toLocaleTimeString();
|
|
161
|
+
const status = event.previous === undefined
|
|
162
|
+
? tone(event.status, event.status)
|
|
163
|
+
: `${event.previous} → ${tone(event.status, event.status)}`;
|
|
164
|
+
if (event.type === "workflow") {
|
|
165
|
+
return `${time} workflow ${shortId(event.id)} ${status}`;
|
|
166
|
+
}
|
|
167
|
+
return [
|
|
168
|
+
`${time} task ${shortId(event.id)}`,
|
|
169
|
+
status,
|
|
170
|
+
event.operation,
|
|
171
|
+
truncate(printable(event.target), 48),
|
|
172
|
+
`${event.effect}/${event.risk}`,
|
|
173
|
+
]
|
|
174
|
+
.filter((part) => part !== "")
|
|
175
|
+
.join(" ");
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Polls rather than subscribes: the writer may be another process (`melra
|
|
179
|
+
* serve`, a `melra run`), and SQLite has no cross-process change feed. Each poll
|
|
180
|
+
* is a short autocommit read on a read-only connection; in WAL mode a reader
|
|
181
|
+
* never blocks a writer, so a watch left open beside a server costs it nothing.
|
|
182
|
+
* Changes are found by diffing the last status seen per id, not by an
|
|
183
|
+
* `updatedAt` high-water mark, because two writes in the same millisecond would
|
|
184
|
+
* share a timestamp and a strict `>` would lose one of them.
|
|
185
|
+
*/
|
|
186
|
+
export function watchCommand(env, options) {
|
|
187
|
+
const human = humanOutput(options.json);
|
|
188
|
+
const seenTasks = new Map();
|
|
189
|
+
const seenWorkflows = new Map();
|
|
190
|
+
let store;
|
|
191
|
+
let primed = false;
|
|
192
|
+
const emit = (event) => write(human ? describe(event) : printable(JSON.stringify(event), true));
|
|
193
|
+
const poll = () => {
|
|
194
|
+
// The database appears with the first task; until then there is nothing to read.
|
|
195
|
+
store ??= openStore(env);
|
|
196
|
+
if (store === undefined) {
|
|
197
|
+
primed = true;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
// ponytail: rereads the newest 500 tasks and every workflow run each second;
|
|
201
|
+
// add an `updated_at >` query to the store if that ever shows up in a profile.
|
|
202
|
+
const tasks = store.listTasks(500).reverse();
|
|
203
|
+
const runs = store.listWorkflowRuns();
|
|
204
|
+
for (const task of tasks) {
|
|
205
|
+
const previous = seenTasks.get(task.id);
|
|
206
|
+
if (previous === task.status)
|
|
207
|
+
continue;
|
|
208
|
+
seenTasks.set(task.id, task.status);
|
|
209
|
+
// The first read is the baseline: what already happened is `melra tasks`.
|
|
210
|
+
if (!primed)
|
|
211
|
+
continue;
|
|
212
|
+
emit({
|
|
213
|
+
type: "task",
|
|
214
|
+
at: task.updatedAt,
|
|
215
|
+
id: task.id,
|
|
216
|
+
status: task.status,
|
|
217
|
+
...(previous === undefined ? {} : { previous }),
|
|
218
|
+
operation: operationName(task),
|
|
219
|
+
target: taskTarget(task),
|
|
220
|
+
effect: task.policyDecision.effect,
|
|
221
|
+
risk: task.policyDecision.risk,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
for (const run of runs) {
|
|
225
|
+
const previous = seenWorkflows.get(run.id);
|
|
226
|
+
if (previous === run.status)
|
|
227
|
+
continue;
|
|
228
|
+
seenWorkflows.set(run.id, run.status);
|
|
229
|
+
if (!primed)
|
|
230
|
+
continue;
|
|
231
|
+
emit({
|
|
232
|
+
type: "workflow",
|
|
233
|
+
at: run.updatedAt,
|
|
234
|
+
id: run.id,
|
|
235
|
+
status: run.status,
|
|
236
|
+
...(previous === undefined ? {} : { previous }),
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
primed = true;
|
|
240
|
+
};
|
|
241
|
+
return new Promise((resolveExit) => {
|
|
242
|
+
let timer;
|
|
243
|
+
const stop = (code) => {
|
|
244
|
+
if (timer !== undefined)
|
|
245
|
+
clearInterval(timer);
|
|
246
|
+
process.removeListener("SIGINT", onInterrupt);
|
|
247
|
+
process.removeListener("SIGTERM", onTerminate);
|
|
248
|
+
store?.close();
|
|
249
|
+
resolveExit(code);
|
|
250
|
+
};
|
|
251
|
+
// 128 + signal number, as a shell reports a process killed by it.
|
|
252
|
+
const onInterrupt = () => stop(130);
|
|
253
|
+
const onTerminate = () => stop(143);
|
|
254
|
+
process.once("SIGINT", onInterrupt);
|
|
255
|
+
process.once("SIGTERM", onTerminate);
|
|
256
|
+
const tick = () => {
|
|
257
|
+
try {
|
|
258
|
+
poll();
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
process.stderr.write(`melra: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
262
|
+
stop(1);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
tick();
|
|
266
|
+
// On stderr so stdout stays pure NDJSON; it also tells a caller that the
|
|
267
|
+
// baseline is taken and anything from here on will be reported.
|
|
268
|
+
process.stderr.write(`Watching ${databasePath(env)} for task and workflow changes. Ctrl-C to stop.\n`);
|
|
269
|
+
timer = setInterval(tick, POLL_MS);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
// Whether something accepts a connection there. Nothing is sent — no token, no
|
|
273
|
+
// request — so this cannot leak a credential to whatever holds the port.
|
|
274
|
+
function reachable(options) {
|
|
275
|
+
return new Promise((resolveProbe) => {
|
|
276
|
+
const socket = connect(options);
|
|
277
|
+
const done = (ok) => {
|
|
278
|
+
socket.destroy();
|
|
279
|
+
resolveProbe(ok);
|
|
280
|
+
};
|
|
281
|
+
socket.setTimeout(500, () => done(false));
|
|
282
|
+
socket.once("connect", () => done(true));
|
|
283
|
+
socket.once("error", () => done(false));
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function httpPort() {
|
|
287
|
+
const port = Number(process.env.MELRA_HTTP_PORT);
|
|
288
|
+
return Number.isInteger(port) && port > 0 && port < 65_536 ? port : DEFAULT_HTTP_PORT;
|
|
289
|
+
}
|
|
290
|
+
async function sizeOnDisk(path) {
|
|
291
|
+
// The WAL holds committed pages not yet checkpointed into the main file.
|
|
292
|
+
const sizes = await Promise.all([path, `${path}-wal`].map((file) => stat(file).then((s) => s.size, () => 0)));
|
|
293
|
+
return sizes.reduce((total, size) => total + size, 0);
|
|
294
|
+
}
|
|
295
|
+
function bytes(size) {
|
|
296
|
+
if (size < 1024)
|
|
297
|
+
return `${size} B`;
|
|
298
|
+
if (size < 1024 * 1024)
|
|
299
|
+
return `${(size / 1024).toFixed(1)} KB`;
|
|
300
|
+
return `${(size / 1024 / 1024).toFixed(1)} MB`;
|
|
301
|
+
}
|
|
302
|
+
function countBy(values) {
|
|
303
|
+
const counts = {};
|
|
304
|
+
for (const value of values)
|
|
305
|
+
counts[value] = (counts[value] ?? 0) + 1;
|
|
306
|
+
return counts;
|
|
307
|
+
}
|
|
308
|
+
function summary(counts) {
|
|
309
|
+
const total = Object.values(counts).reduce((sum, count) => sum + count, 0);
|
|
310
|
+
if (total === 0)
|
|
311
|
+
return "none";
|
|
312
|
+
const parts = Object.entries(counts)
|
|
313
|
+
.sort(([, a], [, b]) => b - a)
|
|
314
|
+
.map(([status, count]) => `${count} ${tone(status, status)}`);
|
|
315
|
+
return `${total} total: ${parts.join(", ")}`;
|
|
316
|
+
}
|
|
317
|
+
export async function statusCommand(env, options) {
|
|
318
|
+
// The mode a server started here would run in: strictest of flag, variable,
|
|
319
|
+
// and policy file, as `createMelraRuntime` decides it.
|
|
320
|
+
let policyError;
|
|
321
|
+
let policyMode;
|
|
322
|
+
let policyUnhinged = false;
|
|
323
|
+
if (options.policyPath !== undefined) {
|
|
324
|
+
try {
|
|
325
|
+
const loaded = await loadPolicy(options.policyPath, env.workspaceRoot);
|
|
326
|
+
policyMode = loaded.mode;
|
|
327
|
+
policyUnhinged = loaded.unhinged;
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
policyError = error instanceof Error ? error.message : String(error);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const mode = env.mode === "enforced" || policyMode === "enforced" ? "enforced" : "developer";
|
|
334
|
+
const path = databasePath(env);
|
|
335
|
+
const { tasks, workflows, lastActivity } = withStore(env, { tasks: {}, workflows: {}, lastActivity: undefined }, (store) => {
|
|
336
|
+
const runs = store.listWorkflowRuns();
|
|
337
|
+
const latest = [store.listTasks(1)[0]?.updatedAt, runs.at(-1)?.updatedAt]
|
|
338
|
+
.filter((at) => at !== undefined)
|
|
339
|
+
.sort()
|
|
340
|
+
.at(-1);
|
|
341
|
+
return {
|
|
342
|
+
tasks: store.taskStatusCounts(),
|
|
343
|
+
workflows: countBy(runs.map((run) => run.status)),
|
|
344
|
+
lastActivity: latest,
|
|
345
|
+
};
|
|
346
|
+
});
|
|
347
|
+
const port = httpPort();
|
|
348
|
+
const [http, socket] = await Promise.all([
|
|
349
|
+
reachable({ host: "127.0.0.1", port }),
|
|
350
|
+
env.socketPath === undefined ? undefined : reachable({ path: env.socketPath }),
|
|
351
|
+
]);
|
|
352
|
+
const report = {
|
|
353
|
+
product: "MELRA",
|
|
354
|
+
version: PRODUCT_VERSION,
|
|
355
|
+
mode,
|
|
356
|
+
unhinged: env.unhinged || policyUnhinged,
|
|
357
|
+
workspace: env.workspaceRoot,
|
|
358
|
+
dataDirectory: env.dataDirectory,
|
|
359
|
+
policy: options.policyPath ?? null,
|
|
360
|
+
...(policyError === undefined ? {} : { policyError }),
|
|
361
|
+
database: {
|
|
362
|
+
path,
|
|
363
|
+
exists: existsSync(path),
|
|
364
|
+
bytes: await sizeOnDisk(path),
|
|
365
|
+
},
|
|
366
|
+
tasks,
|
|
367
|
+
workflows,
|
|
368
|
+
awaitingApproval: tasks.awaiting_approval ?? 0,
|
|
369
|
+
lastActivity: lastActivity ?? null,
|
|
370
|
+
server: {
|
|
371
|
+
http: { address: `127.0.0.1:${port}`, state: http ? "reachable" : "not running" },
|
|
372
|
+
...(env.socketPath === undefined
|
|
373
|
+
? {}
|
|
374
|
+
: { socket: { path: env.socketPath, state: socket === true ? "reachable" : "not running" } }),
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
if (!humanOutput(options.json)) {
|
|
378
|
+
write(printable(JSON.stringify(report, null, 2), true));
|
|
379
|
+
return 0;
|
|
380
|
+
}
|
|
381
|
+
const row = (label, value) => write(` ${label.padEnd(11)} ${value}`);
|
|
382
|
+
write(`MELRA ${PRODUCT_VERSION} ${mode} mode${report.unhinged ? " UNSAFE-LOCAL: no guardrails" : ""}`);
|
|
383
|
+
row("Workspace", env.workspaceRoot);
|
|
384
|
+
row("Data", env.dataDirectory);
|
|
385
|
+
row("Policy", policyError !== undefined
|
|
386
|
+
? `${options.policyPath} (invalid: ${policyError})`
|
|
387
|
+
: (options.policyPath ?? "built-in defaults"));
|
|
388
|
+
row("Database", report.database.exists ? `${path} (${bytes(report.database.bytes)})` : `${path} (not created yet)`);
|
|
389
|
+
row("Tasks", summary(tasks));
|
|
390
|
+
row("Workflows", summary(workflows));
|
|
391
|
+
if (report.awaitingApproval > 0)
|
|
392
|
+
row("Waiting", approvalHint(report.awaitingApproval));
|
|
393
|
+
row("Last active", lastActivity === undefined ? "never" : ago(lastActivity));
|
|
394
|
+
row("HTTP", `${report.server.http.address} ${report.server.http.state}`);
|
|
395
|
+
if (report.server.socket !== undefined) {
|
|
396
|
+
row("Socket", `${report.server.socket.path} ${report.server.socket.state}`);
|
|
397
|
+
}
|
|
398
|
+
if (!http && socket !== true) {
|
|
399
|
+
write();
|
|
400
|
+
write("Open the console with: melra serve --http --open");
|
|
401
|
+
}
|
|
402
|
+
return 0;
|
|
403
|
+
}
|
|
404
|
+
//# sourceMappingURL=activity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text a terminal shows as text and nothing else. Everything in an approval
|
|
3
|
+
* render except its labels was chosen by the agent asking for approval, and a
|
|
4
|
+
* raw escape sequence in it can erase the line saying so, paint a different
|
|
5
|
+
* effect, and hide the real one. Each hidden character is spelled out as
|
|
6
|
+
* `\uXXXX` per UTF-16 unit, which inside JSON is also a valid escape for it.
|
|
7
|
+
*/
|
|
8
|
+
export declare function printable(text: string, keepNewlines?: boolean): string;
|
|
9
|
+
export interface ApprovalScreenView {
|
|
10
|
+
task: {
|
|
11
|
+
id: string;
|
|
12
|
+
approval?: {
|
|
13
|
+
expiresAt: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
contract: {
|
|
17
|
+
capability: string;
|
|
18
|
+
target: string;
|
|
19
|
+
effect: string;
|
|
20
|
+
risk: string;
|
|
21
|
+
operation?: unknown;
|
|
22
|
+
metadata: {
|
|
23
|
+
goal: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
renderDigest: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The approval screen, ending with what MELRA itself vouches for: the full
|
|
30
|
+
* contract first, so however long the agent's content runs it cannot push the
|
|
31
|
+
* effect off the screen, then the operation and the summary, each line
|
|
32
|
+
* bounded, right above the question.
|
|
33
|
+
*/
|
|
34
|
+
export declare function approvalScreen(view: ApprovalScreenView): string;
|
|
35
|
+
//# sourceMappingURL=approval-screen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-screen.d.ts","sourceRoot":"","sources":["../src/approval-screen.ts"],"names":[],"mappings":"AAYA;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,UAAQ,GAAG,MAAM,CASpE;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE;YAAE,SAAS,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACvD,QAAQ,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;KAC5B,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB;AAiFD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAa/D"}
|