jeo-code 0.11.6 → 0.12.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/CHANGELOG.md +39 -0
- package/README.ja.md +3 -3
- package/README.ko.md +3 -3
- package/README.md +3 -3
- package/README.zh.md +3 -3
- package/package.json +1 -1
- package/src/agent/engine.ts +15 -0
- package/src/agent/skill-router.ts +163 -0
- package/src/ai/model-discovery.ts +32 -9
- package/src/commands/auth.ts +7 -1
- package/src/commands/launch.ts +4 -1
- package/src/prompts/skills/karpathy-guidelines/AGENTS.md +32 -0
- package/src/prompts/skills/karpathy-guidelines/SKILL.md +90 -0
- package/src/skills/catalog.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,45 @@ The README mirrors the latest 5 entries — regenerate with `bun run changelog:s
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.12.1] - 2026-10-16
|
|
13
|
+
_Logged-in OpenAI subscription models were invisible on proxy-configured machines._
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- **OpenAI OAuth catalog discarded when a custom base URL is set** (`src/ai/model-discovery.ts`) — with `OPENAI_BASE_URL`/config `openaiBaseUrl` configured, discovery dropped the stored OAuth credential, probed the proxy keyless (`auth rejected`), and the Codex second pass never fired (it only covered `api_key` primaries). OpenAI has no static fallback by design, so the picker showed zero models despite a valid login. New `codexCatalog` option queries the ChatGPT subscription catalog ignoring any custom base URL; `discoverModels` now appends it whenever the primary pass did not already return the OAuth catalog. The post-login report (`jeo auth login openai`) uses it too.
|
|
17
|
+
|
|
18
|
+
### Verified
|
|
19
|
+
- Live on a proxy-configured machine: `openai` rows went from 1 failed keyless row to keyless-fail + 7-model OAuth catalog; `providerPickEntries` returns 7 rows. `bun run typecheck` clean; discovery suites green including 2 new regression tests.
|
|
20
|
+
|
|
21
|
+
## [0.12.1] - 2026-10-16
|
|
22
|
+
_Explicitly select the official agy full agent with its own live model catalog and session, separate from jeo's Cloud Code Assist backend._
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- **Opt-in official agy discovery and execution** — `agy/<official-cli-slug>` selects the installed, externally authenticated official CLI as a full agent, not a raw-model adapter or CCA alias. `/model provider agy` reads the live `agy models` list, preserves exact slugs, and reports empty lists and failures without static fallback. CLI catalogs stay process-local; no identity or credential parity with jeo OAuth is assumed.
|
|
26
|
+
- **Session-owned resume and process lifecycle** — saved jeo sessions retain their own CLI conversation ID rather than resuming the CLI's unrelated latest conversation. Turns support cancellation and bounded timeouts. The requested model and upstream quota/auth/permission errors remain visible, with no fallback to CCA, another model, or another account.
|
|
27
|
+
- **Explicit execution boundary** — the CLI owns its tools, sandbox, permissions, and conversation; jeo approvals do not mediate its inner tool calls. The bridge is text-only, excluded from automatic raw-model/subagent routing, and rejects images and jeo-only tool/system/step/thinking controls it cannot enforce.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- **CCA account model discovery** — combine `agentModelSorts`, `tieredModelIds`, and `defaultAgentModelId` instead of treating one metadata list as the whole chat catalog. Existing `antigravity/<CCA-id>` discovery remains scoped to the selected jeo OAuth account, without claiming direct CCA Argon support.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
- **Malformed normalized CCA IDs** — reject invalid discovery responses instead of replacing an account's known-good cache with malformed IDs. Authoritative empty lists remain empty, failed discovery remains a failure, and existing account-cache isolation is preserved.
|
|
34
|
+
|
|
35
|
+
### Verification and release status
|
|
36
|
+
- A real, isolated source-jeo invocation of `jeo launch --model agy/gemini-4-argon-low --plan --no-tui --no-session --no-skills "Explain this repository"` exited **0**, reporting **30.5k input / 11 output tokens**. This verifies that CLI bridge invocation, not direct CCA Argon access or availability for every account.
|
|
37
|
+
- Three independent code, TypeScript, and security reviewers identified six failure-path issues; test-first fixes and regression coverage are in progress. Final release gates and public publication are not yet claimed.
|
|
38
|
+
|
|
39
|
+
## [0.12.0] - 2026-10-16
|
|
40
|
+
_Karpathy behavioral guardrails become always-on discipline, and skill routing gains an ECC single-harness inventory plus a Jev-style advisory router._
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
- **Bundled `karpathy-guidelines` skill** (`src/prompts/skills/karpathy-guidelines/SKILL.md`, registered in `src/skills/catalog.ts`) — the four `multica-ai/andrej-karpathy-skills` principles (think before coding, simplicity first, surgical changes, goal-driven execution), operationalized for jeo: ambiguity handling points at `deep-interview`, goal-driven verification points at the done-verification gate. Guidance-only, no executor or MCP tool.
|
|
44
|
+
- **Always-on `KARPATHY_DISCIPLINE` prompt block** (`src/agent/engine.ts`, `src/commands/launch.ts`) — appended to `executorSystemPrompt()` and the interactive system prompt alongside `WORKING_DISCIPLINE`. Existing discipline constants are byte-stable; the Karpathy block is additive. The JEO workflow-routing brief now states the guidelines apply to every coding turn without an explicit skill invocation.
|
|
45
|
+
- **ECC + Jev-style skill router** (`src/agent/skill-router.ts`, `docs/ecc-jev-routing.md`) — heuristic advisory `routeSkillsForTask()` (Jev `route-skills` parity: gate 0.30 / fit 0.30, `sharded` vs `shortlist` strategy, top-k 3, stopword-filtered overlap with a decisive explicit-name bonus, fail-open explicit-none) plus `inventorySkillConflicts()` (ECC single-harness rule: one skill identity, one source — duplicate normalized names from distinct paths are reported, never silently mixed). The router only suggests; `$skill` remains the sole execution entrypoint and the model is never switched.
|
|
46
|
+
- **ECC/Jev operation-flow doc** (`docs/ecc-jev-routing.md`) — source analysis of `andrej-karpathy-skills`, ECC, and the Jev control plane, with the jeo-code mapping table and the per-turn flow.
|
|
47
|
+
|
|
48
|
+
### Verified
|
|
49
|
+
- `bun run typecheck` clean; new `test/karpathy-skill-router.test.ts` (8 tests: skill registration, four-principle prompt wiring, explicit-name routing, gate/fit explicit-none, sharded/shortlist strategy, inventory conflicts) green alongside the skill/prompt/engine suites (228 pass across 17 files).
|
|
50
|
+
|
|
12
51
|
## [0.11.6] - 2026-10-16
|
|
13
52
|
_Live Antigravity account model discovery now serves the actual account's available models instead of assuming static availability._
|
|
14
53
|
|
package/README.ja.md
CHANGED
|
@@ -395,10 +395,10 @@ CI は `.github/workflows/npm-publish.yml` で公開します — GitHub リリ
|
|
|
395
395
|
|
|
396
396
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
397
397
|
- **[Unreleased]**
|
|
398
|
+
- **[0.12.1]** (2026-10-16) — Logged-in OpenAI subscription models were invisible on proxy-configured machines.
|
|
399
|
+
- **[0.12.1]** (2026-10-16) — Explicitly select the official agy full agent with its own live model catalog and session, separate from jeo's Cloud Code Assist backend.
|
|
400
|
+
- **[0.12.0]** (2026-10-16) — Karpathy behavioral guardrails become always-on discipline, and skill routing gains an ECC single-harness inventory plus a Jev-style advisory router.
|
|
398
401
|
- **[0.11.6]** (2026-10-16) — Live Antigravity account model discovery now serves the actual account's available models instead of assuming static availability.
|
|
399
|
-
- **[0.11.5]** (2026-10-04) — Anthropic login now runs Opus 5.5 and Sonnet 5.5 as the selected models: the OAuth client version gate and incompatible fast-mode temperature are fixed, with real request and streaming responses verified.
|
|
400
|
-
- **[0.11.4]** (2026-10-01) — The release pipeline could not actually release: 13 tests failed on Linux CI only, and the stored npm token no longer authenticated. Both are fixed at the root — the suite is order-independent, and publishing no longer depends on a secret that can expire.
|
|
401
|
-
- **[0.11.3]** (2026-10-01) — Remote control grew from one Telegram bot into one shared daemon serving Telegram, Discord, and Slack — and the workflow gates that were meant to block unverified work (`approve`/`team` plan identity, `done` re-checks, the autopilot ratchet) now actually block it.
|
|
402
402
|
|
|
403
403
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
404
404
|
<!-- CHANGELOG:END -->
|
package/README.ko.md
CHANGED
|
@@ -397,10 +397,10 @@ CI는 `.github/workflows/npm-publish.yml`로 배포합니다 — GitHub 릴리
|
|
|
397
397
|
|
|
398
398
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
399
399
|
- **[Unreleased]**
|
|
400
|
+
- **[0.12.1]** (2026-10-16) — Logged-in OpenAI subscription models were invisible on proxy-configured machines.
|
|
401
|
+
- **[0.12.1]** (2026-10-16) — Explicitly select the official agy full agent with its own live model catalog and session, separate from jeo's Cloud Code Assist backend.
|
|
402
|
+
- **[0.12.0]** (2026-10-16) — Karpathy behavioral guardrails become always-on discipline, and skill routing gains an ECC single-harness inventory plus a Jev-style advisory router.
|
|
400
403
|
- **[0.11.6]** (2026-10-16) — Live Antigravity account model discovery now serves the actual account's available models instead of assuming static availability.
|
|
401
|
-
- **[0.11.5]** (2026-10-04) — Anthropic login now runs Opus 5.5 and Sonnet 5.5 as the selected models: the OAuth client version gate and incompatible fast-mode temperature are fixed, with real request and streaming responses verified.
|
|
402
|
-
- **[0.11.4]** (2026-10-01) — The release pipeline could not actually release: 13 tests failed on Linux CI only, and the stored npm token no longer authenticated. Both are fixed at the root — the suite is order-independent, and publishing no longer depends on a secret that can expire.
|
|
403
|
-
- **[0.11.3]** (2026-10-01) — Remote control grew from one Telegram bot into one shared daemon serving Telegram, Discord, and Slack — and the workflow gates that were meant to block unverified work (`approve`/`team` plan identity, `done` re-checks, the autopilot ratchet) now actually block it.
|
|
404
404
|
|
|
405
405
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
406
406
|
<!-- CHANGELOG:END -->
|
package/README.md
CHANGED
|
@@ -389,10 +389,10 @@ Huge thanks to [gajae-code](https://github.com/Yeachan-Heo/gajae-code) for the i
|
|
|
389
389
|
|
|
390
390
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
391
391
|
- **[Unreleased]**
|
|
392
|
+
- **[0.12.1]** (2026-10-16) — Logged-in OpenAI subscription models were invisible on proxy-configured machines.
|
|
393
|
+
- **[0.12.1]** (2026-10-16) — Explicitly select the official agy full agent with its own live model catalog and session, separate from jeo's Cloud Code Assist backend.
|
|
394
|
+
- **[0.12.0]** (2026-10-16) — Karpathy behavioral guardrails become always-on discipline, and skill routing gains an ECC single-harness inventory plus a Jev-style advisory router.
|
|
392
395
|
- **[0.11.6]** (2026-10-16) — Live Antigravity account model discovery now serves the actual account's available models instead of assuming static availability.
|
|
393
|
-
- **[0.11.5]** (2026-10-04) — Anthropic login now runs Opus 5.5 and Sonnet 5.5 as the selected models: the OAuth client version gate and incompatible fast-mode temperature are fixed, with real request and streaming responses verified.
|
|
394
|
-
- **[0.11.4]** (2026-10-01) — The release pipeline could not actually release: 13 tests failed on Linux CI only, and the stored npm token no longer authenticated. Both are fixed at the root — the suite is order-independent, and publishing no longer depends on a secret that can expire.
|
|
395
|
-
- **[0.11.3]** (2026-10-01) — Remote control grew from one Telegram bot into one shared daemon serving Telegram, Discord, and Slack — and the workflow gates that were meant to block unverified work (`approve`/`team` plan identity, `done` re-checks, the autopilot ratchet) now actually block it.
|
|
396
396
|
|
|
397
397
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
398
398
|
<!-- CHANGELOG:END -->
|
package/README.zh.md
CHANGED
|
@@ -393,10 +393,10 @@ CI 通过 `.github/workflows/npm-publish.yml` 发布 — GitHub 发布 release
|
|
|
393
393
|
|
|
394
394
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
395
395
|
- **[Unreleased]**
|
|
396
|
+
- **[0.12.1]** (2026-10-16) — Logged-in OpenAI subscription models were invisible on proxy-configured machines.
|
|
397
|
+
- **[0.12.1]** (2026-10-16) — Explicitly select the official agy full agent with its own live model catalog and session, separate from jeo's Cloud Code Assist backend.
|
|
398
|
+
- **[0.12.0]** (2026-10-16) — Karpathy behavioral guardrails become always-on discipline, and skill routing gains an ECC single-harness inventory plus a Jev-style advisory router.
|
|
396
399
|
- **[0.11.6]** (2026-10-16) — Live Antigravity account model discovery now serves the actual account's available models instead of assuming static availability.
|
|
397
|
-
- **[0.11.5]** (2026-10-04) — Anthropic login now runs Opus 5.5 and Sonnet 5.5 as the selected models: the OAuth client version gate and incompatible fast-mode temperature are fixed, with real request and streaming responses verified.
|
|
398
|
-
- **[0.11.4]** (2026-10-01) — The release pipeline could not actually release: 13 tests failed on Linux CI only, and the stored npm token no longer authenticated. Both are fixed at the root — the suite is order-independent, and publishing no longer depends on a secret that can expire.
|
|
399
|
-
- **[0.11.3]** (2026-10-01) — Remote control grew from one Telegram bot into one shared daemon serving Telegram, Discord, and Slack — and the workflow gates that were meant to block unverified work (`approve`/`team` plan identity, `done` re-checks, the autopilot ratchet) now actually block it.
|
|
400
400
|
|
|
401
401
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
402
402
|
<!-- CHANGELOG:END -->
|
package/package.json
CHANGED
package/src/agent/engine.ts
CHANGED
|
@@ -227,6 +227,20 @@ export const VERIFICATION_DIRECTIVE =
|
|
|
227
227
|
"Distinguish a passing test from a met requirement: never weaken, skip, or narrow a test to make it pass. " +
|
|
228
228
|
"When you write tests, exercise observable behavior, edge values, branch conditions, invariants, and error handling — never assert defaults or tautologies.";
|
|
229
229
|
|
|
230
|
+
/** Karpathy behavioral guardrails (multica-ai/andrej-karpathy-skills, MIT):
|
|
231
|
+
* think-before-coding, simplicity-first, surgical-changes, goal-driven
|
|
232
|
+
* execution — operationalized for jeo's tool loop. Kept SEPARATE from
|
|
233
|
+
* WORKING_DISCIPLINE so existing prompt contracts stay byte-stable; callers
|
|
234
|
+
* opt in by appending this block. Mirrors the bundled `karpathy-guidelines`
|
|
235
|
+
* skill's SKILL.md in compact system-prompt form. */
|
|
236
|
+
export const KARPATHY_DISCIPLINE = [
|
|
237
|
+
"Karpathy discipline (caution over speed on non-trivial work; use judgment on trivial one-liners):",
|
|
238
|
+
"- Think before coding: state assumptions explicitly; when multiple interpretations exist, present them instead of picking silently; push back when a simpler approach exists; stop and ask when confused.",
|
|
239
|
+
"- Simplicity first: minimum code that solves the problem — no unasked features, no single-use abstractions, no speculative flexibility, no impossible-scenario error handling. If 200 lines could be 50, rewrite it.",
|
|
240
|
+
"- Surgical changes: touch only what the request requires; match existing style; mention unrelated dead code instead of deleting it; remove only the orphans YOUR changes created. Every changed line must trace to the request.",
|
|
241
|
+
"- Goal-driven execution: turn tasks into verifiable goals (repro test before fix, tests-before/after for refactors, per-step verify checks) and loop until the verification signal passes — a stale pass from before the last edit does not count.",
|
|
242
|
+
].join("\n");
|
|
243
|
+
|
|
230
244
|
|
|
231
245
|
export function executorSystemPrompt(
|
|
232
246
|
role = "Executor Agent, a senior software developer",
|
|
@@ -238,6 +252,7 @@ export function executorSystemPrompt(
|
|
|
238
252
|
`Accomplish the user's request by calling tools and verifying your work.\n\n` +
|
|
239
253
|
`${protocol}\n\n` +
|
|
240
254
|
`${WORKING_DISCIPLINE}\n\n` +
|
|
255
|
+
`${KARPATHY_DISCIPLINE}\n\n` +
|
|
241
256
|
`${OUTPUT_DISCIPLINE}\n\n` +
|
|
242
257
|
verificationDirective
|
|
243
258
|
);
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ECC single-harness + Jev-style skill routing for jeo-code.
|
|
3
|
+
*
|
|
4
|
+
* Two concerns live here on purpose, mirroring the external operating layer:
|
|
5
|
+
*
|
|
6
|
+
* 1. ECC inventory (fail-closed on duplicates): exactly ONE harness path per
|
|
7
|
+
* skill identity. A later skill dir's same-named skill OVERRIDES (that is the
|
|
8
|
+
* documented `loadSkills` precedence), but two DIFFERENT source paths
|
|
9
|
+
* claiming the same normalized name inside ONE resolution pass is a duplicate
|
|
10
|
+
* installation — report it instead of silently shadowing.
|
|
11
|
+
*
|
|
12
|
+
* 2. Jev `route-skills` heuristic (advisory, always fail-open): scores a task
|
|
13
|
+
* against the loaded skill catalog with zero I/O and returns a top-k
|
|
14
|
+
* selection plus an advisory routing note. Gate and fit thresholds are both
|
|
15
|
+
* `0.30`, matching the Jev control plane. This never installs skills, never
|
|
16
|
+
* changes the model, and never throws — an empty/ambiguous task yields an
|
|
17
|
+
* explicit none with a reason, not a guess.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { SkillDoc } from "../skills/catalog";
|
|
21
|
+
|
|
22
|
+
/** Gate below which no skill is selected (explicit none, reason "gate"). */
|
|
23
|
+
export const SKILL_ROUTE_GATE = 0.3;
|
|
24
|
+
/** Fit below which a top candidate is still rejected (explicit none, reason "fits"). */
|
|
25
|
+
export const SKILL_ROUTE_FIT = 0.3;
|
|
26
|
+
/** Max skills compared in one scoring shard (Jev `choiceCap` analogue). */
|
|
27
|
+
export const SKILL_ROUTE_CHOICE_CAP = 6;
|
|
28
|
+
/** Max skills returned. */
|
|
29
|
+
export const SKILL_ROUTE_TOP_K = 3;
|
|
30
|
+
|
|
31
|
+
export interface SkillRouteCandidate {
|
|
32
|
+
name: string;
|
|
33
|
+
score: number;
|
|
34
|
+
reasons: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface SkillRouteSelection {
|
|
38
|
+
topK: SkillRouteCandidate[];
|
|
39
|
+
/** "gate" = nothing cleared the gate; "fits" = cleared gate but failed fit; "ok" = advisory selection. */
|
|
40
|
+
reason: "gate" | "fits" | "ok";
|
|
41
|
+
/** "sharded" when ceil(catalogSize / choiceCap) <= 4, otherwise "shortlist". */
|
|
42
|
+
strategy: "sharded" | "shortlist";
|
|
43
|
+
/** Advisory only — never an install or model instruction. */
|
|
44
|
+
routing: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const TOKEN_RE = /[a-z0-9][a-z0-9._-]*/gi;
|
|
48
|
+
|
|
49
|
+
/** Closed-class / low-signal words excluded from routing overlap — without
|
|
50
|
+
* this, chit-chat ("how are you") spuriously matches every long skill doc. */
|
|
51
|
+
const STOPWORDS = new Set([
|
|
52
|
+
"the", "are", "you", "your", "and", "for", "with", "that", "this", "have",
|
|
53
|
+
"has", "had", "what", "when", "where", "which", "how", "why", "who", "whom",
|
|
54
|
+
"there", "here", "today", "hello", "please", "just", "like", "from", "into",
|
|
55
|
+
"over", "under", "about", "after", "before", "then", "than", "also", "only",
|
|
56
|
+
"very", "much", "more", "most", "some", "such", "will", "would", "could",
|
|
57
|
+
"should", "does", "did", "not", "but", "all",
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
function tokens(text: string): Set<string> {
|
|
61
|
+
const out = new Set<string>();
|
|
62
|
+
for (const m of text.toLowerCase().matchAll(TOKEN_RE)) {
|
|
63
|
+
const t = m[0];
|
|
64
|
+
if (t.length >= 3 && !STOPWORDS.has(t)) out.add(t);
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function skillText(s: SkillDoc): string {
|
|
70
|
+
return `${s.name} ${s.summary} ${s.whenToUse} ${s.details}`.toLowerCase();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Score one skill against the task: keyword overlap over the skill's own
|
|
75
|
+
* name/summary/when/details vocabulary. Name-token hits weigh more (explicit
|
|
76
|
+
* user intent, e.g. "ralplan" in the task). Pure, deterministic.
|
|
77
|
+
*/
|
|
78
|
+
export function scoreSkillForTask(task: string, skill: SkillDoc): { score: number; reasons: string[] } {
|
|
79
|
+
const taskTokens = tokens(task);
|
|
80
|
+
if (taskTokens.size === 0) return { score: 0, reasons: [] };
|
|
81
|
+
const text = skillText(skill);
|
|
82
|
+
const textTokens = tokens(text);
|
|
83
|
+
let overlap = 0;
|
|
84
|
+
const reasons: string[] = [];
|
|
85
|
+
for (const t of taskTokens) {
|
|
86
|
+
if (textTokens.has(t)) {
|
|
87
|
+
overlap++;
|
|
88
|
+
if (reasons.length < 5) reasons.push(t);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const nameTokens = tokens(skill.name.replace(/[:/]/g, " "));
|
|
92
|
+
let nameHits = 0;
|
|
93
|
+
for (const t of taskTokens) if (nameTokens.has(t)) nameHits++;
|
|
94
|
+
// Overlap ratio over task vocabulary + a decisive name bonus: an explicit
|
|
95
|
+
// skill-name mention in the task (e.g. "ralplan") must dominate generic
|
|
96
|
+
// vocabulary overlap from longer skill docs.
|
|
97
|
+
const score = overlap / taskTokens.size + Math.min(nameHits * 1.0, 1.5);
|
|
98
|
+
return { score, reasons };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Jev-style `route-skills`: heuristic top-k skill selection for one task.
|
|
103
|
+
* Never throws; empty input yields explicit none with reason "gate".
|
|
104
|
+
*/
|
|
105
|
+
export function routeSkillsForTask(task: string, skills: SkillDoc[], topK = SKILL_ROUTE_TOP_K): SkillRouteSelection {
|
|
106
|
+
const strategy: SkillRouteSelection["strategy"] =
|
|
107
|
+
Math.ceil(skills.length / SKILL_ROUTE_CHOICE_CAP) <= 4 ? "sharded" : "shortlist";
|
|
108
|
+
const trimmed = task.trim();
|
|
109
|
+
if (!trimmed) {
|
|
110
|
+
return { topK: [], reason: "gate", strategy, routing: "No task text — no skill suggested. Answer directly." };
|
|
111
|
+
}
|
|
112
|
+
const scored = skills.map(s => {
|
|
113
|
+
const { score, reasons } = scoreSkillForTask(trimmed, s);
|
|
114
|
+
return { name: s.name, score, reasons };
|
|
115
|
+
});
|
|
116
|
+
scored.sort((a, b) => b.score - a.score || (a.name < b.name ? -1 : 1));
|
|
117
|
+
const gated = scored.filter(c => c.score >= SKILL_ROUTE_GATE).slice(0, topK);
|
|
118
|
+
if (gated.length === 0) {
|
|
119
|
+
return { topK: [], reason: "gate", strategy, routing: "No skill cleared the gate — answer directly without a workflow skill." };
|
|
120
|
+
}
|
|
121
|
+
if (gated[0]!.score < SKILL_ROUTE_FIT) {
|
|
122
|
+
return { topK: [], reason: "fits", strategy, routing: "Top candidate failed the fit threshold — answer directly." };
|
|
123
|
+
}
|
|
124
|
+
const names = gated.map(c => `$${c.name}`).join(", ");
|
|
125
|
+
return {
|
|
126
|
+
topK: gated,
|
|
127
|
+
reason: "ok",
|
|
128
|
+
strategy,
|
|
129
|
+
routing: `Advisory only: the task resembles ${names}. Only follow a skill when the user invoked it via $skill or the task truly fits that bundled workflow; never recite skill docs.`,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** One duplicate-identity report from an ECC inventory scan. */
|
|
134
|
+
export interface SkillInventoryConflict {
|
|
135
|
+
normalized: string;
|
|
136
|
+
paths: string[];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* ECC inventory scan: group resolved skills by normalized name and report
|
|
141
|
+
* identities claimed by more than one DISTINCT source path. Bundled skills
|
|
142
|
+
* (no `sourcePath`) share one canonical path so they never conflict with
|
|
143
|
+
* each other. Pure — no filesystem access.
|
|
144
|
+
*/
|
|
145
|
+
export function inventorySkillConflicts(skills: SkillDoc[]): SkillInventoryConflict[] {
|
|
146
|
+
const byName = new Map<string, Set<string>>();
|
|
147
|
+
for (const s of skills) {
|
|
148
|
+
const normalized = s.name.toLowerCase();
|
|
149
|
+
const p = s.sourcePath ?? `(bundled) src/prompts/skills/${s.name}/SKILL.md`;
|
|
150
|
+
let set = byName.get(normalized);
|
|
151
|
+
if (!set) {
|
|
152
|
+
set = new Set();
|
|
153
|
+
byName.set(normalized, set);
|
|
154
|
+
}
|
|
155
|
+
set.add(p);
|
|
156
|
+
}
|
|
157
|
+
const out: SkillInventoryConflict[] = [];
|
|
158
|
+
for (const [normalized, paths] of byName) {
|
|
159
|
+
if (paths.size > 1) out.push({ normalized, paths: [...paths].sort() });
|
|
160
|
+
}
|
|
161
|
+
out.sort((a, b) => (a.normalized < b.normalized ? -1 : 1));
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
@@ -63,6 +63,17 @@ export interface DiscoveryOptions {
|
|
|
63
63
|
* queries both OpenAI catalogs when both credentials are configured.
|
|
64
64
|
*/
|
|
65
65
|
preferOAuth?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Query the ChatGPT Codex OAuth catalog even when a custom OpenAI base URL
|
|
68
|
+
* (config `openaiBaseUrl` or `OPENAI_BASE_URL`) is configured. A stored
|
|
69
|
+
* subscription is an independent catalog that lives at ChatGPT, never at
|
|
70
|
+
* the proxy — without this, a proxy-configured machine silently drops the
|
|
71
|
+
* OAuth credential, probes the proxy keyless, and surfaces zero models
|
|
72
|
+
* despite a valid login. Implies `preferOAuth` for OpenAI. Used by
|
|
73
|
+
* `discoverModels`' second pass and the post-login report; has no effect
|
|
74
|
+
* on other providers.
|
|
75
|
+
*/
|
|
76
|
+
codexCatalog?: boolean;
|
|
66
77
|
}
|
|
67
78
|
|
|
68
79
|
const DEFAULT_TIMEOUT = 5000;
|
|
@@ -106,6 +117,7 @@ export function discoveryRequest(
|
|
|
106
117
|
cred: Credential | undefined,
|
|
107
118
|
baseUrl?: string,
|
|
108
119
|
oauthAccountId?: string,
|
|
120
|
+
opts?: { forceCodexCatalog?: boolean },
|
|
109
121
|
): { url: string; headers: Record<string, string>; method?: "GET" | "POST"; body?: string } {
|
|
110
122
|
// Catalog-driven compat providers: OpenAI `${base}/models` (Bearer) or Anthropic
|
|
111
123
|
// `${base}/v1/models` (x-api-key). Both return { data: [{ id }] }.
|
|
@@ -123,7 +135,7 @@ export function discoveryRequest(
|
|
|
123
135
|
return { url: "https://api.anthropic.com/v1/models", headers: anthropicHeaders(cred!) };
|
|
124
136
|
case "openai": {
|
|
125
137
|
const token = cred?.kind === "oauth" || cred?.kind === "api_key" ? cred.token : "";
|
|
126
|
-
if (cred?.kind === "oauth" && !baseUrl && !process.env.OPENAI_BASE_URL) {
|
|
138
|
+
if (cred?.kind === "oauth" && (opts?.forceCodexCatalog || (!baseUrl && !process.env.OPENAI_BASE_URL))) {
|
|
127
139
|
const accountId = extractChatgptAccountId(token) || oauthAccountId;
|
|
128
140
|
const headers: Record<string, string> = {
|
|
129
141
|
Authorization: `Bearer ${token}`,
|
|
@@ -348,6 +360,11 @@ export async function listProviderModels(
|
|
|
348
360
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
349
361
|
const limit = opts.limit ?? (provider === "openai" || provider === "antigravity" ? Number.POSITIVE_INFINITY : DEFAULT_LIMIT);
|
|
350
362
|
let baseUrl = opts.baseUrl;
|
|
363
|
+
// An explicit Codex-catalog request (discoverModels' second pass, the
|
|
364
|
+
// post-login report) ignores every custom base URL: the subscription
|
|
365
|
+
// catalog lives at ChatGPT, never at the proxy. Function-scoped (not
|
|
366
|
+
// block-scoped) so the request builder below can see it.
|
|
367
|
+
const forceCodexCatalog = provider === "openai" && !!opts.codexCatalog;
|
|
351
368
|
|
|
352
369
|
let cred: Credential | undefined;
|
|
353
370
|
let oauthAccountId: string | undefined;
|
|
@@ -365,7 +382,7 @@ export async function listProviderModels(
|
|
|
365
382
|
cred = raw;
|
|
366
383
|
source = cred.kind === "oauth" ? "oauth" : cred.kind === "api_key" ? "api_key" : "none";
|
|
367
384
|
const config = opts.config ?? (await readGlobalConfig());
|
|
368
|
-
if (provider === "openai") baseUrl = (baseUrl ?? config.openaiBaseUrl ?? process.env.OPENAI_BASE_URL)?.replace(/\/+$/, "");
|
|
385
|
+
if (provider === "openai" && !forceCodexCatalog) baseUrl = (baseUrl ?? config.openaiBaseUrl ?? process.env.OPENAI_BASE_URL)?.replace(/\/+$/, "");
|
|
369
386
|
|
|
370
387
|
if (provider === "antigravity") {
|
|
371
388
|
// Antigravity lists models from the LIVE Cloud Code Assist endpoint
|
|
@@ -390,12 +407,13 @@ export async function listProviderModels(
|
|
|
390
407
|
// no api-key header), so never swap its credential to an api_key.
|
|
391
408
|
// `preferOAuth` (post-login report only) skips this swap so the report
|
|
392
409
|
// reflects the freshly stored OAuth credential, not an unrelated key.
|
|
393
|
-
|
|
410
|
+
// `codexCatalog` implies the same (plus base-URL immunity above).
|
|
411
|
+
if (provider !== "antigravity" && cred.kind === "oauth" && config.providers?.[prov] && !opts.preferOAuth && !forceCodexCatalog) {
|
|
394
412
|
// An API key is the broader, documented path — prefer it for live discovery.
|
|
395
413
|
cred = { kind: "api_key", provider: prov, token: config.providers[prov]! };
|
|
396
414
|
source = "api_key";
|
|
397
415
|
}
|
|
398
|
-
if (provider === "openai" && baseUrl && cred.kind === "oauth") {
|
|
416
|
+
if (provider === "openai" && baseUrl && cred.kind === "oauth" && !forceCodexCatalog) {
|
|
399
417
|
// Subscription credentials belong to ChatGPT, not a configured proxy.
|
|
400
418
|
const key = config.providers?.openai;
|
|
401
419
|
cred = key ? { kind: "api_key", provider: "openai", token: key } : { kind: "none", provider: "openai" };
|
|
@@ -456,7 +474,7 @@ export async function listProviderModels(
|
|
|
456
474
|
}
|
|
457
475
|
setAntigravityAccountScope(scope.accountId);
|
|
458
476
|
}
|
|
459
|
-
const { url, headers, method, body: requestBody } = discoveryRequest(provider, cred, baseUrl, oauthAccountId);
|
|
477
|
+
const { url, headers, method, body: requestBody } = discoveryRequest(provider, cred, baseUrl, oauthAccountId, forceCodexCatalog ? { forceCodexCatalog: true } : undefined);
|
|
460
478
|
const res = await fetchImpl(url, { method: method ?? "GET", headers, body: requestBody, signal });
|
|
461
479
|
if (!res.ok) {
|
|
462
480
|
const reason = res.status === 401 || res.status === 403 ? "auth rejected" : `HTTP ${res.status}`;
|
|
@@ -584,12 +602,17 @@ export async function discoverModels(
|
|
|
584
602
|
baseUrl: p === "ollama" ? (cfg.ollamaBaseUrl ?? opts.baseUrl) : p === "lmstudio" ? (cfg.lmstudioBaseUrl ?? opts.baseUrl) : p === "openai" ? (cfg.openaiBaseUrl ?? opts.baseUrl) : opts.baseUrl,
|
|
585
603
|
};
|
|
586
604
|
const primary = await listProviderModels(p, discoveryOpts);
|
|
587
|
-
//
|
|
588
|
-
//
|
|
589
|
-
|
|
605
|
+
// A stored ChatGPT subscription is a second, independent catalog: the
|
|
606
|
+
// primary pass may have covered an API key or a custom proxy (or failed
|
|
607
|
+
// keyless against one) without ever asking the Codex endpoint. Whenever
|
|
608
|
+
// the primary pass did NOT already return the OAuth catalog, query it as
|
|
609
|
+
// an additional result so logged-in subscription models stay visible —
|
|
610
|
+
// otherwise a proxy-configured machine shows zero OpenAI models despite
|
|
611
|
+
// a valid login. The Codex pass ignores any custom base URL by construction.
|
|
612
|
+
if (p === "openai" && primary.source !== "oauth") {
|
|
590
613
|
const credential = await resolveCredential("openai");
|
|
591
614
|
if (credential.kind === "oauth") {
|
|
592
|
-
return [primary, await listProviderModels(p, { ...discoveryOpts, preferOAuth: true })];
|
|
615
|
+
return [primary, await listProviderModels(p, { ...discoveryOpts, baseUrl: undefined, preferOAuth: true, codexCatalog: true })];
|
|
593
616
|
}
|
|
594
617
|
}
|
|
595
618
|
return [primary];
|
package/src/commands/auth.ts
CHANGED
|
@@ -156,7 +156,13 @@ const LIVE_MODEL_REPORT_PROVIDERS = new Set<AuthProvider>(["openai", "anthropic"
|
|
|
156
156
|
|
|
157
157
|
async function reportLiveModels(provider: AuthProvider): Promise<void> {
|
|
158
158
|
try {
|
|
159
|
-
|
|
159
|
+
// The OpenAI subscription catalog lives at ChatGPT, never at a custom
|
|
160
|
+
// proxy — request it explicitly so the report works on proxy-configured
|
|
161
|
+
// machines too (otherwise the OAuth credential is discarded for the
|
|
162
|
+
// proxy and the report shows nothing despite a fresh login).
|
|
163
|
+
const result = await listProviderModels(provider, provider === "openai"
|
|
164
|
+
? { preferOAuth: true, codexCatalog: true }
|
|
165
|
+
: { preferOAuth: true });
|
|
160
166
|
if (result.ok) {
|
|
161
167
|
// Persist immediately: the very next `jeo` launch then knows this account's
|
|
162
168
|
// real model set (including ids newer than the maintained static snapshot)
|
package/src/commands/launch.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { createInterface } from "node:readline/promises";
|
|
|
2
2
|
import { emitKeypressEvents } from "node:readline";
|
|
3
3
|
import { StringDecoder } from "node:string_decoder";
|
|
4
4
|
import { PassThrough } from "node:stream";
|
|
5
|
-
import { runAgentLoop, DEFAULT_TOOLS, TOOL_PROTOCOL, WORKING_DISCIPLINE, OUTPUT_DISCIPLINE, VERIFICATION_DIRECTIVE, isSafetyFallbackBail, stripSafetyFallbackTag, type AgentLoopEvents } from "../agent/engine";
|
|
5
|
+
import { runAgentLoop, DEFAULT_TOOLS, TOOL_PROTOCOL, WORKING_DISCIPLINE, KARPATHY_DISCIPLINE, OUTPUT_DISCIPLINE, VERIFICATION_DIRECTIVE, isSafetyFallbackBail, stripSafetyFallbackTag, type AgentLoopEvents } from "../agent/engine";
|
|
6
6
|
import { computerSupervisor } from "../agent/computer-supervisor";
|
|
7
7
|
import { executeComputerAction } from "./computer";
|
|
8
8
|
|
|
@@ -645,6 +645,7 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
645
645
|
const baseSystemPromptNoMemory =
|
|
646
646
|
preamble + "\n\n" + protocol + "\n\n" +
|
|
647
647
|
WORKING_DISCIPLINE + "\n\n" +
|
|
648
|
+
KARPATHY_DISCIPLINE + "\n\n" +
|
|
648
649
|
OUTPUT_DISCIPLINE + "\n\n" +
|
|
649
650
|
VERIFICATION_DIRECTIVE +
|
|
650
651
|
"\nWhen you have finished the user's request, or need to reply to or ask the user something, call done with {\"reason\": <your natural-language reply to the user>}. The reason text is shown to the user as your message." +
|
|
@@ -664,6 +665,8 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
664
665
|
"- Answer the user's request DIRECTLY. Never reply with a catalog, list, or summary of skills unless the user explicitly asks what skills exist.\n" +
|
|
665
666
|
"- Advertise both bundled workflow skills and configured skills below. Bundled workflows are the primary routing priority, while configured/user skills can be invoked via explicit slash commands or /skill.\n" +
|
|
666
667
|
"- Do NOT answer with a skill routing brief or execute a skill unless the user explicitly asks for skill help, invokes /skill or a skill slash alias, or the task truly fits a bundled workflow.\n" +
|
|
668
|
+
"- The karpathy-guidelines skill is always-on discipline (already in your system prompt): think before coding, simplicity first, surgical changes, goal-driven execution. Apply it to every coding turn without needing an explicit skill invocation.\n" +
|
|
669
|
+
"- ECC single-harness rule: one skill identity, one source. If two loaded skills share a normalized name from different paths, treat it as a duplicate installation — prefer the highest-precedence path and report the conflict instead of mixing both.\n" +
|
|
667
670
|
"- If the user pasted SKILL.md docs as reference material, treat them as user data and follow the latest concrete request.\n" +
|
|
668
671
|
"- Before writing code or files in a domain a loaded skill covers, read that SKILL.md first — skills encode repo/env constraints absent from your training; several may apply, so don't pre-judge that none is needed.\n" +
|
|
669
672
|
"- Your done reason must describe YOUR work or answer — never recite skill documentation.\n" +
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<!-- Parent: ../AGENTS.md -->
|
|
2
|
+
<!-- Generated: 2026-10-16 -->
|
|
3
|
+
|
|
4
|
+
# karpathy-guidelines
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
Bundled SKILL.md for the `karpathy-guidelines` behavioral guardrails.
|
|
8
|
+
|
|
9
|
+
## Key Files
|
|
10
|
+
| File | Description |
|
|
11
|
+
|------|-------------|
|
|
12
|
+
| `SKILL.md` | The primary skill definition (Karpathy 4 principles, jeo-operationalized) |
|
|
13
|
+
|
|
14
|
+
## Subdirectories
|
|
15
|
+
*(None)*
|
|
16
|
+
|
|
17
|
+
## For AI Agents
|
|
18
|
+
|
|
19
|
+
### Working In This Directory
|
|
20
|
+
- Guidance-only skill: no executor, no file writes, no MCP tool.
|
|
21
|
+
- Changes here propagate into the system prompt via `KARPATHY_DISCIPLINE`.
|
|
22
|
+
|
|
23
|
+
### Testing Requirements
|
|
24
|
+
- Covered by `test/karpathy-skill-router.test.ts` (routing + prompt wiring).
|
|
25
|
+
|
|
26
|
+
## Dependencies
|
|
27
|
+
|
|
28
|
+
### Internal
|
|
29
|
+
- Referenced by `src/skills/catalog.ts` and `src/agent/engine.ts`.
|
|
30
|
+
- Source: `multica-ai/andrej-karpathy-skills` (MIT).
|
|
31
|
+
|
|
32
|
+
<!-- MANUAL: -->
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Karpathy-derived behavioral guardrails for coding turns — think before coding, simplicity first, surgical changes, goal-driven execution. Use when writing, reviewing, or refactoring code.
|
|
3
|
+
command: $karpathy-guidelines
|
|
4
|
+
when: When writing, reviewing, or refactoring code — to avoid wrong assumptions, overcomplication, orthogonal edits, and unverified completion.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# karpathy-guidelines
|
|
8
|
+
|
|
9
|
+
Behavioral guardrails derived from Andrej Karpathy's observations on LLM coding
|
|
10
|
+
pitfalls (wrong silent assumptions, hidden confusion, overcomplicated code,
|
|
11
|
+
orthogonal edits, weak success criteria). Source:
|
|
12
|
+
`multica-ai/andrej-karpathy-skills` (`CLAUDE.md` + `skills/karpathy-guidelines`).
|
|
13
|
+
|
|
14
|
+
**Tradeoff:** these guidelines bias toward caution over speed. For trivial tasks
|
|
15
|
+
(simple typo fixes, obvious one-liners), use judgment — not every change needs
|
|
16
|
+
the full rigor. The goal is reducing costly mistakes on non-trivial work.
|
|
17
|
+
|
|
18
|
+
## 1. Think Before Coding
|
|
19
|
+
|
|
20
|
+
**Don't assume. Don't hide confusion. Surface tradeoffs.**
|
|
21
|
+
|
|
22
|
+
Before implementing:
|
|
23
|
+
|
|
24
|
+
- State assumptions explicitly. If uncertain, ask rather than guess.
|
|
25
|
+
- If multiple interpretations exist, present them — don't pick silently.
|
|
26
|
+
- If a simpler approach exists, say so. Push back when warranted.
|
|
27
|
+
- If something is unclear, stop. Name what's confusing. Ask.
|
|
28
|
+
|
|
29
|
+
In jeo terms: this is the `deep-interview` ambiguity gate applied at turn
|
|
30
|
+
scope. A `$deep-interview`-grade clarification belongs before code, not after
|
|
31
|
+
a mistaken implementation.
|
|
32
|
+
|
|
33
|
+
## 2. Simplicity First
|
|
34
|
+
|
|
35
|
+
**Minimum code that solves the problem. Nothing speculative.**
|
|
36
|
+
|
|
37
|
+
- No features beyond what was asked.
|
|
38
|
+
- No abstractions for single-use code.
|
|
39
|
+
- No "flexibility" or "configurability" that wasn't requested.
|
|
40
|
+
- No error handling for impossible scenarios.
|
|
41
|
+
- If 200 lines could be 50, rewrite it.
|
|
42
|
+
|
|
43
|
+
The test: would a senior engineer say this is overcomplicated? If yes,
|
|
44
|
+
simplify. Prefer boring, explicit code over clever constructions.
|
|
45
|
+
|
|
46
|
+
## 3. Surgical Changes
|
|
47
|
+
|
|
48
|
+
**Touch only what you must. Clean up only your own mess.**
|
|
49
|
+
|
|
50
|
+
When editing existing code:
|
|
51
|
+
|
|
52
|
+
- Don't "improve" adjacent code, comments, or formatting.
|
|
53
|
+
- Don't refactor things that aren't broken.
|
|
54
|
+
- Match existing style, even if you'd do it differently.
|
|
55
|
+
- If you notice unrelated dead code, mention it — don't delete it.
|
|
56
|
+
|
|
57
|
+
When your changes create orphans:
|
|
58
|
+
|
|
59
|
+
- Remove imports/variables/functions that YOUR changes made unused.
|
|
60
|
+
- Don't remove pre-existing dead code unless asked.
|
|
61
|
+
|
|
62
|
+
The test: every changed line should trace directly to the user's request.
|
|
63
|
+
|
|
64
|
+
## 4. Goal-Driven Execution
|
|
65
|
+
|
|
66
|
+
**Define success criteria. Loop until verified.**
|
|
67
|
+
|
|
68
|
+
Transform tasks into verifiable goals:
|
|
69
|
+
|
|
70
|
+
- "Add validation" → "Write tests for invalid inputs, then make them pass"
|
|
71
|
+
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
|
|
72
|
+
- "Refactor X" → "Ensure tests pass before and after"
|
|
73
|
+
|
|
74
|
+
For multi-step tasks, state a brief plan:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
1. [Step] → verify: [check]
|
|
78
|
+
2. [Step] → verify: [check]
|
|
79
|
+
3. [Step] → verify: [check]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Strong success criteria let the loop run independently. Weak criteria
|
|
83
|
+
("make it work") require constant clarification. In jeo this maps directly
|
|
84
|
+
onto the done-verification gate (`loop-guards.ts`): no mutation without a
|
|
85
|
+
passing test/build/typecheck signal, and a stale verification after a later
|
|
86
|
+
edit does not count.
|
|
87
|
+
|
|
88
|
+
These guidelines are working if: fewer unnecessary changes in diffs, fewer
|
|
89
|
+
rewrites due to overcomplication, and clarifying questions come before
|
|
90
|
+
implementation rather than after mistakes.
|
package/src/skills/catalog.ts
CHANGED
|
@@ -3,6 +3,7 @@ import deepDiveSkillRaw from "../prompts/skills/deep-dive/SKILL.md" with { type:
|
|
|
3
3
|
import ralplanSkillRaw from "../prompts/skills/ralplan/SKILL.md" with { type: "text" };
|
|
4
4
|
import teamSkillRaw from "../prompts/skills/team/SKILL.md" with { type: "text" };
|
|
5
5
|
import ultragoalSkillRaw from "../prompts/skills/ultragoal/SKILL.md" with { type: "text" };
|
|
6
|
+
import karpathyGuidelinesSkillRaw from "../prompts/skills/karpathy-guidelines/SKILL.md" with { type: "text" };
|
|
6
7
|
|
|
7
8
|
const MAX_SKILL_SUMMARY_CHARS = 180;
|
|
8
9
|
const MAX_SKILL_DETAILS_CHARS = 8_000;
|
|
@@ -28,6 +29,7 @@ export const SKILLS: SkillDoc[] = [
|
|
|
28
29
|
parseSkillMarkdown("ralplan", ralplanSkillRaw),
|
|
29
30
|
parseSkillMarkdown("team", teamSkillRaw),
|
|
30
31
|
parseSkillMarkdown("ultragoal", ultragoalSkillRaw),
|
|
32
|
+
parseSkillMarkdown("karpathy-guidelines", karpathyGuidelinesSkillRaw),
|
|
31
33
|
];
|
|
32
34
|
export const BUILTIN_SKILL_NAMES = SKILLS.map(s => s.name.toLowerCase());
|
|
33
35
|
|