@yagni-app/code-staging 0.3.0-staging.1077.1 → 0.3.0-staging.1079.1

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/cli.d.ts CHANGED
@@ -28,6 +28,20 @@ export declare function seedEditorPadding(piAgentDir: string): void;
28
28
  * settings file or a write failure must never block the launch.
29
29
  */
30
30
  export declare function seedCollapseChangelog(piAgentDir: string): void;
31
+ /**
32
+ * Seed `hideThinkingBlock` into the per-profile pi `settings.json` so the
33
+ * model's raw chain-of-thought collapses to a single labeled line instead of
34
+ * streaming its entire reasoning to the terminal. Fills the key in only when
35
+ * absent — an explicit user choice (including false, e.g. via Ctrl+T) is never
36
+ * overwritten. Best-effort: a missing/corrupt settings file or a write failure
37
+ * must never block the launch.
38
+ *
39
+ * Returns true only when this call actually collapsed reasoning for the first
40
+ * time (the key was absent and the write succeeded), so the caller can pass a
41
+ * one-time hint to the extension. Ctrl+T still reveals the full trace and
42
+ * persists the user's choice, so this default is always reversible.
43
+ */
44
+ export declare function seedHideThinkingBlock(piAgentDir: string): boolean;
31
45
  export declare const HELP_TEXT: string;
32
46
  /** Parse `use <name> [--base-url <url>]` argv into its parts. */
33
47
  export declare function parseUseArgs(args: string[]): {
package/dist/cli.js CHANGED
@@ -64,6 +64,11 @@ async function confirmOnTty(question) {
64
64
  * - writes ATOMICALLY (temp file + rename) and preserves the existing file's
65
65
  * permissions, so a crash mid-write can never truncate the user's settings.
66
66
  * Any failure is swallowed: seeding must never block or break a launch.
67
+ *
68
+ * Returns true only when this call actually wrote the key (the key was absent
69
+ * and the write succeeded), letting callers distinguish a first-seed from a
70
+ * no-op so they can surface a one-time hint. Returns false on any existing
71
+ * value (explicit or previously seeded), a back-off case, or a write failure.
67
72
  */
68
73
  function seedSetting(piAgentDir, key, value) {
69
74
  try {
@@ -74,22 +79,22 @@ function seedSetting(piAgentDir, key, value) {
74
79
  // Refuse to follow a symlink: we must only ever write a regular, real
75
80
  // settings file the user (or pi) owns.
76
81
  if (lstatSync(settingsPath).isSymbolicLink())
77
- return;
82
+ return false;
78
83
  let parsed;
79
84
  try {
80
85
  parsed = JSON.parse(readFileSync(settingsPath, "utf8"));
81
86
  }
82
87
  catch {
83
- return; // corrupt file: back off rather than clobber the user's settings
88
+ return false; // corrupt file: back off rather than clobber the user's settings
84
89
  }
85
90
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
86
- return; // non-object settings: leave it alone
91
+ return false; // non-object settings: leave it alone
87
92
  }
88
93
  settings = parsed;
89
94
  existingMode = lstatSync(settingsPath).mode & 0o777;
90
95
  }
91
96
  if (settings[key] !== undefined)
92
- return; // user already chose
97
+ return false; // user (or a prior seed) already set it
93
98
  settings[key] = value;
94
99
  // Atomic write: serialize to a temp file in the same directory, then
95
100
  // rename over the target. A crash leaves either the old file or the temp
@@ -106,9 +111,11 @@ function seedSetting(piAgentDir, key, value) {
106
111
  // replaces the inode, which would otherwise reset to 0600).
107
112
  if (existingMode !== undefined)
108
113
  chmodSync(settingsPath, existingMode);
114
+ return true;
109
115
  }
110
116
  catch {
111
117
  // never block launch on a settings-seed failure
118
+ return false;
112
119
  }
113
120
  }
114
121
  /**
@@ -131,6 +138,22 @@ export function seedEditorPadding(piAgentDir) {
131
138
  export function seedCollapseChangelog(piAgentDir) {
132
139
  seedSetting(piAgentDir, "collapseChangelog", true);
133
140
  }
141
+ /**
142
+ * Seed `hideThinkingBlock` into the per-profile pi `settings.json` so the
143
+ * model's raw chain-of-thought collapses to a single labeled line instead of
144
+ * streaming its entire reasoning to the terminal. Fills the key in only when
145
+ * absent — an explicit user choice (including false, e.g. via Ctrl+T) is never
146
+ * overwritten. Best-effort: a missing/corrupt settings file or a write failure
147
+ * must never block the launch.
148
+ *
149
+ * Returns true only when this call actually collapsed reasoning for the first
150
+ * time (the key was absent and the write succeeded), so the caller can pass a
151
+ * one-time hint to the extension. Ctrl+T still reveals the full trace and
152
+ * persists the user's choice, so this default is always reversible.
153
+ */
154
+ export function seedHideThinkingBlock(piAgentDir) {
155
+ return seedSetting(piAgentDir, "hideThinkingBlock", true);
156
+ }
134
157
  async function runDefault(passthroughArgs) {
135
158
  // Cache-backed update nudge (never a network wait), then a background cache
136
159
  // refresh that completes while the session runs. Both fail soft.
@@ -168,6 +191,12 @@ async function runDefault(passthroughArgs) {
168
191
  // unreadable settings.json must never block the launch.
169
192
  seedEditorPadding(piAgentDir);
170
193
  seedCollapseChangelog(piAgentDir);
194
+ // Collapse raw chain-of-thought to one line on first launch. Seeded here
195
+ // (before the extension boots) so `setHiddenThinkingLabel`/any Ctrl+T toggle
196
+ // in this session sees the collapsed default. `seededHideThinking` is true
197
+ // only THIS launch — a downstream one-time hint must not re-nag on the next
198
+ // real run once the key already exists.
199
+ const seededHideThinking = seedHideThinkingBlock(piAgentDir);
171
200
  // Generate the shadow pi package so the terminal title/process name read
172
201
  // "YAGNI Code" instead of "pi"/"π". Best-effort: if it can't be built we
173
202
  // still launch (un-rebranded but hermetic), never blocking the agent.
@@ -216,6 +245,7 @@ async function runDefault(passthroughArgs) {
216
245
  stateDir: credentialsDir(),
217
246
  cliVersion: cliVersion(),
218
247
  baseEnv: process.env,
248
+ ...(seededHideThinking ? { hideThinkingSeeded: true } : {}),
219
249
  });
220
250
  }
221
251
  catch (err) {
@@ -615,6 +615,28 @@ export async function registerYagni(pi, deps = {}) {
615
615
  // line 3. The factory captures ctx so the footer can read session data
616
616
  // (token stats, context usage) that isn't on the footerData provider.
617
617
  ctx.ui?.setFooter?.((tui, theme, footerData) => createYagniFooterFactory(ctx, modeHolder)(tui, theme, footerData));
618
+ // Label the collapsed chain-of-thought line so users know it is reasoning
619
+ // and how to reveal the full trace. Harmless when reasoning is expanded
620
+ // (the label only shows on hidden thinking blocks). Fails closed to pi's
621
+ // default "Thinking..." label.
622
+ try {
623
+ ctx.ui?.setHiddenThinkingLabel?.("Reasoning — Ctrl+T to expand");
624
+ }
625
+ catch {
626
+ // A label must never disrupt session start.
627
+ }
628
+ // One-time hint naming what changed now that reasoning is collapsed by
629
+ // default (option 2). Gated on the launcher's YAGNI_HIDE_THINKING_SEEDED
630
+ // marker so it fires only on the launch that actually seeded the key — it
631
+ // never re-nags on subsequent runs, even though the label above persists.
632
+ if (env.YAGNI_HIDE_THINKING_SEEDED === "1") {
633
+ try {
634
+ ctx.ui?.notify("Reasoning is collapsed by default — Ctrl+T shows the full trace at any time.", "info");
635
+ }
636
+ catch {
637
+ // A hint must never disrupt session start.
638
+ }
639
+ }
618
640
  }
619
641
  // Best-effort, once at session start: if the token is at or near expiry, say
620
642
  // so via a single notice so a long session does not silently start 401-ing
@@ -370,12 +370,13 @@ export function registerPermissionGate(pi, deps = {}) {
370
370
  };
371
371
  }
372
372
  }
373
- // Guardian disabled + prompt band: auto mode blocks, review falls through to confirm.
373
+ // Guardian disabled (kill switch / env var) or not wired: pre-Guardian
374
+ // behavior. Auto mode allows prompt-band commands — the kill switch must
375
+ // never leave sessions stricter than before Guardian existed. The
376
+ // forbidden band still blocks above (decideGate), and review mode still
377
+ // falls through to the user confirm below.
374
378
  if (decision.classify === "prompt" && (!guardianState || guardianDisabled) && mode === "auto") {
375
- return {
376
- block: true,
377
- reason: "Ambiguous command blocked (Guardian disabled). Switch to /mode review to approve manually.",
378
- };
379
+ return {};
379
380
  }
380
381
  if (decision.confirm) {
381
382
  // Review mode needs a confirmation. With no dialog-capable UI (headless),
package/dist/launch.d.ts CHANGED
@@ -71,6 +71,13 @@ export interface BuildLaunchOptions {
71
71
  cliVersion?: string;
72
72
  /** Base environment to extend (defaults to process.env at call sites). */
73
73
  baseEnv?: NodeJS.ProcessEnv;
74
+ /**
75
+ * Whether this launch freshly collapsed reasoning (seeded `hideThinkingBlock`
76
+ * for the first time). Forwarded as `YAGNI_HIDE_THINKING_SEEDED=1` so the
77
+ * extension can surface a single one-time "reasoning is collapsed" hint.
78
+ * Omitted/false on repeat launches: the hint must not re-nag.
79
+ */
80
+ hideThinkingSeeded?: boolean;
74
81
  /** Clock seam for the token-expiry preflight (defaults to Date.now). */
75
82
  now?: () => number;
76
83
  /**
package/dist/launch.js CHANGED
@@ -97,6 +97,10 @@ export function buildLaunch(creds, passthroughArgs, opts) {
97
97
  // Match the e2b harness defaults: skip pi's update check + telemetry.
98
98
  PI_SKIP_VERSION_CHECK: "1",
99
99
  PI_TELEMETRY: "0",
100
+ // One-time marker for the "reasoning is collapsed" hint: only set on the
101
+ // launch that actually seeded the collapse default. Absent on every later
102
+ // launch so the hint never re-nags. (See hideThinkingSeeded in the docs.)
103
+ ...(opts.hideThinkingSeeded ? { YAGNI_HIDE_THINKING_SEEDED: "1" } : {}),
100
104
  // Forward the chosen horizontal pad so the extension's footer aligns with
101
105
  // the editor (which the launcher pads by seeding editorPaddingX). The
102
106
  // footer can't read pi's settings, so the value crosses over env.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yagni-app/code-staging",
3
- "version": "0.3.0-staging.1077.1",
3
+ "version": "0.3.0-staging.1079.1",
4
4
  "description": "YAGNI Code: a terminal coding agent that already knows your company. One YAGNI login routes the model and grounds the agent in your team's context.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "YAGNI, Inc. <jack@yagni.app> (https://yagni.app)",
@@ -38,5 +38,5 @@
38
38
  "@earendil-works/pi-tui": "0.84.1",
39
39
  "typebox": "^1.3.11"
40
40
  },
41
- "yagniSourceSha": "38b2372ff55b9374b52e94a3836be6e8c942b8df"
41
+ "yagniSourceSha": "a542e64e336db6c91e55455e9eb5d4cb584e012b"
42
42
  }