opencode-recall 0.1.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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -0
  3. package/dist/index.d.ts +4 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +123 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/config.d.ts +73 -0
  8. package/dist/lib/config.d.ts.map +1 -0
  9. package/dist/lib/config.js +779 -0
  10. package/dist/lib/config.js.map +1 -0
  11. package/dist/lib/explore-tool.d.ts +11 -0
  12. package/dist/lib/explore-tool.d.ts.map +1 -0
  13. package/dist/lib/explore-tool.js +240 -0
  14. package/dist/lib/explore-tool.js.map +1 -0
  15. package/dist/lib/hooks.d.ts +10 -0
  16. package/dist/lib/hooks.d.ts.map +1 -0
  17. package/dist/lib/hooks.js +58 -0
  18. package/dist/lib/hooks.js.map +1 -0
  19. package/dist/lib/logger.d.ts +31 -0
  20. package/dist/lib/logger.d.ts.map +1 -0
  21. package/dist/lib/logger.js +183 -0
  22. package/dist/lib/logger.js.map +1 -0
  23. package/dist/lib/messages/index.d.ts +3 -0
  24. package/dist/lib/messages/index.d.ts.map +1 -0
  25. package/dist/lib/messages/index.js +3 -0
  26. package/dist/lib/messages/index.js.map +1 -0
  27. package/dist/lib/messages/inject.d.ts +5 -0
  28. package/dist/lib/messages/inject.d.ts.map +1 -0
  29. package/dist/lib/messages/inject.js +114 -0
  30. package/dist/lib/messages/inject.js.map +1 -0
  31. package/dist/lib/messages/prune.d.ts +5 -0
  32. package/dist/lib/messages/prune.d.ts.map +1 -0
  33. package/dist/lib/messages/prune.js +179 -0
  34. package/dist/lib/messages/prune.js.map +1 -0
  35. package/dist/lib/messages/utils.d.ts +10 -0
  36. package/dist/lib/messages/utils.d.ts.map +1 -0
  37. package/dist/lib/messages/utils.js +193 -0
  38. package/dist/lib/messages/utils.js.map +1 -0
  39. package/dist/lib/prompts/agent/rcl-explorer.d.ts +2 -0
  40. package/dist/lib/prompts/agent/rcl-explorer.d.ts.map +1 -0
  41. package/dist/lib/prompts/agent/rcl-explorer.js +39 -0
  42. package/dist/lib/prompts/agent/rcl-explorer.js.map +1 -0
  43. package/dist/lib/prompts/discard-tool-spec.d.ts +2 -0
  44. package/dist/lib/prompts/discard-tool-spec.d.ts.map +1 -0
  45. package/dist/lib/prompts/discard-tool-spec.js +41 -0
  46. package/dist/lib/prompts/discard-tool-spec.js.map +1 -0
  47. package/dist/lib/prompts/extract-tool-spec.d.ts +2 -0
  48. package/dist/lib/prompts/extract-tool-spec.d.ts.map +1 -0
  49. package/dist/lib/prompts/extract-tool-spec.js +48 -0
  50. package/dist/lib/prompts/extract-tool-spec.js.map +1 -0
  51. package/dist/lib/prompts/index.d.ts +2 -0
  52. package/dist/lib/prompts/index.d.ts.map +1 -0
  53. package/dist/lib/prompts/index.js +41 -0
  54. package/dist/lib/prompts/index.js.map +1 -0
  55. package/dist/lib/prompts/nudge/both.d.ts +2 -0
  56. package/dist/lib/prompts/nudge/both.d.ts.map +1 -0
  57. package/dist/lib/prompts/nudge/both.js +11 -0
  58. package/dist/lib/prompts/nudge/both.js.map +1 -0
  59. package/dist/lib/prompts/nudge/discard.d.ts +2 -0
  60. package/dist/lib/prompts/nudge/discard.d.ts.map +1 -0
  61. package/dist/lib/prompts/nudge/discard.js +10 -0
  62. package/dist/lib/prompts/nudge/discard.js.map +1 -0
  63. package/dist/lib/prompts/nudge/extract.d.ts +2 -0
  64. package/dist/lib/prompts/nudge/extract.d.ts.map +1 -0
  65. package/dist/lib/prompts/nudge/extract.js +10 -0
  66. package/dist/lib/prompts/nudge/extract.js.map +1 -0
  67. package/dist/lib/prompts/restore-tool-spec.d.ts +2 -0
  68. package/dist/lib/prompts/restore-tool-spec.d.ts.map +1 -0
  69. package/dist/lib/prompts/restore-tool-spec.js +21 -0
  70. package/dist/lib/prompts/restore-tool-spec.js.map +1 -0
  71. package/dist/lib/prompts/system/both.d.ts +2 -0
  72. package/dist/lib/prompts/system/both.d.ts.map +1 -0
  73. package/dist/lib/prompts/system/both.js +72 -0
  74. package/dist/lib/prompts/system/both.js.map +1 -0
  75. package/dist/lib/prompts/system/core.d.ts +2 -0
  76. package/dist/lib/prompts/system/core.d.ts.map +1 -0
  77. package/dist/lib/prompts/system/core.js +26 -0
  78. package/dist/lib/prompts/system/core.js.map +1 -0
  79. package/dist/lib/prompts/system/discard.d.ts +2 -0
  80. package/dist/lib/prompts/system/discard.d.ts.map +1 -0
  81. package/dist/lib/prompts/system/discard.js +63 -0
  82. package/dist/lib/prompts/system/discard.js.map +1 -0
  83. package/dist/lib/prompts/system/extract.d.ts +2 -0
  84. package/dist/lib/prompts/system/extract.d.ts.map +1 -0
  85. package/dist/lib/prompts/system/extract.js +63 -0
  86. package/dist/lib/prompts/system/extract.js.map +1 -0
  87. package/dist/lib/protected-file-patterns.d.ts +12 -0
  88. package/dist/lib/protected-file-patterns.d.ts.map +1 -0
  89. package/dist/lib/protected-file-patterns.js +69 -0
  90. package/dist/lib/protected-file-patterns.js.map +1 -0
  91. package/dist/lib/pruned-blobs.d.ts +19 -0
  92. package/dist/lib/pruned-blobs.d.ts.map +1 -0
  93. package/dist/lib/pruned-blobs.js +111 -0
  94. package/dist/lib/pruned-blobs.js.map +1 -0
  95. package/dist/lib/rcl-pointer.d.ts +3 -0
  96. package/dist/lib/rcl-pointer.d.ts.map +1 -0
  97. package/dist/lib/rcl-pointer.js +63 -0
  98. package/dist/lib/rcl-pointer.js.map +1 -0
  99. package/dist/lib/restore-tool.d.ts +15 -0
  100. package/dist/lib/restore-tool.d.ts.map +1 -0
  101. package/dist/lib/restore-tool.js +142 -0
  102. package/dist/lib/restore-tool.js.map +1 -0
  103. package/dist/lib/shared-utils.d.ts +4 -0
  104. package/dist/lib/shared-utils.d.ts.map +1 -0
  105. package/dist/lib/shared-utils.js +14 -0
  106. package/dist/lib/shared-utils.js.map +1 -0
  107. package/dist/lib/state/index.d.ts +4 -0
  108. package/dist/lib/state/index.d.ts.map +1 -0
  109. package/dist/lib/state/index.js +4 -0
  110. package/dist/lib/state/index.js.map +1 -0
  111. package/dist/lib/state/persistence.d.ts +16 -0
  112. package/dist/lib/state/persistence.d.ts.map +1 -0
  113. package/dist/lib/state/persistence.js +73 -0
  114. package/dist/lib/state/persistence.js.map +1 -0
  115. package/dist/lib/state/state.d.ts +8 -0
  116. package/dist/lib/state/state.d.ts.map +1 -0
  117. package/dist/lib/state/state.js +114 -0
  118. package/dist/lib/state/state.js.map +1 -0
  119. package/dist/lib/state/tool-cache.d.ts +13 -0
  120. package/dist/lib/state/tool-cache.d.ts.map +1 -0
  121. package/dist/lib/state/tool-cache.js +79 -0
  122. package/dist/lib/state/tool-cache.js.map +1 -0
  123. package/dist/lib/state/types.d.ts +33 -0
  124. package/dist/lib/state/types.d.ts.map +1 -0
  125. package/dist/lib/state/types.js +2 -0
  126. package/dist/lib/state/types.js.map +1 -0
  127. package/dist/lib/state/utils.d.ts +2 -0
  128. package/dist/lib/state/utils.d.ts.map +1 -0
  129. package/dist/lib/state/utils.js +10 -0
  130. package/dist/lib/state/utils.js.map +1 -0
  131. package/dist/lib/strategies/deduplication.d.ts +10 -0
  132. package/dist/lib/strategies/deduplication.d.ts.map +1 -0
  133. package/dist/lib/strategies/deduplication.js +94 -0
  134. package/dist/lib/strategies/deduplication.js.map +1 -0
  135. package/dist/lib/strategies/index.d.ts +5 -0
  136. package/dist/lib/strategies/index.d.ts.map +1 -0
  137. package/dist/lib/strategies/index.js +5 -0
  138. package/dist/lib/strategies/index.js.map +1 -0
  139. package/dist/lib/strategies/purge-errors.d.ts +13 -0
  140. package/dist/lib/strategies/purge-errors.d.ts.map +1 -0
  141. package/dist/lib/strategies/purge-errors.js +59 -0
  142. package/dist/lib/strategies/purge-errors.js.map +1 -0
  143. package/dist/lib/strategies/supersede-writes.d.ts +13 -0
  144. package/dist/lib/strategies/supersede-writes.d.ts.map +1 -0
  145. package/dist/lib/strategies/supersede-writes.js +84 -0
  146. package/dist/lib/strategies/supersede-writes.js.map +1 -0
  147. package/dist/lib/strategies/tools.d.ts +14 -0
  148. package/dist/lib/strategies/tools.d.ts.map +1 -0
  149. package/dist/lib/strategies/tools.js +135 -0
  150. package/dist/lib/strategies/tools.js.map +1 -0
  151. package/dist/lib/strategies/utils.d.ts +13 -0
  152. package/dist/lib/strategies/utils.d.ts.map +1 -0
  153. package/dist/lib/strategies/utils.js +93 -0
  154. package/dist/lib/strategies/utils.js.map +1 -0
  155. package/dist/lib/ui/notification.d.ts +8 -0
  156. package/dist/lib/ui/notification.d.ts.map +1 -0
  157. package/dist/lib/ui/notification.js +54 -0
  158. package/dist/lib/ui/notification.js.map +1 -0
  159. package/dist/lib/ui/utils.d.ts +15 -0
  160. package/dist/lib/ui/utils.d.ts.map +1 -0
  161. package/dist/lib/ui/utils.js +87 -0
  162. package/dist/lib/ui/utils.js.map +1 -0
  163. package/package.json +63 -0
@@ -0,0 +1,69 @@
1
+ function normalizePath(input) {
2
+ return input.replaceAll("\\\\", "/");
3
+ }
4
+ function escapeRegExpChar(ch) {
5
+ return /[\\.^$+{}()|\[\]]/.test(ch) ? `\\${ch}` : ch;
6
+ }
7
+ /**
8
+ * Basic glob matching with support for `**`, `*`, and `?`.
9
+ *
10
+ * Notes:
11
+ * - Matching is performed against the full (normalized) string.
12
+ * - `*` and `?` do not match `/`.
13
+ * - `**` matches across `/`.
14
+ */
15
+ export function matchesGlob(inputPath, pattern) {
16
+ if (!pattern)
17
+ return false;
18
+ const input = normalizePath(inputPath);
19
+ const pat = normalizePath(pattern);
20
+ let regex = "^";
21
+ for (let i = 0; i < pat.length; i++) {
22
+ const ch = pat[i];
23
+ if (ch === "*") {
24
+ const next = pat[i + 1];
25
+ if (next === "*") {
26
+ const after = pat[i + 2];
27
+ if (after === "/") {
28
+ // **/ (zero or more directories)
29
+ regex += "(?:.*/)?";
30
+ i += 2;
31
+ continue;
32
+ }
33
+ // **
34
+ regex += ".*";
35
+ i++;
36
+ continue;
37
+ }
38
+ // *
39
+ regex += "[^/]*";
40
+ continue;
41
+ }
42
+ if (ch === "?") {
43
+ regex += "[^/]";
44
+ continue;
45
+ }
46
+ if (ch === "/") {
47
+ regex += "/";
48
+ continue;
49
+ }
50
+ regex += escapeRegExpChar(ch);
51
+ }
52
+ regex += "$";
53
+ return new RegExp(regex).test(input);
54
+ }
55
+ export function getFilePathFromParameters(parameters) {
56
+ if (typeof parameters !== "object" || parameters === null) {
57
+ return undefined;
58
+ }
59
+ const filePath = parameters.filePath;
60
+ return typeof filePath === "string" && filePath.length > 0 ? filePath : undefined;
61
+ }
62
+ export function isProtectedFilePath(filePath, patterns) {
63
+ if (!filePath)
64
+ return false;
65
+ if (!patterns || patterns.length === 0)
66
+ return false;
67
+ return patterns.some((pattern) => matchesGlob(filePath, pattern));
68
+ }
69
+ //# sourceMappingURL=protected-file-patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protected-file-patterns.js","sourceRoot":"","sources":["../../lib/protected-file-patterns.ts"],"names":[],"mappings":"AAAA,SAAS,aAAa,CAAC,KAAa;IAChC,OAAO,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AACxC,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAU;IAChC,OAAO,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AACxD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB,EAAE,OAAe;IAC1D,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAE1B,MAAM,KAAK,GAAG,aAAa,CAAC,SAAS,CAAC,CAAA;IACtC,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IAElC,IAAI,KAAK,GAAG,GAAG,CAAA;IAEf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;QAEjB,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YACvB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACf,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;gBACxB,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBAChB,kCAAkC;oBAClC,KAAK,IAAI,UAAU,CAAA;oBACnB,CAAC,IAAI,CAAC,CAAA;oBACN,SAAQ;gBACZ,CAAC;gBAED,KAAK;gBACL,KAAK,IAAI,IAAI,CAAA;gBACb,CAAC,EAAE,CAAA;gBACH,SAAQ;YACZ,CAAC;YAED,IAAI;YACJ,KAAK,IAAI,OAAO,CAAA;YAChB,SAAQ;QACZ,CAAC;QAED,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACb,KAAK,IAAI,MAAM,CAAA;YACf,SAAQ;QACZ,CAAC;QAED,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACb,KAAK,IAAI,GAAG,CAAA;YACZ,SAAQ;QACZ,CAAC;QAED,KAAK,IAAI,gBAAgB,CAAC,EAAE,CAAC,CAAA;IACjC,CAAC;IAED,KAAK,IAAI,GAAG,CAAA;IAEZ,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,UAAmB;IACzD,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxD,OAAO,SAAS,CAAA;IACpB,CAAC;IAED,MAAM,QAAQ,GAAI,UAAsC,CAAC,QAAQ,CAAA;IACjE,OAAO,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAA;AACrF,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAA4B,EAAE,QAAkB;IAChF,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3B,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAEpD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;AACrE,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { Logger } from "./logger";
2
+ export type PrunedBlobKind = "tool-output" | "tool-input";
3
+ export interface PrunedBlobFile {
4
+ version: 1;
5
+ kind: PrunedBlobKind;
6
+ savedAt: string;
7
+ sessionId: string;
8
+ callID: string;
9
+ data: unknown;
10
+ }
11
+ export declare function getRclBlobsDir(workingDirectory: string, logger?: Logger): string;
12
+ export declare function getBlobPath(workingDirectory: string, sessionId: string, callID: string, kind: PrunedBlobKind): string;
13
+ /**
14
+ * Writes the blob file only once (idempotent). Returns absolute file path.
15
+ * If sessionId is missing (e.g., very early) or the write fails, returns null.
16
+ */
17
+ export declare function saveBlobIfMissing(sessionId: string | null, callID: string, kind: PrunedBlobKind, data: unknown, workingDirectory: string, logger?: Logger): string | null;
18
+ export declare function formatBlobPointer(blobPath: string, workingDirectory?: string): string;
19
+ //# sourceMappingURL=pruned-blobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pruned-blobs.d.ts","sourceRoot":"","sources":["../../lib/pruned-blobs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAWtC,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,YAAY,CAAA;AAEzD,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,CAAC,CAAA;IACV,IAAI,EAAE,cAAc,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,OAAO,CAAA;CAChB;AA+CD,wBAAgB,cAAc,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAKhF;AAED,wBAAgB,WAAW,CACvB,gBAAgB,EAAE,MAAM,EACxB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,cAAc,GACrB,MAAM,CAKR;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,OAAO,EACb,gBAAgB,EAAE,MAAM,EACxB,MAAM,CAAC,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAkCf;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAUrF"}
@@ -0,0 +1,111 @@
1
+ import { existsSync, mkdirSync, statSync, writeFileSync } from "fs";
2
+ import { dirname, join, relative } from "path";
3
+ /**
4
+ * Stores pruned tool content on disk and returns a file pointer that can be
5
+ * re-read later if needed.
6
+ *
7
+ * Project-local storage:
8
+ * <project>/.opencode/rcl/blobs/<sessionId>/
9
+ */
10
+ const BLOBS_SUBDIR = join("rcl", "blobs");
11
+ function ensureDir(path) {
12
+ if (!existsSync(path)) {
13
+ mkdirSync(path, { recursive: true });
14
+ }
15
+ }
16
+ function normalizePathForTool(p) {
17
+ // OpenCode tools typically accept POSIX-style paths, even on Windows.
18
+ return p.replaceAll("\\", "/");
19
+ }
20
+ function findOrCreateOpencodeDir(startDir, logger) {
21
+ let current = startDir;
22
+ // Walk upwards looking for an existing `.opencode` directory.
23
+ for (let i = 0; i < 100; i++) {
24
+ const candidate = join(current, ".opencode");
25
+ if (existsSync(candidate)) {
26
+ try {
27
+ if (statSync(candidate).isDirectory()) {
28
+ return candidate;
29
+ }
30
+ }
31
+ catch { }
32
+ }
33
+ const parent = dirname(current);
34
+ if (parent === current) {
35
+ break;
36
+ }
37
+ current = parent;
38
+ }
39
+ // Fallback: create `.opencode` in the current working directory.
40
+ const fallback = join(startDir, ".opencode");
41
+ try {
42
+ ensureDir(fallback);
43
+ }
44
+ catch (err) {
45
+ logger?.warn("Failed to create .opencode directory for Recall blob storage", {
46
+ startDir,
47
+ error: err?.message ?? String(err),
48
+ });
49
+ }
50
+ return fallback;
51
+ }
52
+ export function getRclBlobsDir(workingDirectory, logger) {
53
+ const opencodeDir = findOrCreateOpencodeDir(workingDirectory, logger);
54
+ const blobsDir = join(opencodeDir, BLOBS_SUBDIR);
55
+ ensureDir(blobsDir);
56
+ return blobsDir;
57
+ }
58
+ export function getBlobPath(workingDirectory, sessionId, callID, kind) {
59
+ // callID/sessionId in OpenCode are already safe-ish, but keep it defensive.
60
+ const safeCallId = callID.replaceAll("/", "_");
61
+ const suffix = kind === "tool-output" ? "output.json" : "input.json";
62
+ return join(getRclBlobsDir(workingDirectory), sessionId, `${safeCallId}.${suffix}`);
63
+ }
64
+ /**
65
+ * Writes the blob file only once (idempotent). Returns absolute file path.
66
+ * If sessionId is missing (e.g., very early) or the write fails, returns null.
67
+ */
68
+ export function saveBlobIfMissing(sessionId, callID, kind, data, workingDirectory, logger) {
69
+ if (!sessionId) {
70
+ return null;
71
+ }
72
+ try {
73
+ const sessionDir = join(getRclBlobsDir(workingDirectory, logger), sessionId);
74
+ ensureDir(sessionDir);
75
+ const blobPath = getBlobPath(workingDirectory, sessionId, callID, kind);
76
+ if (existsSync(blobPath)) {
77
+ return blobPath;
78
+ }
79
+ const blob = {
80
+ version: 1,
81
+ kind,
82
+ savedAt: new Date().toISOString(),
83
+ sessionId,
84
+ callID,
85
+ data,
86
+ };
87
+ writeFileSync(blobPath, JSON.stringify(blob, null, 2), "utf-8");
88
+ return blobPath;
89
+ }
90
+ catch (err) {
91
+ logger?.warn("Failed to persist pruned blob", {
92
+ sessionId,
93
+ callID,
94
+ kind,
95
+ error: err?.message ?? String(err),
96
+ });
97
+ return null;
98
+ }
99
+ }
100
+ export function formatBlobPointer(blobPath, workingDirectory) {
101
+ // Prefer a project-relative pointer to avoid leaking home-directory paths and to improve portability.
102
+ if (workingDirectory) {
103
+ try {
104
+ const rel = relative(workingDirectory, blobPath);
105
+ return normalizePathForTool(rel);
106
+ }
107
+ catch { }
108
+ }
109
+ return normalizePathForTool(blobPath);
110
+ }
111
+ //# sourceMappingURL=pruned-blobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pruned-blobs.js","sourceRoot":"","sources":["../../lib/pruned-blobs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function extractToolOutputPath(input: string): string;
2
+ export declare function extractRclBlobPath(input: string): string;
3
+ //# sourceMappingURL=rcl-pointer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rcl-pointer.d.ts","sourceRoot":"","sources":["../../lib/rcl-pointer.ts"],"names":[],"mappings":"AAyBA,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAsB3D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBxD"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Extracts a Recall (RCL) blob file path from:
3
+ * - a raw path: ".opencode/rcl/blobs/<sessionId>/<callId>.output.json"
4
+ * - a pointer: "[RCL:o:<path>]" / "[RCL:i:<path>]"
5
+ * - a string that contains such a pointer, possibly with extra annotations.
6
+ * - an OpenCode truncation notice like: "Full output saved to: /.../tool-output/..."
7
+ *
8
+ * This is intentionally lenient so users (and models) can paste the whole
9
+ * pointer block (e.g. with size notes) into tools like rcl_restore/rcl_explore.
10
+ */
11
+ const FULL_OUTPUT_SAVED_RE = /Full output saved to:\s*(.+?)(?:\s*$|\n)/i;
12
+ function sanitizePath(raw) {
13
+ return raw
14
+ .trim()
15
+ .replace(/^["'`]/, "")
16
+ .replace(/["'`),\]]+$/, "")
17
+ .replaceAll("\\", "/");
18
+ }
19
+ function isToolOutputPath(raw) {
20
+ const normalized = raw.replaceAll("\\", "/");
21
+ return normalized.includes("/tool-output/") || normalized.startsWith("tool-output/");
22
+ }
23
+ export function extractToolOutputPath(input) {
24
+ const trimmed = String(input ?? "").trim();
25
+ if (!trimmed)
26
+ return "";
27
+ const pointerMatch = trimmed.match(/\[RCL:[oi]:(.+?)\]/);
28
+ if (pointerMatch?.[1]) {
29
+ const candidate = sanitizePath(pointerMatch[1]);
30
+ if (candidate && isToolOutputPath(candidate))
31
+ return candidate;
32
+ }
33
+ const match = trimmed.match(FULL_OUTPUT_SAVED_RE);
34
+ if (match?.[1]) {
35
+ const candidate = sanitizePath(match[1]);
36
+ if (candidate && isToolOutputPath(candidate))
37
+ return candidate;
38
+ }
39
+ const hasWhitespace = /\s/.test(trimmed);
40
+ if (!hasWhitespace && isToolOutputPath(trimmed)) {
41
+ return sanitizePath(trimmed);
42
+ }
43
+ return "";
44
+ }
45
+ export function extractRclBlobPath(input) {
46
+ const trimmed = String(input ?? "").trim();
47
+ if (!trimmed)
48
+ return "";
49
+ // Exact pointer match.
50
+ const full = trimmed.match(/^\[RCL:[oi]:(.+)\]$/);
51
+ if (full?.[1])
52
+ return full[1].trim();
53
+ // Pointer embedded in a larger string (e.g. "[RCL:o:...]\n(note...)").
54
+ const embedded = trimmed.match(/\[RCL:[oi]:(.+?)\]/);
55
+ if (embedded?.[1])
56
+ return embedded[1].trim();
57
+ const toolOutputPath = extractToolOutputPath(trimmed);
58
+ if (toolOutputPath)
59
+ return toolOutputPath;
60
+ // Assume it's already a path.
61
+ return trimmed;
62
+ }
63
+ //# sourceMappingURL=rcl-pointer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rcl-pointer.js","sourceRoot":"","sources":["../../lib/rcl-pointer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,oBAAoB,GAAG,2CAA2C,CAAA;AAExE,SAAS,YAAY,CAAC,GAAW;IAC7B,OAAO,GAAG;SACL,IAAI,EAAE;SACN,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAC9B,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACjC,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC5C,OAAO,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,cAAc,CAAC,CAAA;AACxF,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAa;IAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC1C,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAA;IAEvB,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACxD,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;QAC/C,IAAI,SAAS,IAAI,gBAAgB,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAA;IAClE,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACjD,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACb,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QACxC,IAAI,SAAS,IAAI,gBAAgB,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAA;IAClE,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxC,IAAI,CAAC,aAAa,IAAI,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,OAAO,YAAY,CAAC,OAAO,CAAC,CAAA;IAChC,CAAC;IAED,OAAO,EAAE,CAAA;AACb,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC1C,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAA;IAEvB,uBAAuB;IACvB,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAA;IACjD,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAEpC,uEAAuE;IACvE,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACpD,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAE5C,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAA;IACrD,IAAI,cAAc;QAAE,OAAO,cAAc,CAAA;IAEzC,8BAA8B;IAC9B,OAAO,OAAO,CAAA;AAClB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { tool } from "@opencode-ai/plugin";
2
+ import type { Logger } from "./logger";
3
+ export interface RestoreToolContext {
4
+ logger: Logger;
5
+ workingDirectory: string;
6
+ config: {
7
+ tools: {
8
+ settings: {
9
+ restoreMaxBytes: number;
10
+ };
11
+ };
12
+ };
13
+ }
14
+ export declare function createRestoreTool(ctx: RestoreToolContext): ReturnType<typeof tool>;
15
+ //# sourceMappingURL=restore-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restore-tool.d.ts","sourceRoot":"","sources":["../../lib/restore-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAG1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAOtC,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,gBAAgB,EAAE,MAAM,CAAA;IACxB,MAAM,EAAE;QAAE,KAAK,EAAE;YAAE,QAAQ,EAAE;gBAAE,eAAe,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,CAAA;KAAE,CAAA;CAC/D;AAoDD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,kBAAkB,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAkGlF"}
@@ -0,0 +1,142 @@
1
+ import { tool } from "@opencode-ai/plugin";
2
+ import { readFileSync, statSync } from "fs";
3
+ import { isAbsolute, resolve, sep } from "path";
4
+ import { getRclBlobsDir } from "./pruned-blobs";
5
+ import { loadPrompt } from "./prompts";
6
+ import { extractRclBlobPath, extractToolOutputPath } from "./rcl-pointer";
7
+ const RESTORE_TOOL_DESCRIPTION = loadPrompt("restore-tool-spec");
8
+ function isUnderDir(filePath, dirPath) {
9
+ const file = resolve(filePath);
10
+ const dir = resolve(dirPath);
11
+ return file === dir || file.startsWith(dir + sep);
12
+ }
13
+ function parseBlobFile(raw) {
14
+ try {
15
+ const parsed = JSON.parse(raw);
16
+ if (!parsed || typeof parsed !== "object")
17
+ return null;
18
+ if (parsed.version !== 1)
19
+ return null;
20
+ if (!("data" in parsed))
21
+ return null;
22
+ return parsed;
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ function readFileSize(filePath) {
29
+ try {
30
+ const stats = statSync(filePath);
31
+ return typeof stats.size === "number" ? stats.size : null;
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ function shouldBlockLargeRestore(size, maxBytes, force) {
38
+ if (force)
39
+ return false;
40
+ if (size === null)
41
+ return false;
42
+ return size > maxBytes;
43
+ }
44
+ function formatBytes(size) {
45
+ if (size === null || !Number.isFinite(size))
46
+ return "unknown";
47
+ if (size < 1000)
48
+ return `${size}B`;
49
+ if (size < 1_000_000)
50
+ return `${(size / 1000).toFixed(1).replace(/\.0$/, "")}KB`;
51
+ if (size < 1_000_000_000)
52
+ return `${(size / 1_000_000).toFixed(1).replace(/\.0$/, "")}MB`;
53
+ return `${(size / 1_000_000_000).toFixed(1).replace(/\.0$/, "")}GB`;
54
+ }
55
+ function buildLargeRestoreWarning(path, size, reason) {
56
+ const sizeLabel = formatBytes(size);
57
+ return (`Refusing to restore large content (${sizeLabel}). ${reason}\n` +
58
+ `Prefer: rcl_explore(path="${path}", question="<what to find?>")\n` +
59
+ `Override: rcl_restore(path="${path}", force=true)`);
60
+ }
61
+ export function createRestoreTool(ctx) {
62
+ return tool({
63
+ description: RESTORE_TOOL_DESCRIPTION,
64
+ args: {
65
+ path: tool.schema
66
+ .string()
67
+ .describe("A Recall blob path (or [RCL:o:...] / [RCL:i:...] pointer), or an OpenCode tool-output path / truncation line."),
68
+ force: tool.schema
69
+ .boolean()
70
+ .optional()
71
+ .describe("Allow restoring large blobs into the main context. If false, use rcl_explore instead."),
72
+ },
73
+ async execute(args) {
74
+ const rawArg = String(args.path ?? "").trim();
75
+ if (!rawArg) {
76
+ return "Missing required argument: path";
77
+ }
78
+ const toolOutputPath = extractToolOutputPath(rawArg);
79
+ if (toolOutputPath) {
80
+ const absPath = isAbsolute(toolOutputPath)
81
+ ? resolve(toolOutputPath)
82
+ : resolve(ctx.workingDirectory, toolOutputPath);
83
+ const fileSize = readFileSize(absPath);
84
+ const maxBytes = ctx.config?.tools?.settings?.restoreMaxBytes ?? 8000;
85
+ if (shouldBlockLargeRestore(fileSize, maxBytes, args.force)) {
86
+ return buildLargeRestoreWarning(toolOutputPath, fileSize, "This tool output looks large; use rcl_explore to avoid bloating context.");
87
+ }
88
+ try {
89
+ return readFileSync(absPath, "utf-8");
90
+ }
91
+ catch (err) {
92
+ ctx.logger.warn("rcl_restore failed to read tool-output file", {
93
+ path: absPath,
94
+ error: err?.message ?? String(err),
95
+ });
96
+ return `Failed to restore tool output: ${err?.message ?? String(err)}`;
97
+ }
98
+ }
99
+ const inputPath = extractRclBlobPath(rawArg);
100
+ if (!inputPath || typeof inputPath !== "string") {
101
+ return "Missing required argument: path";
102
+ }
103
+ // Resolve relative paths against the project working directory.
104
+ const absPath = isAbsolute(inputPath)
105
+ ? resolve(inputPath)
106
+ : resolve(ctx.workingDirectory, inputPath);
107
+ // Security guard: only allow restoring from the Recall blobs directory.
108
+ const blobsDir = getRclBlobsDir(ctx.workingDirectory, ctx.logger);
109
+ if (!isUnderDir(absPath, blobsDir)) {
110
+ return `Invalid path. Only files under ${blobsDir} can be restored.`;
111
+ }
112
+ if (!absPath.endsWith(".output.json") && !absPath.endsWith(".input.json")) {
113
+ return "Invalid blob file. Expected a *.output.json or *.input.json file.";
114
+ }
115
+ const fileSize = readFileSize(absPath);
116
+ const maxBytes = ctx.config?.tools?.settings?.restoreMaxBytes ?? 8000;
117
+ if (shouldBlockLargeRestore(fileSize, maxBytes, args.force)) {
118
+ return buildLargeRestoreWarning(inputPath, fileSize, "This blob looks large; use rcl_explore to avoid bloating context.");
119
+ }
120
+ try {
121
+ const raw = readFileSync(absPath, "utf-8");
122
+ const blob = parseBlobFile(raw);
123
+ if (!blob) {
124
+ return "Invalid blob file format.";
125
+ }
126
+ const data = blob.data;
127
+ if (typeof data === "string") {
128
+ return data;
129
+ }
130
+ return JSON.stringify(data, null, 2);
131
+ }
132
+ catch (err) {
133
+ ctx.logger.warn("rcl_restore failed", {
134
+ path: absPath,
135
+ error: err?.message ?? String(err),
136
+ });
137
+ return `Failed to restore blob: ${err?.message ?? String(err)}`;
138
+ }
139
+ },
140
+ });
141
+ }
142
+ //# sourceMappingURL=restore-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restore-tool.js","sourceRoot":"","sources":["../../lib/restore-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAE/C,OAAO,EAAE,cAAc,EAAuB,MAAM,gBAAgB,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAEzE,MAAM,wBAAwB,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAA;AAQhE,SAAS,UAAU,CAAC,QAAgB,EAAE,OAAe;IACjD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5B,OAAO,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,CAAA;AACrD,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAC9B,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC9B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QACtD,IAAK,MAAc,CAAC,OAAO,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QAC9C,IAAI,CAAC,CAAC,MAAM,IAAK,MAAc,CAAC;YAAE,OAAO,IAAI,CAAA;QAC7C,OAAO,MAAwB,CAAA;IACnC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAA;IACf,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB;IAClC,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAChC,OAAO,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;IAC7D,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAA;IACf,CAAC;AACL,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAmB,EAAE,QAAgB,EAAE,KAAe;IACnF,IAAI,KAAK;QAAE,OAAO,KAAK,CAAA;IACvB,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IAC/B,OAAO,IAAI,GAAG,QAAQ,CAAA;AAC1B,CAAC;AAED,SAAS,WAAW,CAAC,IAAmB;IACpC,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAA;IAC7D,IAAI,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,IAAI,GAAG,CAAA;IAClC,IAAI,IAAI,GAAG,SAAS;QAAE,OAAO,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAA;IAChF,IAAI,IAAI,GAAG,aAAa;QAAE,OAAO,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAA;IACzF,OAAO,GAAG,CAAC,IAAI,GAAG,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAA;AACvE,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAY,EAAE,IAAmB,EAAE,MAAc;IAC/E,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,CAAA;IACnC,OAAO,CACH,sCAAsC,SAAS,MAAM,MAAM,IAAI;QAC/D,6BAA6B,IAAI,kCAAkC;QACnE,+BAA+B,IAAI,gBAAgB,CACtD,CAAA;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAuB;IACrD,OAAO,IAAI,CAAC;QACR,WAAW,EAAE,wBAAwB;QACrC,IAAI,EAAE;YACF,IAAI,EAAE,IAAI,CAAC,MAAM;iBACZ,MAAM,EAAE;iBACR,QAAQ,CACL,+GAA+G,CAClH;YACL,KAAK,EAAE,IAAI,CAAC,MAAM;iBACb,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,QAAQ,CACL,uFAAuF,CAC1F;SACR;QACD,KAAK,CAAC,OAAO,CAAC,IAAI;YACd,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;YAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACV,OAAO,iCAAiC,CAAA;YAC5C,CAAC;YAED,MAAM,cAAc,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAA;YACpD,IAAI,cAAc,EAAE,CAAC;gBACjB,MAAM,OAAO,GAAG,UAAU,CAAC,cAAc,CAAC;oBACtC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;oBACzB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAA;gBACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;gBACtC,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,IAAI,IAAI,CAAA;gBACrE,IAAI,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC1D,OAAO,wBAAwB,CAC3B,cAAc,EACd,QAAQ,EACR,0EAA0E,CAC7E,CAAA;gBACL,CAAC;gBACD,IAAI,CAAC;oBACD,OAAO,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;gBACzC,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAChB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,6CAA6C,EAAE;wBAC3D,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC;qBACrC,CAAC,CAAA;oBACF,OAAO,kCAAkC,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAA;gBAC1E,CAAC;YACL,CAAC;YAED,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;YAC5C,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;gBAC9C,OAAO,iCAAiC,CAAA;YAC5C,CAAC;YAED,gEAAgE;YAChE,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC;gBACjC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;gBACpB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAA;YAE9C,wEAAwE;YACxE,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;YACjE,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACjC,OAAO,kCAAkC,QAAQ,mBAAmB,CAAA;YACxE,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACxE,OAAO,mEAAmE,CAAA;YAC9E,CAAC;YAED,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;YACtC,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,IAAI,IAAI,CAAA;YACrE,IAAI,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1D,OAAO,wBAAwB,CAC3B,SAAS,EACT,QAAQ,EACR,mEAAmE,CACtE,CAAA;YACL,CAAC;YAED,IAAI,CAAC;gBACD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;gBAC1C,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;gBAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;oBACR,OAAO,2BAA2B,CAAA;gBACtC,CAAC;gBAED,MAAM,IAAI,GAAI,IAAY,CAAC,IAAI,CAAA;gBAC/B,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC3B,OAAO,IAAI,CAAA;gBACf,CAAC;gBACD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;YACxC,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAChB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE;oBAClC,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC;iBACrC,CAAC,CAAA;gBACF,OAAO,2BAA2B,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAA;YACnE,CAAC;QACL,CAAC;KACJ,CAAC,CAAA;AACN,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { SessionState, WithParts } from "./state";
2
+ export declare const isMessageCompacted: (state: SessionState, msg: WithParts) => boolean;
3
+ export declare const getLastUserMessage: (messages: WithParts[]) => WithParts | null;
4
+ //# sourceMappingURL=shared-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-utils.d.ts","sourceRoot":"","sources":["../../lib/shared-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAGjD,eAAO,MAAM,kBAAkB,GAAI,OAAO,YAAY,EAAE,KAAK,SAAS,KAAG,OAExE,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,UAAU,SAAS,EAAE,KAAG,SAAS,GAAG,IAQtE,CAAA"}
@@ -0,0 +1,14 @@
1
+ import { isIgnoredUserMessage } from "./messages/utils";
2
+ export const isMessageCompacted = (state, msg) => {
3
+ return msg.info.time.created < state.lastCompaction;
4
+ };
5
+ export const getLastUserMessage = (messages) => {
6
+ for (let i = messages.length - 1; i >= 0; i--) {
7
+ const msg = messages[i];
8
+ if (msg.info.role === "user" && !isIgnoredUserMessage(msg)) {
9
+ return msg;
10
+ }
11
+ }
12
+ return null;
13
+ };
14
+ //# sourceMappingURL=shared-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-utils.js","sourceRoot":"","sources":["../../lib/shared-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAEvD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAmB,EAAE,GAAc,EAAW,EAAE;IAC/E,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,cAAc,CAAA;AACvD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAqB,EAAoB,EAAE;IAC1E,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QACvB,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC;YACzD,OAAO,GAAG,CAAA;QACd,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAA;AACf,CAAC,CAAA"}
@@ -0,0 +1,4 @@
1
+ export * from "./persistence";
2
+ export * from "./types";
3
+ export * from "./state";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/state/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
@@ -0,0 +1,4 @@
1
+ export * from "./persistence";
2
+ export * from "./types";
3
+ export * from "./state";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/state/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * State persistence module for Recall (RCL).
3
+ * Persists pruned tool IDs across sessions so they survive OpenCode restarts.
4
+ * Storage location: ~/.local/share/opencode/storage/plugin/rcl/{sessionId}.json
5
+ */
6
+ import type { SessionState, SessionStats, Prune } from "./types";
7
+ import type { Logger } from "../logger";
8
+ export interface PersistedSessionState {
9
+ sessionName?: string;
10
+ prune: Prune;
11
+ stats: SessionStats;
12
+ lastUpdated: string;
13
+ }
14
+ export declare function saveSessionState(sessionState: SessionState, logger: Logger, sessionName?: string): Promise<void>;
15
+ export declare function loadSessionState(sessionId: string, logger: Logger): Promise<PersistedSessionState | null>;
16
+ //# sourceMappingURL=persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../lib/state/persistence.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAEvC,MAAM,WAAW,qBAAqB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,KAAK,CAAA;IACZ,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACtB;AAcD,wBAAsB,gBAAgB,CAClC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,EACd,WAAW,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CA8BvC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * State persistence module for Recall (RCL).
3
+ * Persists pruned tool IDs across sessions so they survive OpenCode restarts.
4
+ * Storage location: ~/.local/share/opencode/storage/plugin/rcl/{sessionId}.json
5
+ */
6
+ import * as fs from "fs/promises";
7
+ import { existsSync } from "fs";
8
+ import { homedir } from "os";
9
+ import { join } from "path";
10
+ const STORAGE_DIR = join(homedir(), ".local", "share", "opencode", "storage", "plugin", "rcl");
11
+ async function ensureStorageDir() {
12
+ if (!existsSync(STORAGE_DIR)) {
13
+ await fs.mkdir(STORAGE_DIR, { recursive: true });
14
+ }
15
+ }
16
+ function getSessionFilePath(sessionId) {
17
+ return join(STORAGE_DIR, `${sessionId}.json`);
18
+ }
19
+ export async function saveSessionState(sessionState, logger, sessionName) {
20
+ try {
21
+ if (!sessionState.sessionId) {
22
+ return;
23
+ }
24
+ await ensureStorageDir();
25
+ const state = {
26
+ sessionName: sessionName,
27
+ prune: sessionState.prune,
28
+ stats: sessionState.stats,
29
+ lastUpdated: new Date().toISOString(),
30
+ };
31
+ const filePath = getSessionFilePath(sessionState.sessionId);
32
+ const content = JSON.stringify(state, null, 2);
33
+ await fs.writeFile(filePath, content, "utf-8");
34
+ logger.info("Saved session state to disk", {
35
+ sessionId: sessionState.sessionId,
36
+ totalTokensSaved: state.stats.totalPruneTokens,
37
+ });
38
+ }
39
+ catch (error) {
40
+ logger.error("Failed to save session state", {
41
+ sessionId: sessionState.sessionId,
42
+ error: error?.message,
43
+ });
44
+ }
45
+ }
46
+ export async function loadSessionState(sessionId, logger) {
47
+ try {
48
+ const filePath = getSessionFilePath(sessionId);
49
+ if (!existsSync(filePath)) {
50
+ return null;
51
+ }
52
+ const content = await fs.readFile(filePath, "utf-8");
53
+ const state = JSON.parse(content);
54
+ if (!state || !state.prune || !Array.isArray(state.prune.toolIds) || !state.stats) {
55
+ logger.warn("Invalid session state file, ignoring", {
56
+ sessionId: sessionId,
57
+ });
58
+ return null;
59
+ }
60
+ logger.info("Loaded session state from disk", {
61
+ sessionId: sessionId,
62
+ });
63
+ return state;
64
+ }
65
+ catch (error) {
66
+ logger.warn("Failed to load session state", {
67
+ sessionId: sessionId,
68
+ error: error?.message,
69
+ });
70
+ return null;
71
+ }
72
+ }
73
+ //# sourceMappingURL=persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../../lib/state/persistence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { SessionState, WithParts } from "./types";
2
+ import type { Logger } from "../logger";
3
+ export declare const checkSession: (client: any, state: SessionState, logger: Logger, messages: WithParts[]) => Promise<void>;
4
+ export declare function createSessionState(): SessionState;
5
+ export declare function resetSessionState(state: SessionState): void;
6
+ export declare function ensureSessionInitialized(client: any, state: SessionState, sessionId: string, logger: Logger, messages: WithParts[]): Promise<void>;
7
+ export declare function countTurns(state: SessionState, messages: WithParts[]): number;
8
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../lib/state/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAsB,SAAS,EAAE,MAAM,SAAS,CAAA;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAKvC,eAAO,MAAM,YAAY,GACrB,QAAQ,GAAG,EACX,OAAO,YAAY,EACnB,QAAQ,MAAM,EACd,UAAU,SAAS,EAAE,KACtB,OAAO,CAAC,IAAI,CA4Bd,CAAA;AAED,wBAAgB,kBAAkB,IAAI,YAAY,CAkBjD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAgB3D;AAED,wBAAsB,wBAAwB,CAC1C,MAAM,EAAE,GAAG,EACX,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,SAAS,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAYD,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,CAa7E"}