@daniel156161/prism 0.2.78 → 0.2.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pi/pi-env.d.ts +1 -1
- package/dist/pi/pi-env.js +1 -1
- package/dist/pi/pi-patch-interactive.js +8 -5
- package/dist/pi/pi-patch-interactive.js.map +1 -1
- package/dist/prism-extensions/integrations/ai-memory-errors.d.ts +16 -0
- package/dist/prism-extensions/integrations/ai-memory-errors.js +52 -0
- package/dist/prism-extensions/integrations/ai-memory-errors.js.map +1 -0
- package/dist/prism-extensions/integrations/ai-memory-system.d.ts +3 -0
- package/dist/prism-extensions/integrations/ai-memory-system.js +175 -15
- package/dist/prism-extensions/integrations/ai-memory-system.js.map +1 -1
- package/dist/prism-extensions/integrations/research-tools.js +3 -3
- package/dist/prism-extensions/integrations/research-tools.js.map +1 -1
- package/dist/prism-extensions/integrations/youtube.d.ts +2 -2
- package/dist/prism-extensions/integrations/youtube.js +6 -7
- package/dist/prism-extensions/integrations/youtube.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/README.md +4 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +5 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +3 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +6 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/README.md +8 -1
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-individual.json +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-individual.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-individual.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-individual.js +15 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-individual.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-individual.models.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-individual.models.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-individual.models.js +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-individual.models.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-client/CHANGELOG.md +1 -1
- package/node_modules/@earendil-works/pi-client/package.json +2 -2
- package/node_modules/@earendil-works/pi-coding-agent/CHANGELOG.md +31 -2
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js +3 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/auth-check.d.ts +19 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/auth-check.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/auth-check.js +50 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/auth-check.js.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/auth-command.d.ts +24 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/auth-command.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/auth-command.js +102 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/auth-command.js.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/credential-print.d.ts +4 -14
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/credential-print.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/credential-print.js +38 -79
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/credential-print.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/auth-storage.js +78 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts +5 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/keybindings.d.ts +8 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/keybindings.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-runtime.d.ts +2 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-runtime.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-runtime.js +3 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-runtime.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.d.ts +4 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js +6 -4
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.d.ts +4 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js +11 -7
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.d.ts +4 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js +5 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.d.ts +4 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js +5 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.d.ts +4 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js +5 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.d.ts +4 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js +6 -2
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.d.ts +4 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js +6 -2
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/main.js +57 -21
- package/node_modules/@earendil-works/pi-coding-agent/dist/main.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +234 -2561
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.js +11 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/server/create-harness.d.ts +26 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/server/create-harness.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/server/create-harness.js +104 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/server/create-harness.js.map +1 -0
- package/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md +3 -2
- package/node_modules/@earendil-works/pi-coding-agent/docs/keybindings.md +9 -5
- package/node_modules/@earendil-works/pi-coding-agent/docs/providers.md +8 -1
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/gondolin/package-lock.json +2 -2
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/gondolin/package.json +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/sandbox/package-lock.json +2 -2
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/sandbox/package.json +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/with-deps/package-lock.json +2 -2
- package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/with-deps/package.json +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/package.json +7 -7
- package/node_modules/@earendil-works/pi-protocol/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/keybindings.d.ts +10 -0
- package/node_modules/@earendil-works/pi-tui/dist/keybindings.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/keybindings.js +8 -0
- package/node_modules/@earendil-works/pi-tui/dist/keybindings.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/latex.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/latex.js +188 -48
- package/node_modules/@earendil-works/pi-tui/dist/latex.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.d.ts +12 -0
- package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js +146 -12
- package/node_modules/@earendil-works/pi-tui/dist/tui-alt-screen.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/child_process.d.ts +0 -1
- package/node_modules/@types/node/crypto.d.ts +6 -6
- package/node_modules/@types/node/dns/promises.d.ts +5 -5
- package/node_modules/@types/node/dns.d.ts +5 -5
- package/node_modules/@types/node/fs.d.ts +7 -0
- package/node_modules/@types/node/http.d.ts +30 -0
- package/node_modules/@types/node/http2.d.ts +4 -4
- package/node_modules/@types/node/os.d.ts +30 -30
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/@types/node/perf_hooks.d.ts +2 -1
- package/node_modules/@types/node/process.d.ts +42 -43
- package/node_modules/@types/node/quic.d.ts +1049 -84
- package/node_modules/@types/node/sqlite.d.ts +14 -1
- package/node_modules/@types/node/stream/iter.d.ts +3 -2
- package/node_modules/@types/node/test.d.ts +61 -0
- package/node_modules/@types/node/v8.d.ts +20 -23
- package/package.json +6 -6
- package/src/prism-extensions/integrations/ai-memory-errors.ts +53 -0
- package/src/prism-extensions/integrations/ai-memory-system.ts +179 -15
- package/src/prism-extensions/integrations/research-tools.ts +3 -3
- package/src/prism-extensions/integrations/youtube.ts +6 -6
|
@@ -298,10 +298,23 @@ declare module "node:sqlite" {
|
|
|
298
298
|
* Loads a shared library into the database connection. This method is a wrapper
|
|
299
299
|
* around [`sqlite3_load_extension()`](https://www.sqlite.org/c3ref/load_extension.html). It is required to enable the
|
|
300
300
|
* `allowExtension` option when constructing the `DatabaseSync` instance.
|
|
301
|
+
*
|
|
302
|
+
* ```js
|
|
303
|
+
* import { DatabaseSync } from 'node:sqlite';
|
|
304
|
+
* const database = new DatabaseSync(':memory:', { allowExtension: true });
|
|
305
|
+
*
|
|
306
|
+
* // Load using the entry point derived from the filename.
|
|
307
|
+
* database.loadExtension('./decimal.dylib');
|
|
308
|
+
*
|
|
309
|
+
* // Override the entry point when the derived name does not match.
|
|
310
|
+
* database.loadExtension('./base64.dylib', 'sqlite3_base64_init');
|
|
301
311
|
* @since v22.13.0
|
|
302
312
|
* @param path The path to the shared library to load.
|
|
313
|
+
* @param entryPoint The name of the extension's entry-point function. When
|
|
314
|
+
* omitted, SQLite derives the entry point from the shared library's filename;
|
|
315
|
+
* pass this argument explicitly when the derived name does not match.
|
|
303
316
|
*/
|
|
304
|
-
loadExtension(path: string): void;
|
|
317
|
+
loadExtension(path: string, entryPoint?: string): void;
|
|
305
318
|
/**
|
|
306
319
|
* Enables or disables the `loadExtension` SQL function, and the `loadExtension()`
|
|
307
320
|
* method. When `allowExtension` is `false` when constructing, you cannot enable
|
|
@@ -311,8 +311,9 @@ declare module "node:stream/iter" {
|
|
|
311
311
|
* return `false` or `-1`, deferring to the async path. The per-write
|
|
312
312
|
* `options.signal` parameter from the Writer interface is also ignored.
|
|
313
313
|
*
|
|
314
|
-
* The result is cached per instance
|
|
315
|
-
*
|
|
314
|
+
* The result is cached per instance and backpressure policy -- calling
|
|
315
|
+
* `fromWritable()` twice with the same stream and `backpressure` option returns
|
|
316
|
+
* the same Writer.
|
|
316
317
|
*
|
|
317
318
|
* For duck-typed streams that do not expose `writableHighWaterMark`,
|
|
318
319
|
* `writableLength`, or similar properties, sensible defaults are used.
|
|
@@ -264,6 +264,15 @@ declare module "node:test" {
|
|
|
264
264
|
* @since v22.1.0
|
|
265
265
|
*/
|
|
266
266
|
testSkipPatterns?: string | RegExp | ReadonlyArray<string | RegExp> | undefined;
|
|
267
|
+
/**
|
|
268
|
+
* A tag name, or an array of tag names,
|
|
269
|
+
* used to filter tests by their declared tags. Tests must contain every
|
|
270
|
+
* listed tag to run. Equivalent to passing `--experimental-test-tag-filter`
|
|
271
|
+
* on the command line. See [Test tags](https://nodejs.org/docs/latest-v26.x/api/test.html#test-tags).
|
|
272
|
+
* @default undefined
|
|
273
|
+
* @since v26.2.0
|
|
274
|
+
*/
|
|
275
|
+
testTagFilters?: string | readonly string[] | undefined;
|
|
267
276
|
/**
|
|
268
277
|
* The number of milliseconds after which the test execution will fail.
|
|
269
278
|
* If unspecified, subtests inherit this value from their parent.
|
|
@@ -668,6 +677,12 @@ declare module "node:test" {
|
|
|
668
677
|
* The nesting level of the test.
|
|
669
678
|
*/
|
|
670
679
|
nesting: number;
|
|
680
|
+
/**
|
|
681
|
+
* The flattened lowercased tags declared on the test
|
|
682
|
+
* and its ancestor suites, in declaration order. Empty for untagged tests.
|
|
683
|
+
* See [Test tags](https://nodejs.org/docs/latest-v26.x/api/test.html#test-tags).
|
|
684
|
+
*/
|
|
685
|
+
tags: string[];
|
|
671
686
|
/**
|
|
672
687
|
* A numeric identifier for this test instance, unique
|
|
673
688
|
* within the test file's process. Consistent across all events for the same
|
|
@@ -696,6 +711,12 @@ declare module "node:test" {
|
|
|
696
711
|
* The nesting level of the test.
|
|
697
712
|
*/
|
|
698
713
|
nesting: number;
|
|
714
|
+
/**
|
|
715
|
+
* The flattened lowercased tags declared on the test
|
|
716
|
+
* and its ancestor suites, in declaration order. Empty for untagged tests.
|
|
717
|
+
* See [Test tags](https://nodejs.org/docs/latest-v26.x/api/test.html#test-tags).
|
|
718
|
+
*/
|
|
719
|
+
tags: string[];
|
|
699
720
|
/**
|
|
700
721
|
* A numeric identifier for this test instance, unique
|
|
701
722
|
* within the test file's process. Consistent across all events for the same
|
|
@@ -717,6 +738,12 @@ declare module "node:test" {
|
|
|
717
738
|
* The nesting level of the test.
|
|
718
739
|
*/
|
|
719
740
|
nesting: number;
|
|
741
|
+
/**
|
|
742
|
+
* The flattened lowercased tags declared on the test
|
|
743
|
+
* and its ancestor suites, in declaration order. Empty for untagged tests.
|
|
744
|
+
* See [Test tags](https://nodejs.org/docs/latest-v26.x/api/test.html#test-tags).
|
|
745
|
+
*/
|
|
746
|
+
tags: string[];
|
|
720
747
|
/**
|
|
721
748
|
* A numeric identifier for this test instance, unique
|
|
722
749
|
* within the test file's process. Consistent across all events for the same
|
|
@@ -762,6 +789,12 @@ declare module "node:test" {
|
|
|
762
789
|
* The nesting level of the test.
|
|
763
790
|
*/
|
|
764
791
|
nesting: number;
|
|
792
|
+
/**
|
|
793
|
+
* The flattened lowercased tags declared on the test
|
|
794
|
+
* and its ancestor suites, in declaration order. Empty for untagged tests.
|
|
795
|
+
* See [Test tags](https://nodejs.org/docs/latest-v26.x/api/test.html#test-tags).
|
|
796
|
+
*/
|
|
797
|
+
tags: string[];
|
|
765
798
|
/**
|
|
766
799
|
* A numeric identifier for this test instance, unique
|
|
767
800
|
* within the test file's process. Consistent across all events for the same
|
|
@@ -823,6 +856,12 @@ declare module "node:test" {
|
|
|
823
856
|
* The nesting level of the test.
|
|
824
857
|
*/
|
|
825
858
|
nesting: number;
|
|
859
|
+
/**
|
|
860
|
+
* The flattened lowercased tags declared on the test
|
|
861
|
+
* and its ancestor suites, in declaration order. Empty for untagged tests.
|
|
862
|
+
* See [Test tags](https://nodejs.org/docs/latest-v26.x/api/test.html#test-tags).
|
|
863
|
+
*/
|
|
864
|
+
tags: string[];
|
|
826
865
|
/**
|
|
827
866
|
* A numeric identifier for this test instance, unique
|
|
828
867
|
* within the test file's process. Consistent across all events for the same
|
|
@@ -861,6 +900,12 @@ declare module "node:test" {
|
|
|
861
900
|
* The nesting level of the test.
|
|
862
901
|
*/
|
|
863
902
|
nesting: number;
|
|
903
|
+
/**
|
|
904
|
+
* The flattened lowercased tags declared on the test
|
|
905
|
+
* and its ancestor suites, in declaration order. Empty for untagged tests.
|
|
906
|
+
* See [Test tags](https://nodejs.org/docs/latest-v26.x/api/test.html#test-tags).
|
|
907
|
+
*/
|
|
908
|
+
tags: string[];
|
|
864
909
|
/**
|
|
865
910
|
* A numeric identifier for this test instance, unique
|
|
866
911
|
* within the test file's process. Consistent across all events for the same
|
|
@@ -1082,6 +1127,13 @@ declare module "node:test" {
|
|
|
1082
1127
|
* @since v21.7.0, v20.12.0
|
|
1083
1128
|
*/
|
|
1084
1129
|
readonly attempt: number;
|
|
1130
|
+
/**
|
|
1131
|
+
* A frozen array of the test's flattened lowercased tags, in declaration
|
|
1132
|
+
* order, including any tags inherited from ancestor suites. Empty when the
|
|
1133
|
+
* test has no tags. See [Test tags](https://nodejs.org/docs/latest-v26.x/api/test.html#test-tags).
|
|
1134
|
+
* @since v26.2.0
|
|
1135
|
+
*/
|
|
1136
|
+
readonly tags: readonly string[];
|
|
1085
1137
|
/**
|
|
1086
1138
|
* The unique identifier of the worker running the current test file. This value is
|
|
1087
1139
|
* derived from the `NODE_TEST_WORKER_ID` environment variable. When running tests
|
|
@@ -1443,6 +1495,15 @@ declare module "node:test" {
|
|
|
1443
1495
|
* @default false
|
|
1444
1496
|
*/
|
|
1445
1497
|
skip?: boolean | string | undefined;
|
|
1498
|
+
/**
|
|
1499
|
+
* An array of string labels associated with the test.
|
|
1500
|
+
* Used together with `--experimental-test-tag-filter` to filter which
|
|
1501
|
+
* tests run. Tags inherit from suites to nested tests by union. See
|
|
1502
|
+
* [Test tags](https://nodejs.org/docs/latest-v26.x/api/test.html#test-tags).
|
|
1503
|
+
* @default []
|
|
1504
|
+
* @since v26.2.0
|
|
1505
|
+
*/
|
|
1506
|
+
tags?: readonly string[] | undefined;
|
|
1446
1507
|
/**
|
|
1447
1508
|
* A number of milliseconds the test will fail after. If unspecified, subtests inherit this
|
|
1448
1509
|
* value from their parent.
|
|
@@ -89,23 +89,22 @@ declare module "node:v8" {
|
|
|
89
89
|
* `total_allocated_bytes` The value of total allocated bytes since the Isolate
|
|
90
90
|
* creation.
|
|
91
91
|
*
|
|
92
|
-
* ```
|
|
92
|
+
* ```json
|
|
93
93
|
* {
|
|
94
|
-
* total_heap_size: 7326976,
|
|
95
|
-
* total_heap_size_executable: 4194304,
|
|
96
|
-
* total_physical_size: 7326976,
|
|
97
|
-
* total_available_size: 1152656,
|
|
98
|
-
* used_heap_size: 3476208,
|
|
99
|
-
* heap_size_limit: 1535115264,
|
|
100
|
-
* malloced_memory: 16384,
|
|
101
|
-
* peak_malloced_memory: 1127496,
|
|
102
|
-
* does_zap_garbage: 0,
|
|
103
|
-
* number_of_native_contexts: 1,
|
|
104
|
-
* number_of_detached_contexts: 0,
|
|
105
|
-
* total_global_handles_size: 8192,
|
|
106
|
-
* used_global_handles_size: 3296,
|
|
107
|
-
* external_memory: 318824
|
|
108
|
-
* total_allocated_bytes: 45224088
|
|
94
|
+
* "total_heap_size": 7326976,
|
|
95
|
+
* "total_heap_size_executable": 4194304,
|
|
96
|
+
* "total_physical_size": 7326976,
|
|
97
|
+
* "total_available_size": 1152656,
|
|
98
|
+
* "used_heap_size": 3476208,
|
|
99
|
+
* "heap_size_limit": 1535115264,
|
|
100
|
+
* "malloced_memory": 16384,
|
|
101
|
+
* "peak_malloced_memory": 1127496,
|
|
102
|
+
* "does_zap_garbage": 0,
|
|
103
|
+
* "number_of_native_contexts": 1,
|
|
104
|
+
* "number_of_detached_contexts": 0,
|
|
105
|
+
* "total_global_handles_size": 8192,
|
|
106
|
+
* "used_global_handles_size": 3296,
|
|
107
|
+
* "external_memory": 318824
|
|
109
108
|
* }
|
|
110
109
|
* ```
|
|
111
110
|
* @since v1.0.0
|
|
@@ -386,12 +385,12 @@ declare module "node:v8" {
|
|
|
386
385
|
* V8 [`GetHeapCodeAndMetadataStatistics`](https://v8docs.nodesource.com/node-13.2/d5/dda/classv8_1_1_isolate.html#a6079122af17612ef54ef3348ce170866) API. Returns an object with the
|
|
387
386
|
* following properties:
|
|
388
387
|
*
|
|
389
|
-
* ```
|
|
388
|
+
* ```json
|
|
390
389
|
* {
|
|
391
|
-
* code_and_metadata_size: 212208,
|
|
392
|
-
* bytecode_and_metadata_size: 161368,
|
|
393
|
-
* external_script_source_size: 1410794,
|
|
394
|
-
* cpu_profiler_metadata_size: 0
|
|
390
|
+
* "code_and_metadata_size": 212208,
|
|
391
|
+
* "bytecode_and_metadata_size": 161368,
|
|
392
|
+
* "external_script_source_size": 1410794,
|
|
393
|
+
* "cpu_profiler_metadata_size": 0
|
|
395
394
|
* }
|
|
396
395
|
* ```
|
|
397
396
|
* @since v12.8.0
|
|
@@ -963,8 +962,6 @@ declare module "node:v8" {
|
|
|
963
962
|
* For example, if the `entry.js` contains the following script:
|
|
964
963
|
*
|
|
965
964
|
* ```js
|
|
966
|
-
* 'use strict';
|
|
967
|
-
*
|
|
968
965
|
* import fs from 'node:fs';
|
|
969
966
|
* import zlib from 'node:zlib';
|
|
970
967
|
* import path from 'node:path';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daniel156161/prism",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.81",
|
|
4
4
|
"description": "Prism-branded wrapper around pi that stores config in ~/.prism",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"package:publish:npm": "node scripts/publish-npm-package.mjs"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@earendil-works/pi-ai": "^0.84.
|
|
29
|
-
"@earendil-works/pi-coding-agent": "^0.84.
|
|
30
|
-
"pi-mcp-adapter": "^2.
|
|
28
|
+
"@earendil-works/pi-ai": "^0.84.1",
|
|
29
|
+
"@earendil-works/pi-coding-agent": "^0.84.1",
|
|
30
|
+
"pi-mcp-adapter": "^2.21.1",
|
|
31
31
|
"pkce-challenge": "^6.0.0",
|
|
32
32
|
"typebox": "^1.3.11"
|
|
33
33
|
},
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"@earendil-works/pi-coding-agent"
|
|
36
36
|
],
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@types/node": "^26.
|
|
39
|
-
"tsx": "^4.23.
|
|
38
|
+
"@types/node": "^26.2.0",
|
|
39
|
+
"tsx": "^4.23.11",
|
|
40
40
|
"typescript": "^7.0.2"
|
|
41
41
|
},
|
|
42
42
|
"files": [
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error and diagnostics formatting for the AI Memory System integration.
|
|
3
|
+
*
|
|
4
|
+
* The API returns a structured error body (`{"error": {...}, "request_id": ...}`).
|
|
5
|
+
* Collapsing that into "HTTP 500 <raw json>" made intermittent failures
|
|
6
|
+
* impossible to trace, so the request id, the failing route and the query are
|
|
7
|
+
* kept in the message the model and the user actually see.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type AiMemoryRequestContext = {
|
|
11
|
+
method: string
|
|
12
|
+
path: string
|
|
13
|
+
query?: string
|
|
14
|
+
filters?: Record<string, unknown>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function parseBody(text: string): any {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(text)
|
|
20
|
+
} catch {
|
|
21
|
+
return undefined
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function errorDetail(body: any, fallback: string): string {
|
|
26
|
+
if (!body || typeof body !== "object") return fallback.slice(0, 500)
|
|
27
|
+
const error = body.error ?? body
|
|
28
|
+
const detail = error?.message ?? error?.detail ?? body?.detail
|
|
29
|
+
if (typeof detail === "string" && detail.trim()) return detail.trim()
|
|
30
|
+
if (Array.isArray(detail)) return detail.map((item: any) => item?.msg ?? JSON.stringify(item)).join("; ")
|
|
31
|
+
return fallback.slice(0, 500)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function formatApiFailure(status: number, text: string, context: AiMemoryRequestContext): string {
|
|
35
|
+
const body = parseBody(text)
|
|
36
|
+
const requestId = body?.request_id ?? body?.error?.request_id
|
|
37
|
+
const code = body?.error?.code ?? body?.code
|
|
38
|
+
const parts = [`AI Memory ${context.method} ${context.path} failed: HTTP ${status}`]
|
|
39
|
+
parts.push(errorDetail(body, text))
|
|
40
|
+
if (code) parts.push(`code=${code}`)
|
|
41
|
+
if (requestId) parts.push(`request_id=${requestId}`)
|
|
42
|
+
if (context.query) parts.push(`query=${JSON.stringify(context.query)}`)
|
|
43
|
+
if (context.filters && Object.keys(context.filters).length > 0) parts.push(`filters=${JSON.stringify(context.filters)}`)
|
|
44
|
+
return parts.join(" | ")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function formatDegradedNotice(degraded: any): string {
|
|
48
|
+
const stages: string[] = Array.isArray(degraded?.stages) ? degraded.stages : []
|
|
49
|
+
if (stages.length === 0) return ""
|
|
50
|
+
const errors = degraded?.errors ?? {}
|
|
51
|
+
const details = stages.map((stage) => (errors?.[stage] ? `${stage} (${errors[stage]})` : stage)).join(", ")
|
|
52
|
+
return `Warnung: Teilausfall im Retrieval — degradierte Stufen: ${details}. Ergebnisse können unvollständig sein.`
|
|
53
|
+
}
|
|
@@ -2,8 +2,10 @@ type ExtensionAPI = any
|
|
|
2
2
|
|
|
3
3
|
import { Type } from "typebox"
|
|
4
4
|
import { readSettings } from "../core/shared-config.js"
|
|
5
|
+
import { formatApiFailure, formatDegradedNotice } from "./ai-memory-errors.js"
|
|
5
6
|
import { renderCollapsibleTextResult } from "../ui/collapsed-text-rendering.js"
|
|
6
|
-
import {
|
|
7
|
+
import { obsidianOpenUrl } from "./obsidian-memory.js"
|
|
8
|
+
import { ansiHyperlink, formatBracketedToolCall, renderSingleLineToolCall, type ThemeLike } from "../ui/tool-call-rendering.js"
|
|
7
9
|
|
|
8
10
|
const DEFAULT_BASE_URL = "http://127.0.0.1:8765"
|
|
9
11
|
const DEFAULT_LIMIT = 8
|
|
@@ -108,7 +110,15 @@ async function postJson<T>(path: string, body: unknown, timeoutMs = aiMemoryRequ
|
|
|
108
110
|
signal: AbortSignal.timeout(timeoutMs),
|
|
109
111
|
})
|
|
110
112
|
const text = await response.text()
|
|
111
|
-
if (!response.ok)
|
|
113
|
+
if (!response.ok) {
|
|
114
|
+
const payload = body as any
|
|
115
|
+
throw new Error(formatApiFailure(response.status, text, {
|
|
116
|
+
method: "POST",
|
|
117
|
+
path,
|
|
118
|
+
query: typeof payload?.query === "string" ? payload.query : undefined,
|
|
119
|
+
filters: payload?.filters,
|
|
120
|
+
}))
|
|
121
|
+
}
|
|
112
122
|
return JSON.parse(text) as T
|
|
113
123
|
}
|
|
114
124
|
|
|
@@ -121,7 +131,7 @@ async function putJson<T>(path: string, body: unknown, timeoutMs = aiMemoryReque
|
|
|
121
131
|
signal: AbortSignal.timeout(timeoutMs),
|
|
122
132
|
})
|
|
123
133
|
const text = await response.text()
|
|
124
|
-
if (!response.ok) throw new Error(
|
|
134
|
+
if (!response.ok) throw new Error(formatApiFailure(response.status, text, { method: "PUT", path }))
|
|
125
135
|
return JSON.parse(text) as T
|
|
126
136
|
}
|
|
127
137
|
|
|
@@ -134,7 +144,7 @@ async function deleteJson<T>(path: string, body: unknown, timeoutMs = aiMemoryRe
|
|
|
134
144
|
signal: AbortSignal.timeout(timeoutMs),
|
|
135
145
|
})
|
|
136
146
|
const text = await response.text()
|
|
137
|
-
if (!response.ok) throw new Error(
|
|
147
|
+
if (!response.ok) throw new Error(formatApiFailure(response.status, text, { method: "DELETE", path }))
|
|
138
148
|
return JSON.parse(text) as T
|
|
139
149
|
}
|
|
140
150
|
|
|
@@ -152,7 +162,7 @@ async function methodJson<T>(
|
|
|
152
162
|
signal: AbortSignal.timeout(timeoutMs),
|
|
153
163
|
})
|
|
154
164
|
const text = await response.text()
|
|
155
|
-
if (!response.ok) throw new Error(
|
|
165
|
+
if (!response.ok) throw new Error(formatApiFailure(response.status, text, { method, path }))
|
|
156
166
|
return JSON.parse(text) as T
|
|
157
167
|
}
|
|
158
168
|
|
|
@@ -163,7 +173,7 @@ async function getJson<T>(path: string, timeoutMs = aiMemoryStatusTimeoutMs()):
|
|
|
163
173
|
signal: AbortSignal.timeout(timeoutMs),
|
|
164
174
|
})
|
|
165
175
|
const text = await response.text()
|
|
166
|
-
if (!response.ok) throw new Error(
|
|
176
|
+
if (!response.ok) throw new Error(formatApiFailure(response.status, text, { method: "GET", path }))
|
|
167
177
|
return JSON.parse(text) as T
|
|
168
178
|
}
|
|
169
179
|
|
|
@@ -176,11 +186,19 @@ function formatSearchResults(results: any[]): string {
|
|
|
176
186
|
const lexical = Number(row.lexical_score ?? 0).toFixed(4)
|
|
177
187
|
const graph = Number(row.graph_score ?? 0).toFixed(1)
|
|
178
188
|
const fact = Number(row.fact_score ?? 0).toFixed(1)
|
|
189
|
+
const feedback = Number(row.feedback_score ?? 0).toFixed(2)
|
|
190
|
+
const stale = Number(row.stale_score ?? 0).toFixed(2)
|
|
179
191
|
const excerpt = String(row.text ?? "").replace(/\s+/g, " ").trim().slice(0, 700)
|
|
180
|
-
return `${index + 1}. score=${score} vector=${vector} keyword=${keyword} lexical=${lexical} graph=${graph} fact=${fact}\nsource=${row.source}:${row.path} > ${row.heading}\n${excerpt}`
|
|
192
|
+
return `${index + 1}. score=${score} vector=${vector} keyword=${keyword} lexical=${lexical} graph=${graph} fact=${fact} feedback=${feedback} stale=${stale}\nsource=${row.source}:${row.path} > ${row.heading}\n${excerpt}`
|
|
181
193
|
}).join("\n\n")
|
|
182
194
|
}
|
|
183
195
|
|
|
196
|
+
export function formatSearchResponse(data: any): string {
|
|
197
|
+
const results = Array.isArray(data?.results) ? data.results : []
|
|
198
|
+
const notices = [formatDegradedNotice(data?.degraded), String(data?.hint ?? "").trim()].filter(Boolean)
|
|
199
|
+
return [...notices, formatSearchResults(results)].join("\n\n")
|
|
200
|
+
}
|
|
201
|
+
|
|
184
202
|
function formatReadResult(data: any): string {
|
|
185
203
|
const source = String(data?.source ?? "unknown")
|
|
186
204
|
const path = String(data?.path ?? "unknown")
|
|
@@ -277,9 +295,25 @@ function renderAiMemoryResult(result: any, options: { expanded?: boolean; isPart
|
|
|
277
295
|
})
|
|
278
296
|
}
|
|
279
297
|
|
|
280
|
-
function formatAiMemoryToolCall(toolName: string, args: any, theme: ThemeLike): string {
|
|
298
|
+
export function formatAiMemoryToolCall(toolName: string, args: any, theme: ThemeLike): string {
|
|
281
299
|
const label = toolName.replace(/^ai_memory_/, "ai memory ").replace(/_/g, " ")
|
|
282
|
-
|
|
300
|
+
const rawValue = args?.query || args?.id || args?.path || args?.session || ""
|
|
301
|
+
const value = typeof rawValue === "string" && rawValue.trim() ? rawValue.trim() : "..."
|
|
302
|
+
const linksToVaultNote = ["ai_memory_vault_write", "ai_memory_vault_edit", "ai_memory_vault_delete"].includes(toolName)
|
|
303
|
+
if (linksToVaultNote && value !== "...") {
|
|
304
|
+
return `${theme.fg("toolTitle", theme.bold(label))} ${theme.fg("accent", ansiHyperlink(obsidianOpenUrl(value), value))}`
|
|
305
|
+
}
|
|
306
|
+
return formatBracketedToolCall(label, value, theme)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function formatVaultWriteResult(action: "Wrote" | "Edited", params: any, responsePath: unknown): string {
|
|
310
|
+
const path = String(responsePath ?? params.path ?? "")
|
|
311
|
+
const frontmatter = params.frontmatter === undefined ? "" : String(params.frontmatter).trim()
|
|
312
|
+
const heading = action === "Edited" ? `# ${String(params.heading ?? "").trim()}` : ""
|
|
313
|
+
const body = String(params.body ?? "")
|
|
314
|
+
const writtenContent = [frontmatter, heading, body].filter(Boolean).join("\n\n") || "(empty)"
|
|
315
|
+
const status = action === "Wrote" ? `Wrote: ${path}\n\n` : ""
|
|
316
|
+
return `${status}Write content:\n${writtenContent}`
|
|
283
317
|
}
|
|
284
318
|
|
|
285
319
|
export default function aiMemorySystemExtension(pi: ExtensionAPI): void {
|
|
@@ -305,12 +339,12 @@ export default function aiMemorySystemExtension(pi: ExtensionAPI): void {
|
|
|
305
339
|
path: Type.Optional(Type.String({ description: "Path substring filter" })),
|
|
306
340
|
}),
|
|
307
341
|
async execute(_id: string, params: any) {
|
|
308
|
-
const data = await postJson<{ results: any[] }>("/search", {
|
|
342
|
+
const data = await postJson<{ results: any[]; degraded?: any; hint?: string }>("/search", {
|
|
309
343
|
query: String(params.query ?? ""),
|
|
310
344
|
limit: clampLimit(params.limit),
|
|
311
345
|
filters: cleanFilters(params),
|
|
312
346
|
})
|
|
313
|
-
return { content: [{ type: "text", text:
|
|
347
|
+
return { content: [{ type: "text", text: formatSearchResponse(data) }], details: { count: data.results?.length ?? 0, results: data.results, degraded: data.degraded, hint: data.hint } }
|
|
314
348
|
},
|
|
315
349
|
renderCall(args: any, theme: ThemeLike, context: any) {
|
|
316
350
|
return renderSingleLineToolCall(formatAiMemoryToolCall("ai_memory_search", args, theme), context)
|
|
@@ -369,6 +403,130 @@ export default function aiMemorySystemExtension(pi: ExtensionAPI): void {
|
|
|
369
403
|
},
|
|
370
404
|
})
|
|
371
405
|
|
|
406
|
+
pi.registerTool({
|
|
407
|
+
name: "ai_memory_rate_result",
|
|
408
|
+
label: "AI Memory Rate Result",
|
|
409
|
+
description: "Rate one retrieved memory result so future ranking learns from it.",
|
|
410
|
+
promptSnippet: "Use ai_memory_rate_result when a retrieved memory was clearly helpful, irrelevant, outdated, or wrong.",
|
|
411
|
+
promptGuidelines: [
|
|
412
|
+
"Rate the path exactly as returned by ai_memory_search.",
|
|
413
|
+
"Use 'outdated' or 'wrong' when the user corrects information that came from memory.",
|
|
414
|
+
"This changes ranking only; it never writes or deletes a note.",
|
|
415
|
+
],
|
|
416
|
+
parameters: Type.Object({
|
|
417
|
+
path: Type.String({ description: "Path of the rated result, e.g. 02 Projekte/Memory.md" }),
|
|
418
|
+
rating: Type.String({ description: "helpful, irrelevant, outdated, or wrong" }),
|
|
419
|
+
query: Type.Optional(Type.String({ description: "Search query that produced the result" })),
|
|
420
|
+
reason: Type.Optional(Type.String({ description: "Short reason in German" })),
|
|
421
|
+
source: Type.Optional(Type.String({ description: "obsidian or prism_session" })),
|
|
422
|
+
chunk_id: Type.Optional(Type.String({ description: "Exact chunk id if known" })),
|
|
423
|
+
session_id: Type.Optional(Type.String({ description: "Originating session id" })),
|
|
424
|
+
}),
|
|
425
|
+
async execute(_id: string, params: any) {
|
|
426
|
+
const data = await postJson<any>("/retrieval-feedback", {
|
|
427
|
+
path: String(params.path ?? ""),
|
|
428
|
+
rating: String(params.rating ?? ""),
|
|
429
|
+
query: String(params.query ?? ""),
|
|
430
|
+
reason: String(params.reason ?? ""),
|
|
431
|
+
source: String(params.source ?? ""),
|
|
432
|
+
chunk_id: String(params.chunk_id ?? ""),
|
|
433
|
+
session_id: String(params.session_id ?? ""),
|
|
434
|
+
})
|
|
435
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }], details: data }
|
|
436
|
+
},
|
|
437
|
+
renderCall(args: any, theme: ThemeLike, context: any) {
|
|
438
|
+
return renderSingleLineToolCall(formatAiMemoryToolCall("ai_memory_rate_result", args, theme), context)
|
|
439
|
+
},
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
pi.registerTool({
|
|
443
|
+
name: "ai_memory_session_review",
|
|
444
|
+
label: "AI Memory Session Review",
|
|
445
|
+
description: "Review a Prism session for outcome evidence and human-approved durable lesson proposals.",
|
|
446
|
+
promptSnippet: "Review a completed session and return pending lessons; this does not approve them.",
|
|
447
|
+
parameters: Type.Object({
|
|
448
|
+
session: Type.Optional(Type.String({ description: "Session path/id or latest" })),
|
|
449
|
+
force: Type.Optional(Type.Boolean({ description: "Review an unchanged session again" })),
|
|
450
|
+
}),
|
|
451
|
+
async execute(_id: string, params: any) {
|
|
452
|
+
const data = await postJson<any>("/session-review", {
|
|
453
|
+
session: typeof params.session === "string" ? params.session : "latest",
|
|
454
|
+
force: params.force === true,
|
|
455
|
+
})
|
|
456
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }], details: data }
|
|
457
|
+
},
|
|
458
|
+
renderCall(args: any, theme: ThemeLike, context: any) {
|
|
459
|
+
return renderSingleLineToolCall(formatAiMemoryToolCall("ai_memory_session_review", args, theme), context)
|
|
460
|
+
},
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
pi.registerTool({
|
|
464
|
+
name: "ai_memory_propose_lesson",
|
|
465
|
+
label: "AI Memory Propose Lesson",
|
|
466
|
+
description: "Create a pending durable lesson proposal. User approval is still required before writing memory.",
|
|
467
|
+
promptSnippet: "Propose a lesson from explicit user feedback without promoting it automatically.",
|
|
468
|
+
parameters: Type.Object({
|
|
469
|
+
category: Type.String({ description: "correction, decision, preference, workflow, or quality" }),
|
|
470
|
+
title: Type.String({ description: "Short German title" }),
|
|
471
|
+
rule: Type.String({ description: "Proposed durable rule in German" }),
|
|
472
|
+
rationale: Type.Optional(Type.String({ description: "Why the rule matters" })),
|
|
473
|
+
evidence: Type.String({ description: "Exact user feedback supporting the proposal" }),
|
|
474
|
+
session_id: Type.Optional(Type.String({ description: "Originating session id" })),
|
|
475
|
+
confidence: Type.Optional(Type.Number({ description: "Confidence from 0 to 1" })),
|
|
476
|
+
}),
|
|
477
|
+
async execute(_id: string, params: any) {
|
|
478
|
+
const data = await postJson<any>("/lessons", {
|
|
479
|
+
category: String(params.category ?? ""),
|
|
480
|
+
title: String(params.title ?? ""),
|
|
481
|
+
rule: String(params.rule ?? ""),
|
|
482
|
+
rationale: String(params.rationale ?? ""),
|
|
483
|
+
evidence: String(params.evidence ?? ""),
|
|
484
|
+
session_id: String(params.session_id ?? "manual"),
|
|
485
|
+
confidence: params.confidence === undefined ? 0.8 : Number(params.confidence),
|
|
486
|
+
})
|
|
487
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }], details: data }
|
|
488
|
+
},
|
|
489
|
+
renderCall(args: any, theme: ThemeLike, context: any) {
|
|
490
|
+
return renderSingleLineToolCall(formatAiMemoryToolCall("ai_memory_propose_lesson", args, theme), context)
|
|
491
|
+
},
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
pi.registerTool({
|
|
495
|
+
name: "ai_memory_feedback",
|
|
496
|
+
label: "AI Memory Feedback",
|
|
497
|
+
description: "List pending lessons or approve/reject one proposal. Approval writes durable memory.",
|
|
498
|
+
promptSnippet: "Use only after explicit user approval to approve a proposed durable lesson.",
|
|
499
|
+
promptGuidelines: ["Never approve a lesson without explicit user approval in the current conversation."],
|
|
500
|
+
parameters: Type.Object({
|
|
501
|
+
action: Type.Optional(Type.String({ description: "list (default), approve, or reject" })),
|
|
502
|
+
proposal_id: Type.Optional(Type.String({ description: "Required for approve/reject" })),
|
|
503
|
+
status: Type.Optional(Type.String({ description: "List filter: pending, approved, or rejected" })),
|
|
504
|
+
session_id: Type.Optional(Type.String({ description: "Optional session filter for listing" })),
|
|
505
|
+
}),
|
|
506
|
+
async execute(_id: string, params: any) {
|
|
507
|
+
const action = String(params.action ?? "list")
|
|
508
|
+
let data: any
|
|
509
|
+
if (action === "list") {
|
|
510
|
+
const query = new URLSearchParams()
|
|
511
|
+
if (params.status) query.set("status", String(params.status))
|
|
512
|
+
if (params.session_id) query.set("session_id", String(params.session_id))
|
|
513
|
+
data = await getJson<any>(`/lessons${query.size ? `?${query}` : ""}`, aiMemoryRequestTimeoutMs())
|
|
514
|
+
} else {
|
|
515
|
+
if (!["approve", "reject"].includes(action) || !params.proposal_id) {
|
|
516
|
+
throw new Error("action must be list, approve, or reject; proposal_id is required for decisions")
|
|
517
|
+
}
|
|
518
|
+
data = await methodJson<any>("DECISION", "/lessons", aiMemoryRequestTimeoutMs(), {
|
|
519
|
+
proposal_id: String(params.proposal_id),
|
|
520
|
+
decision: action,
|
|
521
|
+
})
|
|
522
|
+
}
|
|
523
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }], details: data }
|
|
524
|
+
},
|
|
525
|
+
renderCall(args: any, theme: ThemeLike, context: any) {
|
|
526
|
+
return renderSingleLineToolCall(formatAiMemoryToolCall("ai_memory_feedback", args, theme), context)
|
|
527
|
+
},
|
|
528
|
+
})
|
|
529
|
+
|
|
372
530
|
// ── File-backed vault ops (write/edit/list/delete) ──
|
|
373
531
|
|
|
374
532
|
pi.registerTool({
|
|
@@ -396,7 +554,7 @@ export default function aiMemorySystemExtension(pi: ExtensionAPI): void {
|
|
|
396
554
|
name: "ai_memory_vault_write",
|
|
397
555
|
label: "AI Memory Vault Write",
|
|
398
556
|
description: "Create/overwrite a Markdown file in the configured Obsidian vault.",
|
|
399
|
-
promptSnippet: "Write vault file [path
|
|
557
|
+
promptSnippet: "Write vault file [show path and written body/frontmatter]",
|
|
400
558
|
parameters: Type.Object({
|
|
401
559
|
path: Type.String({ description: "Vault-relative path, e.g. 02 Projekte/Test.md" }),
|
|
402
560
|
frontmatter: Type.Optional(Type.String({ description: "Optional YAML frontmatter including leading/trailing --- lines" })),
|
|
@@ -408,18 +566,21 @@ export default function aiMemorySystemExtension(pi: ExtensionAPI): void {
|
|
|
408
566
|
frontmatter: params.frontmatter !== undefined ? String(params.frontmatter) : null,
|
|
409
567
|
body: String(params.body ?? ""),
|
|
410
568
|
})
|
|
411
|
-
return { content: [{ type: "text", text:
|
|
569
|
+
return { content: [{ type: "text", text: formatVaultWriteResult("Wrote", params, data.path) }], details: data }
|
|
412
570
|
},
|
|
413
571
|
renderCall(args: any, theme: ThemeLike, context: any) {
|
|
414
572
|
return renderSingleLineToolCall(formatAiMemoryToolCall("ai_memory_vault_write", args, theme), context)
|
|
415
573
|
},
|
|
574
|
+
renderResult(result: any, options: any, theme: ThemeLike) {
|
|
575
|
+
return renderAiMemoryResult(result, options, theme)
|
|
576
|
+
},
|
|
416
577
|
})
|
|
417
578
|
|
|
418
579
|
pi.registerTool({
|
|
419
580
|
name: "ai_memory_vault_edit",
|
|
420
581
|
label: "AI Memory Vault Edit",
|
|
421
582
|
description: "Replace the content block under a given heading in a Markdown file (or append if missing).",
|
|
422
|
-
promptSnippet: "Edit vault file section
|
|
583
|
+
promptSnippet: "Edit vault file section [show path, heading, and written body/frontmatter]",
|
|
423
584
|
parameters: Type.Object({
|
|
424
585
|
path: Type.String({ description: "Vault-relative path" }),
|
|
425
586
|
heading: Type.String({ description: "Heading text without leading #, e.g. 'Update 2026-01-01 — Thema'" }),
|
|
@@ -433,11 +594,14 @@ export default function aiMemorySystemExtension(pi: ExtensionAPI): void {
|
|
|
433
594
|
frontmatter: params.frontmatter !== undefined ? String(params.frontmatter) : null,
|
|
434
595
|
body: String(params.body ?? ""),
|
|
435
596
|
})
|
|
436
|
-
return { content: [{ type: "text", text:
|
|
597
|
+
return { content: [{ type: "text", text: formatVaultWriteResult("Edited", params, data.path) }], details: data }
|
|
437
598
|
},
|
|
438
599
|
renderCall(args: any, theme: ThemeLike, context: any) {
|
|
439
600
|
return renderSingleLineToolCall(formatAiMemoryToolCall("ai_memory_vault_edit", args, theme), context)
|
|
440
601
|
},
|
|
602
|
+
renderResult(result: any, options: any, theme: ThemeLike) {
|
|
603
|
+
return renderAiMemoryResult(result, options, theme)
|
|
604
|
+
},
|
|
441
605
|
})
|
|
442
606
|
|
|
443
607
|
pi.registerTool({
|
|
@@ -332,7 +332,7 @@ export async function webSearch(query: string, limit = 10): Promise<string> {
|
|
|
332
332
|
export async function webFetch(url: string, maxChars = 20_000): Promise<string> {
|
|
333
333
|
const safeUrl = validateHttpUrl(url)
|
|
334
334
|
const safeMaxChars = clampLimit(maxChars, 20_000, 1_000, 100_000)
|
|
335
|
-
if (isYouTubeUrl(safeUrl)) return fetchYouTubeContent(safeUrl
|
|
335
|
+
if (isYouTubeUrl(safeUrl)) return fetchYouTubeContent(safeUrl)
|
|
336
336
|
const response = await fetch(safeUrl, { headers: { "User-Agent": "Mozilla/5.0 (compatible; prism-research/1.0)" }, signal: AbortSignal.timeout(15_000) })
|
|
337
337
|
const text = await response.text()
|
|
338
338
|
if (!response.ok) throw new Error(`Fetch failed for ${safeUrl}: HTTP ${response.status}`)
|
|
@@ -392,8 +392,8 @@ export default function researchToolsExtension(pi: ExtensionAPI): void {
|
|
|
392
392
|
pi.registerTool({
|
|
393
393
|
name: "web_fetch",
|
|
394
394
|
label: "web fetch",
|
|
395
|
-
description: "Fetch readable text from a web page for citation-backed research. For YouTube URLs, extracts structured video metadata
|
|
396
|
-
promptSnippet: "Fetch readable text from a web page. For YouTube URLs, extracts structured video metadata
|
|
395
|
+
description: "Fetch readable text from a web page for citation-backed research. For YouTube URLs, extracts structured video metadata and the complete transcript without applying maxChars truncation.",
|
|
396
|
+
promptSnippet: "Fetch readable text from a web page. For YouTube URLs, extracts structured video metadata and the complete transcript without truncation.",
|
|
397
397
|
parameters: Type.Object({ url: Type.String(), maxChars: Type.Optional(Type.Number()) }),
|
|
398
398
|
async execute(_id: string, params: any) {
|
|
399
399
|
return { content: [{ type: "text", text: await webFetch(params.url, params.maxChars || 20_000) }], details: { url: params.url } }
|