@lapis-notes/ai 0.1.2 → 0.1.5

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 (69) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE.md +3 -7
  3. package/README.md +1 -1
  4. package/dist/ai-plugin.d.ts +2 -2
  5. package/dist/ai-plugin.js +28 -11
  6. package/dist/catalog/ai-catalog-panel.svelte +20 -3
  7. package/dist/chat/ai-chat-panel.svelte +187 -87
  8. package/dist/chat/ai-chat-panel.svelte.d.ts +2 -0
  9. package/dist/chat/ai-view-bootstrap.d.ts +1 -0
  10. package/dist/chat/ai-view-bootstrap.js +32 -12
  11. package/dist/chat/ai-view-panel.svelte +14 -0
  12. package/dist/chat/ai-view.d.ts +1 -1
  13. package/dist/chat/chat-controller.svelte.d.ts +1 -1
  14. package/dist/chat/chat-controller.svelte.js +94 -29
  15. package/dist/chat/chat-tool-display.d.ts +2 -12
  16. package/dist/chat/chat-tool-display.js +2 -206
  17. package/dist/chat/composer-model-catalog.d.ts +20 -0
  18. package/dist/chat/composer-model-catalog.js +44 -0
  19. package/dist/commands/agent.d.ts +1 -1
  20. package/dist/commands/agent.js +6 -1
  21. package/dist/conversations/context-handoff.d.ts +1 -25
  22. package/dist/conversations/context-handoff.js +1 -207
  23. package/dist/conversations/hashes.d.ts +1 -5
  24. package/dist/conversations/hashes.js +1 -40
  25. package/dist/core/types.d.ts +1 -241
  26. package/dist/core/types.js +1 -50
  27. package/dist/history/ai-history-panel.svelte +4 -1
  28. package/dist/host/controller-connection.d.ts +14 -0
  29. package/dist/host/controller-connection.js +62 -0
  30. package/dist/host/controller-runtime.d.ts +13 -0
  31. package/dist/host/controller-runtime.js +112 -0
  32. package/dist/host/create-host-runtimes.d.ts +2 -1
  33. package/dist/host/create-host-runtimes.js +5 -7
  34. package/dist/index.d.ts +1 -1
  35. package/dist/memory/candidate-extractor.d.ts +2 -25
  36. package/dist/memory/candidate-extractor.js +1 -191
  37. package/dist/memory/hashes.d.ts +1 -5
  38. package/dist/memory/hashes.js +1 -37
  39. package/dist/memory/memory-record-store.d.ts +3 -48
  40. package/dist/memory/memory-record-store.js +16 -220
  41. package/dist/memory/memory-scheduler.d.ts +1 -21
  42. package/dist/memory/memory-scheduler.js +1 -143
  43. package/dist/memory/native-memory-service.d.ts +1 -72
  44. package/dist/memory/native-memory-service.js +1 -1256
  45. package/dist/memory/paths.d.ts +1 -13
  46. package/dist/memory/paths.js +1 -60
  47. package/dist/memory/runtime-consolidation-provider.d.ts +2 -18
  48. package/dist/memory/runtime-consolidation-provider.js +1 -154
  49. package/dist/memory/types.d.ts +1 -139
  50. package/dist/providers/acp-model-provider.d.ts +8 -3
  51. package/dist/providers/acp-model-provider.js +21 -49
  52. package/dist/providers/model-provider.d.ts +3 -2
  53. package/dist/providers/model-provider.js +15 -2
  54. package/dist/runtime-adapters.d.ts +3 -0
  55. package/dist/runtime-adapters.js +2 -0
  56. package/dist/settings/acp-agents.d.ts +4 -1
  57. package/dist/settings/acp-agents.js +5 -1
  58. package/dist/settings/ai-settings-tab.js +8 -6
  59. package/dist/settings/ai-settings.d.ts +4 -4
  60. package/dist/settings/ai-settings.js +5 -3
  61. package/dist/settings/register-ai-settings.js +27 -14
  62. package/dist/tools/app-tool-host.d.ts +22 -2
  63. package/dist/tools/app-tool-host.js +51 -4
  64. package/dist/tools/desktop-app-tool-bridge.d.ts +4 -1
  65. package/dist/tools/desktop-app-tool-bridge.js +94 -157
  66. package/manifest.json +20 -2
  67. package/package.json +17 -7
  68. package/registry-content/overview.md +10 -0
  69. package/registry.json +211 -2
@@ -69,6 +69,7 @@ export class AiChatController {
69
69
  #onComposerDefaults;
70
70
  #refreshSkills = false;
71
71
  #activeRecallAbort;
72
+ #controllerContextReady = new WeakSet();
72
73
  #pendingHandoffs = new WeakMap();
73
74
  #approvalGrants = [];
74
75
  #followedScope;
@@ -466,32 +467,90 @@ export class AiChatController {
466
467
  return;
467
468
  throw new Error("Agent session did not start.");
468
469
  }
469
- const recallAbort = new AbortController();
470
- this.#activeRecallAbort?.abort();
471
- this.#activeRecallAbort = recallAbort;
472
- const recalledBlocks = await this.#memoryRecall
473
- ?.recall(text, {
474
- scopeDir: this.location?.scopeDir ?? this.directoryContext,
475
- conversationId: this.location?.conversationId,
476
- agentBindingId: this.#activeBindingId,
477
- runId: `turn-${turnId}`,
478
- }, recallAbort.signal)
479
- .catch(() => []);
480
- if (this.#activeRecallAbort === recallAbort) {
481
- this.#activeRecallAbort = undefined;
470
+ const session = this.session;
471
+ const sharedPreparation = this.runtime.capabilities().preparesContext === true;
472
+ const location = this.location ? { ...this.location } : null;
473
+ const bindingId = this.#activeBindingId;
474
+ const authorized = () => !this.#isAbandoned(turnId) &&
475
+ this.session === session &&
476
+ this.location?.conversationId === location?.conversationId;
477
+ const prepareContext = async (signal) => {
478
+ if (!authorized())
479
+ throw new Error("Conversation context is no longer active.");
480
+ const recallAbort = new AbortController();
481
+ const abort = () => recallAbort.abort();
482
+ if (signal.aborted)
483
+ abort();
484
+ signal.addEventListener("abort", abort, { once: true });
485
+ this.#activeRecallAbort?.abort();
486
+ this.#activeRecallAbort = recallAbort;
487
+ try {
488
+ let handoff = this.#pendingHandoffs.get(session);
489
+ if (sharedPreparation && this.repository && location && bindingId) {
490
+ const current = await this.repository.read(location);
491
+ const bindings = reduceAgentBindings(current.agents);
492
+ const binding = bindings.find((item) => item.id === bindingId);
493
+ handoff = await buildConversationContextHandoff(current.transcript, {
494
+ conversationId: current.metadata.id,
495
+ targetBindingId: bindingId,
496
+ ...(this.#controllerContextReady.has(session) &&
497
+ binding?.context
498
+ ? {
499
+ after: {
500
+ entryId: binding.context.throughEntryId,
501
+ entryHash: binding.context.throughEntryHash,
502
+ },
503
+ }
504
+ : {}),
505
+ bindings,
506
+ summaries: current.agents.filter((record) => record.type === "handoff.summary.created"),
507
+ });
508
+ const context = this.#sessionContexts.get(session);
509
+ if (context) {
510
+ context.handoff = handoff;
511
+ if (context.pendingSwitch?.type === "agent.switch")
512
+ Object.assign(context.pendingSwitch, {
513
+ handoffId: handoff?.handoffId,
514
+ handoffMode: handoff?.mode,
515
+ handoffThroughEntryId: handoff?.throughEntryId,
516
+ omittedEntryCount: handoff?.omittedEntryCount,
517
+ });
518
+ }
519
+ }
520
+ const recalledBlocks = await this.#memoryRecall
521
+ ?.recall(text, {
522
+ scopeDir: location?.scopeDir ?? this.directoryContext,
523
+ conversationId: location?.conversationId,
524
+ agentBindingId: bindingId,
525
+ runId: `turn-${turnId}`,
526
+ }, recallAbort.signal)
527
+ .catch(() => []);
528
+ if (recallAbort.signal.aborted || !authorized())
529
+ throw new Error("Conversation preparation was cancelled.");
530
+ this.#pendingHandoffs.delete(session);
531
+ return [
532
+ ...(handoff ? [handoff.block] : []),
533
+ ...(recalledBlocks ?? []),
534
+ ];
535
+ }
536
+ finally {
537
+ signal.removeEventListener("abort", abort);
538
+ if (this.#activeRecallAbort === recallAbort)
539
+ this.#activeRecallAbort = undefined;
540
+ }
541
+ };
542
+ if (sharedPreparation) {
543
+ await session.send(text, {
544
+ prepareContext,
545
+ authorizeContext: async () => authorized(),
546
+ });
547
+ }
548
+ else {
549
+ const blocks = await prepareContext(new AbortController().signal);
550
+ if (this.#isAbandoned(turnId))
551
+ return;
552
+ await session.send(text, { contextBlocks: blocks });
482
553
  }
483
- if (this.#isAbandoned(turnId))
484
- return;
485
- const handoff = this.#pendingHandoffs.get(this.session);
486
- const contextBlocks = [
487
- ...(handoff ? [handoff.block] : []),
488
- ...(recalledBlocks ?? []),
489
- ];
490
- await this.session.send(text, {
491
- contextBlocks,
492
- });
493
- if (handoff)
494
- this.#pendingHandoffs.delete(this.session);
495
554
  if (!this.repository)
496
555
  await this.#persist();
497
556
  }
@@ -753,6 +812,8 @@ export class AiChatController {
753
812
  };
754
813
  try {
755
814
  for await (const event of session.events()) {
815
+ if (event.type === "completed")
816
+ this.#controllerContextReady.add(session);
756
817
  if ((event.type === "tool.start" || event.type === "tool.end") &&
757
818
  event.server === APP_TOOL_MCP_SERVER_NAME) {
758
819
  continue;
@@ -1402,10 +1463,10 @@ export class AiChatController {
1402
1463
  }
1403
1464
  const followedScope = this.#followedScope ?? this.directoryContext;
1404
1465
  const input = this.#followedScope !== undefined || this.directoryContext
1405
- ? (this.#createConversation?.(followedScope) ?? {
1466
+ ? this.#createConversation?.(followedScope) ?? {
1406
1467
  scopeDir: followedScope,
1407
- })
1408
- : (this.#createConversation?.() ?? { scopeDir: "" });
1468
+ }
1469
+ : this.#createConversation?.() ?? { scopeDir: "" };
1409
1470
  const created = await this.repository.create(input);
1410
1471
  this.location = created.location;
1411
1472
  this.conversationStatus = created.metadata.status;
@@ -1465,7 +1526,7 @@ export class AiChatController {
1465
1526
  this.appToolsUnavailableReason =
1466
1527
  descriptor.status === "runtime-unavailable" && runtime.id === "fake"
1467
1528
  ? null
1468
- : (descriptor.unavailableReason ?? null);
1529
+ : descriptor.unavailableReason ?? null;
1469
1530
  return descriptor;
1470
1531
  }
1471
1532
  catch (error) {
@@ -1667,6 +1728,10 @@ export class AiChatController {
1667
1728
  ...request,
1668
1729
  appToolSession,
1669
1730
  skillSnapshot,
1731
+ metadata: {
1732
+ ...request.metadata,
1733
+ ...(await this.#sessionBootstrapMetadata(snapshot.location.scopeDir, snapshot.metadata.launchContext?.notePath, snapshot.metadata.id, appToolSession?.tools ?? [], skillSnapshot?.skills ?? [])),
1734
+ },
1670
1735
  });
1671
1736
  const configured = await this.#configureBinding(resumed, compatibleBinding, request);
1672
1737
  if (!configured)
@@ -1,17 +1,7 @@
1
+ import { isOneLineToolAlert, presentToolPayload, toolCallTarget } from "@lapismd/design-core/ai/chat";
1
2
  import type { AiChatItem } from "./chat-items";
2
3
  export type AiChatToolItem = Extract<AiChatItem, {
3
4
  type: "tool";
4
5
  }>;
5
- export type ToolPayloadLanguage = "json" | "bash" | "plaintext";
6
- export type PresentedToolPayload = {
7
- code: string;
8
- language: ToolPayloadLanguage;
9
- };
10
- export type ToolPayloadHint = {
11
- toolName?: string;
12
- input?: string;
13
- };
14
- export declare function presentToolPayload(value?: string, hint?: ToolPayloadHint): PresentedToolPayload | undefined;
15
- export declare function isOneLineAlert(payload: PresentedToolPayload): boolean;
16
- export declare function toolCallTarget(input?: string, server?: string): string | undefined;
6
+ export { isOneLineToolAlert as isOneLineAlert, presentToolPayload, toolCallTarget, };
17
7
  export declare function toolCallStatus(state: AiChatToolItem["state"]): "complete" | "error" | "running";
@@ -1,70 +1,5 @@
1
- const SUMMARY_KEYS = [
2
- "command",
3
- "path",
4
- "file",
5
- "query",
6
- "url",
7
- "pattern",
8
- "target",
9
- ];
10
- const PRIMARY_KEYS = [
11
- "output",
12
- "content",
13
- "text",
14
- "result",
15
- "stdout",
16
- "aggregated",
17
- ];
18
- const METADATA_KEYS = new Set([
19
- "ok",
20
- "status",
21
- "success",
22
- "isError",
23
- "server",
24
- "tool",
25
- "name",
26
- ]);
27
- const STRUCTURAL_SIBLINGS = new Set([
28
- "path",
29
- "command",
30
- "query",
31
- "file",
32
- "url",
33
- "pattern",
34
- "target",
35
- "locations",
36
- ]);
37
- const RUNNER_TOOL_NAMES = new Set([
38
- "bash",
39
- "sh",
40
- "shell",
41
- "exec",
42
- "command",
43
- "terminal",
44
- "run",
45
- ]);
46
- const MAX_PARSE_DEPTH = 3;
47
- export function presentToolPayload(value, hint) {
48
- if (value == null || value === "")
49
- return undefined;
50
- const extracted = extractDisplayValue(value, 0);
51
- if (extracted == null || extracted === "")
52
- return undefined;
53
- if (isRecord(extracted) || Array.isArray(extracted)) {
54
- return { code: JSON.stringify(extracted, null, 2), language: "json" };
55
- }
56
- const text = String(extracted);
57
- if (!text)
58
- return undefined;
59
- return { code: text, language: detectTextLanguage(text, hint) };
60
- }
61
- export function isOneLineAlert(payload) {
62
- return payload.language === "plaintext" && !payload.code.includes("\n");
63
- }
64
- export function toolCallTarget(input, server) {
65
- const summary = summarizeToolInput(input);
66
- return summary || server || undefined;
67
- }
1
+ import { isOneLineToolAlert, presentToolPayload, toolCallTarget, } from "@lapismd/design-core/ai/chat";
2
+ export { isOneLineToolAlert as isOneLineAlert, presentToolPayload, toolCallTarget, };
68
3
  export function toolCallStatus(state) {
69
4
  if (state === "completed")
70
5
  return "complete";
@@ -72,142 +7,3 @@ export function toolCallStatus(state) {
72
7
  return "error";
73
8
  return "running";
74
9
  }
75
- function extractDisplayValue(value, depth) {
76
- const parsed = tryParseJson(value);
77
- if (parsed === undefined)
78
- return value;
79
- if (typeof parsed === "string") {
80
- if (depth + 1 >= MAX_PARSE_DEPTH)
81
- return parsed;
82
- return extractDisplayValue(parsed, depth + 1);
83
- }
84
- if (Array.isArray(parsed) || !isRecord(parsed))
85
- return parsed;
86
- const mcpText = mcpContentText(parsed);
87
- if (mcpText != null)
88
- return extractDisplayValue(mcpText, depth + 1);
89
- const unwrapped = unwrapEnvelope(parsed);
90
- if (unwrapped !== undefined)
91
- return extractDisplayValue(unwrapped, depth + 1);
92
- return parsed;
93
- }
94
- function tryParseJson(value) {
95
- if (typeof value !== "string")
96
- return value;
97
- const trimmed = value.trim();
98
- if (!trimmed)
99
- return undefined;
100
- if (!trimmed.startsWith("{") &&
101
- !trimmed.startsWith("[") &&
102
- !trimmed.startsWith('"')) {
103
- return undefined;
104
- }
105
- try {
106
- return JSON.parse(trimmed);
107
- }
108
- catch {
109
- return undefined;
110
- }
111
- }
112
- function unwrapEnvelope(record) {
113
- const keys = Object.keys(record);
114
- const primary = PRIMARY_KEYS.find((key) => record[key] != null && record[key] !== "");
115
- if (!primary)
116
- return undefined;
117
- const rest = keys.filter((key) => key !== primary);
118
- if (rest.some((key) => !METADATA_KEYS.has(key)))
119
- return undefined;
120
- return record[primary];
121
- }
122
- function mcpContentText(record) {
123
- if (!Array.isArray(record.content) || record.content.length === 0) {
124
- return undefined;
125
- }
126
- const rest = Object.keys(record).filter((key) => key !== "content");
127
- if (rest.some((key) => STRUCTURAL_SIBLINGS.has(key)))
128
- return undefined;
129
- if (rest.some((key) => !METADATA_KEYS.has(key)))
130
- return undefined;
131
- const parts = record.content.flatMap((entry) => {
132
- if (typeof entry === "string" && entry)
133
- return [entry];
134
- if (isRecord(entry) && typeof entry.text === "string" && entry.text) {
135
- return [entry.text];
136
- }
137
- return [];
138
- });
139
- return parts.length > 0 ? parts.join("\n") : undefined;
140
- }
141
- function detectTextLanguage(text, hint) {
142
- if (isRunnerToolName(hint?.toolName))
143
- return "bash";
144
- if (hasCommandInput(hint?.input))
145
- return "bash";
146
- if (text.includes("\n"))
147
- return "bash";
148
- if (looksLikeCli(text))
149
- return "bash";
150
- return "plaintext";
151
- }
152
- function isRunnerToolName(name) {
153
- if (!name)
154
- return false;
155
- const normalized = name.trim().toLowerCase();
156
- if (RUNNER_TOOL_NAMES.has(normalized))
157
- return true;
158
- const leaf = normalized.split(/[:/]/u).at(-1);
159
- return leaf != null && RUNNER_TOOL_NAMES.has(leaf);
160
- }
161
- function hasCommandInput(input) {
162
- if (!input)
163
- return false;
164
- try {
165
- const parsed = JSON.parse(input);
166
- return (isRecord(parsed) &&
167
- typeof parsed.command === "string" &&
168
- parsed.command.trim() !== "");
169
- }
170
- catch {
171
- return false;
172
- }
173
- }
174
- function looksLikeCli(text) {
175
- const trimmed = text.trim();
176
- return (/^[$%] /u.test(trimmed) ||
177
- /^error:/imu.test(trimmed) ||
178
- /\b(?:stderr|exit \d+)\b/iu.test(trimmed) ||
179
- /\|/.test(trimmed));
180
- }
181
- function summarizeToolInput(input) {
182
- if (!input)
183
- return undefined;
184
- try {
185
- const parsed = JSON.parse(input);
186
- if (typeof parsed === "string" && parsed.trim())
187
- return parsed.trim();
188
- if (!isRecord(parsed))
189
- return undefined;
190
- for (const key of SUMMARY_KEYS) {
191
- const value = parsed[key];
192
- if (typeof value === "string" && value.trim())
193
- return value.trim();
194
- }
195
- const locations = parsed.locations;
196
- if (Array.isArray(locations)) {
197
- const first = locations[0];
198
- if (isRecord(first) && typeof first.path === "string" && first.path) {
199
- return first.path;
200
- }
201
- }
202
- }
203
- catch {
204
- const line = input.trim().split("\n")[0] ?? "";
205
- if (!line)
206
- return undefined;
207
- return line.length > 80 ? `${line.slice(0, 77)}…` : line;
208
- }
209
- return undefined;
210
- }
211
- function isRecord(value) {
212
- return value != null && typeof value === "object" && !Array.isArray(value);
213
- }
@@ -0,0 +1,20 @@
1
+ import type { ModelRef } from "../core/types";
2
+ import type { AcpAgentId } from "../settings/acp-agents";
3
+ import type { AiPluginSettings } from "../settings/ai-settings";
4
+ export type ComposerModelCatalogState = {
5
+ agent: AcpAgentId;
6
+ runtime: AiPluginSettings["defaultRuntime"];
7
+ models: ModelRef[];
8
+ model: string;
9
+ loading: boolean;
10
+ error: string | null;
11
+ };
12
+ /** Each selection owns its result; a previous harness cannot overwrite it. */
13
+ export declare class ComposerModelCatalog {
14
+ #private;
15
+ readonly load: (agent: AcpAgentId, runtime: AiPluginSettings["defaultRuntime"]) => Promise<ModelRef[]>;
16
+ readonly update: (state: ComposerModelCatalogState) => void;
17
+ constructor(load: (agent: AcpAgentId, runtime: AiPluginSettings["defaultRuntime"]) => Promise<ModelRef[]>, update: (state: ComposerModelCatalogState) => void);
18
+ refresh(agent: AcpAgentId, runtime: AiPluginSettings["defaultRuntime"], saved: string): Promise<void>;
19
+ cancel(): void;
20
+ }
@@ -0,0 +1,44 @@
1
+ /** Each selection owns its result; a previous harness cannot overwrite it. */
2
+ export class ComposerModelCatalog {
3
+ load;
4
+ update;
5
+ #generation = 0;
6
+ constructor(load, update) {
7
+ this.load = load;
8
+ this.update = update;
9
+ }
10
+ async refresh(agent, runtime, saved) {
11
+ const generation = ++this.#generation;
12
+ const state = {
13
+ agent,
14
+ runtime,
15
+ models: [],
16
+ model: saved,
17
+ loading: true,
18
+ error: null,
19
+ };
20
+ this.update(state);
21
+ try {
22
+ const models = (await this.load(agent, runtime)).filter((model) => model.provider === agent || !model.provider);
23
+ if (generation !== this.#generation)
24
+ return;
25
+ const model = models.some((entry) => entry.model === saved)
26
+ ? saved
27
+ : ((models.find((entry) => entry.isDefault) ?? models[0])?.model ??
28
+ saved);
29
+ this.update({ ...state, models, model, loading: false });
30
+ }
31
+ catch (error) {
32
+ if (generation !== this.#generation)
33
+ return;
34
+ this.update({
35
+ ...state,
36
+ loading: false,
37
+ error: error instanceof Error ? error.message : String(error),
38
+ });
39
+ }
40
+ }
41
+ cancel() {
42
+ this.#generation++;
43
+ }
44
+ }
@@ -1,7 +1,7 @@
1
1
  import type { AcpAgentId } from "../settings/acp-agents";
2
2
  export type ComposerAgentSelection = {
3
3
  agent: AcpAgentId;
4
- runtimePreference: "acp" | "codex-native" | "fake";
4
+ runtimePreference: "acp" | "codex-native" | "opencode-native" | "fake";
5
5
  label: string;
6
6
  };
7
7
  export declare function composerAgentLabel(agent?: string, runtimePreference?: string): string;
@@ -21,6 +21,9 @@ const KNOWN = {
21
21
  runtimePreference: "codex-native",
22
22
  label: "Codex Native",
23
23
  },
24
+ opencode: { agent: "opencode", runtimePreference: "acp", label: "OpenCode ACP" },
25
+ "opencode-acp": { agent: "opencode", runtimePreference: "acp", label: "OpenCode ACP" },
26
+ "opencode-native": { agent: "opencode", runtimePreference: "opencode-native", label: "OpenCode Native" },
24
27
  fake: { agent: "codex", runtimePreference: "fake", label: "Fake" },
25
28
  };
26
29
  export function composerAgentLabel(agent, runtimePreference) {
@@ -28,7 +31,9 @@ export function composerAgentLabel(agent, runtimePreference) {
28
31
  return "Fake";
29
32
  if (runtimePreference === "codex-native")
30
33
  return "Codex Native";
31
- return agent === "cursor" ? "Cursor ACP" : "Codex ACP";
34
+ if (runtimePreference === "opencode-native")
35
+ return "OpenCode Native";
36
+ return agent === "cursor" ? "Cursor ACP" : agent === "opencode" ? "OpenCode ACP" : "Codex ACP";
32
37
  }
33
38
  export function parseAgentCommand(raw) {
34
39
  const name = raw.trim().toLowerCase();
@@ -1,25 +1 @@
1
- import type { ConversationHandoffContextBlock } from "../core/types";
2
- import type { AgentBindingCreatedRecord, HandoffSummaryCreatedRecord, HandoffProjectionMode, TranscriptEntry } from "./types";
3
- export declare const MAX_CONTEXT_HANDOFF_TOKENS = 12000;
4
- export declare const MAX_CONTEXT_HANDOFF_CODE_POINTS: number;
5
- export type ConversationContextCursor = {
6
- entryId: string;
7
- entryHash: string;
8
- };
9
- export type ConversationContextHandoff = {
10
- block: ConversationHandoffContextBlock;
11
- throughEntryId: string;
12
- throughEntryHash: string;
13
- handoffId: string;
14
- mode: HandoffProjectionMode;
15
- omittedEntryCount: number;
16
- };
17
- export type ConversationContextHandoffOptions = {
18
- conversationId?: string;
19
- targetBindingId?: string;
20
- after?: ConversationContextCursor;
21
- bindings?: readonly AgentBindingCreatedRecord[];
22
- summaries?: readonly HandoffSummaryCreatedRecord[];
23
- maxTokens?: number;
24
- };
25
- export declare function buildConversationContextHandoff(transcript: readonly TranscriptEntry[], options?: ConversationContextHandoffOptions | number): Promise<ConversationContextHandoff | undefined>;
1
+ export { buildConversationContextHandoff, MAX_CONTEXT_HANDOFF_TOKENS, MAX_CONTEXT_HANDOFF_CODE_POINTS, type ConversationContextCursor, type ConversationContextHandoff, type ConversationContextHandoffOptions, } from "@lapismd/ai-controller/memory/lapis";