@plurnk/plurnk 0.60.1 → 0.65.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agui.d.ts +26 -0
- package/dist/agui.d.ts.map +1 -0
- package/dist/agui.js +83 -0
- package/dist/agui.js.map +1 -0
- package/dist/agui_cli.d.ts +50 -0
- package/dist/agui_cli.d.ts.map +1 -0
- package/dist/agui_cli.js +152 -0
- package/dist/agui_cli.js.map +1 -0
- package/dist/auth.d.ts +2 -15
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +41 -74
- package/dist/auth.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/completion.d.ts.map +1 -1
- package/dist/dispatcher.d.ts +2 -0
- package/dist/dispatcher.d.ts.map +1 -1
- package/dist/dispatcher.js +44 -0
- package/dist/dispatcher.js.map +1 -1
- package/dist/openpaths.d.ts.map +1 -1
- package/dist/paste.d.ts.map +1 -1
- package/dist/proposal.d.ts +6 -0
- package/dist/proposal.d.ts.map +1 -1
- package/dist/proposal.js +38 -0
- package/dist/proposal.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +25 -21
- package/dist/render.js.map +1 -1
- package/dist/rpc.d.ts.map +1 -1
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +1 -1
- package/dist/stream.js.map +1 -1
- package/dist/subcommands.d.ts.map +1 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js.map +1 -1
- package/dist/transport.d.ts +71 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +168 -0
- package/dist/transport.js.map +1 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +41 -7
- package/dist/tui.js.map +1 -1
- package/package.json +3 -3
package/dist/agui.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface AguiEvent {
|
|
2
|
+
type: string;
|
|
3
|
+
[k: string]: unknown;
|
|
4
|
+
}
|
|
5
|
+
export interface BridgeTarget {
|
|
6
|
+
bridgeUrl: string;
|
|
7
|
+
token?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function runViaBridge(target: BridgeTarget, run: {
|
|
10
|
+
threadId: string;
|
|
11
|
+
prompt: string;
|
|
12
|
+
runId?: string;
|
|
13
|
+
forwardedProps?: Record<string, unknown>;
|
|
14
|
+
}, signal?: AbortSignal): AsyncGenerator<AguiEvent>;
|
|
15
|
+
export declare const resolveViaBridge: (target: BridgeTarget, resolution: {
|
|
16
|
+
threadId: string;
|
|
17
|
+
logEntryId: number;
|
|
18
|
+
decision: "accept" | "reject" | "cancel";
|
|
19
|
+
body?: string;
|
|
20
|
+
}) => Promise<void>;
|
|
21
|
+
export declare const rpcViaBridge: <T = unknown>(target: BridgeTarget, call: {
|
|
22
|
+
threadId: string;
|
|
23
|
+
method: string;
|
|
24
|
+
params?: object;
|
|
25
|
+
}) => Promise<T>;
|
|
26
|
+
//# sourceMappingURL=agui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agui.d.ts","sourceRoot":"","sources":["../src/agui.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE;AAOjE,MAAM,WAAW,YAAY;IAAG,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;AAMnE,wBAAuB,YAAY,CAC/B,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EACnG,MAAM,CAAC,EAAE,WAAW,GACrB,cAAc,CAAC,SAAS,CAAC,CAgC3B;AAID,eAAO,MAAM,gBAAgB,WACjB,YAAY,cACR;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,KAC9G,OAAO,CAAC,IAAI,CAYd,CAAC;AAIF,eAAO,MAAM,YAAY,GAAU,CAAC,GAAG,OAAO,UAClC,YAAY,QACd;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAC5D,OAAO,CAAC,CAAC,CASX,CAAC"}
|
package/dist/agui.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// The Node consumer of the plurnk-agui bridge — the migration substrate for the
|
|
2
|
+
// terminal clients (plurnk-agui#1: CLI first, then TUI). A migrated client stops
|
|
3
|
+
// speaking raw WS to the daemon and instead POSTs a run to the bridge and
|
|
4
|
+
// consumes the AG-UI SSE projection. This module is that transport, mirroring the
|
|
5
|
+
// reference frontend (demo/index.html): POST / for a run, POST /resolve for a
|
|
6
|
+
// stopped-world proposal, POST /plurnk/rpc for the management escape hatch.
|
|
7
|
+
//
|
|
8
|
+
// Pure transport: it yields the daemon-authoritative AG-UI events; rendering (the
|
|
9
|
+
// waterfall, proposals, the gauge) stays with each client. plurnk fidelity rides
|
|
10
|
+
// the CUSTOM plurnk.* events (esp. plurnk.row — the full wire row).
|
|
11
|
+
const jsonHeaders = (token) => ({
|
|
12
|
+
"content-type": "application/json",
|
|
13
|
+
...(token !== undefined && token.length > 0 ? { authorization: `Bearer ${token}` } : {}),
|
|
14
|
+
});
|
|
15
|
+
// Run one turn through the bridge, async-yielding each AG-UI event until the
|
|
16
|
+
// bridge ends the stream (it does so after RUN_FINISHED / RUN_ERROR). Breaking
|
|
17
|
+
// out of the iteration drops the connection, which the bridge treats as the abort
|
|
18
|
+
// signal (its req.on("close") cancels the loop) — hanging up IS cancellation.
|
|
19
|
+
export async function* runViaBridge(target, run, signal) {
|
|
20
|
+
const res = await fetch(new URL("/", target.bridgeUrl), {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: jsonHeaders(target.token),
|
|
23
|
+
signal, // abort ⇒ drop the SSE ⇒ the bridge cancels the loop (its req.on close)
|
|
24
|
+
body: JSON.stringify({
|
|
25
|
+
threadId: run.threadId,
|
|
26
|
+
runId: run.runId,
|
|
27
|
+
messages: [{ role: "user", content: run.prompt }],
|
|
28
|
+
...(run.forwardedProps !== undefined ? { forwardedProps: { plurnk: run.forwardedProps } } : {}),
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
if (!res.ok || res.body === null) {
|
|
32
|
+
const detail = await res.text().catch(() => "");
|
|
33
|
+
throw new Error(`bridge run failed: ${res.status}${detail.length > 0 ? ` — ${detail}` : ""}`);
|
|
34
|
+
}
|
|
35
|
+
const reader = res.body.getReader();
|
|
36
|
+
const decoder = new TextDecoder();
|
|
37
|
+
let buf = "";
|
|
38
|
+
for (;;) {
|
|
39
|
+
const { done, value } = await reader.read();
|
|
40
|
+
if (done)
|
|
41
|
+
break;
|
|
42
|
+
buf += decoder.decode(value, { stream: true });
|
|
43
|
+
// SSE frames are `data: <json>\n\n`; accumulate until a full frame is buffered
|
|
44
|
+
// (a chunk can split a frame), then parse each complete one.
|
|
45
|
+
let sep;
|
|
46
|
+
while ((sep = buf.indexOf("\n\n")) !== -1) {
|
|
47
|
+
const frame = buf.slice(0, sep);
|
|
48
|
+
buf = buf.slice(sep + 2);
|
|
49
|
+
if (frame.startsWith("data: "))
|
|
50
|
+
yield JSON.parse(frame.slice(6));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Answer a stopped-world proposal (file edit, MCP auth, [300] question) — the
|
|
55
|
+
// bridge passes it through to loop.resolve.
|
|
56
|
+
export const resolveViaBridge = async (target, resolution) => {
|
|
57
|
+
const res = await fetch(new URL("/resolve", target.bridgeUrl), {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: jsonHeaders(target.token),
|
|
60
|
+
body: JSON.stringify({
|
|
61
|
+
threadId: resolution.threadId,
|
|
62
|
+
logEntryId: resolution.logEntryId,
|
|
63
|
+
decision: resolution.decision,
|
|
64
|
+
...(resolution.body !== undefined ? { body: resolution.body } : {}),
|
|
65
|
+
}),
|
|
66
|
+
});
|
|
67
|
+
if (!res.ok)
|
|
68
|
+
throw new Error(`bridge resolve failed: ${res.status}`);
|
|
69
|
+
};
|
|
70
|
+
// The management escape hatch: a daemon JSON-RPC method scoped to the thread's own
|
|
71
|
+
// session (§agui-management-plane). Returns the daemon's result verbatim.
|
|
72
|
+
export const rpcViaBridge = async (target, call) => {
|
|
73
|
+
const res = await fetch(new URL("/plurnk/rpc", target.bridgeUrl), {
|
|
74
|
+
method: "POST",
|
|
75
|
+
headers: jsonHeaders(target.token),
|
|
76
|
+
body: JSON.stringify({ threadId: call.threadId, method: call.method, params: call.params ?? {} }),
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok)
|
|
79
|
+
throw new Error(`bridge rpc ${call.method} failed: ${res.status}`);
|
|
80
|
+
const parsed = await res.json();
|
|
81
|
+
return parsed.result;
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=agui.js.map
|
package/dist/agui.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agui.js","sourceRoot":"","sources":["../src/agui.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { LogEntryWire } from "./render.ts";
|
|
2
|
+
import { type Resolution, type ProposalParams } from "./proposal.ts";
|
|
3
|
+
import type { TelemetryEvent } from "./telemetry.ts";
|
|
4
|
+
import { type AguiEvent, type BridgeTarget } from "./agui.ts";
|
|
5
|
+
interface TerminatedValue {
|
|
6
|
+
sessionId: number | null;
|
|
7
|
+
loopId: number;
|
|
8
|
+
finalStatus: number;
|
|
9
|
+
hitMaxTurns: boolean;
|
|
10
|
+
turnIds: number[];
|
|
11
|
+
usage: {
|
|
12
|
+
promptTokens: number;
|
|
13
|
+
completionTokens: number;
|
|
14
|
+
costPico: number;
|
|
15
|
+
contextTokens: number;
|
|
16
|
+
contextSize: number | null;
|
|
17
|
+
meta: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface CliRunResult {
|
|
21
|
+
exitCode: number;
|
|
22
|
+
entries: LogEntryWire[];
|
|
23
|
+
telemetry: TelemetryEvent[];
|
|
24
|
+
response: string;
|
|
25
|
+
terminated: TerminatedValue | null;
|
|
26
|
+
modelRunId: number | null;
|
|
27
|
+
}
|
|
28
|
+
export interface CliRunSinks {
|
|
29
|
+
out: (s: string) => void;
|
|
30
|
+
err: (s: string) => void;
|
|
31
|
+
telemetry: (e: TelemetryEvent) => void;
|
|
32
|
+
json: boolean;
|
|
33
|
+
yolo: boolean;
|
|
34
|
+
noReviewChannel: boolean;
|
|
35
|
+
review: (p: ProposalParams) => Promise<Resolution>;
|
|
36
|
+
resolve: (r: {
|
|
37
|
+
logEntryId: number;
|
|
38
|
+
decision: "accept" | "reject" | "cancel";
|
|
39
|
+
body?: string;
|
|
40
|
+
}) => Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
export declare const consumeCliRun: (events: AsyncIterable<AguiEvent>, io: CliRunSinks) => Promise<CliRunResult>;
|
|
43
|
+
export declare const runCliViaBridge: (target: BridgeTarget, prompt: string, opts: {
|
|
44
|
+
threadId: string;
|
|
45
|
+
yolo: boolean;
|
|
46
|
+
json: boolean;
|
|
47
|
+
projectRoot?: string | null;
|
|
48
|
+
}) => Promise<number>;
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=agui_cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agui_cli.d.ts","sourceRoot":"","sources":["../src/agui_cli.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAoC,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,EAAkC,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAO9F,UAAU,eAAe;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;CACjK;AAED,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IACxB,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzB,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzB,SAAS,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,IAAI,CAAC;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACnD,OAAO,EAAE,CAAC,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClH;AAkBD,eAAO,MAAM,aAAa,WAAkB,aAAa,CAAC,SAAS,CAAC,MAAM,WAAW,KAAG,OAAO,CAAC,YAAY,CAmD3G,CAAC;AAMF,eAAO,MAAM,eAAe,WAChB,YAAY,UACZ,MAAM,QACR;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,KACtF,OAAO,CAAC,MAAM,CAqChB,CAAC"}
|
package/dist/agui_cli.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// CLI one-shot through the plurnk-agui bridge (plurnk-agui#1, migration slice 2):
|
|
2
|
+
// text mode. The bridge owns the WS + session; we POST the run and render the
|
|
3
|
+
// AG-UI SSE projection. A FAMILY client renders from CUSTOM plurnk.row (the full
|
|
4
|
+
// wire row) for full fidelity — the generic AG-UI events (TEXT_MESSAGE/…) are for
|
|
5
|
+
// third-party frontends — so this reuses runCli's exact text-mode rendering:
|
|
6
|
+
// stdout = the terminal broadcast body (the answer), stderr = the per-row trace.
|
|
7
|
+
//
|
|
8
|
+
// json mode is NOT routed here yet: the Translator's terminated projection drops
|
|
9
|
+
// costPico/loopId, so a faithful json record needs bridge-side enrichment (mine
|
|
10
|
+
// to add as owner) — until then json rides the daemon (dual-surface, per charter).
|
|
11
|
+
import process from "node:process";
|
|
12
|
+
import { formatPlain, isTerminalBroadcast, exitCodeForLoop, buildJsonRecord } from "./cli.js";
|
|
13
|
+
import { extractSendBody } from "./render.js";
|
|
14
|
+
import { reviewProposal, isServerResolved } from "./proposal.js";
|
|
15
|
+
import { report } from "./telemetry.js";
|
|
16
|
+
import StreamTrace from "./stream.js";
|
|
17
|
+
import { runViaBridge, resolveViaBridge } from "./agui.js";
|
|
18
|
+
// Settle a stopped-world proposal that arrived over the bridge, mirroring the WS
|
|
19
|
+
// CLI's three paths — but the answer rides POST /resolve, not loop.resolve.
|
|
20
|
+
const settleProposal = async (p, io) => {
|
|
21
|
+
if (isServerResolved(p))
|
|
22
|
+
return; // the daemon settled it in-process (bridge flags.yolo); a client resolve would race
|
|
23
|
+
if (io.yolo) {
|
|
24
|
+
await io.resolve({ logEntryId: p.logEntryId, decision: "accept" });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (io.noReviewChannel) {
|
|
28
|
+
await io.resolve({ logEntryId: p.logEntryId, decision: "reject" });
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const resolution = await io.review(p);
|
|
32
|
+
await io.resolve({ logEntryId: p.logEntryId, decision: resolution.decision, ...(resolution.body !== undefined ? { body: resolution.body } : {}) });
|
|
33
|
+
};
|
|
34
|
+
// Drive a bridge run's AG-UI event stream. Text mode renders to the sinks
|
|
35
|
+
// (stdout = answer, stderr = trace); json mode stays silent and accumulates the
|
|
36
|
+
// full record (entries/telemetry/response/terminated/modelRunId) for the caller
|
|
37
|
+
// to emit as ONE document. plurnk.terminated is the authoritative outcome (its
|
|
38
|
+
// finalStatus/hitMaxTurns win over the RUN_ERROR-inferred code). Event source
|
|
39
|
+
// injected so it's testable without a live bridge.
|
|
40
|
+
export const consumeCliRun = async (events, io) => {
|
|
41
|
+
let finalStatus = 200;
|
|
42
|
+
let hitMaxTurns = false;
|
|
43
|
+
let response = "";
|
|
44
|
+
let terminated = null;
|
|
45
|
+
let modelRunId = null;
|
|
46
|
+
const entries = [];
|
|
47
|
+
const telemetry = [];
|
|
48
|
+
const streams = new StreamTrace();
|
|
49
|
+
for await (const e of events) {
|
|
50
|
+
if (e.type === "RUN_ERROR") {
|
|
51
|
+
const code = Number(e.code);
|
|
52
|
+
finalStatus = Number.isFinite(code) && code > 0 ? code : 500;
|
|
53
|
+
hitMaxTurns = /maxTurns/.test(String(e.message ?? ""));
|
|
54
|
+
if (!io.json)
|
|
55
|
+
io.err(`${String(e.message ?? "")}\n`);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (e.type !== "CUSTOM")
|
|
59
|
+
continue; // generic vocab is for third-party frontends
|
|
60
|
+
const name = e.name;
|
|
61
|
+
const value = e.value;
|
|
62
|
+
if (name === "plurnk.row") {
|
|
63
|
+
const entry = value;
|
|
64
|
+
const runId = entry.run_id;
|
|
65
|
+
if (modelRunId === null && entry.origin === "model" && typeof runId === "number")
|
|
66
|
+
modelRunId = runId;
|
|
67
|
+
if (isTerminalBroadcast(entry))
|
|
68
|
+
response = extractSendBody(entry.tx, false);
|
|
69
|
+
if (io.json) {
|
|
70
|
+
entries.push(entry);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
io.err(`${formatPlain(entry)}\n`);
|
|
74
|
+
if (isTerminalBroadcast(entry) && response.length > 0)
|
|
75
|
+
io.out(`${response}\n`);
|
|
76
|
+
}
|
|
77
|
+
else if (name === "plurnk.terminated") {
|
|
78
|
+
terminated = value;
|
|
79
|
+
finalStatus = terminated.finalStatus; // authoritative outcome
|
|
80
|
+
hitMaxTurns = terminated.hitMaxTurns;
|
|
81
|
+
}
|
|
82
|
+
else if (name === "plurnk.telemetry") {
|
|
83
|
+
if (io.json)
|
|
84
|
+
telemetry.push(value);
|
|
85
|
+
else
|
|
86
|
+
io.telemetry(value);
|
|
87
|
+
}
|
|
88
|
+
else if (name === "plurnk.stream") {
|
|
89
|
+
// plurnk.stream carries the whole lifecycle: a concluded payload has
|
|
90
|
+
// closeStatus; a start/event payload has state. (json: streams aren't in
|
|
91
|
+
// the record — content is fetched on demand via `read L/T/S`.)
|
|
92
|
+
if (!io.json) {
|
|
93
|
+
if (typeof value.closeStatus === "number") {
|
|
94
|
+
io.err(`${streams.concluded(value)}\n`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const line = streams.event(value);
|
|
98
|
+
if (line !== null)
|
|
99
|
+
io.err(`${line}\n`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (name === "plurnk.proposal") {
|
|
104
|
+
await settleProposal(value, io);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { exitCode: exitCodeForLoop(finalStatus, hitMaxTurns), entries, telemetry, response, terminated, modelRunId };
|
|
108
|
+
};
|
|
109
|
+
// Wire the live bridge + terminal for one CLI prompt. text: stdout=answer,
|
|
110
|
+
// stderr=trace. json: silent, then ONE buildJsonRecord document on stdout —
|
|
111
|
+
// identical schema to the WS path (plurnk.terminated carries sessionId/loopId/
|
|
112
|
+
// turnIds/cost; modelRunId derived from the rows).
|
|
113
|
+
export const runCliViaBridge = async (target, prompt, opts) => {
|
|
114
|
+
const noReviewChannel = !opts.yolo && process.stdin.isTTY !== true;
|
|
115
|
+
if (!opts.json)
|
|
116
|
+
process.stderr.write(`bridge: ${target.bridgeUrl}\nprompt: ${prompt}\n\n`);
|
|
117
|
+
const forwardedProps = opts.projectRoot !== undefined && opts.projectRoot !== null ? { projectRoot: opts.projectRoot } : undefined;
|
|
118
|
+
const started = Date.now();
|
|
119
|
+
const result = await consumeCliRun(runViaBridge(target, { threadId: opts.threadId, prompt, forwardedProps }), {
|
|
120
|
+
out: (s) => process.stdout.write(s),
|
|
121
|
+
err: (s) => process.stderr.write(s),
|
|
122
|
+
telemetry: (e) => report(e),
|
|
123
|
+
json: opts.json,
|
|
124
|
+
yolo: opts.yolo,
|
|
125
|
+
noReviewChannel,
|
|
126
|
+
review: reviewProposal,
|
|
127
|
+
resolve: (r) => resolveViaBridge(target, { threadId: opts.threadId, ...r }),
|
|
128
|
+
});
|
|
129
|
+
if (opts.json) {
|
|
130
|
+
const t = result.terminated;
|
|
131
|
+
const doc = buildJsonRecord({
|
|
132
|
+
session: { id: t?.sessionId ?? 0, name: opts.threadId },
|
|
133
|
+
prompt,
|
|
134
|
+
response: result.response,
|
|
135
|
+
entries: result.entries,
|
|
136
|
+
telemetry: result.telemetry,
|
|
137
|
+
result: {
|
|
138
|
+
loopId: t?.loopId ?? 0,
|
|
139
|
+
modelRunId: result.modelRunId ?? undefined,
|
|
140
|
+
turnIds: t?.turnIds ?? [],
|
|
141
|
+
finalStatus: t?.finalStatus ?? 200,
|
|
142
|
+
hitMaxTurns: t?.hitMaxTurns ?? false,
|
|
143
|
+
usage: t?.usage,
|
|
144
|
+
},
|
|
145
|
+
wallMs: Date.now() - started,
|
|
146
|
+
timedOut: false,
|
|
147
|
+
});
|
|
148
|
+
process.stdout.write(`${JSON.stringify(doc)}\n`);
|
|
149
|
+
}
|
|
150
|
+
return result.exitCode;
|
|
151
|
+
};
|
|
152
|
+
//# sourceMappingURL=agui_cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agui_cli.js","sourceRoot":"","sources":["../src/agui_cli.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
import type Rpc from "./rpc.ts";
|
|
2
|
-
export declare const parseCallback: (url: string) => {
|
|
3
|
-
code: string;
|
|
4
|
-
state: string | null;
|
|
5
|
-
} | null;
|
|
6
|
-
export declare const expectedState: (authorizationUrl: string) => string | null;
|
|
7
|
-
export interface Loopback {
|
|
8
|
-
redirectUri: string;
|
|
9
|
-
capture: (timeoutMs: number) => Promise<{
|
|
10
|
-
code: string;
|
|
11
|
-
state: string | null;
|
|
12
|
-
} | null>;
|
|
13
|
-
}
|
|
14
|
-
export declare const bindLoopback: () => Promise<Loopback>;
|
|
15
2
|
export interface OAuthResult {
|
|
16
3
|
ok: boolean;
|
|
17
4
|
message: string;
|
|
18
5
|
}
|
|
19
6
|
export declare const runOAuth: (rpc: Rpc, target: string, io: {
|
|
20
7
|
print: (line: string) => void;
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
sleep?: (ms: number) => Promise<void>;
|
|
9
|
+
nowMs?: () => number;
|
|
23
10
|
}) => Promise<OAuthResult>;
|
|
24
11
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC,MAAM,WAAW,WAAW;IAAG,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAkB7D,eAAO,MAAM,QAAQ,QACZ,GAAG,UACA,MAAM,MACV;IAAE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;CAAE,KACnG,OAAO,CAAC,WAAW,CAqBrB,CAAC"}
|
package/dist/auth.js
CHANGED
|
@@ -1,79 +1,46 @@
|
|
|
1
|
-
// OAuth
|
|
1
|
+
// OAuth Device Authorization Grant (RFC 8628) for auth-protected execs
|
|
2
|
+
// (client #116 / execs-mcp#2 / plurnk-service#353). The loopback flow it
|
|
3
|
+
// replaces assumed browser-and-daemon co-location and was unusable over a
|
|
4
|
+
// remote daemon (SSH/jumpbox: the 127.0.0.1 callback lands on the daemon host).
|
|
2
5
|
//
|
|
3
|
-
// The mechanics (discovery/
|
|
4
|
-
// two stateless methods; the CLIENT owns the interactive half
|
|
5
|
-
// the
|
|
6
|
-
// 1.
|
|
7
|
-
// 2.
|
|
8
|
-
// 3.
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
import http from "node:http";
|
|
14
|
-
import { spawn } from "node:child_process";
|
|
6
|
+
// The mechanics (discovery/DCR/device-authorization/token-poll) are execs-mcp's;
|
|
7
|
+
// the service relays two stateless methods; the CLIENT owns the interactive half
|
|
8
|
+
// — print the verification URL + user code, then DRIVE the poll loop:
|
|
9
|
+
// 1. auth.authorize({ target }) → { verificationUri, userCode, device, interval, expiresIn }
|
|
10
|
+
// 2. print "visit <uri>, enter <code>" (or verificationUriComplete)
|
|
11
|
+
// 3. poll auth.authorize.poll({ target, device }) every `interval`s until the
|
|
12
|
+
// status settles (authorized | denied | expired) or expiresIn elapses
|
|
13
|
+
// No redirect, no local server, no token on the client — works identically on a
|
|
14
|
+
// laptop or ten jumpboxes deep. `target` is the EXEC tag needing auth (an MCP
|
|
15
|
+
// server name, e.g. `notion`).
|
|
15
16
|
import process from "node:process";
|
|
16
|
-
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
// guard in runOAuth only enforces it when the authorization URL committed to one.
|
|
21
|
-
export const parseCallback = (url) => {
|
|
22
|
-
const q = new URL(url, "http://127.0.0.1").searchParams;
|
|
23
|
-
const code = q.get("code");
|
|
24
|
-
return code !== null ? { code, state: q.get("state") } : null;
|
|
25
|
-
};
|
|
26
|
-
// The `state` an authorization URL commits to — for the client's defense-in-depth
|
|
27
|
-
// guard (execs-mcp owns authoritative validation). null when the URL carries none.
|
|
28
|
-
export const expectedState = (authorizationUrl) => new URL(authorizationUrl).searchParams.get("state");
|
|
29
|
-
// Best-effort browser open — never throws; a failed open degrades to the printed
|
|
30
|
-
// URL (headless / SSH / no opener). darwin=open, win32=start, else xdg-open.
|
|
31
|
-
const openBrowser = (url) => {
|
|
32
|
-
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
33
|
-
try {
|
|
34
|
-
spawn(cmd, [url], { stdio: "ignore", detached: true }).unref();
|
|
35
|
-
}
|
|
36
|
-
catch { /* the printed URL is the fallback */ }
|
|
37
|
-
};
|
|
38
|
-
// Stand up the transient loopback on an ephemeral port. Exported for direct
|
|
39
|
-
// testing of the capture leg (bind → hit → assert) without a daemon or browser.
|
|
40
|
-
export const bindLoopback = () => new Promise((resolve) => {
|
|
41
|
-
let onHit = () => { };
|
|
42
|
-
const hit = new Promise((r) => { onHit = r; });
|
|
43
|
-
const server = http.createServer((req, res) => {
|
|
44
|
-
const parsed = req.url !== undefined ? parseCallback(req.url) : null;
|
|
45
|
-
res.writeHead(200, { "content-type": "text/html" });
|
|
46
|
-
res.end("<!doctype html><meta charset=utf-8><body>plurnk: authorization received — you can close this tab.</body>");
|
|
47
|
-
if (parsed !== null)
|
|
48
|
-
onHit(parsed);
|
|
49
|
-
});
|
|
50
|
-
server.listen(0, "127.0.0.1", () => {
|
|
51
|
-
const addr = server.address();
|
|
52
|
-
const port = typeof addr === "object" && addr !== null ? addr.port : 0;
|
|
53
|
-
const capture = (timeoutMs) => {
|
|
54
|
-
const timer = setTimeout(() => onHit(null), timeoutMs);
|
|
55
|
-
return hit.finally(() => { clearTimeout(timer); server.close(); });
|
|
56
|
-
};
|
|
57
|
-
resolve({ redirectUri: `http://127.0.0.1:${port}/callback`, capture });
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
// Drive the full flow for `target`. `io.print` writes progress above the prompt;
|
|
61
|
-
// `io.open` is injectable (tests pass a no-op); `io.timeoutMs` bounds the wait.
|
|
17
|
+
const realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
18
|
+
// Drive the full device-grant flow for `target`. `io.print` writes progress above
|
|
19
|
+
// the prompt; `io.sleep`/`io.nowMs` are injectable (tests pass a no-op clock so
|
|
20
|
+
// the poll loop doesn't wait real seconds).
|
|
62
21
|
export const runOAuth = async (rpc, target, io) => {
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
io.print(`
|
|
68
|
-
io.print(`
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
22
|
+
const sleep = io.sleep ?? realSleep;
|
|
23
|
+
const now = io.nowMs ?? Date.now;
|
|
24
|
+
const a = await rpc.call("auth.authorize", { target });
|
|
25
|
+
io.print(` 🔒 authorize ${target} — visit:`);
|
|
26
|
+
io.print(` ${process.env.NO_COLOR ? a.verificationUri : `\x1b[1m${a.verificationUri}\x1b[0m`}`);
|
|
27
|
+
io.print(` 🔑 and enter code: ${a.userCode}`);
|
|
28
|
+
if (a.verificationUriComplete !== undefined)
|
|
29
|
+
io.print(` (or open directly: ${a.verificationUriComplete})`);
|
|
30
|
+
let intervalMs = Math.max(1, a.interval) * 1000;
|
|
31
|
+
const deadline = now() + Math.max(1, a.expiresIn) * 1000;
|
|
32
|
+
while (now() < deadline) {
|
|
33
|
+
const { status } = await rpc.call("auth.authorize.poll", { target, device: a.device });
|
|
34
|
+
if (status === "authorized")
|
|
35
|
+
return { ok: true, message: `${target} authorized — retry the operation` };
|
|
36
|
+
if (status === "denied")
|
|
37
|
+
return { ok: false, message: `${target}: authorization denied` };
|
|
38
|
+
if (status === "expired")
|
|
39
|
+
return { ok: false, message: `${target}: authorization expired — run /auth ${target} again` };
|
|
40
|
+
if (status === "slow_down")
|
|
41
|
+
intervalMs += 5_000; // RFC 8628 §3.5 — back off, don't abort
|
|
42
|
+
await sleep(intervalMs);
|
|
43
|
+
}
|
|
44
|
+
return { ok: false, message: `${target}: authorization timed out — run /auth ${target} again` };
|
|
78
45
|
};
|
|
79
46
|
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,yEAAyE;AACzE,0EAA0E;AAC1E,gFAAgF;AAChF,EAAE;AACF,iFAAiF;AACjF,iFAAiF;AACjF,sEAAsE;AACtE,+FAA+F;AAC/F,sEAAsE;AACtE,gFAAgF;AAChF,2EAA2E;AAC3E,gFAAgF;AAChF,8EAA8E;AAC9E,+BAA+B;AAE/B,OAAO,OAAO,MAAM,cAAc,CAAC;AAgBnC,MAAM,SAAS,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAEvF,kFAAkF;AAClF,gFAAgF;AAChF,4CAA4C;AAC5C,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EACzB,GAAQ,EACR,MAAc,EACd,EAAkG,EAC9E,EAAE;IACtB,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,IAAI,SAAS,CAAC;IACpC,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC;IACjC,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,CAAkB,CAAC;IAExE,EAAE,CAAC,KAAK,CAAC,kBAAkB,MAAM,WAAW,CAAC,CAAC;IAC9C,EAAE,CAAC,KAAK,CAAC,QAAQ,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,eAAe,SAAS,EAAE,CAAC,CAAC;IACpG,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC/C,IAAI,CAAC,CAAC,uBAAuB,KAAK,SAAS;QAAE,EAAE,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,uBAAuB,GAAG,CAAC,CAAC;IAE/G,IAAI,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IAChD,MAAM,QAAQ,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IACzD,OAAO,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QACtB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAA2B,CAAC;QACjH,IAAI,MAAM,KAAK,YAAY;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,mCAAmC,EAAE,CAAC;QACxG,IAAI,MAAM,KAAK,QAAQ;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,wBAAwB,EAAE,CAAC;QAC1F,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,uCAAuC,MAAM,QAAQ,EAAE,CAAC;QACxH,IAAI,MAAM,KAAK,WAAW;YAAE,UAAU,IAAI,KAAK,CAAC,CAAG,wCAAwC;QAC3F,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,yCAAyC,MAAM,QAAQ,EAAE,CAAC;AACpG,CAAC,CAAC"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAmCrD,UAAU,aAAa;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAIpD,eAAO,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAmCrD,UAAU,aAAa;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAIpD,eAAO,MAAM,eAAe,gBAAiB,MAAM,eAAe,OAAO,KAAG,MAK3E,CAAC;AAUF,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAkCrC,eAAO,MAAM,eAAe,UAAW;IACnC,OAAO,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IACzD,OAAO,EAAE,YAAY,EAAE,CAAC;IAAC,SAAS,EAAE,cAAc,EAAE,CAAC;IACrD,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC;IAClJ,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;CACrC,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAsBzB,CAAC;AAIF,eAAO,MAAM,cAAc,SAAU,MAAM,WAAW,MAAM,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAGpH,CAAC;AAEH,eAAO,MAAM,WAAW,UAAW,YAAY,KAAG,MAoBjD,CAAC;AAMF,eAAO,MAAM,mBAAmB,UAAW,YAAY,KAAG,OAKL,CAAC;AA8BtD,eAAO,MAAM,qBAAqB,UAAW;IACzC,OAAO,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,OAAO,EAAE,YAAY,EAAE,CAAC;IAAC,SAAS,EAAE,cAAc,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;CACxE,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAOxB,CAAC;AAOH,eAAO,MAAM,SAAS,QAAe,GAAG,QAAQ,MAAM,WAAW,aAAa,QAAQ;IAClF,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;CAChC,KAAG,OAAO,CAAC,MAAM,CAkFjB,CAAC;AAEF,eAAO,MAAM,MAAM,QAAe,GAAG,UAAU,MAAM,WAAW,aAAa,QAAQ;IACjF,IAAI,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC/E,KAAG,OAAO,CAAC,MAAM,CAyMjB,CAAC"}
|
package/dist/completion.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../src/completion.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../src/completion.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,WAAW,SAAU,MAAM,KAAG,MAAM,GAAG,IAanD,CAAC;AAYF,eAAO,MAAM,YAAY,SAAU,MAAM,KAAG,MAAM,GAAG,IAGpD,CAAC;AAGF,eAAO,MAAM,WAAW,UAAW,MAAM,KAAG,CAAC,MAAM,EAAE,EAAE,MAAM,CAG5D,CAAC;AAMF,eAAO,MAAM,YAAY,YAAmB,MAAM,OAAO,MAAM,KAAG,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAgB3F,CAAC"}
|
package/dist/dispatcher.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export interface Settings {
|
|
|
23
23
|
client?: string;
|
|
24
24
|
autoReadAgents?: boolean;
|
|
25
25
|
execs?: Record<string, string>;
|
|
26
|
+
questions?: boolean;
|
|
26
27
|
}
|
|
27
28
|
export declare const buildSettings: (values: {
|
|
28
29
|
"files-items"?: string;
|
|
@@ -30,6 +31,7 @@ export declare const buildSettings: (values: {
|
|
|
30
31
|
"max-commands"?: string;
|
|
31
32
|
"no-git"?: boolean;
|
|
32
33
|
"no-agents-md"?: boolean;
|
|
34
|
+
questions?: boolean;
|
|
33
35
|
}, cwd: string) => Promise<Settings>;
|
|
34
36
|
export declare const CLIENT_VERSION: string;
|
|
35
37
|
export declare const CLIENT_ID_CLI: string;
|
package/dist/dispatcher.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../src/dispatcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../src/dispatcher.ts"],"names":[],"mappings":"AA4CA,eAAO,MAAM,gBAAgB,YAAa,MAAM,GAAG,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAUxF,CAAC;AASF,eAAO,MAAM,gBAAgB,UAAW,MAAM,GAAG,SAAS,QAAO,MAAM,CAAC,UAAU,KAAiB,MAAM,GAAG,SAI3G,CAAC;AAUF,eAAO,MAAM,kBAAkB,SAAS,MAAM,CAAC,UAAU,KAAiB,MAAM,CAAC,MAAM,EAAE,MAAM,CAQ9F,CAAC;AAIF,eAAO,MAAM,kBAAkB,QAAS,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,IAKrE,CAAC;AAgKF,MAAM,WAAW,UAAU;IAAG,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAKvF,eAAO,MAAM,gBAAgB,WAAY;IACrC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACtE,KAAG,UAAU,EAKb,CAAC;AASF,MAAM,WAAW,QAAQ;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,eAAO,MAAM,aAAa,WACd;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,OACxI,MAAM,KACZ,OAAO,CAAC,QAAQ,CA4ClB,CAAC;AAMF,eAAO,MAAM,cAAc,QAAqF,CAAC;AAQjH,eAAO,MAAM,aAAa,QAAyC,CAAC;AACpE,eAAO,MAAM,aAAa,QAAyC,CAAC;AAEpE,UAAU,gBAAgB;IAAG,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE;AAa9G,eAAO,MAAM,kBAAkB,aAAc,gBAAgB,GAAG,SAAS,mBAAmB,MAAM,KAAG,MAAM,GAAG,SAQ7G,CAAC;AAoLF,eAAO,MAAM,IAAI,SAAgB,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAuOvD,CAAC"}
|