@tiens.nguyen/gu-cli 1.0.725 → 1.0.727
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/gonext_agent_chat.py +7 -8
- package/gu-repl.mjs +5 -5
- package/package.json +1 -1
- package/prompt_scaffold_check.py +12 -9
- package/terminal-layout.mjs +7 -5
package/gonext_agent_chat.py
CHANGED
|
@@ -1757,15 +1757,15 @@ def _load_prompt_scaffold(api_base: str, worker_key: str):
|
|
|
1757
1757
|
file is NOT quietly replaced by the database version, or an edit that broke it would look like
|
|
1758
1758
|
it had no effect."""
|
|
1759
1759
|
if os.path.isfile(_LOCAL_SCAFFOLD_PATH):
|
|
1760
|
-
where =
|
|
1760
|
+
where = _psc.LOCAL_SCAFFOLD_LABEL # never the path — see prompt_scaffold_check.py
|
|
1761
1761
|
try:
|
|
1762
1762
|
with open(_LOCAL_SCAFFOLD_PATH, encoding="utf-8") as f:
|
|
1763
1763
|
text = f.read()
|
|
1764
1764
|
except Exception as e: # noqa: BLE001
|
|
1765
1765
|
raise _AgentConfigError(
|
|
1766
|
-
f"The agent couldn't start:
|
|
1766
|
+
f"The agent couldn't start: {where} could not be read "
|
|
1767
1767
|
f"({type(e).__name__}). Fix it, or delete it to use the gu service's.") from None
|
|
1768
|
-
problem = _scaffold_problem(text,
|
|
1768
|
+
problem = _scaffold_problem(text, where)
|
|
1769
1769
|
if problem:
|
|
1770
1770
|
raise _AgentConfigError(
|
|
1771
1771
|
f"The agent couldn't start: {problem}. Fix it, or delete it to use the gu service's.")
|
|
@@ -2356,7 +2356,8 @@ def _render_prompt(messages, max_chars: int = 400_000) -> str:
|
|
|
2356
2356
|
# the API and shown on the token-usage page — so it would hand the hidden text to
|
|
2357
2357
|
# anyone who opens a step. Its size stays visible, the text does not.
|
|
2358
2358
|
v = _PROMPT_SCAFFOLD_VERSION["v"]
|
|
2359
|
-
|
|
2359
|
+
# The same words whatever the source — a local file is never announced (the user's call).
|
|
2360
|
+
label = f" v{v}" if isinstance(v, int) else ""
|
|
2360
2361
|
text = (f"[prompt scaffold{label} with the tool signatures — "
|
|
2361
2362
|
f"{len(text)} characters, not shown]")
|
|
2362
2363
|
out.append(f"───── {role or 'message'} ─────\n{text}")
|
|
@@ -12177,10 +12178,8 @@ def run_agent_chat(cfg):
|
|
|
12177
12178
|
# TURN_FAILED) instead of quietly running on a different prompt. The version is
|
|
12178
12179
|
# logged; the text never is.
|
|
12179
12180
|
_scaffold, _scaffold_version, _scaffold_source = _load_prompt_scaffold(worker_api_base, worker_api_key)
|
|
12180
|
-
if
|
|
12181
|
-
|
|
12182
|
-
# change the agent. One line in the thinking area, not a banner.
|
|
12183
|
-
_emit({"type": "step", "text": f"using your local prompt scaffold ({_scaffold_source})"})
|
|
12181
|
+
# A LOCAL FILE IS USED SILENTLY — no line, no location (the user's call: "if it is on
|
|
12182
|
+
# .gonext location, not say anything"). Only a BROKEN one speaks, and without the path.
|
|
12184
12183
|
try:
|
|
12185
12184
|
import yaml as _yaml
|
|
12186
12185
|
import os as _os
|
package/gu-repl.mjs
CHANGED
|
@@ -8744,14 +8744,14 @@ const wrapThought = (s, width, maxLines) => {
|
|
|
8744
8744
|
* own conversation.
|
|
8745
8745
|
*/
|
|
8746
8746
|
/**
|
|
8747
|
-
* WHERE THIS SESSION'S SCAFFOLD COMES FROM, said at `gu` start (task #246) — "scaffold
|
|
8748
|
-
* the user's own
|
|
8749
|
-
*
|
|
8747
|
+
* WHERE THIS SESSION'S SCAFFOLD COMES FROM, said at `gu` start (task #246) — "scaffold fetched" from
|
|
8748
|
+
* the gu service; NOTHING at all when it is the user's own local file (by request — its location is
|
|
8749
|
+
* never printed), unless that file is broken. Background: startup never waits on it (an offline private-mode machine would otherwise
|
|
8750
8750
|
* sit for 10s); the line prints when the answer arrives, or at the next prompt if a turn is running.
|
|
8751
8751
|
*
|
|
8752
8752
|
* · A LOCAL FILE is checked with the worker's OWN checker (prompt_scaffold_check.py — size,
|
|
8753
|
-
* placeholders, a trial render)
|
|
8754
|
-
*
|
|
8753
|
+
* placeholders, a trial render); a good one is silent, a broken one is reported. The API is not
|
|
8754
|
+
* asked: turns use the file.
|
|
8755
8755
|
* · Otherwise the API is asked to REFRESH — the fetch that the rest of the session then reuses
|
|
8756
8756
|
* ("keep in cache until the user type gu").
|
|
8757
8757
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiens.nguyen/gu-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.727",
|
|
4
4
|
"description": "Gu CLI — the gu terminal plus the local worker that runs agent / OCR / PDF / embedding jobs on your Mac (Ollama / MLX / OpenAI-compatible).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/prompt_scaffold_check.py
CHANGED
|
@@ -6,9 +6,9 @@ at startup (`python3 prompt_scaffold_check.py`) so the "scaffold loaded" line it
|
|
|
6
6
|
file really passed — not just that a file exists. Needs only jinja2 (a smolagents dependency), so
|
|
7
7
|
the startup check is quick.
|
|
8
8
|
|
|
9
|
-
python3 prompt_scaffold_check.py [path] → one JSON line: {"exists", "
|
|
9
|
+
python3 prompt_scaffold_check.py [path] → one JSON line: {"exists", "chars", "problem"}
|
|
10
10
|
|
|
11
|
-
It never prints the scaffold text.
|
|
11
|
+
It never prints the scaffold text, nor where the file is.
|
|
12
12
|
"""
|
|
13
13
|
import json
|
|
14
14
|
import os
|
|
@@ -19,7 +19,10 @@ import sys
|
|
|
19
19
|
# file — the scaffold stays off users' disks unless they put it there themselves — so it is an
|
|
20
20
|
# override for trying a wording before inserting it into production, not a cache.
|
|
21
21
|
LOCAL_SCAFFOLD_PATH = os.path.join(os.path.expanduser("~"), ".gonext", "prompt-scaffolds", "code-agent.txt")
|
|
22
|
-
|
|
22
|
+
# How the file is NAMED in anything a person reads: never its location. Asked for: "dont say out loud
|
|
23
|
+
# where is the location of the scaffold file … not say anything". The deploy app's own Commands
|
|
24
|
+
# window is the one place the path is written down, for its owner.
|
|
25
|
+
LOCAL_SCAFFOLD_LABEL = "your local scaffold file"
|
|
23
26
|
|
|
24
27
|
# What a scaffold must keep — the same list the API and the deploy app use.
|
|
25
28
|
SCAFFOLD_REQUIRED = (
|
|
@@ -97,18 +100,18 @@ def scaffold_problem(template, source: str) -> str:
|
|
|
97
100
|
def check_file(path: str = LOCAL_SCAFFOLD_PATH, label: str = LOCAL_SCAFFOLD_LABEL) -> dict:
|
|
98
101
|
"""The local override's state, for `gu` at startup. Never includes the text."""
|
|
99
102
|
if not os.path.isfile(path):
|
|
100
|
-
return {"exists": False
|
|
103
|
+
return {"exists": False}
|
|
101
104
|
try:
|
|
102
105
|
with open(path, encoding="utf-8") as f:
|
|
103
106
|
text = f.read()
|
|
104
107
|
except Exception as e: # noqa: BLE001
|
|
105
|
-
return {"exists": True, "
|
|
106
|
-
"problem": f"
|
|
107
|
-
return {"exists": True, "
|
|
108
|
-
"problem": scaffold_problem(text,
|
|
108
|
+
return {"exists": True, "chars": 0,
|
|
109
|
+
"problem": f"{label} could not be read ({type(e).__name__})"}
|
|
110
|
+
return {"exists": True, "chars": len(text),
|
|
111
|
+
"problem": scaffold_problem(text, label)}
|
|
109
112
|
|
|
110
113
|
|
|
111
114
|
if __name__ == "__main__":
|
|
112
115
|
target = sys.argv[1] if len(sys.argv) > 1 else LOCAL_SCAFFOLD_PATH
|
|
113
|
-
label = LOCAL_SCAFFOLD_LABEL
|
|
116
|
+
label = LOCAL_SCAFFOLD_LABEL
|
|
114
117
|
print(json.dumps(check_file(target, label)))
|
package/terminal-layout.mjs
CHANGED
|
@@ -1770,20 +1770,22 @@ export function lazyModuleNames(text) {
|
|
|
1770
1770
|
|
|
1771
1771
|
/**
|
|
1772
1772
|
* The one line `gu` prints at startup about the agent's prompt scaffold (task #246) — asked for so
|
|
1773
|
-
* the user
|
|
1774
|
-
*
|
|
1773
|
+
* the user knows where this session's scaffold came from — the gu service ("fetched") — and hears
|
|
1774
|
+
* NOTHING when it is their own local file (by request). Pure; gu-repl gathers the facts.
|
|
1775
1775
|
*
|
|
1776
1776
|
* local — prompt_scaffold_check.py's answer: { exists, path, chars, problem } (null = not run)
|
|
1777
1777
|
* refresh — POST /api/worker/prompt-scaffold/refresh: { status, ok, version, error, kept }
|
|
1778
1778
|
* private — private mode (the local API), which decides what "update" advice means
|
|
1779
|
-
* Returns { kind: "ok" | "warn" | "err", text }.
|
|
1779
|
+
* Returns { kind: "ok" | "warn" | "err", text }, or null when there is nothing to say.
|
|
1780
1780
|
*/
|
|
1781
1781
|
export function scaffoldStartupNotice({ local = null, refresh = null, private: privateMode = false } = {}) {
|
|
1782
|
-
|
|
1782
|
+
// YOUR LOCAL FILE, WORKING: nothing is said — no line, no location (the user's call: "dont say
|
|
1783
|
+
// out loud where is the location of the scaffold file … not say anything"). null = print nothing.
|
|
1784
|
+
// A BROKEN one still speaks, without the path: otherwise every turn fails with no explanation.
|
|
1783
1785
|
if (local?.exists) {
|
|
1784
1786
|
return local.problem
|
|
1785
1787
|
? { kind: "err", text: `scaffold: ${local.problem} — fix it, or delete it to use the gu service's` }
|
|
1786
|
-
:
|
|
1788
|
+
: null;
|
|
1787
1789
|
}
|
|
1788
1790
|
if (!refresh) return { kind: "warn", text: "scaffold: couldn't ask the API — the first turn will try again" };
|
|
1789
1791
|
if (refresh.status === 404) {
|