@oh-my-pi/pi-coding-agent 15.7.1 → 15.7.3
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 +95 -6
- package/dist/types/auto-thinking/classifier.d.ts +35 -0
- package/dist/types/cli/args.d.ts +1 -1
- package/dist/types/cli/extension-flags.d.ts +36 -0
- package/dist/types/config/config-file.d.ts +4 -0
- package/dist/types/config/file-lock.d.ts +23 -0
- package/dist/types/config/keybindings.d.ts +2 -1
- package/dist/types/config/model-registry.d.ts +6 -0
- package/dist/types/config/settings-schema.d.ts +112 -69
- package/dist/types/edit/hashline/diff.d.ts +9 -3
- package/dist/types/eval/__tests__/agent-bridge.test.d.ts +1 -0
- package/dist/types/eval/__tests__/budget-bridge.test.d.ts +1 -0
- package/dist/types/eval/__tests__/idle-timeout.test.d.ts +1 -0
- package/dist/types/eval/agent-bridge.d.ts +25 -0
- package/dist/types/eval/backend.d.ts +17 -2
- package/dist/types/eval/budget-bridge.d.ts +29 -0
- package/dist/types/eval/idle-timeout.d.ts +28 -0
- package/dist/types/eval/js/executor.d.ts +8 -0
- package/dist/types/eval/js/tool-bridge.d.ts +2 -1
- package/dist/types/eval/py/executor.d.ts +13 -0
- package/dist/types/exec/bash-executor.d.ts +1 -0
- package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
- package/dist/types/extensibility/extensions/runner.d.ts +7 -0
- package/dist/types/extensibility/plugins/git-url.d.ts +11 -1
- package/dist/types/extensibility/plugins/manager.d.ts +12 -1
- package/dist/types/extensibility/shared-events.d.ts +2 -2
- package/dist/types/memory-backend/index.d.ts +1 -1
- package/dist/types/memory-backend/resolve.d.ts +1 -1
- package/dist/types/memory-backend/types.d.ts +3 -3
- package/dist/types/mnemopi/backend.d.ts +4 -0
- package/dist/types/mnemopi/config.d.ts +29 -0
- package/dist/types/mnemopi/state.d.ts +72 -0
- package/dist/types/modes/components/custom-editor.d.ts +2 -2
- package/dist/types/modes/components/model-selector.d.ts +3 -2
- package/dist/types/modes/components/omfg-panel.d.ts +19 -0
- package/dist/types/modes/controllers/command-controller.d.ts +7 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -3
- package/dist/types/modes/controllers/omfg-controller.d.ts +10 -0
- package/dist/types/modes/controllers/omfg-rule.d.ts +26 -0
- package/dist/types/modes/gradient-highlight.d.ts +5 -1
- package/dist/types/modes/interactive-mode.d.ts +7 -3
- package/dist/types/modes/magic-keywords.d.ts +14 -0
- package/dist/types/modes/markdown-prose.d.ts +27 -0
- package/dist/types/modes/orchestrate.d.ts +7 -2
- package/dist/types/modes/shared.d.ts +1 -1
- package/dist/types/modes/theme/theme.d.ts +2 -1
- package/dist/types/modes/turn-budget.d.ts +18 -0
- package/dist/types/modes/types.d.ts +7 -3
- package/dist/types/modes/ultrathink.d.ts +7 -2
- package/dist/types/modes/workflow.d.ts +15 -0
- package/dist/types/sdk.d.ts +15 -4
- package/dist/types/session/agent-session.d.ts +59 -23
- package/dist/types/session/session-manager.d.ts +18 -0
- package/dist/types/session/session-storage.d.ts +6 -0
- package/dist/types/session/shake-types.d.ts +24 -0
- package/dist/types/task/executor.d.ts +2 -2
- package/dist/types/thinking.d.ts +39 -1
- package/dist/types/tiny/device.d.ts +3 -3
- package/dist/types/tiny/models.d.ts +34 -1
- package/dist/types/tiny/title-protocol.d.ts +4 -0
- package/dist/types/tools/index.d.ts +19 -3
- package/dist/types/tools/memory-edit.d.ts +1 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
- package/package.json +10 -10
- package/src/auto-thinking/classifier.ts +180 -0
- package/src/autoresearch/tools/run-experiment.ts +45 -113
- package/src/cli/args.ts +39 -16
- package/src/cli/extension-flags.ts +48 -0
- package/src/cli/plugin-cli.ts +11 -2
- package/src/config/config-file.ts +98 -13
- package/src/config/file-lock.ts +60 -17
- package/src/config/keybindings.ts +78 -27
- package/src/config/model-registry.ts +7 -1
- package/src/config/settings-schema.ts +118 -71
- package/src/config/settings.ts +12 -0
- package/src/edit/hashline/diff.ts +87 -22
- package/src/edit/renderer.ts +16 -12
- package/src/edit/streaming.ts +17 -6
- package/src/eval/__tests__/agent-bridge.test.ts +433 -0
- package/src/eval/__tests__/budget-bridge.test.ts +69 -0
- package/src/eval/__tests__/idle-timeout.test.ts +66 -0
- package/src/eval/__tests__/shared-executors.test.ts +53 -0
- package/src/eval/agent-bridge.ts +295 -0
- package/src/eval/backend.ts +17 -2
- package/src/eval/budget-bridge.ts +48 -0
- package/src/eval/idle-timeout.ts +80 -0
- package/src/eval/js/executor.ts +35 -7
- package/src/eval/js/index.ts +2 -1
- package/src/eval/js/shared/local-module-loader.ts +75 -10
- package/src/eval/js/shared/prelude.txt +85 -1
- package/src/eval/js/tool-bridge.ts +9 -0
- package/src/eval/py/executor.ts +41 -14
- package/src/eval/py/index.ts +2 -1
- package/src/eval/py/prelude.py +132 -1
- package/src/exec/bash-executor.ts +2 -3
- package/src/extensibility/custom-tools/types.ts +2 -2
- package/src/extensibility/extensions/runner.ts +12 -2
- package/src/extensibility/plugins/git-url.ts +90 -4
- package/src/extensibility/plugins/manager.ts +103 -7
- package/src/extensibility/shared-events.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +88 -88
- package/src/main.ts +50 -56
- package/src/memory-backend/index.ts +1 -1
- package/src/memory-backend/resolve.ts +3 -3
- package/src/memory-backend/types.ts +3 -3
- package/src/{mnemosyne → mnemopi}/backend.ts +70 -70
- package/src/{mnemosyne → mnemopi}/config.ts +36 -36
- package/src/{mnemosyne → mnemopi}/state.ts +67 -67
- package/src/modes/acp/acp-agent.ts +13 -3
- package/src/modes/components/agent-dashboard.ts +6 -6
- package/src/modes/components/custom-editor.ts +4 -11
- package/src/modes/components/extensions/state-manager.ts +3 -4
- package/src/modes/components/footer.ts +18 -12
- package/src/modes/components/hook-selector.ts +86 -20
- package/src/modes/components/model-selector.ts +20 -11
- package/src/modes/components/oauth-selector.ts +93 -21
- package/src/modes/components/omfg-panel.ts +141 -0
- package/src/modes/components/settings-defs.ts +9 -2
- package/src/modes/components/settings-selector.ts +4 -1
- package/src/modes/components/status-line/segments.ts +13 -5
- package/src/modes/components/tips.txt +2 -1
- package/src/modes/components/tool-execution.ts +38 -19
- package/src/modes/components/tree-selector.ts +4 -3
- package/src/modes/components/user-message-selector.ts +94 -19
- package/src/modes/components/user-message.ts +8 -1
- package/src/modes/controllers/command-controller.ts +57 -0
- package/src/modes/controllers/event-controller.ts +65 -3
- package/src/modes/controllers/input-controller.ts +14 -11
- package/src/modes/controllers/omfg-controller.ts +283 -0
- package/src/modes/controllers/omfg-rule.ts +647 -0
- package/src/modes/controllers/selector-controller.ts +21 -6
- package/src/modes/gradient-highlight.ts +23 -6
- package/src/modes/interactive-mode.ts +41 -7
- package/src/modes/magic-keywords.ts +20 -0
- package/src/modes/markdown-prose.ts +247 -0
- package/src/modes/orchestrate.ts +17 -11
- package/src/modes/shared.ts +3 -11
- package/src/modes/theme/theme.ts +6 -0
- package/src/modes/turn-budget.ts +31 -0
- package/src/modes/types.ts +7 -1
- package/src/modes/ultrathink.ts +16 -10
- package/src/modes/utils/hotkeys-markdown.ts +1 -1
- package/src/modes/workflow.ts +42 -0
- package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
- package/src/prompts/system/auto-thinking-difficulty.md +12 -0
- package/src/prompts/system/omfg-user.md +51 -0
- package/src/prompts/system/system-prompt.md +1 -0
- package/src/prompts/system/workflow-notice.md +70 -0
- package/src/prompts/tools/eval.md +13 -1
- package/src/prompts/tools/memory-edit.md +1 -1
- package/src/sdk.ts +86 -38
- package/src/session/agent-session.ts +558 -80
- package/src/session/session-manager.ts +32 -0
- package/src/session/session-storage.ts +68 -8
- package/src/session/shake-types.ts +44 -0
- package/src/slash-commands/builtin-registry.ts +41 -16
- package/src/task/executor.ts +3 -3
- package/src/task/index.ts +6 -6
- package/src/thinking.ts +73 -1
- package/src/tiny/device.ts +4 -10
- package/src/tiny/models.ts +54 -2
- package/src/tiny/title-protocol.ts +11 -1
- package/src/tiny/worker.ts +19 -7
- package/src/tools/eval.ts +202 -26
- package/src/tools/grouped-file-output.ts +9 -2
- package/src/tools/index.ts +17 -5
- package/src/tools/memory-edit.ts +4 -4
- package/src/tools/memory-recall.ts +5 -5
- package/src/tools/memory-reflect.ts +5 -5
- package/src/tools/memory-retain.ts +4 -4
- package/src/tools/render-utils.ts +2 -1
- package/src/tools/search.ts +480 -76
- package/dist/types/mnemosyne/backend.d.ts +0 -4
- package/dist/types/mnemosyne/config.d.ts +0 -29
- package/dist/types/mnemosyne/state.d.ts +0 -72
- /package/dist/types/{mnemosyne → mnemopi}/index.d.ts +0 -0
- /package/src/{mnemosyne → mnemopi}/index.ts +0 -0
|
@@ -1837,6 +1837,12 @@ export class SessionManager {
|
|
|
1837
1837
|
premiumRequests: 0,
|
|
1838
1838
|
cost: 0,
|
|
1839
1839
|
} satisfies UsageStatistics;
|
|
1840
|
+
/** Per-turn output-token budget set by a `+Nk` directive (total null when none this turn). */
|
|
1841
|
+
#turnBudget: { total: number | null; hard: boolean } = { total: null, hard: false };
|
|
1842
|
+
/** Cumulative `output` snapshot captured when the current turn budget window opened. */
|
|
1843
|
+
#turnBaselineOutput = 0;
|
|
1844
|
+
/** Output tokens consumed by eval-spawned subagents in the current turn window. */
|
|
1845
|
+
#turnEvalOutput = 0;
|
|
1840
1846
|
#persistWriter: NdjsonFileWriter | undefined;
|
|
1841
1847
|
#persistWriterPath: string | undefined;
|
|
1842
1848
|
#persistChain: Promise<void> = Promise.resolve();
|
|
@@ -2397,6 +2403,32 @@ export class SessionManager {
|
|
|
2397
2403
|
return this.#usageStatistics;
|
|
2398
2404
|
}
|
|
2399
2405
|
|
|
2406
|
+
/**
|
|
2407
|
+
* Open a new per-turn budget window: snapshot the cumulative output baseline,
|
|
2408
|
+
* reset the eval-subagent counter, and set the (optional) ceiling. Called once
|
|
2409
|
+
* per real user message; `total` is null when no `+Nk` directive was present.
|
|
2410
|
+
*/
|
|
2411
|
+
beginTurnBudget(total: number | null, hard: boolean): void {
|
|
2412
|
+
this.#turnBudget = { total, hard };
|
|
2413
|
+
this.#turnBaselineOutput = this.#usageStatistics.output;
|
|
2414
|
+
this.#turnEvalOutput = 0;
|
|
2415
|
+
}
|
|
2416
|
+
|
|
2417
|
+
/** Record output tokens consumed by an eval-spawned subagent in the current turn. */
|
|
2418
|
+
recordEvalSubagentOutput(output: number): void {
|
|
2419
|
+
if (Number.isFinite(output) && output > 0) this.#turnEvalOutput += output;
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
/**
|
|
2423
|
+
* Current turn budget for the eval `budget` helper: the ceiling (null = none),
|
|
2424
|
+
* output tokens spent this turn (main loop + eval-spawned subagents, no
|
|
2425
|
+
* double-count), and whether the ceiling is hard.
|
|
2426
|
+
*/
|
|
2427
|
+
getTurnBudget(): { total: number | null; spent: number; hard: boolean } {
|
|
2428
|
+
const mainDelta = Math.max(0, this.#usageStatistics.output - this.#turnBaselineOutput);
|
|
2429
|
+
return { total: this.#turnBudget.total, spent: mainDelta + this.#turnEvalOutput, hard: this.#turnBudget.hard };
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2400
2432
|
getSessionDir(): string {
|
|
2401
2433
|
return this.sessionDir;
|
|
2402
2434
|
}
|
|
@@ -272,8 +272,8 @@ class MemorySessionStorageWriter implements SessionStorageWriter {
|
|
|
272
272
|
if (this.#closed) throw new Error("Writer closed");
|
|
273
273
|
if (this.#error) throw this.#error;
|
|
274
274
|
try {
|
|
275
|
-
|
|
276
|
-
this.#storage.
|
|
275
|
+
// O(1) chunked append — see MemorySessionStorage.appendChunkSync.
|
|
276
|
+
this.#storage.appendChunkSync(this.#path, line);
|
|
277
277
|
} catch (err) {
|
|
278
278
|
throw this.#recordError(err);
|
|
279
279
|
}
|
|
@@ -302,8 +302,26 @@ class MemorySessionStorageWriter implements SessionStorageWriter {
|
|
|
302
302
|
}
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
+
/**
|
|
306
|
+
* Mirror entry stored per path. Chunks accumulate via O(1) `push` on
|
|
307
|
+
* `appendChunkSync`; readers materialise into a single string lazily.
|
|
308
|
+
* `byteLen` is kept in sync so `statSync` is O(1) (and returns true UTF-8
|
|
309
|
+
* bytes, not character count).
|
|
310
|
+
*/
|
|
311
|
+
interface MirrorEntry {
|
|
312
|
+
chunks: string[];
|
|
313
|
+
byteLen: number;
|
|
314
|
+
mtimeMs: number;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function materialiseMirror(entry: MirrorEntry): string {
|
|
318
|
+
if (entry.chunks.length === 0) return "";
|
|
319
|
+
if (entry.chunks.length === 1) return entry.chunks[0];
|
|
320
|
+
return entry.chunks.join("");
|
|
321
|
+
}
|
|
322
|
+
|
|
305
323
|
export class MemorySessionStorage implements SessionStorage {
|
|
306
|
-
#files = new Map<string,
|
|
324
|
+
#files = new Map<string, MirrorEntry>();
|
|
307
325
|
|
|
308
326
|
ensureDirSync(_dir: string): void {
|
|
309
327
|
// No-op for in-memory storage.
|
|
@@ -314,20 +332,40 @@ export class MemorySessionStorage implements SessionStorage {
|
|
|
314
332
|
}
|
|
315
333
|
|
|
316
334
|
writeTextSync(path: string, content: string): void {
|
|
317
|
-
this.#files.set(path, {
|
|
335
|
+
this.#files.set(path, {
|
|
336
|
+
chunks: content.length === 0 ? [] : [content],
|
|
337
|
+
byteLen: Buffer.byteLength(content, "utf-8"),
|
|
338
|
+
mtimeMs: Date.now(),
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Internal O(1) append used by {@link MemorySessionStorageWriter}. Lazily
|
|
344
|
+
* creates the entry. External callers should go through `openWriter()`
|
|
345
|
+
* rather than touching the mirror directly.
|
|
346
|
+
*/
|
|
347
|
+
appendChunkSync(path: string, chunk: string): void {
|
|
348
|
+
let entry = this.#files.get(path);
|
|
349
|
+
if (!entry) {
|
|
350
|
+
entry = { chunks: [], byteLen: 0, mtimeMs: Date.now() };
|
|
351
|
+
this.#files.set(path, entry);
|
|
352
|
+
}
|
|
353
|
+
entry.chunks.push(chunk);
|
|
354
|
+
entry.byteLen += Buffer.byteLength(chunk, "utf-8");
|
|
355
|
+
entry.mtimeMs = Date.now();
|
|
318
356
|
}
|
|
319
357
|
|
|
320
358
|
readTextSync(path: string): string {
|
|
321
359
|
const entry = this.#files.get(path);
|
|
322
360
|
if (!entry) throw new Error(`File not found: ${path}`);
|
|
323
|
-
return entry
|
|
361
|
+
return materialiseMirror(entry);
|
|
324
362
|
}
|
|
325
363
|
|
|
326
364
|
statSync(path: string): SessionStorageStat {
|
|
327
365
|
const entry = this.#files.get(path);
|
|
328
366
|
if (!entry) throw new Error(`File not found: ${path}`);
|
|
329
367
|
return {
|
|
330
|
-
size: entry.
|
|
368
|
+
size: entry.byteLen,
|
|
331
369
|
mtimeMs: entry.mtimeMs,
|
|
332
370
|
mtime: new Date(entry.mtimeMs),
|
|
333
371
|
};
|
|
@@ -353,13 +391,35 @@ export class MemorySessionStorage implements SessionStorage {
|
|
|
353
391
|
readText(path: string): Promise<string> {
|
|
354
392
|
const entry = this.#files.get(path);
|
|
355
393
|
if (!entry) return Promise.reject(new Error(`File not found: ${path}`));
|
|
356
|
-
return Promise.resolve(entry
|
|
394
|
+
return Promise.resolve(materialiseMirror(entry));
|
|
357
395
|
}
|
|
358
396
|
|
|
359
397
|
readTextPrefix(path: string, maxBytes: number): Promise<string> {
|
|
360
398
|
const entry = this.#files.get(path);
|
|
361
399
|
if (!entry) return Promise.reject(new Error(`File not found: ${path}`));
|
|
362
|
-
|
|
400
|
+
if (entry.chunks.length === 0 || maxBytes <= 0) return Promise.resolve("");
|
|
401
|
+
|
|
402
|
+
// Walk chunks until the byte budget is exhausted. Avoids materialising
|
|
403
|
+
// the full mirror just to slice a prefix — bounded work for big files.
|
|
404
|
+
let accumulatedBytes = 0;
|
|
405
|
+
const out: string[] = [];
|
|
406
|
+
for (const chunk of entry.chunks) {
|
|
407
|
+
const chunkBytes = Buffer.byteLength(chunk, "utf-8");
|
|
408
|
+
if (accumulatedBytes + chunkBytes <= maxBytes) {
|
|
409
|
+
out.push(chunk);
|
|
410
|
+
accumulatedBytes += chunkBytes;
|
|
411
|
+
if (accumulatedBytes === maxBytes) break;
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
// Boundary chunk: slice in byte space and decode. Result MAY be
|
|
415
|
+
// shorter than the budget if a multi-byte codepoint straddles the
|
|
416
|
+
// boundary — matches `peekFile` semantics (partial decode at cap).
|
|
417
|
+
const remainingBytes = maxBytes - accumulatedBytes;
|
|
418
|
+
const utf8 = Buffer.from(chunk, "utf-8");
|
|
419
|
+
out.push(utf8Decoder.decode(utf8.subarray(0, remainingBytes)));
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
422
|
+
return Promise.resolve(out.join(""));
|
|
363
423
|
}
|
|
364
424
|
|
|
365
425
|
writeText(path: string, content: string): Promise<void> {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public shape of the `shake` operation, kept in a dependency-free leaf module
|
|
3
|
+
* so slash-command registries and controllers can import `formatShakeSummary`
|
|
4
|
+
* without pulling in the heavy `agent-session` module graph (which would form
|
|
5
|
+
* an import cycle through the slash-command registry).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Mode selector for `AgentSession.shake`. */
|
|
9
|
+
export type ShakeMode = "elide" | "summary" | "images";
|
|
10
|
+
|
|
11
|
+
/** Outcome of an `AgentSession.shake` run. */
|
|
12
|
+
export interface ShakeResult {
|
|
13
|
+
mode: ShakeMode;
|
|
14
|
+
/** Whole tool-call results dropped/compressed. */
|
|
15
|
+
toolResultsDropped: number;
|
|
16
|
+
/** Large fenced/XML blocks dropped/compressed. */
|
|
17
|
+
blocksDropped: number;
|
|
18
|
+
/** Image blocks removed (images mode only). */
|
|
19
|
+
imagesDropped?: number;
|
|
20
|
+
/** Estimated context tokens reclaimed. */
|
|
21
|
+
tokensFreed: number;
|
|
22
|
+
/** Session artifact holding the dropped originals, when persisted. */
|
|
23
|
+
artifactId?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** One-line operator summary of a {@link ShakeResult} (shared by TUI + ACP). */
|
|
27
|
+
export function formatShakeSummary(result: ShakeResult): string {
|
|
28
|
+
if (result.mode === "images") {
|
|
29
|
+
const n = result.imagesDropped ?? 0;
|
|
30
|
+
return n === 0
|
|
31
|
+
? "No images found in this session."
|
|
32
|
+
: `Dropped ${n} image${n === 1 ? "" : "s"} from this session.`;
|
|
33
|
+
}
|
|
34
|
+
const parts: string[] = [];
|
|
35
|
+
if (result.toolResultsDropped > 0) {
|
|
36
|
+
parts.push(`${result.toolResultsDropped} tool result${result.toolResultsDropped === 1 ? "" : "s"}`);
|
|
37
|
+
}
|
|
38
|
+
if (result.blocksDropped > 0) {
|
|
39
|
+
parts.push(`${result.blocksDropped} block${result.blocksDropped === 1 ? "" : "s"}`);
|
|
40
|
+
}
|
|
41
|
+
if (parts.length === 0) return "Nothing to shake.";
|
|
42
|
+
const verb = result.mode === "summary" ? "Compressed" : "Shook";
|
|
43
|
+
return `${verb} ${parts.join(" + ")} (~${result.tokensFreed} tokens freed).`;
|
|
44
|
+
}
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
} from "../extensibility/plugins/marketplace";
|
|
22
22
|
import { resolveMemoryBackend } from "../memory-backend";
|
|
23
23
|
import type { InteractiveModeContext } from "../modes/types";
|
|
24
|
+
import { formatShakeSummary, type ShakeMode } from "../session/shake-types";
|
|
24
25
|
import { getChangelogPath, parseChangelog } from "../utils/changelog";
|
|
25
26
|
import { buildContextReportText } from "./helpers/context-report";
|
|
26
27
|
import { formatDuration } from "./helpers/format";
|
|
@@ -57,6 +58,15 @@ const shutdownHandlerTui = (_command: ParsedSlashCommand, runtime: TuiSlashComma
|
|
|
57
58
|
return commandConsumed();
|
|
58
59
|
};
|
|
59
60
|
|
|
61
|
+
/** Parse the `/shake` subcommand into a {@link ShakeMode}; empty defaults to elide. */
|
|
62
|
+
function parseShakeMode(args: string): ShakeMode | { error: string } {
|
|
63
|
+
const verb = args.trim().toLowerCase();
|
|
64
|
+
if (verb === "" || verb === "elide") return "elide";
|
|
65
|
+
if (verb === "summary") return "summary";
|
|
66
|
+
if (verb === "images") return "images";
|
|
67
|
+
return { error: `Unknown /shake mode "${verb}". Use elide, summary, or images.` };
|
|
68
|
+
}
|
|
69
|
+
|
|
60
70
|
const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
61
71
|
{
|
|
62
72
|
name: "settings",
|
|
@@ -811,27 +821,31 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
811
821
|
},
|
|
812
822
|
},
|
|
813
823
|
{
|
|
814
|
-
name: "
|
|
815
|
-
description: "
|
|
816
|
-
acpDescription: "
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
+
name: "shake",
|
|
825
|
+
description: "Drop heavy content from context (tool results, large blocks)",
|
|
826
|
+
acpDescription: "Shake heavy content out of the conversation context",
|
|
827
|
+
subcommands: [
|
|
828
|
+
{ name: "elide", description: "Strip tool results + large blocks (default)" },
|
|
829
|
+
{ name: "summary", description: "Compress heavy regions with a local on-device model" },
|
|
830
|
+
{ name: "images", description: "Strip image blocks" },
|
|
831
|
+
],
|
|
832
|
+
acpInputHint: "[elide|summary|images]",
|
|
833
|
+
allowArgs: true,
|
|
834
|
+
handle: async (command, runtime) => {
|
|
835
|
+
const mode = parseShakeMode(command.args);
|
|
836
|
+
if (typeof mode !== "string") return usage(mode.error, runtime);
|
|
837
|
+
const result = await runtime.session.shake(mode);
|
|
838
|
+
await runtime.output(formatShakeSummary(result));
|
|
824
839
|
return commandConsumed();
|
|
825
840
|
},
|
|
826
|
-
handleTui: async (
|
|
841
|
+
handleTui: async (command, runtime) => {
|
|
827
842
|
runtime.ctx.editor.setText("");
|
|
828
|
-
const
|
|
829
|
-
if (
|
|
830
|
-
runtime.ctx.
|
|
843
|
+
const mode = parseShakeMode(command.args);
|
|
844
|
+
if (typeof mode !== "string") {
|
|
845
|
+
runtime.ctx.showWarning(mode.error);
|
|
831
846
|
return;
|
|
832
847
|
}
|
|
833
|
-
runtime.ctx.
|
|
834
|
-
runtime.ctx.showStatus(`Dropped ${removed} image${removed === 1 ? "" : "s"} from this session.`);
|
|
848
|
+
await runtime.ctx.handleShakeCommand(mode);
|
|
835
849
|
},
|
|
836
850
|
},
|
|
837
851
|
{
|
|
@@ -864,6 +878,17 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
864
878
|
await runtime.ctx.handleBtwCommand(question);
|
|
865
879
|
},
|
|
866
880
|
},
|
|
881
|
+
{
|
|
882
|
+
name: "omfg",
|
|
883
|
+
description: "Forge a TTSR rule from a complaint to stop a recurring behavior",
|
|
884
|
+
inlineHint: "<complaint>",
|
|
885
|
+
allowArgs: true,
|
|
886
|
+
handleTui: async (command, runtime) => {
|
|
887
|
+
const complaint = command.text.slice(`/${command.name}`.length).trim();
|
|
888
|
+
runtime.ctx.editor.setText("");
|
|
889
|
+
await runtime.ctx.handleOmfgCommand(complaint);
|
|
890
|
+
},
|
|
891
|
+
},
|
|
867
892
|
{
|
|
868
893
|
name: "retry",
|
|
869
894
|
description: "Retry the last failed agent turn",
|
package/src/task/executor.ts
CHANGED
|
@@ -21,7 +21,7 @@ import type { HindsightSessionState } from "../hindsight/state";
|
|
|
21
21
|
import type { LocalProtocolOptions } from "../internal-urls";
|
|
22
22
|
import { callTool } from "../mcp/client";
|
|
23
23
|
import type { MCPManager } from "../mcp/manager";
|
|
24
|
-
import type {
|
|
24
|
+
import type { MnemopiSessionState } from "../mnemopi/state";
|
|
25
25
|
import subagentSystemPromptTemplate from "../prompts/system/subagent-system-prompt.md" with { type: "text" };
|
|
26
26
|
import submitReminderTemplate from "../prompts/system/subagent-yield-reminder.md" with { type: "text" };
|
|
27
27
|
import { AgentRegistry } from "../registry/agent-registry";
|
|
@@ -186,7 +186,7 @@ export interface ExecutorOptions {
|
|
|
186
186
|
*/
|
|
187
187
|
parentArtifactManager?: ArtifactManager;
|
|
188
188
|
parentHindsightSessionState?: HindsightSessionState;
|
|
189
|
-
|
|
189
|
+
parentMnemopiSessionState?: MnemopiSessionState;
|
|
190
190
|
/** Parent agent's eval executor session id. Subagents reuse it so eval state is shared. */
|
|
191
191
|
parentEvalSessionId?: string;
|
|
192
192
|
/**
|
|
@@ -1245,7 +1245,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1245
1245
|
spawns: spawnsEnv,
|
|
1246
1246
|
taskDepth: childDepth,
|
|
1247
1247
|
parentHindsightSessionState: options.parentHindsightSessionState,
|
|
1248
|
-
|
|
1248
|
+
parentMnemopiSessionState: options.parentMnemopiSessionState,
|
|
1249
1249
|
parentTaskPrefix: id,
|
|
1250
1250
|
agentId: id,
|
|
1251
1251
|
agentDisplayName: agent.name,
|
package/src/task/index.ts
CHANGED
|
@@ -762,8 +762,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
762
762
|
const tempArtifactsDir = artifactsDir ? null : path.join(os.tmpdir(), `omp-task-${Snowflake.next()}`);
|
|
763
763
|
const effectiveArtifactsDir = artifactsDir || tempArtifactsDir!;
|
|
764
764
|
|
|
765
|
-
|
|
766
|
-
const localProtocolOptions: LocalProtocolOptions = {
|
|
765
|
+
const localProtocolOptions: LocalProtocolOptions = this.session.localProtocolOptions ?? {
|
|
767
766
|
getArtifactsDir: this.session.getArtifactsDir ?? (() => null),
|
|
768
767
|
getSessionId: this.session.getSessionId ?? (() => null),
|
|
769
768
|
};
|
|
@@ -864,6 +863,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
864
863
|
);
|
|
865
864
|
const promptTemplates = this.session.promptTemplates;
|
|
866
865
|
const parentEvalSessionId = this.session.getEvalSessionId?.() ?? undefined;
|
|
866
|
+
const mcpManager = this.session.mcpManager ?? MCPManager.instance();
|
|
867
867
|
|
|
868
868
|
// Initialize progress for all tasks
|
|
869
869
|
for (let i = 0; i < tasksWithUniqueIds.length; i++) {
|
|
@@ -921,7 +921,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
921
921
|
authStorage: this.session.authStorage,
|
|
922
922
|
modelRegistry: this.session.modelRegistry,
|
|
923
923
|
settings: this.session.settings,
|
|
924
|
-
mcpManager
|
|
924
|
+
mcpManager,
|
|
925
925
|
contextFiles,
|
|
926
926
|
skills: availableSkills,
|
|
927
927
|
autoloadSkills: resolvedAutoloadSkills,
|
|
@@ -930,7 +930,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
930
930
|
localProtocolOptions,
|
|
931
931
|
parentArtifactManager,
|
|
932
932
|
parentHindsightSessionState: this.session.getHindsightSessionState?.(),
|
|
933
|
-
|
|
933
|
+
parentMnemopiSessionState: this.session.getMnemopiSessionState?.(),
|
|
934
934
|
parentTelemetry: this.session.getTelemetry?.(),
|
|
935
935
|
parentEvalSessionId,
|
|
936
936
|
});
|
|
@@ -978,7 +978,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
978
978
|
authStorage: this.session.authStorage,
|
|
979
979
|
modelRegistry: this.session.modelRegistry,
|
|
980
980
|
settings: this.session.settings,
|
|
981
|
-
mcpManager
|
|
981
|
+
mcpManager,
|
|
982
982
|
contextFiles,
|
|
983
983
|
skills: availableSkills,
|
|
984
984
|
autoloadSkills: resolvedAutoloadSkills,
|
|
@@ -987,7 +987,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
987
987
|
localProtocolOptions,
|
|
988
988
|
parentArtifactManager,
|
|
989
989
|
parentHindsightSessionState: this.session.getHindsightSessionState?.(),
|
|
990
|
-
|
|
990
|
+
parentMnemopiSessionState: this.session.getMnemopiSessionState?.(),
|
|
991
991
|
parentTelemetry: this.session.getTelemetry?.(),
|
|
992
992
|
parentEvalSessionId,
|
|
993
993
|
});
|
package/src/thinking.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ResolvedThinkingLevel, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import { clampThinkingLevelForModel,
|
|
2
|
+
import { clampThinkingLevelForModel, Effort, getSupportedEfforts, type Model, THINKING_EFFORTS } from "@oh-my-pi/pi-ai";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Metadata used to render thinking selector values in the coding-agent UI.
|
|
@@ -85,3 +85,75 @@ export function resolveThinkingLevelForModel(
|
|
|
85
85
|
}
|
|
86
86
|
return clampThinkingLevelForModel(model, level);
|
|
87
87
|
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Sentinel selector for the coding-agent "auto" thinking mode. Kept entirely
|
|
91
|
+
* inside the coding-agent layer: it is never an {@link Effort} or
|
|
92
|
+
* {@link ThinkingLevel}, so provider mapping/clamping keeps seeing concrete
|
|
93
|
+
* efforts. The session resolves `auto` to a concrete effort each turn.
|
|
94
|
+
*/
|
|
95
|
+
export const AUTO_THINKING = "auto" as const;
|
|
96
|
+
|
|
97
|
+
/** A thinking selector as configured by the user — a concrete level or `auto`. */
|
|
98
|
+
export type ConfiguredThinkingLevel = ThinkingLevel | typeof AUTO_THINKING;
|
|
99
|
+
|
|
100
|
+
/** Metadata used to render the `auto` selector value alongside concrete levels. */
|
|
101
|
+
export interface ConfiguredThinkingLevelMetadata {
|
|
102
|
+
value: ConfiguredThinkingLevel;
|
|
103
|
+
label: string;
|
|
104
|
+
description: string;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const AUTO_THINKING_METADATA: ConfiguredThinkingLevelMetadata = {
|
|
108
|
+
value: AUTO_THINKING,
|
|
109
|
+
label: "auto",
|
|
110
|
+
description: "Auto-detect per prompt (low–xhigh)",
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Parses a configured thinking selector, accepting `auto` in addition to every
|
|
115
|
+
* value {@link parseThinkingLevel} accepts. {@link parseThinkingLevel} itself
|
|
116
|
+
* stays strict so model-suffix parsing (`model:high`) keeps rejecting `auto`.
|
|
117
|
+
*/
|
|
118
|
+
export function parseConfiguredThinkingLevel(value: string | null | undefined): ConfiguredThinkingLevel | undefined {
|
|
119
|
+
if (value === AUTO_THINKING) return AUTO_THINKING;
|
|
120
|
+
return parseThinkingLevel(value);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Returns display metadata for a configured selector, including `auto`. */
|
|
124
|
+
export function getConfiguredThinkingLevelMetadata(level: ConfiguredThinkingLevel): ConfiguredThinkingLevelMetadata {
|
|
125
|
+
return level === AUTO_THINKING ? AUTO_THINKING_METADATA : getThinkingLevelMetadata(level);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Resolves an auto-classified effort against the active model's supported
|
|
130
|
+
* range. Unlike {@link clampThinkingLevelForModel}, `auto` never resolves below
|
|
131
|
+
* {@link Effort.Low}: the eligible pool is the model's supported efforts at or
|
|
132
|
+
* above Low (falling back to the full supported set only when the model maxes
|
|
133
|
+
* out below Low). Within that pool the request snaps to the highest level not
|
|
134
|
+
* exceeding it, or the pool minimum when the request is below the pool.
|
|
135
|
+
*/
|
|
136
|
+
export function clampAutoThinkingEffort(model: Model | undefined, effort: Effort): Effort {
|
|
137
|
+
const supported = model ? getSupportedEfforts(model) : THINKING_EFFORTS;
|
|
138
|
+
if (supported.length === 0) return effort;
|
|
139
|
+
const lowIndex = THINKING_EFFORTS.indexOf(Effort.Low);
|
|
140
|
+
const eligible = supported.filter(level => THINKING_EFFORTS.indexOf(level) >= lowIndex);
|
|
141
|
+
const pool = eligible.length > 0 ? eligible : supported;
|
|
142
|
+
const requestedIndex = THINKING_EFFORTS.indexOf(effort);
|
|
143
|
+
let chosen = pool[0];
|
|
144
|
+
for (const candidate of pool) {
|
|
145
|
+
if (THINKING_EFFORTS.indexOf(candidate) > requestedIndex) break;
|
|
146
|
+
chosen = candidate;
|
|
147
|
+
}
|
|
148
|
+
return chosen;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The provisional concrete level shown while `auto` is configured but before a
|
|
153
|
+
* turn has been classified. Prefers the model's `defaultLevel`, otherwise High,
|
|
154
|
+
* clamped into the auto range. Returns `undefined` for non-reasoning models.
|
|
155
|
+
*/
|
|
156
|
+
export function resolveProvisionalAutoLevel(model: Model | undefined): Effort | undefined {
|
|
157
|
+
if (!model?.reasoning) return undefined;
|
|
158
|
+
return clampAutoThinkingEffort(model, model.thinking?.defaultLevel ?? Effort.High);
|
|
159
|
+
}
|
package/src/tiny/device.ts
CHANGED
|
@@ -27,12 +27,6 @@ const DEVICE_VALUES: Record<TinyModelDevice, true> = {
|
|
|
27
27
|
"webnn-cpu": true,
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
function defaultTinyModelDevice(): TinyModelDevice {
|
|
31
|
-
if (process.platform === "win32") return "dml";
|
|
32
|
-
if (process.platform === "linux" && process.arch === "x64") return "cuda";
|
|
33
|
-
return CPU_DEVICE;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
30
|
function usesDarwinWorkerWebGpu(device: TinyModelDevice): boolean {
|
|
37
31
|
return process.platform === "darwin" && (device === "gpu" || device === "webgpu" || device === "auto");
|
|
38
32
|
}
|
|
@@ -51,7 +45,7 @@ export function resolveTinyModelDevicePreference(
|
|
|
51
45
|
value: string | undefined = $env.PI_TINY_DEVICE,
|
|
52
46
|
): TinyModelDevicePreference {
|
|
53
47
|
return {
|
|
54
|
-
device: normalizeTinyModelDevice(value) ??
|
|
48
|
+
device: normalizeTinyModelDevice(value) ?? CPU_DEVICE,
|
|
55
49
|
raw: value,
|
|
56
50
|
};
|
|
57
51
|
}
|
|
@@ -62,7 +56,7 @@ export function tinyModelDeviceLoadOrder(preference: TinyModelDevicePreference):
|
|
|
62
56
|
return [preference.device, CPU_DEVICE];
|
|
63
57
|
}
|
|
64
58
|
|
|
65
|
-
/** Sentinel `providers.tinyModelDevice` value meaning "use the built-in
|
|
59
|
+
/** Sentinel `providers.tinyModelDevice` value meaning "use the built-in CPU default". */
|
|
66
60
|
export const TINY_MODEL_DEVICE_DEFAULT = "default";
|
|
67
61
|
|
|
68
62
|
/** Accepted values for the `providers.tinyModelDevice` setting (validation + UI). */
|
|
@@ -85,7 +79,7 @@ export const TINY_MODEL_DEVICE_SETTING_VALUES = [
|
|
|
85
79
|
|
|
86
80
|
/** Submenu metadata for the `providers.tinyModelDevice` setting. */
|
|
87
81
|
export const TINY_MODEL_DEVICE_SETTING_OPTIONS = [
|
|
88
|
-
{ value: "default", label: "Default", description: "
|
|
82
|
+
{ value: "default", label: "Default", description: "CPU-only inference" },
|
|
89
83
|
{ value: "gpu", label: "GPU", description: "Accelerated provider (WebGPU/Metal, CUDA, or DirectML)" },
|
|
90
84
|
{ value: "cpu", label: "CPU", description: "CPU-only inference" },
|
|
91
85
|
{ value: "metal", label: "Metal", description: "WebGPU alias for Apple GPUs" },
|
|
@@ -108,7 +102,7 @@ export const TINY_MODEL_DEVICE_SETTING_OPTIONS = [
|
|
|
108
102
|
/**
|
|
109
103
|
* Map a `providers.tinyModelDevice` setting value onto a `PI_TINY_DEVICE` env
|
|
110
104
|
* value for the worker. Returns `undefined` for the default sentinel so the
|
|
111
|
-
* worker keeps its built-in
|
|
105
|
+
* worker keeps its built-in CPU default; the worker still validates the
|
|
112
106
|
* forwarded value via {@link normalizeTinyModelDevice}.
|
|
113
107
|
*/
|
|
114
108
|
export function tinyModelDeviceSettingToEnv(value: string | undefined): string | undefined {
|
package/src/tiny/models.ts
CHANGED
|
@@ -108,7 +108,7 @@ export const ONLINE_MEMORY_MODEL_KEY = "online";
|
|
|
108
108
|
export const DEFAULT_MEMORY_LOCAL_MODEL_KEY = "qwen3-1.7b";
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
|
-
* Local models for
|
|
111
|
+
* Local models for Mnemopi memory tasks (fact extraction + consolidation).
|
|
112
112
|
* These are larger (1B-1.7B) than the title models: structured extraction and
|
|
113
113
|
* faithful summarization need more capacity than 3-6 word titles. All q4.
|
|
114
114
|
* Ranking/recipe rationale lives in docs/local-models.md.
|
|
@@ -177,7 +177,7 @@ export const TINY_MEMORY_MODEL_OPTIONS = [
|
|
|
177
177
|
value: ONLINE_MEMORY_MODEL_KEY,
|
|
178
178
|
label: "Online (smol/remote)",
|
|
179
179
|
description:
|
|
180
|
-
"Use the configured
|
|
180
|
+
"Use the configured Mnemopi LLM mode (smol or remote); no local model download or on-device inference.",
|
|
181
181
|
},
|
|
182
182
|
...TINY_MEMORY_LOCAL_MODELS.map(model => ({
|
|
183
183
|
value: model.key,
|
|
@@ -196,6 +196,34 @@ export function getTinyMemoryModelSpec(key: TinyMemoryLocalModelKey): (typeof TI
|
|
|
196
196
|
return spec;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Shake-summary models. Shake's `summary` mode (and the `shake-summary`
|
|
201
|
+
* compaction strategy) compress heavy regions strictly on-device — there is no
|
|
202
|
+
* online/remote option, so this registry reuses the local memory models only.
|
|
203
|
+
*/
|
|
204
|
+
export const SHAKE_SUMMARY_MODEL_VALUES = [
|
|
205
|
+
"qwen3-1.7b",
|
|
206
|
+
"gemma-3-1b",
|
|
207
|
+
"qwen2.5-1.5b",
|
|
208
|
+
"lfm2-1.2b",
|
|
209
|
+
] as const satisfies readonly TinyMemoryLocalModelKey[];
|
|
210
|
+
|
|
211
|
+
export type ShakeSummaryModelKey = (typeof SHAKE_SUMMARY_MODEL_VALUES)[number];
|
|
212
|
+
|
|
213
|
+
// Guard: every local memory model is offered for shake summary (catches drift).
|
|
214
|
+
type MissingShakeSummaryValue = Exclude<TinyMemoryLocalModelKey, ShakeSummaryModelKey>;
|
|
215
|
+
const SHAKE_SUMMARY_MODEL_VALUES_MATCH_REGISTRY: MissingShakeSummaryValue extends never ? true : never = true;
|
|
216
|
+
void SHAKE_SUMMARY_MODEL_VALUES_MATCH_REGISTRY;
|
|
217
|
+
|
|
218
|
+
export const SHAKE_SUMMARY_MODEL_OPTIONS = TINY_MEMORY_LOCAL_MODELS.map(model => ({
|
|
219
|
+
value: model.key,
|
|
220
|
+
label: model.label,
|
|
221
|
+
description: model.description,
|
|
222
|
+
})) satisfies ReadonlyArray<{ value: ShakeSummaryModelKey; label: string; description: string }>;
|
|
223
|
+
|
|
224
|
+
/** Default shake-summary local model when none is named. */
|
|
225
|
+
export const DEFAULT_SHAKE_SUMMARY_MODEL_KEY: ShakeSummaryModelKey = DEFAULT_MEMORY_LOCAL_MODEL_KEY;
|
|
226
|
+
|
|
199
227
|
/** Any local model key (title or memory), used by the shared inference worker. */
|
|
200
228
|
export type TinyLocalModelKey = TinyTitleLocalModelKey | TinyMemoryLocalModelKey;
|
|
201
229
|
|
|
@@ -216,3 +244,27 @@ export const TINY_LOCAL_MODELS = [
|
|
|
216
244
|
...TINY_TITLE_LOCAL_MODELS,
|
|
217
245
|
...TINY_MEMORY_LOCAL_MODELS,
|
|
218
246
|
] as const satisfies readonly TinyTitleLocalModelSpec[];
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Difficulty-classifier model for the `auto` thinking level. Defaults to the
|
|
250
|
+
* online smol path; the local options reuse the memory-model registry because
|
|
251
|
+
* the shared worker's `complete()` only accepts memory local keys, and the
|
|
252
|
+
* 1B+ memory models classify coding difficulty far more reliably than the
|
|
253
|
+
* sub-1B title models.
|
|
254
|
+
*/
|
|
255
|
+
export const ONLINE_AUTO_THINKING_MODEL_KEY = ONLINE_MEMORY_MODEL_KEY;
|
|
256
|
+
export const AUTO_THINKING_MODEL_VALUES = TINY_MEMORY_MODEL_VALUES;
|
|
257
|
+
export type AutoThinkingModelKey = TinyMemoryModelKey;
|
|
258
|
+
|
|
259
|
+
export const AUTO_THINKING_MODEL_OPTIONS = [
|
|
260
|
+
{
|
|
261
|
+
value: ONLINE_AUTO_THINKING_MODEL_KEY,
|
|
262
|
+
label: "Online (smol)",
|
|
263
|
+
description: "Classify prompt difficulty with the online smol model; no local download or on-device inference.",
|
|
264
|
+
},
|
|
265
|
+
...TINY_MEMORY_LOCAL_MODELS.map(model => ({
|
|
266
|
+
value: model.key,
|
|
267
|
+
label: model.label,
|
|
268
|
+
description: model.description,
|
|
269
|
+
})),
|
|
270
|
+
] satisfies ReadonlyArray<{ value: AutoThinkingModelKey; label: string; description: string }>;
|
|
@@ -30,7 +30,17 @@ export interface TinyTitleProgressEvent {
|
|
|
30
30
|
export type TinyTitleWorkerInbound =
|
|
31
31
|
| { type: "ping"; id: string }
|
|
32
32
|
| { type: "generate"; id: string; modelKey: TinyTitleLocalModelKey; message: string }
|
|
33
|
-
| {
|
|
33
|
+
| {
|
|
34
|
+
type: "complete";
|
|
35
|
+
id: string;
|
|
36
|
+
modelKey: TinyLocalModelKey;
|
|
37
|
+
prompt: string;
|
|
38
|
+
maxTokens?: number;
|
|
39
|
+
/** Optional assistant-turn prefix appended after the generation prompt to pin output format. */
|
|
40
|
+
prefill?: string;
|
|
41
|
+
/** Optional literal stop string; generation halts once it appears in the decoded tail. */
|
|
42
|
+
stop?: string;
|
|
43
|
+
}
|
|
34
44
|
| { type: "download"; id: string; modelKey: TinyLocalModelKey }
|
|
35
45
|
| { type: "close" };
|
|
36
46
|
|