@plurnk/plurnk 0.74.0 โ 0.76.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/.env.defaults +3 -4
- package/README.md +60 -23
- package/completions/_plurnk +13 -0
- package/completions/plurnk.bash +14 -0
- package/completions/plurnk.fish +37 -0
- package/conformance/agui-client.json +863 -0
- package/dist/agents.d.ts +11 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +170 -0
- package/dist/agents.js.map +1 -0
- package/dist/agui.d.ts +1 -0
- package/dist/agui.d.ts.map +1 -1
- package/dist/agui.js +45 -5
- package/dist/agui.js.map +1 -1
- package/dist/agui_cli.d.ts +1 -4
- package/dist/agui_cli.d.ts.map +1 -1
- package/dist/agui_cli.js +29 -9
- package/dist/agui_cli.js.map +1 -1
- package/dist/build-info.json +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +12 -7
- package/dist/cli.js.map +1 -1
- package/dist/color.d.ts +2 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +5 -0
- package/dist/color.js.map +1 -0
- package/dist/completion.js +4 -4
- package/dist/completion.js.map +1 -1
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +4 -2
- package/dist/diagnostics.js.map +1 -1
- package/dist/dispatcher.d.ts +8 -8
- package/dist/dispatcher.d.ts.map +1 -1
- package/dist/dispatcher.js +196 -104
- package/dist/dispatcher.js.map +1 -1
- package/dist/envdefaults.d.ts.map +1 -1
- package/dist/envdefaults.js +4 -6
- package/dist/envdefaults.js.map +1 -1
- package/dist/markdown.d.ts +17 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +234 -0
- package/dist/markdown.js.map +1 -0
- package/dist/mcp.d.ts +11 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +213 -69
- package/dist/mcp.js.map +1 -1
- package/dist/paste.d.ts +1 -0
- package/dist/paste.d.ts.map +1 -1
- package/dist/paste.js +5 -0
- package/dist/paste.js.map +1 -1
- package/dist/paths.d.ts +2 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +12 -0
- package/dist/paths.js.map +1 -0
- package/dist/plan.d.ts +12 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +30 -0
- package/dist/plan.js.map +1 -0
- package/dist/proposal.d.ts +3 -5
- package/dist/proposal.d.ts.map +1 -1
- package/dist/proposal.js +54 -34
- package/dist/proposal.js.map +1 -1
- package/dist/reasoning-events.d.ts +23 -0
- package/dist/reasoning-events.d.ts.map +1 -0
- package/dist/reasoning-events.js +40 -0
- package/dist/reasoning-events.js.map +1 -0
- package/dist/reasoning.d.ts +11 -0
- package/dist/reasoning.d.ts.map +1 -0
- package/dist/reasoning.js +10 -0
- package/dist/reasoning.js.map +1 -0
- package/dist/render.d.ts +4 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +93 -50
- package/dist/render.js.map +1 -1
- package/dist/skills.d.ts +7 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +152 -0
- package/dist/skills.js.map +1 -0
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +11 -11
- package/dist/stream.js.map +1 -1
- package/dist/subcommands.d.ts +3 -0
- package/dist/subcommands.d.ts.map +1 -1
- package/dist/subcommands.js +32 -11
- package/dist/subcommands.js.map +1 -1
- package/dist/transport.d.ts +12 -4
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +77 -21
- package/dist/transport.js.map +1 -1
- package/dist/tui.d.ts +23 -13
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +335 -92
- package/dist/tui.js.map +1 -1
- package/man/plurnk.1 +153 -0
- package/package.json +16 -9
package/dist/proposal.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// a target {scheme, pathname}, a body string (udiff for EDIT, command summary
|
|
8
8
|
// for EXEC), and an opaque attrs object. loop.resolve takes {logEntryId,
|
|
9
9
|
// decision, body?, outcome?}.
|
|
10
|
+
import { colorEnabled } from "./color.js";
|
|
10
11
|
import { spawn } from "node:child_process";
|
|
11
12
|
import { writeFile, readFile, mkdtemp, rm } from "node:fs/promises";
|
|
12
13
|
import { tmpdir } from "node:os";
|
|
@@ -16,7 +17,7 @@ import { join } from "node:path";
|
|
|
16
17
|
// daemon resolves the entry in-process before any human can react. Review UI
|
|
17
18
|
// and a client loop.resolve would race an already-settled proposal.
|
|
18
19
|
export const isServerResolved = ({ flags }) => flags?.auto === true || flags?.noProposals === true;
|
|
19
|
-
const useColor =
|
|
20
|
+
const useColor = colorEnabled();
|
|
20
21
|
const ansi = (code) => useColor ? `\x1b[${code}m` : "";
|
|
21
22
|
const RESET = ansi("0");
|
|
22
23
|
const BOLD = ansi("1");
|
|
@@ -63,14 +64,13 @@ const readSingleKey = () => new Promise((resolve) => {
|
|
|
63
64
|
};
|
|
64
65
|
stdin.on("data", onData);
|
|
65
66
|
});
|
|
66
|
-
// Drop
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
const editInEditor = async (body,
|
|
67
|
+
// Drop a body into a tmpfile, spawn $EDITOR (or VISUAL, or vi) on it, wait
|
|
68
|
+
// for the editor to exit, read the result back. Empty file โ null (git-commit
|
|
69
|
+
// convention). Shared by proposal review and prompt composition (plurnk#26).
|
|
70
|
+
export const editInEditor = async (body, suffix) => {
|
|
70
71
|
const editor = process.env.VISUAL ?? process.env.EDITOR ?? "vi";
|
|
71
|
-
const dir = await mkdtemp(join(tmpdir(), "plurnk-
|
|
72
|
-
const
|
|
73
|
-
const path = join(dir, `proposal${suffix}`);
|
|
72
|
+
const dir = await mkdtemp(join(tmpdir(), "plurnk-edit-"));
|
|
73
|
+
const path = join(dir, `buffer${suffix}`);
|
|
74
74
|
try {
|
|
75
75
|
await writeFile(path, body, "utf8");
|
|
76
76
|
await new Promise((resolve, reject) => {
|
|
@@ -93,21 +93,53 @@ export const renderProposalMenu = (params) => {
|
|
|
93
93
|
+ renderBody(params.op, params.body) + nl
|
|
94
94
|
+ `${DIM}[a]ccept ยท [e]dit ยท [r]eject ยท [c]ancel${RESET} `;
|
|
95
95
|
};
|
|
96
|
-
// โโโ
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
export const
|
|
104
|
-
|
|
96
|
+
// โโโ request-user-input questions ({ยงquestion-tool}) โโโโโโโโโโโโโโโโโโ
|
|
97
|
+
// The question tool's body is the MCP2 form-elicitation shape โ { message,
|
|
98
|
+
// requestedSchema } โ and the answer is the standard ElicitResult payload
|
|
99
|
+
// { action, content }. The client renders the message plus the schema's
|
|
100
|
+
// single-property enum choices as a numbered menu with a free-response escape.
|
|
101
|
+
// The schema's single-property enum choices, if any. Multi-property or
|
|
102
|
+
// non-enum schemas yield [] (the user types a JSON answer).
|
|
103
|
+
export const questionChoices = (schema) => {
|
|
104
|
+
const properties = schema.properties;
|
|
105
|
+
if (typeof properties !== "object" || properties === null)
|
|
106
|
+
return [];
|
|
107
|
+
const keys = Object.keys(properties);
|
|
108
|
+
if (keys.length !== 1)
|
|
109
|
+
return [];
|
|
110
|
+
const property = properties[keys[0]];
|
|
111
|
+
const enums = property?.enum;
|
|
112
|
+
return Array.isArray(enums) ? enums.filter((c) => typeof c === "string") : [];
|
|
113
|
+
};
|
|
114
|
+
// Map a typed line to the standard answer payload for a single-property schema:
|
|
115
|
+
// a digit picks that enum choice; anything else is the property's free-text
|
|
116
|
+
// value. Multi-property schemas expect raw JSON. Empty โ null (re-prompt).
|
|
117
|
+
export const answerForQuestion = (line, schema) => {
|
|
118
|
+
const t = line.trim();
|
|
119
|
+
if (t.length === 0)
|
|
105
120
|
return null;
|
|
106
|
-
const
|
|
107
|
-
if (
|
|
121
|
+
const properties = schema.properties;
|
|
122
|
+
if (typeof properties !== "object" || properties === null)
|
|
123
|
+
return null;
|
|
124
|
+
const keys = Object.keys(properties);
|
|
125
|
+
const choices = questionChoices(schema);
|
|
126
|
+
if (keys.length === 1) {
|
|
127
|
+
const key = keys[0];
|
|
128
|
+
const n = Number(t);
|
|
129
|
+
const value = choices.length > 0 && Number.isInteger(n) && n >= 1 && n <= choices.length
|
|
130
|
+
? choices[n - 1]
|
|
131
|
+
: t;
|
|
132
|
+
return { [key]: value };
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const parsed = JSON.parse(t);
|
|
136
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)
|
|
137
|
+
? parsed
|
|
138
|
+
: null;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
108
141
|
return null;
|
|
109
|
-
|
|
110
|
-
return { question: a.question, choices };
|
|
142
|
+
}
|
|
111
143
|
};
|
|
112
144
|
// The question menu: the question, numbered choices, and the always-present
|
|
113
145
|
// free-response escape. An open question (no choices) is just "type your answer".
|
|
@@ -119,18 +151,6 @@ export const renderQuestionMenu = (question, choices) => {
|
|
|
119
151
|
: `${DIM} type your answer${RESET} `);
|
|
120
152
|
return lines.join("\n");
|
|
121
153
|
};
|
|
122
|
-
// Map a typed line to the answer: a digit 1..N picks that choice's text; anything
|
|
123
|
-
// else is free response (rejecting the premise / an open answer). Empty โ null
|
|
124
|
-
// (caller re-prompts rather than resolving with nothing).
|
|
125
|
-
export const answerForLine = (line, choices) => {
|
|
126
|
-
const t = line.trim();
|
|
127
|
-
if (t.length === 0)
|
|
128
|
-
return null;
|
|
129
|
-
const n = Number(t);
|
|
130
|
-
if (Number.isInteger(n) && n >= 1 && n <= choices.length)
|
|
131
|
-
return choices[n - 1];
|
|
132
|
-
return t;
|
|
133
|
-
};
|
|
134
154
|
// Map a single review key to a resolution. `e` runs $EDITOR (async โ caller
|
|
135
155
|
// must own the terminal during the spawn). Returns null for non-review keys, so
|
|
136
156
|
// callers can pass them through (the TUI lets them reach readline) or default
|
|
@@ -140,7 +160,7 @@ export const keyToResolution = async (key, params) => {
|
|
|
140
160
|
case "a":
|
|
141
161
|
return { decision: "accept" };
|
|
142
162
|
case "e": {
|
|
143
|
-
const edited = await editInEditor(params.body, params.op);
|
|
163
|
+
const edited = await editInEditor(params.body, params.op === "EDIT" ? ".diff" : params.op === "EXEC" ? ".sh" : ".txt");
|
|
144
164
|
if (edited === null)
|
|
145
165
|
return { decision: "cancel", outcome: "empty_editor_buffer" };
|
|
146
166
|
return { decision: "accept", body: edited };
|
package/dist/proposal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposal.js","sourceRoot":"","sources":["../src/proposal.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,+EAA+E;AAC/E,4EAA4E;AAC5E,mEAAmE;AACnE,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,yEAAyE;AACzE,8BAA8B;AAE9B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAqBjC,wEAAwE;AACxE,kEAAkE;AAClE,6EAA6E;AAC7E,oEAAoE;AACpE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAAE,KAAK,EAAkB,EAAW,EAAE,CACnE,KAAK,EAAE,IAAI,KAAK,IAAI,IAAI,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;AAQxD,MAAM,QAAQ,GAAG,
|
|
1
|
+
{"version":3,"file":"proposal.js","sourceRoot":"","sources":["../src/proposal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AguiEvent } from "./agui.ts";
|
|
2
|
+
export type ReasoningUpdate = {
|
|
3
|
+
phase: "start";
|
|
4
|
+
messageId: string;
|
|
5
|
+
} | {
|
|
6
|
+
phase: "content";
|
|
7
|
+
messageId: string;
|
|
8
|
+
delta: string;
|
|
9
|
+
content: string;
|
|
10
|
+
} | {
|
|
11
|
+
phase: "end";
|
|
12
|
+
messageId: string;
|
|
13
|
+
content: string;
|
|
14
|
+
};
|
|
15
|
+
export interface ReasoningEventResult {
|
|
16
|
+
handled: boolean;
|
|
17
|
+
update?: ReasoningUpdate;
|
|
18
|
+
}
|
|
19
|
+
export default class ReasoningEvents {
|
|
20
|
+
#private;
|
|
21
|
+
consume(event: AguiEvent): ReasoningEventResult;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=reasoning-events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning-events.d.ts","sourceRoot":"","sources":["../src/reasoning-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,MAAM,eAAe,GACrB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,eAAe,CAAC;CAC5B;AAKD,MAAM,CAAC,OAAO,OAAO,eAAe;;IAGhC,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,oBAAoB,CAgC9C;CACJ"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Preserve AG-UI's live delta lifecycle while maintaining the accumulated value
|
|
2
|
+
// needed by terminal and editor presentation. Shape validation belongs to
|
|
3
|
+
// HttpAgent; lifecycle integrity belongs here, at the client projection boundary.
|
|
4
|
+
export default class ReasoningEvents {
|
|
5
|
+
#messages = new Map();
|
|
6
|
+
consume(event) {
|
|
7
|
+
if (event.type === "REASONING_START" || event.type === "REASONING_END") {
|
|
8
|
+
return { handled: true };
|
|
9
|
+
}
|
|
10
|
+
if (event.type === "REASONING_MESSAGE_START") {
|
|
11
|
+
if (this.#messages.has(event.messageId)) {
|
|
12
|
+
throw new TypeError(`Reasoning message '${event.messageId}' started twice.`);
|
|
13
|
+
}
|
|
14
|
+
this.#messages.set(event.messageId, "");
|
|
15
|
+
return { handled: true, update: { phase: "start", messageId: event.messageId } };
|
|
16
|
+
}
|
|
17
|
+
if (event.type === "REASONING_MESSAGE_CONTENT") {
|
|
18
|
+
const prior = this.#messages.get(event.messageId);
|
|
19
|
+
if (prior === undefined) {
|
|
20
|
+
throw new TypeError(`Reasoning content for '${event.messageId}' arrived before its start.`);
|
|
21
|
+
}
|
|
22
|
+
const content = prior + event.delta;
|
|
23
|
+
this.#messages.set(event.messageId, content);
|
|
24
|
+
return {
|
|
25
|
+
handled: true,
|
|
26
|
+
update: { phase: "content", messageId: event.messageId, delta: event.delta, content },
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if (event.type === "REASONING_MESSAGE_END") {
|
|
30
|
+
const content = this.#messages.get(event.messageId);
|
|
31
|
+
if (content === undefined) {
|
|
32
|
+
throw new TypeError(`Reasoning message '${event.messageId}' ended before its start.`);
|
|
33
|
+
}
|
|
34
|
+
this.#messages.delete(event.messageId);
|
|
35
|
+
return { handled: true, update: { phase: "end", messageId: event.messageId, content } };
|
|
36
|
+
}
|
|
37
|
+
return { handled: false };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=reasoning-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning-events.js","sourceRoot":"","sources":["../src/reasoning-events.ts"],"names":[],"mappings":"AAYA,gFAAgF;AAChF,0EAA0E;AAC1E,kFAAkF;AAClF,MAAM,CAAC,OAAO,OAAO,eAAe;IAChC,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEtC,OAAO,CAAC,KAAgB;QACpB,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC7B,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,yBAAyB,EAAE,CAAC;YAC3C,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,SAAS,CAAC,sBAAsB,KAAK,CAAC,SAAS,kBAAkB,CAAC,CAAC;YACjF,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACrF,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,2BAA2B,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAClD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACtB,MAAM,IAAI,SAAS,CAAC,0BAA0B,KAAK,CAAC,SAAS,6BAA6B,CAAC,CAAC;YAChG,CAAC;YACD,MAAM,OAAO,GAAG,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;YACpC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC7C,OAAO;gBACH,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE;aACxF,CAAC;QACN,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,uBAAuB,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACpD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,SAAS,CAAC,sBAAsB,KAAK,CAAC,SAAS,2BAA2B,CAAC,CAAC;YAC1F,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC;QAC5F,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;CACJ"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ReasoningCaller {
|
|
2
|
+
call(method: string, params?: object): Promise<unknown>;
|
|
3
|
+
}
|
|
4
|
+
export interface WorkerReasoning {
|
|
5
|
+
policy: string | null;
|
|
6
|
+
supportedPolicies: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare const readWorkerReasoning: (rpc: ReasoningCaller) => Promise<WorkerReasoning>;
|
|
9
|
+
export declare const setWorkerReasoning: (rpc: ReasoningCaller, policy: string) => Promise<WorkerReasoning>;
|
|
10
|
+
export declare const formatWorkerReasoning: (reasoning: WorkerReasoning) => string;
|
|
11
|
+
//# sourceMappingURL=reasoning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning.d.ts","sourceRoot":"","sources":["../src/reasoning.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC5B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,eAAO,MAAM,mBAAmB,QAAe,eAAe,KAAG,OAAO,CAAC,eAAe,CAC3B,CAAC;AAE9D,eAAO,MAAM,kBAAkB,QACtB,eAAe,UACZ,MAAM,KACf,OAAO,CAAC,eAAe,CAC+C,CAAC;AAE1E,eAAO,MAAM,qBAAqB,cAAe,eAAe,KAAG,MAMlE,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const readWorkerReasoning = async (rpc) => await rpc.call("worker.reasoning.get");
|
|
2
|
+
export const setWorkerReasoning = async (rpc, policy) => await rpc.call("worker.reasoning.set", { policy });
|
|
3
|
+
export const formatWorkerReasoning = (reasoning) => {
|
|
4
|
+
const policy = reasoning.policy ?? "(unavailable)";
|
|
5
|
+
const supported = reasoning.supportedPolicies.length === 0
|
|
6
|
+
? "none"
|
|
7
|
+
: reasoning.supportedPolicies.join(", ");
|
|
8
|
+
return `reasoning: ${policy}\nsupported: ${supported}\n`;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=reasoning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning.js","sourceRoot":"","sources":["../src/reasoning.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,GAAoB,EAA4B,EAAE,CACxF,MAAM,GAAG,CAAC,IAAI,CAAC,sBAAsB,CAAoB,CAAC;AAE9D,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EACnC,GAAoB,EACpB,MAAc,EACU,EAAE,CAC1B,MAAM,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,MAAM,EAAE,CAAoB,CAAC;AAE1E,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,SAA0B,EAAU,EAAE;IACxE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,eAAe,CAAC;IACnD,MAAM,SAAS,GAAG,SAAS,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC;QACtD,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,OAAO,cAAc,MAAM,gBAAgB,SAAS,IAAI,CAAC;AAC7D,CAAC,CAAC"}
|
package/dist/render.d.ts
CHANGED
|
@@ -26,10 +26,14 @@ export interface LogEntryWire {
|
|
|
26
26
|
turn_seq: number;
|
|
27
27
|
sequence: number;
|
|
28
28
|
}
|
|
29
|
+
export declare const entryAnnotation: (entry: LogEntryWire) => string | null;
|
|
29
30
|
export declare const isEntryMaterialization: (entry: LogEntryWire) => boolean;
|
|
30
31
|
export declare const coordLabel: (loopSeq: number, turnSeq: number, sequence: number) => string;
|
|
31
32
|
export declare const progressLabel: (percent: number) => string;
|
|
33
|
+
export declare const statusCodeVisible: (entry: Pick<LogEntryWire, "op" | "status_rx">) => boolean;
|
|
32
34
|
export declare const extractSendBody: (txUnknown: unknown, prettify: boolean) => string;
|
|
35
|
+
export declare const renderReasoning: (content: string) => string;
|
|
36
|
+
export declare const renderReasoningPreview: (content: string, columns?: number) => string;
|
|
33
37
|
export declare const isPromptEntry: (entry: LogEntryWire) => boolean;
|
|
34
38
|
export declare const entryTarget: (entry: LogEntryWire) => string | null;
|
|
35
39
|
export declare const entryScope: (entry: LogEntryWire) => string | null;
|
package/dist/render.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|
package/dist/render.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// Glyph palette + line formatting for the TUI log waterfall.
|
|
2
2
|
// Glyphs per TUI.md ยง4 (canonical for the constellation).
|
|
3
|
+
import { colorEnabled } from "./color.js";
|
|
4
|
+
import { stripVTControlCharacters } from "node:util";
|
|
5
|
+
import { looksLikeMarkdown, renderMarkdownDocument } from "./markdown.js";
|
|
6
|
+
import { presentPlan } from "./plan.js";
|
|
3
7
|
// Width-stable glyph palette โ EVERY glyph is plain East-Asian-Wide
|
|
4
8
|
// (width 2 in node and every major terminal); VS16 variation-selector
|
|
5
9
|
// sequences (โ๏ธ โ๏ธ โ๏ธ โ ๏ธ ๐) are banned from the palette entirely after
|
|
@@ -18,7 +22,6 @@ export const OP_GLYPHS = {
|
|
|
18
22
|
SEND: "๐ฌ",
|
|
19
23
|
EXEC: "๐ง",
|
|
20
24
|
BARE: "๐ฎ",
|
|
21
|
-
PLAN: "๐ง ", // the model's per-turn reasoning (grammar 0.70 leads every turn with PLAN)
|
|
22
25
|
};
|
|
23
26
|
export const ORIGIN_GLYPHS = {
|
|
24
27
|
model: "๐ค",
|
|
@@ -70,7 +73,7 @@ export const sendSubGlyph = (status) => {
|
|
|
70
73
|
return " "; // reserve the slot โ never a bare, width-shifting empty string
|
|
71
74
|
};
|
|
72
75
|
// ANSI escape codes. NO_COLOR support per Unix convention.
|
|
73
|
-
const useColor =
|
|
76
|
+
const useColor = colorEnabled();
|
|
74
77
|
const code = (n) => useColor ? `\x1b[${n}m` : "";
|
|
75
78
|
const RESET = code("0");
|
|
76
79
|
const DIM = code("2");
|
|
@@ -143,6 +146,26 @@ const buildExtra = (entry) => {
|
|
|
143
146
|
return "";
|
|
144
147
|
}
|
|
145
148
|
};
|
|
149
|
+
export const entryAnnotation = (entry) => {
|
|
150
|
+
const tx = typeof entry.tx === "string"
|
|
151
|
+
? (() => { try {
|
|
152
|
+
return JSON.parse(entry.tx);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return null;
|
|
156
|
+
} })()
|
|
157
|
+
: entry.tx;
|
|
158
|
+
const raw = tx !== null && typeof tx === "object"
|
|
159
|
+
? tx.annotation
|
|
160
|
+
: null;
|
|
161
|
+
if (typeof raw !== "string")
|
|
162
|
+
return null;
|
|
163
|
+
const plain = stripVTControlCharacters(raw)
|
|
164
|
+
.replace(/[\p{Cc}\p{Cf}]+/gu, " ")
|
|
165
|
+
.replace(/\s+/gu, " ")
|
|
166
|
+
.trim();
|
|
167
|
+
return plain.length === 0 ? null : plain;
|
|
168
|
+
};
|
|
146
169
|
// Machine acquisition is durable ambience, not a live action trace. It remains
|
|
147
170
|
// available through log/replay; interactive clients collapse it into the
|
|
148
171
|
// producer's aggregate progress signal instead of redrawing once per page.
|
|
@@ -159,42 +182,26 @@ export const isEntryMaterialization = (entry) => {
|
|
|
159
182
|
&& entry.op === "EDIT"
|
|
160
183
|
&& attrs?.kind === "entry_materialized";
|
|
161
184
|
};
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
//
|
|
185
|
+
// The default human waterfall carries NO log coordinates (plurnk#21: the
|
|
186
|
+
// 01/02/03 gutter was clutter for end users). Coordinates remain forensic
|
|
187
|
+
// truth on the wire and in --json; this label survives for machine-adjacent
|
|
188
|
+
// surfaces that still want one.
|
|
166
189
|
export const coordLabel = (loopSeq, turnSeq, sequence) => {
|
|
167
190
|
const p = (n) => String(n).padStart(2, "0");
|
|
168
191
|
return `${DIM}${p(loopSeq)}/${p(turnSeq)}/${p(sequence)}${RESET} `;
|
|
169
192
|
};
|
|
170
|
-
// The active prompt
|
|
171
|
-
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
193
|
+
// The active prompt shows a busy gauge in its own slot; idle shows nothing.
|
|
194
|
+
export const progressLabel = (percent) => `${DIM}${`${Math.max(0, Math.min(100, Math.trunc(percent)))}%`.padStart(4, " ")}${RESET} `;
|
|
195
|
+
// Status codes render only where they carry meaning (plurnk#21): every SEND
|
|
196
|
+
// keeps its code (the conversation's protocol truth), every error keeps its
|
|
197
|
+
// code, and routine non-SEND successes show none.
|
|
198
|
+
export const statusCodeVisible = (entry) => entry.op === "SEND" || entry.status_rx >= 400;
|
|
175
199
|
const BOLD = code("1");
|
|
176
200
|
const ITALIC = code("3");
|
|
201
|
+
void ITALIC;
|
|
177
202
|
// A common model-authored inline-math spelling with an exact terminal glyph.
|
|
178
203
|
// This is typographic normalization, not a claim of general LaTeX support.
|
|
179
204
|
const normalizeProse = (s) => s.replaceAll("$\\rightarrow$", "โ");
|
|
180
|
-
// Heuristic: body looks like markdown if it carries any of the structural markers.
|
|
181
|
-
// False positives on plain text containing isolated `*` or `_` are avoided by requiring
|
|
182
|
-
// paired markers or line-anchored constructs.
|
|
183
|
-
const looksLikeMarkdown = (s) => /(^|\n)#{1,6}\s/.test(s) ||
|
|
184
|
-
/\*\*[^*\n]+\*\*/.test(s) ||
|
|
185
|
-
/(^|\n)[-*+]\s/.test(s) ||
|
|
186
|
-
/```/.test(s) ||
|
|
187
|
-
/\[[^\]]+\]\([^)]+\)/.test(s);
|
|
188
|
-
// Minimal vanilla-ANSI markdown: enough to make a reply readable, not a full parser.
|
|
189
|
-
const renderMarkdown = (s) => {
|
|
190
|
-
let out = s;
|
|
191
|
-
out = out.replace(/^(#{1,6})\s+(.*)$/gm, (_m, _h, text) => `${BOLD}${text}${RESET}`);
|
|
192
|
-
out = out.replace(/\*\*([^*\n]+)\*\*/g, (_m, t) => `${BOLD}${t}${RESET}`);
|
|
193
|
-
out = out.replace(/(^|[^*_])[*_]([^*_\n]+)[*_](?!\*)/g, (_m, pre, t) => `${pre}${ITALIC}${t}${RESET}`);
|
|
194
|
-
out = out.replace(/`([^`\n]+)`/g, (_m, t) => `${DIM}${t}${RESET}`);
|
|
195
|
-
out = out.replace(/^[-*+]\s/gm, "โข ");
|
|
196
|
-
return out;
|
|
197
|
-
};
|
|
198
205
|
// Read a SEND body off a log_entry.tx, dispatching by content type.
|
|
199
206
|
// Per plurnk-grammar/schema/SendBody.json: tx.body is { raw, json } | null.
|
|
200
207
|
//
|
|
@@ -216,10 +223,29 @@ export const extractSendBody = (txUnknown, prettify) => {
|
|
|
216
223
|
if (typeof raw !== "string")
|
|
217
224
|
return "";
|
|
218
225
|
const prose = normalizeProse(raw);
|
|
226
|
+
// Tables, fences, and Mermaid project through the one client rendering
|
|
227
|
+
// model (plurnk#15), width-capped at the 80-column ergonomic target.
|
|
219
228
|
if (looksLikeMarkdown(prose))
|
|
220
|
-
return
|
|
229
|
+
return renderMarkdownDocument(prose);
|
|
221
230
|
return prose;
|
|
222
231
|
};
|
|
232
|
+
// Provider reasoning is neither PLAN nor speech. Give it one quiet visual lane
|
|
233
|
+
// without inventing a log coordinate or status it does not own.
|
|
234
|
+
export const renderReasoning = (content) => content
|
|
235
|
+
.split("\n")
|
|
236
|
+
.map((line, index) => `${index === 0 ? " ๐ญ " : " "}${DIM}${line}${RESET}`)
|
|
237
|
+
.join("\n");
|
|
238
|
+
// One physical terminal row for an in-flight reasoning preview. The completed
|
|
239
|
+
// message replaces it with renderReasoning(), so live deltas never accumulate a
|
|
240
|
+
// scrollback line per token.
|
|
241
|
+
export const renderReasoningPreview = (content, columns = 80) => {
|
|
242
|
+
const normalized = content.replace(/\s+/g, " ").trim();
|
|
243
|
+
const capacity = Math.max(8, columns - 7);
|
|
244
|
+
const excerpt = normalized.length > capacity
|
|
245
|
+
? `โฆ${normalized.slice(-(capacity - 1))}`
|
|
246
|
+
: normalized;
|
|
247
|
+
return ` ๐ญ ${DIM}${excerpt}${RESET}`;
|
|
248
|
+
};
|
|
223
249
|
// Bold the model's ANSWER. The model's terminal SEND (200 done / 499 cancelled
|
|
224
250
|
// โ a signal, not a directed target) is its reply to the user; its body renders
|
|
225
251
|
// BOLD so it stands out against the operation-record grid. Intermediate 102
|
|
@@ -246,7 +272,9 @@ const renderBroadcast = (entry) => {
|
|
|
246
272
|
const idGlyph = entry.origin === "model" ? modelSendGlyph(signal) : (ORIGIN_GLYPHS[entry.origin] ?? "?");
|
|
247
273
|
const subGlyph = entry.origin === "model" ? " " : sendSubGlyph(signal);
|
|
248
274
|
const statusText = `${colorForStatus(entry.status_rx)}${entry.status_rx}${RESET}`;
|
|
249
|
-
const
|
|
275
|
+
const annotation = entryAnnotation(entry);
|
|
276
|
+
const header = ` ${[idGlyph, subGlyph, statusText].join(" ")}`
|
|
277
|
+
+ (annotation === null ? "" : ` ${DIM}โ ${annotation}${RESET}`);
|
|
250
278
|
const body = extractSendBody(entry.tx, /* prettify */ true);
|
|
251
279
|
const multiLine = body.includes("\n");
|
|
252
280
|
// Short single-line replies inline after the header (nvim's
|
|
@@ -262,6 +290,26 @@ const renderBroadcast = (entry) => {
|
|
|
262
290
|
const isAnswer = entry.origin === "model" && (entry.signal === 200 || entry.signal === 499);
|
|
263
291
|
return emphasizeLines(lines, isAnswer);
|
|
264
292
|
};
|
|
293
|
+
const renderPlan = (entry) => {
|
|
294
|
+
// A routine PLAN carries no status code (plurnk#21); a failed one keeps
|
|
295
|
+
// its error code and glyph on the first row.
|
|
296
|
+
const status = String(entry.status_rx);
|
|
297
|
+
const failed = entry.status_rx >= 400;
|
|
298
|
+
const firstSlot = failed ? `${sendSubGlyph(entry.status_rx)} ${colorForStatus(entry.status_rx)}${status}${RESET} ` : "";
|
|
299
|
+
const laterSlot = failed ? `${" ".repeat(3 + status.length + 1)}` : "";
|
|
300
|
+
const note = entryAnnotation(entry);
|
|
301
|
+
const presented = presentPlan(entry.tx);
|
|
302
|
+
const rows = presented.length === 0
|
|
303
|
+
? [{ glyph: "๐ญ", text: "no entries" }]
|
|
304
|
+
: presented;
|
|
305
|
+
return rows.map(({ glyph, text }, index) => {
|
|
306
|
+
const prefix = index === 0
|
|
307
|
+
? ` ${glyph} ${firstSlot}`
|
|
308
|
+
: ` ${glyph} ${laterSlot}`;
|
|
309
|
+
const annotation = index === 0 && note !== null ? ` ${DIM}โ ${note}${RESET}` : "";
|
|
310
|
+
return `${prefix}${DIM}${text}${RESET}${annotation}`;
|
|
311
|
+
}).join("\n");
|
|
312
|
+
};
|
|
265
313
|
// The TUI skips actionless prompt rows in the live waterfall: the line the
|
|
266
314
|
// user typed at the readline prompt is already their record, and rendering
|
|
267
315
|
// the broadcast too would duplicate every prompt.
|
|
@@ -291,6 +339,8 @@ export const renderLogEntry = (entry) => {
|
|
|
291
339
|
// not a broadcast.
|
|
292
340
|
if (entry.op === "SEND" && entry.scheme === null && entry.pathname === null)
|
|
293
341
|
return renderBroadcast(entry);
|
|
342
|
+
if (entry.op === "PLAN")
|
|
343
|
+
return renderPlan(entry);
|
|
294
344
|
// ONE identity/action glyph, not origin+op (they were redundant on SEND and
|
|
295
345
|
// cluttered elsewhere). A SEND shows its ACTOR (๐น you / ๐ค model โ the "who's
|
|
296
346
|
// speaking"); any other op shows its OP glyph (๐ง /๐/๐/๐/๐ง โ self-evidently
|
|
@@ -305,7 +355,7 @@ export const renderLogEntry = (entry) => {
|
|
|
305
355
|
? sendSubGlyph(entry.signal)
|
|
306
356
|
: sendSubGlyph(entry.status_rx);
|
|
307
357
|
const statusColor = colorForStatus(entry.status_rx);
|
|
308
|
-
const statusText = `${statusColor}${entry.status_rx}${RESET}
|
|
358
|
+
const statusText = statusCodeVisible(entry) ? `${statusColor}${entry.status_rx}${RESET}` : "";
|
|
309
359
|
// Render whatever target the daemon supplied โ no synthesis. If scheme
|
|
310
360
|
// is null but pathname is set, that's the daemon's choice (e.g. file://
|
|
311
361
|
// shortcut) and we render the bare path.
|
|
@@ -314,25 +364,21 @@ export const renderLogEntry = (entry) => {
|
|
|
314
364
|
const scope = entryScope(entry);
|
|
315
365
|
const scopeText = scope !== null ? `${CYAN}${scope}${RESET}` : "";
|
|
316
366
|
const extra = buildExtra(entry);
|
|
317
|
-
//
|
|
318
|
-
//
|
|
319
|
-
const parts = [idGlyph, subGlyph
|
|
367
|
+
// Columns: idGlyph ยท status glyph (always present โ glyph or reserved blank)
|
|
368
|
+
// ยท code (SEND and errors only, plurnk#21) ยท target ยท extra.
|
|
369
|
+
const parts = [idGlyph, subGlyph];
|
|
370
|
+
if (statusText.length > 0)
|
|
371
|
+
parts.push(statusText);
|
|
320
372
|
if (pathText.length > 0)
|
|
321
373
|
parts.push(pathText);
|
|
322
374
|
if (scopeText.length > 0)
|
|
323
375
|
parts.push(scopeText);
|
|
324
376
|
if (extra.length > 0)
|
|
325
377
|
parts.push(extra);
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const planBody = entry.tx?.body;
|
|
331
|
-
if (typeof planBody === "string" && planBody.trim().length > 0) {
|
|
332
|
-
parts.push(`${DIM}${planBody.replace(/\s*\n\s*/g, " ").trim()}${RESET}`);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
return ` ${coordPrefix(entry)}${parts.join(" ")}`;
|
|
378
|
+
const annotation = entryAnnotation(entry);
|
|
379
|
+
if (annotation !== null)
|
|
380
|
+
parts.push(`${DIM}โ ${annotation}${RESET}`);
|
|
381
|
+
return ` ${parts.join(" ")}`;
|
|
336
382
|
};
|
|
337
383
|
// Compact token count: 49152 โ "49k", 980 โ "980". The gauge stays terse.
|
|
338
384
|
const formatK = (n) => n >= 1000 ? `${Math.round(n / 1000)}k` : `${n}`;
|
|
@@ -348,8 +394,8 @@ export const contextGauge = (tokens, capacity) => gauge("ctx", tokens, capacity)
|
|
|
348
394
|
// usage is absent for non-model ops (op.exec / op.parse have no provider
|
|
349
395
|
// call) โ those render no token part. It is NOT a fallback for missing
|
|
350
396
|
// data: a model loop always carries real usage (plurnk-service #197).
|
|
351
|
-
const STRIKE_THRESHOLD = "https://problems.plurnk.
|
|
352
|
-
const INVALID_EMISSION_EXHAUSTED = "https://problems.plurnk.
|
|
397
|
+
const STRIKE_THRESHOLD = "https://problems.plurnk.xyz/engine/rails/strike-threshold";
|
|
398
|
+
const INVALID_EMISSION_EXHAUSTED = "https://problems.plurnk.xyz/engine/generation/invalid-emission-exhausted";
|
|
353
399
|
// The status class is not the verdict. Preserve the exact terminal Problem so
|
|
354
400
|
// unrelated engine failures do not masquerade as rail strike-outs.
|
|
355
401
|
export const terminalStatusLabel = (result) => {
|
|
@@ -382,9 +428,6 @@ export const renderSummary = (turns, wallMs, result, hitMaxTurns, usage) => {
|
|
|
382
428
|
if (costUsd !== null && !isZeroDecimal(costUsd)) {
|
|
383
429
|
tokenPart += ` ยท loop $${costUsd}`;
|
|
384
430
|
}
|
|
385
|
-
else if (costUsd === null && usage.accounting.requests.length > 0) {
|
|
386
|
-
tokenPart += " ยท loop $unknown";
|
|
387
|
-
}
|
|
388
431
|
}
|
|
389
432
|
return `${DIM} ${tag} ยท ${turns} turn${turns === 1 ? "" : "s"} ยท ${ms}${tokenPart}${RESET}`;
|
|
390
433
|
};
|