maqcli 0.2.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 +223 -0
- package/dist/core/audit.d.ts +43 -0
- package/dist/core/audit.js +77 -0
- package/dist/core/board.d.ts +78 -0
- package/dist/core/board.js +256 -0
- package/dist/core/catalog.d.ts +50 -0
- package/dist/core/catalog.js +103 -0
- package/dist/core/command-catalog.d.ts +44 -0
- package/dist/core/command-catalog.js +86 -0
- package/dist/core/completion.d.ts +24 -0
- package/dist/core/completion.js +309 -0
- package/dist/core/complexity.d.ts +17 -0
- package/dist/core/complexity.js +87 -0
- package/dist/core/config-store.d.ts +33 -0
- package/dist/core/config-store.js +61 -0
- package/dist/core/connectivity.d.ts +34 -0
- package/dist/core/connectivity.js +49 -0
- package/dist/core/cost-tracker.d.ts +89 -0
- package/dist/core/cost-tracker.js +189 -0
- package/dist/core/cost.d.ts +35 -0
- package/dist/core/cost.js +89 -0
- package/dist/core/exec.d.ts +43 -0
- package/dist/core/exec.js +154 -0
- package/dist/core/flows.d.ts +36 -0
- package/dist/core/flows.js +96 -0
- package/dist/core/headroom.d.ts +36 -0
- package/dist/core/headroom.js +88 -0
- package/dist/core/help-topics.d.ts +26 -0
- package/dist/core/help-topics.js +294 -0
- package/dist/core/init-wizard.d.ts +26 -0
- package/dist/core/init-wizard.js +168 -0
- package/dist/core/interactive-registry.d.ts +50 -0
- package/dist/core/interactive-registry.js +86 -0
- package/dist/core/interactive.d.ts +48 -0
- package/dist/core/interactive.js +137 -0
- package/dist/core/logger.d.ts +16 -0
- package/dist/core/logger.js +46 -0
- package/dist/core/memory.d.ts +28 -0
- package/dist/core/memory.js +70 -0
- package/dist/core/metered.d.ts +9 -0
- package/dist/core/metered.js +16 -0
- package/dist/core/model.d.ts +74 -0
- package/dist/core/model.js +199 -0
- package/dist/core/pipeline.d.ts +33 -0
- package/dist/core/pipeline.js +223 -0
- package/dist/core/plugins.d.ts +21 -0
- package/dist/core/plugins.js +38 -0
- package/dist/core/probe.d.ts +48 -0
- package/dist/core/probe.js +156 -0
- package/dist/core/profiles.d.ts +42 -0
- package/dist/core/profiles.js +153 -0
- package/dist/core/providers.d.ts +84 -0
- package/dist/core/providers.js +275 -0
- package/dist/core/recall.d.ts +29 -0
- package/dist/core/recall.js +83 -0
- package/dist/core/registry.d.ts +41 -0
- package/dist/core/registry.js +162 -0
- package/dist/core/router.d.ts +33 -0
- package/dist/core/router.js +40 -0
- package/dist/core/sandbox.d.ts +78 -0
- package/dist/core/sandbox.js +268 -0
- package/dist/core/session.d.ts +105 -0
- package/dist/core/session.js +252 -0
- package/dist/core/skills.d.ts +56 -0
- package/dist/core/skills.js +289 -0
- package/dist/core/subagent.d.ts +40 -0
- package/dist/core/subagent.js +55 -0
- package/dist/core/supervisor.d.ts +37 -0
- package/dist/core/supervisor.js +40 -0
- package/dist/core/tools.d.ts +39 -0
- package/dist/core/tools.js +159 -0
- package/dist/core/types.d.ts +87 -0
- package/dist/core/types.js +10 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +1032 -0
- package/dist/phases/execute.d.ts +39 -0
- package/dist/phases/execute.js +166 -0
- package/dist/phases/plan.d.ts +11 -0
- package/dist/phases/plan.js +118 -0
- package/dist/phases/scout.d.ts +10 -0
- package/dist/phases/scout.js +113 -0
- package/dist/phases/verify.d.ts +22 -0
- package/dist/phases/verify.js +81 -0
- package/dist/server/daemon.d.ts +50 -0
- package/dist/server/daemon.js +377 -0
- package/dist/server/relay-bridge.d.ts +44 -0
- package/dist/server/relay-bridge.js +175 -0
- package/package.json +39 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supervisor → multi-worker graph. A supervisor fans a job out to several
|
|
3
|
+
* worker sessions (parallel `assign`), waits for them all (`join`), and returns
|
|
4
|
+
* their condensed results — building on the SessionRegistry + subagent-style
|
|
5
|
+
* containment. Cross-provider by design: each worker task may pin its own
|
|
6
|
+
* target / provider / model / profile, so one swarm can mix Claude + Codex +
|
|
7
|
+
* raw workers. Unlike CAO this runs on MAQ's efficient, verified pipeline
|
|
8
|
+
* (each worker is a full Scout→Plan→Execute→Verify run).
|
|
9
|
+
*/
|
|
10
|
+
import type { SessionRegistry } from "./session.js";
|
|
11
|
+
export interface WorkerTask {
|
|
12
|
+
task: string;
|
|
13
|
+
target?: string;
|
|
14
|
+
provider?: string;
|
|
15
|
+
model?: string;
|
|
16
|
+
profile?: string;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
dryRun?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface SwarmResult {
|
|
21
|
+
count: number;
|
|
22
|
+
workers: Array<{
|
|
23
|
+
id: string;
|
|
24
|
+
task: string;
|
|
25
|
+
status: string;
|
|
26
|
+
verified?: boolean;
|
|
27
|
+
target?: string;
|
|
28
|
+
}>;
|
|
29
|
+
allVerified: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Run tasks concurrently and join. Each is a full session; the supervisor sees
|
|
33
|
+
* only the summaries (containment), never raw worker transcripts.
|
|
34
|
+
*/
|
|
35
|
+
export declare function runSwarm(registry: SessionRegistry, tasks: WorkerTask[], opts?: {
|
|
36
|
+
maxConcurrency?: number;
|
|
37
|
+
}): Promise<SwarmResult>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supervisor → multi-worker graph. A supervisor fans a job out to several
|
|
3
|
+
* worker sessions (parallel `assign`), waits for them all (`join`), and returns
|
|
4
|
+
* their condensed results — building on the SessionRegistry + subagent-style
|
|
5
|
+
* containment. Cross-provider by design: each worker task may pin its own
|
|
6
|
+
* target / provider / model / profile, so one swarm can mix Claude + Codex +
|
|
7
|
+
* raw workers. Unlike CAO this runs on MAQ's efficient, verified pipeline
|
|
8
|
+
* (each worker is a full Scout→Plan→Execute→Verify run).
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Run tasks concurrently and join. Each is a full session; the supervisor sees
|
|
12
|
+
* only the summaries (containment), never raw worker transcripts.
|
|
13
|
+
*/
|
|
14
|
+
export async function runSwarm(registry, tasks, opts = {}) {
|
|
15
|
+
const limit = Math.max(1, opts.maxConcurrency ?? tasks.length);
|
|
16
|
+
const queue = [...tasks];
|
|
17
|
+
const done = [];
|
|
18
|
+
async function worker() {
|
|
19
|
+
for (;;) {
|
|
20
|
+
const t = queue.shift();
|
|
21
|
+
if (!t)
|
|
22
|
+
return;
|
|
23
|
+
const s = await registry.handoff(t.task, {
|
|
24
|
+
target: t.target,
|
|
25
|
+
provider: t.provider,
|
|
26
|
+
model: t.model,
|
|
27
|
+
profile: t.profile,
|
|
28
|
+
cwd: t.cwd,
|
|
29
|
+
dryRun: t.dryRun,
|
|
30
|
+
});
|
|
31
|
+
done.push(registry.summarize(s));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
await Promise.all(Array.from({ length: Math.min(limit, tasks.length) }, () => worker()));
|
|
35
|
+
return {
|
|
36
|
+
count: done.length,
|
|
37
|
+
workers: done.map((w) => ({ id: w.id, task: w.task, status: w.status, verified: w.verified, target: w.target })),
|
|
38
|
+
allVerified: done.every((w) => w.verified !== false),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool registry — a small, SAFE set of tools the master can offer a model
|
|
3
|
+
* (tool-use) or run itself. Safety first: file tools are sandboxed to the
|
|
4
|
+
* working directory (path-traversal guarded), outputs are size-capped, and
|
|
5
|
+
* network access is OFF unless explicitly enabled (MAQ_ALLOW_NET=1).
|
|
6
|
+
*
|
|
7
|
+
* Each tool exposes a JSON-schema-ish descriptor so it can be advertised to an
|
|
8
|
+
* OpenAI/Anthropic-style tool-use API, plus a `run` that executes locally.
|
|
9
|
+
* Prefer these native tools over MCP servers where both exist — they add no
|
|
10
|
+
* per-tool listing overhead to the model's context.
|
|
11
|
+
*/
|
|
12
|
+
import type { Headroom } from "./headroom.js";
|
|
13
|
+
export interface ToolSchema {
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
parameters: Record<string, {
|
|
17
|
+
type: string;
|
|
18
|
+
description: string;
|
|
19
|
+
required?: boolean;
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
22
|
+
export interface Tool extends ToolSchema {
|
|
23
|
+
run(args: Record<string, unknown>): Promise<unknown> | unknown;
|
|
24
|
+
}
|
|
25
|
+
export interface ToolContext {
|
|
26
|
+
cwd: string;
|
|
27
|
+
headroom?: Headroom;
|
|
28
|
+
allowNet?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare function createToolRegistry(ctx: ToolContext): ToolRegistry;
|
|
31
|
+
export declare class ToolRegistry {
|
|
32
|
+
private tools;
|
|
33
|
+
readonly netEnabled: boolean;
|
|
34
|
+
constructor(tools: Tool[], netEnabled: boolean);
|
|
35
|
+
/** Advertise schemas (for model tool-use, or `maq tools`). */
|
|
36
|
+
schemas(): ToolSchema[];
|
|
37
|
+
names(): string[];
|
|
38
|
+
run(name: string, args?: Record<string, unknown>): Promise<unknown>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool registry — a small, SAFE set of tools the master can offer a model
|
|
3
|
+
* (tool-use) or run itself. Safety first: file tools are sandboxed to the
|
|
4
|
+
* working directory (path-traversal guarded), outputs are size-capped, and
|
|
5
|
+
* network access is OFF unless explicitly enabled (MAQ_ALLOW_NET=1).
|
|
6
|
+
*
|
|
7
|
+
* Each tool exposes a JSON-schema-ish descriptor so it can be advertised to an
|
|
8
|
+
* OpenAI/Anthropic-style tool-use API, plus a `run` that executes locally.
|
|
9
|
+
* Prefer these native tools over MCP servers where both exist — they add no
|
|
10
|
+
* per-tool listing overhead to the model's context.
|
|
11
|
+
*/
|
|
12
|
+
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
13
|
+
import { resolve, join, relative, isAbsolute } from "node:path";
|
|
14
|
+
const MAX_OUT = 64 * 1024;
|
|
15
|
+
/** Resolve a user path safely inside cwd; throws on traversal escape. */
|
|
16
|
+
function safePath(cwd, p) {
|
|
17
|
+
const base = resolve(cwd);
|
|
18
|
+
const target = isAbsolute(p) ? resolve(p) : resolve(base, p);
|
|
19
|
+
const rel = relative(base, target);
|
|
20
|
+
if (rel !== "" && (rel.startsWith("..") || isAbsolute(rel))) {
|
|
21
|
+
throw new Error(`path escapes working directory: ${p}`);
|
|
22
|
+
}
|
|
23
|
+
return target;
|
|
24
|
+
}
|
|
25
|
+
export function createToolRegistry(ctx) {
|
|
26
|
+
const allowNet = ctx.allowNet ?? process.env.MAQ_ALLOW_NET === "1";
|
|
27
|
+
const tools = [
|
|
28
|
+
{
|
|
29
|
+
name: "read_file",
|
|
30
|
+
description: "Read a UTF-8 text file within the working directory.",
|
|
31
|
+
parameters: { path: { type: "string", description: "relative path", required: true } },
|
|
32
|
+
run: (args) => {
|
|
33
|
+
const p = safePath(ctx.cwd, String(args.path ?? ""));
|
|
34
|
+
return readFileSync(p, "utf8").slice(0, MAX_OUT);
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "list_dir",
|
|
39
|
+
description: "List entries of a directory within the working directory.",
|
|
40
|
+
parameters: { path: { type: "string", description: "relative path (default '.')" } },
|
|
41
|
+
run: (args) => {
|
|
42
|
+
const p = safePath(ctx.cwd, String(args.path ?? "."));
|
|
43
|
+
return readdirSync(p).map((name) => {
|
|
44
|
+
const full = join(p, name);
|
|
45
|
+
let kind = "other";
|
|
46
|
+
try {
|
|
47
|
+
kind = statSync(full).isDirectory() ? "dir" : "file";
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
/* ignore */
|
|
51
|
+
}
|
|
52
|
+
return { name, kind };
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "grep_text",
|
|
58
|
+
description: "Search files under a directory for a substring (case-insensitive).",
|
|
59
|
+
parameters: {
|
|
60
|
+
query: { type: "string", description: "substring to find", required: true },
|
|
61
|
+
path: { type: "string", description: "relative dir (default '.')" },
|
|
62
|
+
},
|
|
63
|
+
run: (args) => {
|
|
64
|
+
const q = String(args.query ?? "").toLowerCase();
|
|
65
|
+
if (!q)
|
|
66
|
+
return [];
|
|
67
|
+
const root = safePath(ctx.cwd, String(args.path ?? "."));
|
|
68
|
+
const hits = [];
|
|
69
|
+
const stack = [root];
|
|
70
|
+
const IGNORE = new Set(["node_modules", ".git", "dist", "build", "target"]);
|
|
71
|
+
while (stack.length && hits.length < 200) {
|
|
72
|
+
const dir = stack.pop();
|
|
73
|
+
let entries = [];
|
|
74
|
+
try {
|
|
75
|
+
entries = readdirSync(dir);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
for (const e of entries) {
|
|
81
|
+
if (IGNORE.has(e))
|
|
82
|
+
continue;
|
|
83
|
+
const full = join(dir, e);
|
|
84
|
+
let st;
|
|
85
|
+
try {
|
|
86
|
+
st = statSync(full);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (st.isDirectory())
|
|
92
|
+
stack.push(full);
|
|
93
|
+
else if (st.isFile() && st.size < 512 * 1024) {
|
|
94
|
+
let content = "";
|
|
95
|
+
try {
|
|
96
|
+
content = readFileSync(full, "utf8");
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const lines = content.split(/\r?\n/);
|
|
102
|
+
for (let i = 0; i < lines.length && hits.length < 200; i++) {
|
|
103
|
+
if (lines[i].toLowerCase().includes(q)) {
|
|
104
|
+
hits.push({ file: relative(ctx.cwd, full), line: i + 1, text: lines[i].slice(0, 300) });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return hits;
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
if (ctx.headroom) {
|
|
115
|
+
tools.push({
|
|
116
|
+
name: "headroom_retrieve",
|
|
117
|
+
description: "Retrieve the original, uncompressed content for a Headroom reference (hr_...).",
|
|
118
|
+
parameters: { ref: { type: "string", description: "headroom reference id", required: true } },
|
|
119
|
+
run: (args) => ctx.headroom.retrieve(String(args.ref ?? "")) ?? null,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
if (allowNet) {
|
|
123
|
+
tools.push({
|
|
124
|
+
name: "http_get",
|
|
125
|
+
description: "HTTP GET a URL and return up to 64KB of text (network access is enabled).",
|
|
126
|
+
parameters: { url: { type: "string", description: "http(s) URL", required: true } },
|
|
127
|
+
run: async (args) => {
|
|
128
|
+
const url = String(args.url ?? "");
|
|
129
|
+
if (!/^https?:\/\//i.test(url))
|
|
130
|
+
throw new Error("only http(s) URLs allowed");
|
|
131
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(15000) });
|
|
132
|
+
const text = await res.text();
|
|
133
|
+
return { status: res.status, body: text.slice(0, MAX_OUT) };
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return new ToolRegistry(tools, allowNet);
|
|
138
|
+
}
|
|
139
|
+
export class ToolRegistry {
|
|
140
|
+
tools;
|
|
141
|
+
netEnabled;
|
|
142
|
+
constructor(tools, netEnabled) {
|
|
143
|
+
this.tools = tools;
|
|
144
|
+
this.netEnabled = netEnabled;
|
|
145
|
+
}
|
|
146
|
+
/** Advertise schemas (for model tool-use, or `maq tools`). */
|
|
147
|
+
schemas() {
|
|
148
|
+
return this.tools.map((t) => ({ name: t.name, description: t.description, parameters: t.parameters }));
|
|
149
|
+
}
|
|
150
|
+
names() {
|
|
151
|
+
return this.tools.map((t) => t.name);
|
|
152
|
+
}
|
|
153
|
+
async run(name, args = {}) {
|
|
154
|
+
const tool = this.tools.find((t) => t.name === name);
|
|
155
|
+
if (!tool)
|
|
156
|
+
throw new Error(`no such tool: ${name}`);
|
|
157
|
+
return tool.run(args);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types and the normalized event schema for maqcli.
|
|
3
|
+
*
|
|
4
|
+
* Every worker CLI (Claude Code, Codex, Gemini, raw bash, ...) has its output
|
|
5
|
+
* normalized into these event shapes so the UI / consumers never need
|
|
6
|
+
* per-vendor logic.
|
|
7
|
+
*/
|
|
8
|
+
export type EventType = "task.started" | "phase.started" | "phase.done" | "agent.event" | "agent.stdout" | "agent.stderr" | "tool.call" | "task.paused" | "task.resumed" | "task.cancelled" | "task.done" | "task.error";
|
|
9
|
+
export interface MaqEvent {
|
|
10
|
+
type: EventType;
|
|
11
|
+
/** ISO timestamp */
|
|
12
|
+
ts: string;
|
|
13
|
+
/** Free-form structured payload. */
|
|
14
|
+
data: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
export declare function makeEvent(type: EventType, data?: Record<string, unknown>): MaqEvent;
|
|
17
|
+
/** A detected worker CLI on the host. */
|
|
18
|
+
export interface DetectedAgent {
|
|
19
|
+
name: string;
|
|
20
|
+
/** Absolute path to the resolved binary, if found. */
|
|
21
|
+
binPath: string | null;
|
|
22
|
+
installed: boolean;
|
|
23
|
+
/** Whether the tool's auth/config dir suggests it is authenticated. */
|
|
24
|
+
authenticated: boolean;
|
|
25
|
+
/** Whether the tool exposes a stable machine-readable (JSON) event stream. */
|
|
26
|
+
stableJsonStream: boolean;
|
|
27
|
+
/** Headless invocation template; {task} is substituted at run time. */
|
|
28
|
+
headless: string[] | null;
|
|
29
|
+
}
|
|
30
|
+
export type Complexity = "trivial" | "standard" | "complex";
|
|
31
|
+
export interface ScoutFindings {
|
|
32
|
+
task: string;
|
|
33
|
+
cwd: string;
|
|
34
|
+
files: string[];
|
|
35
|
+
readme: string | null;
|
|
36
|
+
manifestSnippet: string | null;
|
|
37
|
+
recentCommits: string[];
|
|
38
|
+
uncommittedChanges: string;
|
|
39
|
+
complexity: Complexity;
|
|
40
|
+
notes: string[];
|
|
41
|
+
}
|
|
42
|
+
export interface PlanCandidate {
|
|
43
|
+
summary: string;
|
|
44
|
+
steps: string[];
|
|
45
|
+
score: number;
|
|
46
|
+
pass: boolean;
|
|
47
|
+
reason: string;
|
|
48
|
+
}
|
|
49
|
+
export interface Plan {
|
|
50
|
+
winner: PlanCandidate;
|
|
51
|
+
allEvaluated: PlanCandidate[];
|
|
52
|
+
candidatesGenerated: number;
|
|
53
|
+
earlyExit: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface ExecuteResult {
|
|
56
|
+
status: "success" | "failed" | "skipped";
|
|
57
|
+
target: string;
|
|
58
|
+
command: string[] | null;
|
|
59
|
+
exitCode: number | null;
|
|
60
|
+
stdout: string;
|
|
61
|
+
stderr: string;
|
|
62
|
+
filesChanged: string[];
|
|
63
|
+
errors: string[];
|
|
64
|
+
}
|
|
65
|
+
export interface VerifyResult {
|
|
66
|
+
verified: boolean;
|
|
67
|
+
method: string;
|
|
68
|
+
details: string;
|
|
69
|
+
}
|
|
70
|
+
export interface PipelineResult {
|
|
71
|
+
task: string;
|
|
72
|
+
scout: ScoutFindings;
|
|
73
|
+
plan: Plan | null;
|
|
74
|
+
execute: ExecuteResult;
|
|
75
|
+
verify: VerifyResult;
|
|
76
|
+
events: MaqEvent[];
|
|
77
|
+
/** Token/cost accounting for the master's own calls. */
|
|
78
|
+
cost?: {
|
|
79
|
+
calls: number;
|
|
80
|
+
promptTokens: number;
|
|
81
|
+
completionTokens: number;
|
|
82
|
+
totalTokens: number;
|
|
83
|
+
usd: number;
|
|
84
|
+
};
|
|
85
|
+
/** Run id when audit artifacts were written. */
|
|
86
|
+
runId?: string;
|
|
87
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types and the normalized event schema for maqcli.
|
|
3
|
+
*
|
|
4
|
+
* Every worker CLI (Claude Code, Codex, Gemini, raw bash, ...) has its output
|
|
5
|
+
* normalized into these event shapes so the UI / consumers never need
|
|
6
|
+
* per-vendor logic.
|
|
7
|
+
*/
|
|
8
|
+
export function makeEvent(type, data = {}) {
|
|
9
|
+
return { type, ts: new Date().toISOString(), data };
|
|
10
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* maqcli entry point.
|
|
4
|
+
*
|
|
5
|
+
* MAQ master orchestrator: a token-efficient, agent-agnostic supervisor that
|
|
6
|
+
* sits on top of any worker CLI (AI or not) via a Scout -> Plan -> Execute ->
|
|
7
|
+
* Verify pipeline. Zero runtime dependencies; uses only Node built-ins.
|
|
8
|
+
*
|
|
9
|
+
* Commands: detect | config | scout | plan | run | verify | help | version
|
|
10
|
+
*/
|
|
11
|
+
export {};
|