tinker-agent 2.11.0 → 2.13.0

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.
Files changed (36) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/README.md +31 -67
  3. package/package.json +1 -1
  4. package/src/agent/runtime-session-contracts.ts +2 -29
  5. package/src/agent/runtime-session.ts +13 -67
  6. package/src/cli/config.ts +0 -29
  7. package/src/cli/model-profiles.ts +0 -80
  8. package/src/cli/public-config-contract.ts +1 -82
  9. package/src/cli/runner-dependencies.ts +35 -35
  10. package/src/cli/tui-runner.tsx +2 -41
  11. package/src/events/observation-text-log.ts +7 -0
  12. package/src/memory/contracts.ts +0 -256
  13. package/src/memory/memory-create-tool.ts +3 -5
  14. package/src/memory/memory-files.ts +145 -0
  15. package/src/memory/memory-search-output.ts +23 -0
  16. package/src/memory/memory-search-tool.ts +79 -175
  17. package/src/memory/memory-search.ts +115 -0
  18. package/src/observation/observation-builder.ts +5 -1
  19. package/src/session/session-store-contracts.ts +0 -23
  20. package/src/session/session-store.ts +2 -103
  21. package/src/tools/bash.ts +9 -1
  22. package/src/tools/bounded-output-preview.ts +2 -2
  23. package/src/tools/registry.ts +15 -18
  24. package/src/tools/types.ts +12 -0
  25. package/src/tui/app.tsx +6 -4
  26. package/src/tui/event-store.ts +3 -1
  27. package/src/cli/tui-memory.ts +0 -69
  28. package/src/memory/embedding-client.ts +0 -105
  29. package/src/memory/memory-coordinator.ts +0 -1274
  30. package/src/memory/memory-delete-tool.ts +0 -88
  31. package/src/memory/memory-extractor.ts +0 -252
  32. package/src/memory/memory-get-tool.ts +0 -86
  33. package/src/memory/memory-log.ts +0 -88
  34. package/src/memory/memory-store.ts +0 -1133
  35. package/src/memory/memory-update-tool.ts +0 -142
  36. package/src/memory/vector.ts +0 -153
package/src/tui/app.tsx CHANGED
@@ -84,7 +84,9 @@ export type AppProps = {
84
84
  writeClipboard?: (markdown: string) => Promise<void>;
85
85
  onQuit?: () => void;
86
86
  initialNotice?: string;
87
- listStoredMemories?: () => readonly StoredMemorySummary[];
87
+ listStoredMemories?: () =>
88
+ | readonly StoredMemorySummary[]
89
+ | Promise<readonly StoredMemorySummary[]>;
88
90
  memoryDisabledNotice?: string;
89
91
  };
90
92
 
@@ -418,13 +420,13 @@ export function App(props: AppProps) {
418
420
  restoreStaticViewport();
419
421
  };
420
422
 
421
- const openMemoryView = () => {
423
+ const openMemoryView = async () => {
422
424
  if (props.listStoredMemories === undefined) {
423
425
  setNotice(props.memoryDisabledNotice ?? "memory disabled: not configured");
424
426
  return;
425
427
  }
426
428
  try {
427
- const snapshot = props.listStoredMemories();
429
+ const snapshot = await props.listStoredMemories();
428
430
  setNotice(undefined);
429
431
  setMemoryView(snapshot);
430
432
  } catch (error) {
@@ -646,7 +648,7 @@ export function App(props: AppProps) {
646
648
  return true;
647
649
  }
648
650
  if (command.type === "memory") {
649
- openMemoryView();
651
+ void openMemoryView();
650
652
  return true;
651
653
  }
652
654
  if (command.type === "copy") {
@@ -835,7 +835,7 @@ function toolCallSummary(input: { name: string; args: unknown }): string {
835
835
  return `WebSearch ${toolQuery(input.args) ?? ""}`.trim();
836
836
  }
837
837
  if (input.name === "MemorySearch") {
838
- return `MemorySearch ${memorySearchDetail(input.args)}`.trim();
838
+ return `MemorySearch ${toolPattern(input.args) ?? memorySearchDetail(input.args)}`.trim();
839
839
  }
840
840
  if (input.name === "MemoryCreate") {
841
841
  return "MemoryCreate";
@@ -974,6 +974,8 @@ function toolRawResultSummary(name: string, args: unknown, raw: ToolRawResult):
974
974
  if (!raw.ok) {
975
975
  return base;
976
976
  }
977
+ if ("format" in raw)
978
+ return `${base} -> ${raw.returnedResults} matching lines in ${raw.files.length} files`;
977
979
  return `${base} -> ${raw.matches.length} derived memor${raw.matches.length === 1 ? "y" : "ies"}`;
978
980
  case "memory_get":
979
981
  if (!raw.ok) {
@@ -1,69 +0,0 @@
1
- import {
2
- boundedMemoryError,
3
- memoryErrorCode,
4
- type MemoryPaths,
5
- } from "../memory/contracts";
6
- import { MemoryCoordinator } from "../memory/memory-coordinator";
7
- import { MemoryLog } from "../memory/memory-log";
8
- import { resolveMemoryPaths } from "../memory/memory-store";
9
- import type { ResolvedMemoryConfig } from "./config";
10
- import { createModelClient } from "./runner-dependencies";
11
-
12
- export type TuiMemoryInitialization = {
13
- readonly coordinator?: MemoryCoordinator;
14
- readonly notice?: string;
15
- };
16
-
17
- export async function initializeTuiMemory(input: {
18
- readonly config?: ResolvedMemoryConfig;
19
- readonly env: NodeJS.ProcessEnv;
20
- readonly paths?: MemoryPaths;
21
- readonly createCoordinator?: typeof MemoryCoordinator.create;
22
- }): Promise<TuiMemoryInitialization> {
23
- if (input.config === undefined) {
24
- return Object.freeze({});
25
- }
26
-
27
- const paths = input.paths ?? resolveMemoryPaths();
28
- const log = new MemoryLog(paths.log);
29
- try {
30
- const memoryConfig = input.config;
31
- const coordinator = await (input.createCoordinator ?? MemoryCoordinator.create)({
32
- paths,
33
- embedding: memoryConfig.embedding,
34
- extractionContextBudget: memoryConfig.contextBudget,
35
- createExtractionClient: () => {
36
- const profile = memoryConfig.profile;
37
- return createModelClient(
38
- {
39
- modelName: profile.model,
40
- api: profile.api,
41
- apiKey: profile.apiKey,
42
- apiBase: profile.apiBase,
43
- ...(profile.reasoning === undefined
44
- ? {}
45
- : { reasoning: profile.reasoning }),
46
- includeReasoningContent: profile.includeReasoningContent,
47
- stream: profile.stream,
48
- contextBudget: memoryConfig.contextBudget,
49
- inputModalities: profile.inputModalities,
50
- toolResultModalities: profile.toolResultModalities,
51
- },
52
- input.env,
53
- );
54
- },
55
- });
56
- return Object.freeze({ coordinator });
57
- } catch (error) {
58
- const reason = memoryErrorCode(error, "memory_init_failed");
59
- await log.append({
60
- at: new Date().toISOString(),
61
- kind: "init",
62
- outcome: "failed",
63
- reason,
64
- });
65
- return Object.freeze({
66
- notice: `memory disabled: ${boundedMemoryError(error)}`,
67
- });
68
- }
69
- }
@@ -1,105 +0,0 @@
1
- import OpenAI from "openai";
2
- import type { MemoryEmbeddingConfig } from "./contracts";
3
- import { MemoryError } from "./contracts";
4
-
5
- const EMBEDDING_TIMEOUT_MS = 60_000;
6
- const EMBEDDING_MAX_RETRIES = 2;
7
-
8
- export interface MemoryEmbeddingClient {
9
- embed(
10
- inputs: readonly string[],
11
- signal: AbortSignal,
12
- ): Promise<readonly (readonly number[])[]>;
13
- }
14
-
15
- export class OpenAICompatibleEmbeddingClient implements MemoryEmbeddingClient {
16
- private readonly client: OpenAI;
17
-
18
- constructor(
19
- private readonly config: MemoryEmbeddingConfig,
20
- options: { readonly fetch?: typeof fetch } = {},
21
- ) {
22
- this.client = new OpenAI({
23
- apiKey: config.apiKey,
24
- baseURL: config.apiBase,
25
- timeout: EMBEDDING_TIMEOUT_MS,
26
- maxRetries: EMBEDDING_MAX_RETRIES,
27
- ...(options.fetch === undefined ? {} : { fetch: options.fetch }),
28
- });
29
- }
30
-
31
- async embed(
32
- inputs: readonly string[],
33
- signal: AbortSignal,
34
- ): Promise<readonly (readonly number[])[]> {
35
- if (inputs.length === 0) {
36
- throw new MemoryError(
37
- "memory_embedding_input_invalid",
38
- "Embedding input must not be empty.",
39
- );
40
- }
41
- signal.throwIfAborted();
42
-
43
- let response;
44
- try {
45
- response = await this.client.embeddings.create(
46
- {
47
- model: this.config.model,
48
- input: [...inputs],
49
- encoding_format: "float",
50
- },
51
- { signal },
52
- );
53
- } catch (error) {
54
- if (signal.aborted) {
55
- throw error;
56
- }
57
- throw new MemoryError(
58
- "memory_embedding_request_failed",
59
- "Embedding provider request failed.",
60
- { cause: error },
61
- );
62
- }
63
- signal.throwIfAborted();
64
-
65
- if (!Array.isArray(response.data)) {
66
- throw new MemoryError(
67
- "memory_embedding_response_invalid",
68
- "Embedding response did not contain a data array.",
69
- );
70
- }
71
- if (response.data.length !== inputs.length) {
72
- throw new MemoryError(
73
- "memory_embedding_response_invalid",
74
- `Embedding response returned ${response.data.length} vectors for ${inputs.length} inputs.`,
75
- );
76
- }
77
-
78
- const vectors: Array<readonly number[] | undefined> = Array.from({
79
- length: inputs.length,
80
- });
81
- for (const item of response.data) {
82
- if (
83
- !Number.isSafeInteger(item.index) ||
84
- item.index < 0 ||
85
- item.index >= inputs.length ||
86
- vectors[item.index] !== undefined ||
87
- !Array.isArray(item.embedding) ||
88
- item.embedding.some((value) => typeof value !== "number")
89
- ) {
90
- throw new MemoryError(
91
- "memory_embedding_response_invalid",
92
- "Embedding response indices or vectors are invalid.",
93
- );
94
- }
95
- vectors[item.index] = Object.freeze([...item.embedding]);
96
- }
97
- if (vectors.some((vector) => vector === undefined)) {
98
- throw new MemoryError(
99
- "memory_embedding_response_invalid",
100
- "Embedding response did not map every input index.",
101
- );
102
- }
103
- return Object.freeze(vectors as readonly (readonly number[])[]);
104
- }
105
- }