jeopi-cli 16.2.26 → 16.2.28
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 +18 -0
- package/README.md +1 -1
- package/dist/cli.js +3076 -3082
- package/dist/types/advisor/runtime.d.ts +3 -0
- package/dist/types/commands/install.d.ts +1 -1
- package/dist/types/discovery/helpers.d.ts +1 -1
- package/dist/types/export/html/index.d.ts +2 -2
- package/dist/types/export/html/web-palette.d.ts +2 -2
- package/dist/types/session/session-history-format.d.ts +12 -0
- package/dist/types/tiny/text.d.ts +9 -2
- package/dist/types/tools/report-tool-issue.d.ts +1 -1
- package/package.json +13 -12
- package/scripts/generate-share-viewer.ts +5 -5
- package/scripts/jeopi +4 -4
- package/scripts/{omp.ts → jeopi-preload.ts} +4 -4
- package/src/advisor/__tests__/advisor.test.ts +43 -0
- package/src/advisor/runtime.ts +8 -2
- package/src/commands/install.ts +1 -1
- package/src/debug/report-bundle.ts +1 -1
- package/src/debug/system-info.ts +2 -2
- package/src/discovery/builtin.ts +4 -4
- package/src/discovery/helpers.ts +2 -2
- package/src/discovery/omp-plugins.ts +3 -3
- package/src/discovery/ssh.ts +1 -1
- package/src/export/html/index.ts +2 -2
- package/src/export/html/share-loader.js +5 -5
- package/src/export/html/template.css +2 -2
- package/src/export/html/template.js +5 -5
- package/src/export/html/tool-views.generated.js +2 -2
- package/src/export/html/web-palette.ts +2 -2
- package/src/export/share.ts +1 -1
- package/src/internal-urls/docs-index.generated.txt +1 -1
- package/src/memories/index.ts +23 -1
- package/src/modes/acp/acp-agent.ts +12 -6
- package/src/modes/controllers/selector-controller.ts +16 -2
- package/src/session/agent-session.ts +13 -15
- package/src/session/session-history-format.ts +18 -1
- package/src/tiny/text.ts +11 -8
- package/src/tools/image-gen.ts +2 -4
- package/src/tools/report-tool-issue.ts +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* `jeopi install <target>` — top-level convenience over `jeopi plugin install` /
|
|
3
3
|
* `jeopi plugin link`.
|
|
4
4
|
*
|
|
5
|
-
* The docs (omp.
|
|
5
|
+
* The docs (docs/extensions.md, or `jeopi read omp://extensions.md`) advertise
|
|
6
6
|
*
|
|
7
7
|
* jeopi install ./my-extension
|
|
8
8
|
*
|
|
@@ -155,7 +155,7 @@ export declare function calculateDepth(cwd: string, targetDir: string, separator
|
|
|
155
155
|
* Discovery rules:
|
|
156
156
|
* 1. Direct files: `extensions/*.ts` or `*.js` → load
|
|
157
157
|
* 2. Subdirectory with index: `extensions/<ext>/index.ts` or `index.js` → load
|
|
158
|
-
* 3. Subdirectory with package.json: `extensions/<ext>/package.json` with "
|
|
158
|
+
* 3. Subdirectory with package.json: `extensions/<ext>/package.json` with "jeopi"/"pi" field → load declared paths
|
|
159
159
|
*
|
|
160
160
|
* No recursion beyond one level. Complex packages must use package.json manifest.
|
|
161
161
|
* Uses native glob for fast filesystem scanning with gitignore support.
|
|
@@ -7,7 +7,7 @@ export interface ExportOptions {
|
|
|
7
7
|
outputPath?: string;
|
|
8
8
|
/**
|
|
9
9
|
* Which color palette the export ships with.
|
|
10
|
-
* - `"web"` (default) — the
|
|
10
|
+
* - `"web"` (default) — the jeopi brand identity (collab-web pink/purple),
|
|
11
11
|
* so public HTML exports and the `/s/<id>` share viewer match the live
|
|
12
12
|
* `my.omp.sh` client. See `web-palette.ts`.
|
|
13
13
|
* - `"theme"` — derive from `themeName` (or the active TUI theme), preserving
|
|
@@ -27,7 +27,7 @@ export interface ExportOptions {
|
|
|
27
27
|
*
|
|
28
28
|
* Two call shapes:
|
|
29
29
|
* • `generateThemeVars("web" | "theme", themeName?)` — explicit palette.
|
|
30
|
-
* `"web"` (the default for public artifacts) returns the fixed
|
|
30
|
+
* `"web"` (the default for public artifacts) returns the fixed jeopi brand
|
|
31
31
|
* palette from `web-palette.ts` — collab-web pink/purple identity, shared
|
|
32
32
|
* with the live `my.omp.sh` client, so exports and the share viewer render
|
|
33
33
|
* identically to it. `"theme"` derives from the TUI theme via
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Web/export palette — the
|
|
2
|
+
* Web/export palette — the jeopi brand identity shared by the collab-web live
|
|
3
3
|
* client (`my.omp.sh/`) and every public HTML export / share viewer (`/s/<id>`).
|
|
4
4
|
*
|
|
5
5
|
* Why this exists separately from `modes/theme/dark.json`: the `dark` theme is
|
|
6
6
|
* the **default TUI theme** — its amber accent (`#febc38`) drives the terminal
|
|
7
7
|
* status line, syntax highlighting, thinking levels, and bash/python mode
|
|
8
|
-
* colors for every
|
|
8
|
+
* colors for every jeopi user. The public web artifacts want the collab-web
|
|
9
9
|
* pink/purple identity instead, so they pin this palette rather than inheriting
|
|
10
10
|
* the TUI's. Editing `dark.json` to repurpose it for the web would repaint
|
|
11
11
|
* every terminal; this file keeps the two surfaces decoupled.
|
|
@@ -3,6 +3,18 @@ export interface HistoryFormatOptions {
|
|
|
3
3
|
title?: string;
|
|
4
4
|
/** Render assistant thinking blocks (default: elided). */
|
|
5
5
|
includeThinking?: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* When rendering thinking (requires `includeThinking`), disguise it through
|
|
8
|
+
* {@link renderDemotedThinking} for this target model id instead of the literal
|
|
9
|
+
* `_thinking:_ ` label. Anthropic's `reasoning_extraction` classifier can flag a
|
|
10
|
+
* transcript that replays a *different* model's prior thinking back at a
|
|
11
|
+
* Fable/Mythos model labeled as "thinking" — this is the same trigger
|
|
12
|
+
* `renderDemotedThinking` already avoids for cross-model/cross-turn replay in the
|
|
13
|
+
* wire layer. Omitted for the human-facing `history://` dump, where the explicit
|
|
14
|
+
* label is more useful than the disguise and there is no live model on the other
|
|
15
|
+
* end to refuse it.
|
|
16
|
+
*/
|
|
17
|
+
demoteThinkingForModelId?: string;
|
|
6
18
|
/** Render tool intent comment before tool call lines. */
|
|
7
19
|
includeToolIntent?: boolean;
|
|
8
20
|
/** Render watched-session roles as inline `**agent**:` / `**user**:` labels (collapsing consecutive same-role messages) instead of `## ` headings, so a primary transcript embedded inside an advisor turn stays visually distinct. */
|
|
@@ -20,9 +20,16 @@ export declare function formatTitleUserMessage(message: string): string;
|
|
|
20
20
|
export interface TitleConversationTurn {
|
|
21
21
|
role: "user" | "assistant";
|
|
22
22
|
text?: string;
|
|
23
|
-
thinking?: string;
|
|
24
23
|
}
|
|
25
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Format recent user/assistant context for title generation after a todo
|
|
26
|
+
* replan. Assistant `thinking` is intentionally never included: the
|
|
27
|
+
* replan-refresh title model falls back to the session's own current model
|
|
28
|
+
* when no `tiny`/`commit`/`smol` role is configured, so replaying prior
|
|
29
|
+
* reasoning as plaintext here is a `reasoning_extraction` classifier-refusal
|
|
30
|
+
* trigger on Anthropic targets (mirrors the thinking-drop in compaction,
|
|
31
|
+
* memories, and the hindsight transcript extractor).
|
|
32
|
+
*/
|
|
26
33
|
export declare function formatTitleConversationContext(turns: readonly TitleConversationTurn[]): string;
|
|
27
34
|
/**
|
|
28
35
|
* True when a first user message is too low-signal to title (greeting, ack,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* (including from subagents) read the cached decision without prompting.
|
|
14
14
|
*
|
|
15
15
|
* When the user grants consent, push is automatically active against the
|
|
16
|
-
* bundled endpoint (`dev.autoqaPush.endpoint`, default `qa.
|
|
16
|
+
* bundled endpoint (`dev.autoqaPush.endpoint`, default `qa.jeopi.sh`). Each
|
|
17
17
|
* insert schedules a background flush that POSTs pending rows and deletes
|
|
18
18
|
* them on HTTP 2xx. `PI_AUTO_QA_PUSH=1` forces push in non-interactive
|
|
19
19
|
* environments where the consent dialog never fires. Tool execution is
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "jeopi-cli",
|
|
4
|
-
"version": "16.2.
|
|
4
|
+
"version": "16.2.28",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://github.com/akillness/jeopi",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"gen:docs": "bun scripts/generate-docs-index.ts --generate",
|
|
44
44
|
"gen:docs:reset": "bun scripts/generate-docs-index.ts --reset",
|
|
45
45
|
"gen:tool-views": "bun --cwd=../collab-web run gen:tool-views",
|
|
46
|
+
"gen:share-viewer": "bun scripts/generate-share-viewer.ts",
|
|
46
47
|
"gen:bundle": "bun scripts/bundle-dist.ts",
|
|
47
48
|
"gen:mupdf": "bun scripts/embed-mupdf-wasm.ts --generate",
|
|
48
49
|
"gen:mupdf:reset": "bun scripts/embed-mupdf-wasm.ts --reset",
|
|
@@ -56,17 +57,17 @@
|
|
|
56
57
|
"@agentclientprotocol/sdk": "0.25.0",
|
|
57
58
|
"@babel/parser": "^7.29.7",
|
|
58
59
|
"@mozilla/readability": "^0.6.0",
|
|
59
|
-
"jeopi-hashline": "16.2.
|
|
60
|
-
"jeopi-stats": "16.2.
|
|
61
|
-
"jeopi-agent-core": "16.2.
|
|
62
|
-
"jeopi-ai": "16.2.
|
|
63
|
-
"jeopi-catalog": "16.2.
|
|
64
|
-
"jeopi-mnemopi": "16.2.
|
|
65
|
-
"jeopi-natives": "16.2.
|
|
66
|
-
"jeopi-tui": "16.2.
|
|
67
|
-
"jeopi-utils": "16.2.
|
|
68
|
-
"jeopi-wire": "16.2.
|
|
69
|
-
"jeopi-snapcompact": "16.2.
|
|
60
|
+
"jeopi-hashline": "16.2.28",
|
|
61
|
+
"jeopi-stats": "16.2.28",
|
|
62
|
+
"jeopi-agent-core": "16.2.28",
|
|
63
|
+
"jeopi-ai": "16.2.28",
|
|
64
|
+
"jeopi-catalog": "16.2.28",
|
|
65
|
+
"jeopi-mnemopi": "16.2.28",
|
|
66
|
+
"jeopi-natives": "16.2.28",
|
|
67
|
+
"jeopi-tui": "16.2.28",
|
|
68
|
+
"jeopi-utils": "16.2.28",
|
|
69
|
+
"jeopi-wire": "16.2.28",
|
|
70
|
+
"jeopi-snapcompact": "16.2.28",
|
|
70
71
|
"@opentelemetry/api": "^1.9.1",
|
|
71
72
|
"@opentelemetry/context-async-hooks": "^2.7.1",
|
|
72
73
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
/**
|
|
3
|
-
* Build the standalone share-viewer page the
|
|
3
|
+
* Build the standalone share-viewer page the jeopi relay serves at `GET /s/<id>`.
|
|
4
4
|
*
|
|
5
5
|
* Same template as HTML exports, but with no embedded session: share-loader.js
|
|
6
6
|
* (injected right after the empty #session-data tag) fetches the sealed blob
|
|
7
7
|
* (gist or relay store), decrypts it with the `#<key>` fragment in-browser, and
|
|
8
|
-
* hands the JSON to template.js via `window.
|
|
8
|
+
* hands the JSON to template.js via `window.__JEOPI_SESSION_DATA__`.
|
|
9
9
|
*
|
|
10
10
|
* The relay repo's build script runs this and embeds the output via go:embed.
|
|
11
11
|
*/
|
|
@@ -19,18 +19,18 @@ if (!outPath) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
const loaderJs = await Bun.file(new URL("../src/export/html/share-loader.js", import.meta.url).pathname).text();
|
|
22
|
-
// Pin the
|
|
22
|
+
// Pin the jeopi brand palette (collab-web pink/purple identity) — the viewer is
|
|
23
23
|
// a public artifact matching the live my.omp.sh client, not a per-user export
|
|
24
24
|
// that should mirror the host's terminal theme.
|
|
25
25
|
const themeVars = await generateThemeVars("web");
|
|
26
26
|
|
|
27
27
|
const html = getTemplate()
|
|
28
28
|
.replace("<theme-vars/>", () => `<style>:root { ${themeVars} }</style>`)
|
|
29
|
-
.replace("<title>Session Export</title>", () => "<title>
|
|
29
|
+
.replace("<title>Session Export</title>", () => "<title>jeopi session</title>")
|
|
30
30
|
.replace("{{SESSION_DATA}}</script>", () => `</script>\n <script>${loaderJs}</script>`);
|
|
31
31
|
|
|
32
32
|
if (html.includes("{{SESSION_DATA}}")) throw new Error("session-data placeholder survived substitution");
|
|
33
|
-
if (!html.includes("
|
|
33
|
+
if (!html.includes("__JEOPI_SESSION_DATA__")) throw new Error("share loader not injected");
|
|
34
34
|
|
|
35
35
|
await Bun.write(outPath, html);
|
|
36
36
|
console.log(`Generated ${path.resolve(outPath)} (${(html.length / 1024).toFixed(0)} KB)`);
|
package/scripts/jeopi
CHANGED
|
@@ -27,14 +27,14 @@ while [ -L "$self" ]; do
|
|
|
27
27
|
done
|
|
28
28
|
scripts_dir=$(CDPATH= cd -- "$(dirname -- "$self")" && pwd -P)
|
|
29
29
|
cli=$scripts_dir/../src/cli.ts
|
|
30
|
-
preload=$scripts_dir/
|
|
30
|
+
preload=$scripts_dir/jeopi-preload.ts
|
|
31
31
|
timing_preload=$scripts_dir/../../utils/src/module-timer.ts
|
|
32
32
|
|
|
33
|
-
launch_dir=${
|
|
33
|
+
launch_dir=${JEOPI_DEV_LAUNCH_DIR:-${HOME}/.jeopi/.dev-cwd}
|
|
34
34
|
mkdir -p "$launch_dir"
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
export
|
|
36
|
+
JEOPI_LAUNCH_CWD=$PWD
|
|
37
|
+
export JEOPI_LAUNCH_CWD
|
|
38
38
|
cd "$launch_dir"
|
|
39
39
|
if [ -n "${PI_TIMING:-}" ]; then
|
|
40
40
|
exec bun --preload "$preload" --preload "$timing_preload" "$cli" "$@"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Bun `--preload` shim for the
|
|
2
|
+
* Bun `--preload` shim for the jeopi dev launcher (`scripts/jeopi`).
|
|
3
3
|
*
|
|
4
4
|
* The launcher starts Bun from an empty, bunfig-free directory so a foreign
|
|
5
|
-
* project's `bunfig.toml` `preload` cannot run inside the
|
|
5
|
+
* project's `bunfig.toml` `preload` cannot run inside the jeopi CLI: Bun reads
|
|
6
6
|
* `bunfig.toml` from the *current working directory* on startup and evaluates
|
|
7
7
|
* its `preload` entries before the entrypoint, so a bun-shebang bin inherits
|
|
8
8
|
* whatever `preload` the directory you launched from declares (and crashes if
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
* imports run, so it restores the user's real working directory in time for
|
|
11
11
|
* import-time snapshots (e.g. `getProjectDir()` in `jeopi-utils/dirs`).
|
|
12
12
|
*/
|
|
13
|
-
const launchCwd = process.env.
|
|
13
|
+
const launchCwd = process.env.JEOPI_LAUNCH_CWD;
|
|
14
14
|
if (launchCwd) {
|
|
15
|
-
delete process.env.
|
|
15
|
+
delete process.env.JEOPI_LAUNCH_CWD;
|
|
16
16
|
try {
|
|
17
17
|
process.chdir(launchCwd);
|
|
18
18
|
} catch {}
|
|
@@ -1381,6 +1381,49 @@ describe("advisor", () => {
|
|
|
1381
1381
|
expect(strippedNotices).toHaveLength(1);
|
|
1382
1382
|
});
|
|
1383
1383
|
|
|
1384
|
+
it("never sends the literal reasoning_extraction-triggering label when the advisor's own model is Fable/Mythos (no refusal, no degrade)", async () => {
|
|
1385
|
+
const promptInputs: string[] = [];
|
|
1386
|
+
const strippedNotices: number[] = [];
|
|
1387
|
+
const agent: AdvisorAgent = {
|
|
1388
|
+
prompt: async input => {
|
|
1389
|
+
promptInputs.push(input);
|
|
1390
|
+
},
|
|
1391
|
+
abort: () => {},
|
|
1392
|
+
reset: () => {},
|
|
1393
|
+
state: { messages: [], model: { id: "claude-fable-5" } },
|
|
1394
|
+
};
|
|
1395
|
+
const thinking = "secret chain of thought the classifier flags";
|
|
1396
|
+
const messages: AgentMessage[] = [
|
|
1397
|
+
{ role: "user", content: "do the thing", timestamp: 1 } as AgentMessage,
|
|
1398
|
+
{
|
|
1399
|
+
role: "assistant",
|
|
1400
|
+
content: [
|
|
1401
|
+
{ type: "thinking", thinking },
|
|
1402
|
+
{ type: "text", text: "done" },
|
|
1403
|
+
],
|
|
1404
|
+
timestamp: 2,
|
|
1405
|
+
} as AgentMessage,
|
|
1406
|
+
];
|
|
1407
|
+
const host: AdvisorRuntimeHost = {
|
|
1408
|
+
snapshotMessages: () => messages,
|
|
1409
|
+
enqueueAdvice: () => {},
|
|
1410
|
+
notifyThinkingStripped: () => strippedNotices.push(1),
|
|
1411
|
+
};
|
|
1412
|
+
const runtime = new AdvisorRuntime(agent, host, 0);
|
|
1413
|
+
|
|
1414
|
+
runtime.onTurnEnd(messages);
|
|
1415
|
+
await runtime.waitForCatchup(5000, 1);
|
|
1416
|
+
|
|
1417
|
+
// Sent once, on the first attempt — the disguised form carries the
|
|
1418
|
+
// reasoning content but never the literal "_thinking:_" label, so
|
|
1419
|
+
// there is nothing for the classifier to catch and no degrade fires.
|
|
1420
|
+
expect(promptInputs).toHaveLength(1);
|
|
1421
|
+
expect(promptInputs[0]).not.toContain("_thinking:_");
|
|
1422
|
+
expect(promptInputs[0]).toContain(thinking);
|
|
1423
|
+
expect(strippedNotices).toHaveLength(0);
|
|
1424
|
+
expect(runtime.backlog).toBe(0);
|
|
1425
|
+
});
|
|
1426
|
+
|
|
1384
1427
|
it("skips the degrade path when thinking is disabled at construction and falls through to the watchdog", async () => {
|
|
1385
1428
|
const promptInputs: string[] = [];
|
|
1386
1429
|
const strippedNotices: number[] = [];
|
package/src/advisor/runtime.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface AdvisorAgent {
|
|
|
21
21
|
* turn `Agent.#runLoop` records on its internal state.
|
|
22
22
|
*/
|
|
23
23
|
rollbackTo?(count: number): void;
|
|
24
|
-
readonly state: { messages: AgentMessage[]; error?: string };
|
|
24
|
+
readonly state: { messages: AgentMessage[]; error?: string; model?: { id: string } };
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export interface AdvisorRuntimeHost {
|
|
@@ -116,7 +116,12 @@ export class AdvisorRuntime {
|
|
|
116
116
|
* `false` exactly once, the first time a classifier refusal is caught — see
|
|
117
117
|
* the `#drain` catch block. That single flip is sufficient to both change
|
|
118
118
|
* future renders AND guard against re-triggering the degrade path, so no
|
|
119
|
-
* separate one-shot flag is needed alongside it.
|
|
119
|
+
* separate one-shot flag is needed alongside it. When the render target is a
|
|
120
|
+
* Fable/Mythos model, {@link formatSessionHistoryMarkdown}'s
|
|
121
|
+
* `demoteThinkingForModelId` (wired from `agent.state.model.id` in
|
|
122
|
+
* {@link AdvisorRuntime.#renderDelta}) already disguises the rendered thinking
|
|
123
|
+
* before the first send, so this latch mainly guards other/unforeseen
|
|
124
|
+
* classifier triggers on the first turn.
|
|
120
125
|
*/
|
|
121
126
|
#includeThinking: boolean;
|
|
122
127
|
|
|
@@ -243,6 +248,7 @@ export class AdvisorRuntime {
|
|
|
243
248
|
const formattedDelta = obfuscator?.hasSecrets() ? obfuscateAdvisorDelta(obfuscator, delta) : delta;
|
|
244
249
|
const md = formatSessionHistoryMarkdown(formattedDelta, {
|
|
245
250
|
includeThinking: this.#includeThinking,
|
|
251
|
+
demoteThinkingForModelId: this.agent.state.model?.id,
|
|
246
252
|
includeToolIntent: true,
|
|
247
253
|
watchedRoles: true,
|
|
248
254
|
expandPrimaryContext: true,
|
package/src/commands/install.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* `jeopi install <target>` — top-level convenience over `jeopi plugin install` /
|
|
3
3
|
* `jeopi plugin link`.
|
|
4
4
|
*
|
|
5
|
-
* The docs (omp.
|
|
5
|
+
* The docs (docs/extensions.md, or `jeopi read omp://extensions.md`) advertise
|
|
6
6
|
*
|
|
7
7
|
* jeopi install ./my-extension
|
|
8
8
|
*
|
|
@@ -85,7 +85,7 @@ export async function createReportBundle(options: ReportBundleOptions): Promise<
|
|
|
85
85
|
await fs.mkdir(reportsDir, { recursive: true });
|
|
86
86
|
|
|
87
87
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
88
|
-
const outputPath = path.join(reportsDir, `
|
|
88
|
+
const outputPath = path.join(reportsDir, `jeopi-report-${timestamp}.tar.gz`);
|
|
89
89
|
|
|
90
90
|
const data: Record<string, string> = {};
|
|
91
91
|
const files: string[] = [];
|
package/src/debug/system-info.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import * as os from "node:os";
|
|
6
|
-
import { formatBytes, getProjectDir, VERSION } from "jeopi-utils";
|
|
6
|
+
import { APP_NAME, formatBytes, getProjectDir, VERSION } from "jeopi-utils";
|
|
7
7
|
|
|
8
8
|
export interface SystemInfo {
|
|
9
9
|
os: string;
|
|
@@ -86,7 +86,7 @@ export function formatSystemInfo(info: SystemInfo): string {
|
|
|
86
86
|
`CPU: ${info.cpu}`,
|
|
87
87
|
`Memory: ${formatBytes(info.memory.total)} (${formatBytes(info.memory.free)} free)`,
|
|
88
88
|
`Bun: ${info.versions.bun}`,
|
|
89
|
-
`App:
|
|
89
|
+
`App: ${APP_NAME} ${info.versions.app}`,
|
|
90
90
|
`Node: ${info.versions.node} (compat)`,
|
|
91
91
|
`CWD: ${info.cwd}`,
|
|
92
92
|
`Shell: ${info.shell}`,
|
package/src/discovery/builtin.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Builtin Provider (.jeopi)
|
|
3
3
|
*
|
|
4
|
-
* Primary provider for
|
|
4
|
+
* Primary provider for jeopi native configs. Supports all capabilities.
|
|
5
5
|
*/
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
import { YAML } from "bun";
|
|
@@ -36,8 +36,8 @@ import {
|
|
|
36
36
|
} from "./helpers";
|
|
37
37
|
|
|
38
38
|
const PROVIDER_ID = "native";
|
|
39
|
-
const DISPLAY_NAME = "
|
|
40
|
-
const DESCRIPTION = "Native
|
|
39
|
+
const DISPLAY_NAME = "jeopi";
|
|
40
|
+
const DESCRIPTION = "Native jeopi configuration from ~/.jeopi and .jeopi/";
|
|
41
41
|
const PRIORITY = 100;
|
|
42
42
|
|
|
43
43
|
const PATHS = SOURCE_PATHS.native;
|
|
@@ -375,7 +375,7 @@ async function loadRules(ctx: LoadContext): Promise<LoadResult<Rule>> {
|
|
|
375
375
|
}
|
|
376
376
|
|
|
377
377
|
// Top-level RULES.md is a sticky always-apply rule. Documented in
|
|
378
|
-
//
|
|
378
|
+
// docs/context-files.md (or `jeopi read omp://context-files.md`) as the file that gets "re-injected near
|
|
379
379
|
// the current turn so they keep hold across long conversations".
|
|
380
380
|
// User scope: ~/.jeopi/agent/RULES.md
|
|
381
381
|
// Project scope: nearest .jeopi/RULES.md walking up from cwd to repoRoot
|
package/src/discovery/helpers.ts
CHANGED
|
@@ -567,7 +567,7 @@ async function readExtensionModuleManifest(
|
|
|
567
567
|
* Discovery rules:
|
|
568
568
|
* 1. Direct files: `extensions/*.ts` or `*.js` → load
|
|
569
569
|
* 2. Subdirectory with index: `extensions/<ext>/index.ts` or `index.js` → load
|
|
570
|
-
* 3. Subdirectory with package.json: `extensions/<ext>/package.json` with "
|
|
570
|
+
* 3. Subdirectory with package.json: `extensions/<ext>/package.json` with "jeopi"/"pi" field → load declared paths
|
|
571
571
|
*
|
|
572
572
|
* No recursion beyond one level. Complex packages must use package.json manifest.
|
|
573
573
|
* Uses native glob for fast filesystem scanning with gitignore support.
|
|
@@ -940,7 +940,7 @@ export async function listClaudePluginRoots(
|
|
|
940
940
|
}
|
|
941
941
|
}
|
|
942
942
|
} else {
|
|
943
|
-
warnings.push(`Failed to parse
|
|
943
|
+
warnings.push(`Failed to parse jeopi plugin registry: ${ompRegistryPath}`);
|
|
944
944
|
}
|
|
945
945
|
}
|
|
946
946
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* jeopi extension-package sub-discovery provider.
|
|
3
3
|
*
|
|
4
4
|
* When a user configures an extension via `extensions:` (in settings) or
|
|
5
5
|
* `--extension`/`-e` (on the CLI), the docs promise that the package's
|
|
6
6
|
* sibling directories — `skills/`, `hooks/pre|post/`, `tools/`, `commands/`,
|
|
7
|
-
* `rules/`, `prompts/`, and `.mcp.json` — are picked up by
|
|
7
|
+
* `rules/`, `prompts/`, and `.mcp.json` — are picked up by jeopi's standard
|
|
8
8
|
* discovery surfaces. The native `jeopi` provider in `builtin.ts` only walks
|
|
9
9
|
* `.jeopi/` and `~/.jeopi/agent/`, so without this provider those sub-trees are
|
|
10
10
|
* silently ignored.
|
|
@@ -32,7 +32,7 @@ import { buildRuleFromMarkdown, createSourceMeta, loadFilesFromDir, scanSkillsFr
|
|
|
32
32
|
import { listOmpExtensionRoots, type OmpExtensionRoot } from "./omp-extension-roots";
|
|
33
33
|
|
|
34
34
|
const PROVIDER_ID = "omp-plugins";
|
|
35
|
-
const DISPLAY_NAME = "
|
|
35
|
+
const DISPLAY_NAME = "jeopi Extension Packages";
|
|
36
36
|
const DESCRIPTION =
|
|
37
37
|
"Sub-discovery (skills, hooks, tools, commands, rules, prompts, .mcp.json) inside extension packages";
|
|
38
38
|
const PRIORITY = 90;
|
package/src/discovery/ssh.ts
CHANGED
|
@@ -147,7 +147,7 @@ async function load(ctx: LoadContext): Promise<LoadResult<SSHHost>> {
|
|
|
147
147
|
registerProvider(sshCapability.id, {
|
|
148
148
|
id: PROVIDER_ID,
|
|
149
149
|
displayName: DISPLAY_NAME,
|
|
150
|
-
description: "Load SSH hosts from managed
|
|
150
|
+
description: "Load SSH hosts from managed jeopi paths and legacy ssh.json/.ssh.json files",
|
|
151
151
|
priority: 5,
|
|
152
152
|
load,
|
|
153
153
|
});
|
package/src/export/html/index.ts
CHANGED
|
@@ -39,7 +39,7 @@ export interface ExportOptions {
|
|
|
39
39
|
outputPath?: string;
|
|
40
40
|
/**
|
|
41
41
|
* Which color palette the export ships with.
|
|
42
|
-
* - `"web"` (default) — the
|
|
42
|
+
* - `"web"` (default) — the jeopi brand identity (collab-web pink/purple),
|
|
43
43
|
* so public HTML exports and the `/s/<id>` share viewer match the live
|
|
44
44
|
* `my.omp.sh` client. See `web-palette.ts`.
|
|
45
45
|
* - `"theme"` — derive from `themeName` (or the active TUI theme), preserving
|
|
@@ -120,7 +120,7 @@ function deriveExportColors(baseColor: string): { pageBg: string; cardBg: string
|
|
|
120
120
|
*
|
|
121
121
|
* Two call shapes:
|
|
122
122
|
* • `generateThemeVars("web" | "theme", themeName?)` — explicit palette.
|
|
123
|
-
* `"web"` (the default for public artifacts) returns the fixed
|
|
123
|
+
* `"web"` (the default for public artifacts) returns the fixed jeopi brand
|
|
124
124
|
* palette from `web-palette.ts` — collab-web pink/purple identity, shared
|
|
125
125
|
* with the live `my.omp.sh` client, so exports and the share viewer render
|
|
126
126
|
* identically to it. `"theme"` derives from the TUI theme via
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
// SHARE VIEWER BOOTSTRAP
|
|
6
6
|
// ============================================================
|
|
7
7
|
//
|
|
8
|
-
// Served by the
|
|
8
|
+
// Served by the jeopi relay at /s/<id>; the AES-256-GCM key rides in the
|
|
9
9
|
// URL fragment and never leaves the browser. Resolves the session JSON
|
|
10
|
-
// and hands it to template.js via `window.
|
|
10
|
+
// and hands it to template.js via `window.__JEOPI_SESSION_DATA__`:
|
|
11
11
|
// 1. hex ids -> secret GitHub gist holding base64(sealed blob)
|
|
12
12
|
// 2. anything else -> relay blob store at /s/<id>/raw
|
|
13
13
|
// Sealed layout: [12B IV][AES-256-GCM(gzip(session JSON))].
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
if (!res.ok) throw new Error('Gist fetch failed: HTTP ' + res.status);
|
|
37
37
|
var gist = await res.json();
|
|
38
38
|
var files = Object.values(gist.files || {});
|
|
39
|
-
var file = files.find(function(f) { return /\.
|
|
39
|
+
var file = files.find(function(f) { return /\.jeopishare\.txt$/.test(f.filename); }) || files[0];
|
|
40
40
|
if (!file) throw new Error('Gist has no files.');
|
|
41
41
|
var text = file.content;
|
|
42
42
|
if (!text || file.truncated) {
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
new Blob([plain]).stream().pipeThrough(new DecompressionStream('gzip'))
|
|
90
90
|
).json();
|
|
91
91
|
if (data && data.header && data.header.title) {
|
|
92
|
-
document.title = data.header.title + ' —
|
|
92
|
+
document.title = data.header.title + ' — jeopi session';
|
|
93
93
|
}
|
|
94
94
|
return data;
|
|
95
95
|
}
|
|
@@ -98,5 +98,5 @@
|
|
|
98
98
|
// template.js surfaces the failure in-page; swallow the duplicate here
|
|
99
99
|
// so the console does not report an unhandled rejection.
|
|
100
100
|
pending.catch(function() {});
|
|
101
|
-
window.
|
|
101
|
+
window.__JEOPI_SESSION_DATA__ = pending;
|
|
102
102
|
})();
|
|
@@ -697,9 +697,9 @@
|
|
|
697
697
|
margin-left: 10px;
|
|
698
698
|
}
|
|
699
699
|
|
|
700
|
-
/* Tool calls render inside the <
|
|
700
|
+
/* Tool calls render inside the <jeopi-tool-view> web component, which draws
|
|
701
701
|
its own card chrome; the host box collapses to a plain block. */
|
|
702
|
-
|
|
702
|
+
jeopi-tool-view.tool-execution {
|
|
703
703
|
display: block;
|
|
704
704
|
padding: 0;
|
|
705
705
|
background: none;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
//
|
|
8
8
|
// Two boot paths share this template:
|
|
9
9
|
// - Static export: session JSON rides base64-embedded in #session-data.
|
|
10
|
-
// - Share viewer: share-loader.js sets `window.
|
|
10
|
+
// - Share viewer: share-loader.js sets `window.__JEOPI_SESSION_DATA__` to
|
|
11
11
|
// a promise resolving to the session JSON (fetched + decrypted).
|
|
12
12
|
// The entire app lives in bootSession(); its body keeps the original
|
|
13
13
|
// one-level indentation to avoid a whole-file reindent.
|
|
@@ -721,13 +721,13 @@
|
|
|
721
721
|
// TOOL CALL RENDERING
|
|
722
722
|
// ============================================================
|
|
723
723
|
//
|
|
724
|
-
// Tool calls render through the bundled <
|
|
724
|
+
// Tool calls render through the bundled <jeopi-tool-view> web component
|
|
725
725
|
// (tool-views.generated.js — the same React renderers collab-web uses).
|
|
726
726
|
// Payloads are handed over via a global store keyed by data-key, which
|
|
727
727
|
// survives innerHTML serialization and cloneNode round trips.
|
|
728
728
|
|
|
729
729
|
const TOOL_VIEW_DATA = new Map();
|
|
730
|
-
globalThis.
|
|
730
|
+
globalThis.__JEOPI_TOOL_VIEW_DATA = TOOL_VIEW_DATA;
|
|
731
731
|
let toolViewSeq = 0;
|
|
732
732
|
|
|
733
733
|
function renderToolCall(call, sctx) {
|
|
@@ -743,7 +743,7 @@
|
|
|
743
743
|
openAgent: (id) => openSubSession(joinKey(sctx.prefix, id)),
|
|
744
744
|
},
|
|
745
745
|
});
|
|
746
|
-
return '<
|
|
746
|
+
return '<jeopi-tool-view class="tool-execution ' + statusClass + '" data-key="' + key + '" open></jeopi-tool-view>';
|
|
747
747
|
}
|
|
748
748
|
|
|
749
749
|
// ============================================================
|
|
@@ -1619,7 +1619,7 @@
|
|
|
1619
1619
|
messages.appendChild(div);
|
|
1620
1620
|
}
|
|
1621
1621
|
|
|
1622
|
-
const pending = window.
|
|
1622
|
+
const pending = window.__JEOPI_SESSION_DATA__;
|
|
1623
1623
|
if (pending && typeof pending.then === 'function') {
|
|
1624
1624
|
pending.then(bootSession, showLoadError);
|
|
1625
1625
|
} else {
|