@stemtrooper/learningcode 0.4.3 → 0.4.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/README.md CHANGED
@@ -171,6 +171,10 @@ learningcode --mode json # machine-readable output
171
171
  The TLC brand theme and banner ship with the package, so there is nothing to
172
172
  configure.
173
173
 
174
+ LearningCode suppresses Pi's built-in startup header so the TLC banner appears
175
+ without the Pi logo flashing first. Use `learningcode --verbose` to show Pi's
176
+ startup details and loaded-resource list as well.
177
+
174
178
  ```
175
179
  ██╗ ███████╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗
176
180
  ██║ ██╔════╝██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ ██╔════╝██╔═══██╗██╔══██╗██╔════╝
@@ -297,4 +301,4 @@ is also MIT. See [LICENSE](LICENSE).
297
301
 
298
302
  Not affiliated with, endorsed by, or connected to Pi, OpenCode, Anomaly, or any of
299
303
  the model providers reachable through this client. "The Learning Curve", TLC and
300
- Spark are trademarks of The Learning Curve.
304
+ Spark are trademarks of The Learning Curve.
@@ -17,6 +17,7 @@ import {
17
17
  } from "../lib/config.mjs";
18
18
  import { GO_PROVIDER, saveProviderKey } from "../lib/auth.mjs";
19
19
  import { ensureSparkProvider, modelsPath, retargetProvider } from "../lib/models.mjs";
20
+ import { ensureQuietStartup } from "../lib/settings.mjs";
20
21
  import { ensureThemes, preferredTheme } from "../lib/themes.mjs";
21
22
  import { hasToken, looksLikeToken, resolveToken, writeCachedToken } from "../lib/token.mjs";
22
23
 
@@ -45,6 +46,7 @@ Everything else is passed straight through to Pi, so the usual flags work:
45
46
  learningcode -p "explain main.py" one-shot, non-interactive
46
47
  learningcode --mode json machine-readable event stream
47
48
  learningcode --list-models every model Pi can reach
49
+ learningcode --verbose show Pi's startup header and resource list
48
50
 
49
51
  Other providers
50
52
  Any --model other than tlc-spark/... skips the Spark token and the Spark
@@ -230,6 +232,7 @@ async function main() {
230
232
  }
231
233
  await ensureSparkProvider(dir);
232
234
  await ensureThemes(dir);
235
+ await ensureQuietStartup(dir);
233
236
 
234
237
  // `--login` forces a fresh paste even when a token is already cached.
235
238
  const forced = [];
@@ -369,4 +372,4 @@ main().catch((error) => {
369
372
  // Anything the user can act on gets one line. A stack trace is noise for a
370
373
  // student who mistyped a token; keep it for genuine bugs.
371
374
  fail(error instanceof UserError ? error.message : error?.stack || String(error));
372
- });
375
+ });
@@ -0,0 +1,42 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { UserError } from "./config.mjs";
4
+
5
+ /**
6
+ * Pi renders its built-in header before extension `session_start` handlers run.
7
+ * Its supported quietStartup setting prevents that header flashing before the
8
+ * LearningCode banner is installed. Only seed the setting when it is unset, so
9
+ * an explicit choice in the student's LearningCode settings remains theirs.
10
+ */
11
+ export async function ensureQuietStartup(agentDir) {
12
+ const path = join(agentDir, "settings.json");
13
+ let settings;
14
+
15
+ try {
16
+ const contents = await readFile(path, "utf-8");
17
+ try {
18
+ settings = JSON.parse(contents.replace(/^\uFEFF/, ""));
19
+ } catch (error) {
20
+ throw new UserError(`Could not parse Pi settings at ${path}: ${error.message}`);
21
+ }
22
+ } catch (error) {
23
+ if (error instanceof UserError) throw error;
24
+ if (error?.code !== "ENOENT") {
25
+ throw new UserError(`Could not read Pi settings at ${path}: ${error.message}`);
26
+ }
27
+ settings = {};
28
+ }
29
+
30
+ if (!settings || typeof settings !== "object" || Array.isArray(settings)) {
31
+ throw new UserError(`Pi settings at ${path} must contain a JSON object.`);
32
+ }
33
+
34
+ if (typeof settings.quietStartup === "boolean" || settings.quietStartup === "header") {
35
+ return false;
36
+ }
37
+
38
+ settings.quietStartup = true;
39
+ await mkdir(agentDir, { recursive: true });
40
+ await writeFile(path, `${JSON.stringify(settings, null, 2)}\n`, "utf-8");
41
+ return true;
42
+ }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@stemtrooper/learningcode",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "TLC Spark coding agent for students: Pi wired to the Spark OpenAI-compatible endpoint with per-student tokens, quota and seat-queue awareness.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "bin": {
8
- "learningcode": "./bin/learningcode.mjs"
8
+ "learningcode": "bin/learningcode.mjs"
9
9
  },
10
10
  "files": [
11
11
  "assets",