@arnilo/prism 0.0.1

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 (106) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/LICENSE +21 -0
  3. package/README.md +139 -0
  4. package/dist/agents.d.ts +5 -0
  5. package/dist/agents.js +439 -0
  6. package/dist/cli-runner.d.ts +33 -0
  7. package/dist/cli-runner.js +167 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.js +10 -0
  10. package/dist/compaction.d.ts +9 -0
  11. package/dist/compaction.js +67 -0
  12. package/dist/config.d.ts +17 -0
  13. package/dist/config.js +69 -0
  14. package/dist/contracts.d.ts +670 -0
  15. package/dist/contracts.js +2 -0
  16. package/dist/contributions.d.ts +35 -0
  17. package/dist/contributions.js +47 -0
  18. package/dist/credentials.d.ts +22 -0
  19. package/dist/credentials.js +63 -0
  20. package/dist/extensions.d.ts +25 -0
  21. package/dist/extensions.js +131 -0
  22. package/dist/index.d.ts +47 -0
  23. package/dist/index.js +28 -0
  24. package/dist/input.d.ts +57 -0
  25. package/dist/input.js +225 -0
  26. package/dist/manifests.d.ts +28 -0
  27. package/dist/manifests.js +108 -0
  28. package/dist/middleware.d.ts +15 -0
  29. package/dist/middleware.js +49 -0
  30. package/dist/mock-provider.d.ts +6 -0
  31. package/dist/mock-provider.js +14 -0
  32. package/dist/models.d.ts +8 -0
  33. package/dist/models.js +25 -0
  34. package/dist/node/config.d.ts +9 -0
  35. package/dist/node/config.js +51 -0
  36. package/dist/node/session-store-jsonl.d.ts +17 -0
  37. package/dist/node/session-store-jsonl.js +134 -0
  38. package/dist/node/settings.d.ts +7 -0
  39. package/dist/node/settings.js +26 -0
  40. package/dist/node/trust.d.ts +13 -0
  41. package/dist/node/trust.js +56 -0
  42. package/dist/provider-events.d.ts +15 -0
  43. package/dist/provider-events.js +30 -0
  44. package/dist/provider-packages.d.ts +4 -0
  45. package/dist/provider-packages.js +12 -0
  46. package/dist/provider-request-policy.d.ts +9 -0
  47. package/dist/provider-request-policy.js +49 -0
  48. package/dist/providers/openai-compatible.d.ts +9 -0
  49. package/dist/providers/openai-compatible.js +197 -0
  50. package/dist/providers.d.ts +8 -0
  51. package/dist/providers.js +25 -0
  52. package/dist/redaction.d.ts +11 -0
  53. package/dist/redaction.js +68 -0
  54. package/dist/resources.d.ts +5 -0
  55. package/dist/resources.js +30 -0
  56. package/dist/retry.d.ts +11 -0
  57. package/dist/retry.js +48 -0
  58. package/dist/rpc.d.ts +18 -0
  59. package/dist/rpc.js +187 -0
  60. package/dist/security.d.ts +51 -0
  61. package/dist/security.js +60 -0
  62. package/dist/session-stores.d.ts +25 -0
  63. package/dist/session-stores.js +116 -0
  64. package/dist/settings.d.ts +3 -0
  65. package/dist/settings.js +26 -0
  66. package/dist/skills.d.ts +8 -0
  67. package/dist/skills.js +34 -0
  68. package/dist/system-prompts.d.ts +6 -0
  69. package/dist/system-prompts.js +47 -0
  70. package/dist/testing/provider-conformance.d.ts +36 -0
  71. package/dist/testing/provider-conformance.js +164 -0
  72. package/dist/tools.d.ts +25 -0
  73. package/dist/tools.js +109 -0
  74. package/docs/agent-session-runtime.md +167 -0
  75. package/docs/api-page-template.md +32 -0
  76. package/docs/cli-rpc.md +140 -0
  77. package/docs/compaction-and-retry.md +177 -0
  78. package/docs/compaction-llm.md +108 -0
  79. package/docs/compaction-observational-memory.md +123 -0
  80. package/docs/configuration-and-manifests.md +142 -0
  81. package/docs/context-and-skills.md +113 -0
  82. package/docs/contribution-registries.md +118 -0
  83. package/docs/credentials-and-redaction.md +122 -0
  84. package/docs/extensions.md +139 -0
  85. package/docs/index.md +56 -0
  86. package/docs/input-and-prompt-assembly.md +168 -0
  87. package/docs/middleware-hooks.md +123 -0
  88. package/docs/node-filesystem-config.md +85 -0
  89. package/docs/node-jsonl-session-store.md +81 -0
  90. package/docs/provider-conformance.md +109 -0
  91. package/docs/provider-layer.md +172 -0
  92. package/docs/provider-packages.md +171 -0
  93. package/docs/providers/kimi.md +110 -0
  94. package/docs/providers/openai-compatible.md +125 -0
  95. package/docs/providers/openai.md +131 -0
  96. package/docs/providers/opencode-go.md +103 -0
  97. package/docs/providers/openrouter.md +105 -0
  98. package/docs/providers/zai.md +108 -0
  99. package/docs/public-contracts.md +375 -0
  100. package/docs/release-and-install.md +141 -0
  101. package/docs/resource-loading.md +97 -0
  102. package/docs/session-stores-and-branching.md +119 -0
  103. package/docs/settings-auth-trust-security.md +73 -0
  104. package/docs/system-prompts.md +116 -0
  105. package/docs/tools.md +151 -0
  106. package/package.json +93 -0
package/dist/input.js ADDED
@@ -0,0 +1,225 @@
1
+ import { loadTextResource } from "./resources.js";
2
+ export function createDefaultInputBuilder() {
3
+ return {
4
+ name: "default-input",
5
+ async build(input, context = {}) {
6
+ const messages = [];
7
+ messages.push(...instructionMessages(context.systemInstructions, "System instruction"));
8
+ messages.push(...instructionMessages(context.developerInstructions, "Developer instruction"));
9
+ messages.push(...customInstructionMessages(context.instructions));
10
+ messages.push(...summaryMessages(context.summaries));
11
+ messages.push(...(context.history ?? []));
12
+ messages.push(...inputMessages(input));
13
+ messages.push(...await attachmentMessages(context));
14
+ messages.push(...toolResultMessages(context.toolResults));
15
+ return context.middleware ? context.middleware.run("input_assembly", messages) : messages;
16
+ },
17
+ };
18
+ }
19
+ export async function resolveContextProviders(options) {
20
+ const blocks = [];
21
+ for (const provider of options.providers ?? []) {
22
+ throwIfAborted(options.signal);
23
+ blocks.push(...await provider.resolve({
24
+ sessionId: options.sessionId,
25
+ runId: options.runId,
26
+ messages: options.messages,
27
+ metadata: options.metadata,
28
+ signal: options.signal,
29
+ }));
30
+ }
31
+ return options.middleware ? options.middleware.run("context", blocks) : blocks;
32
+ }
33
+ export function createDefaultPromptBuilder() {
34
+ return {
35
+ name: "default-prompt",
36
+ async build(request) {
37
+ return [
38
+ ...contextMessages(request.context),
39
+ ...skillMessages(request.skills),
40
+ ...toolMessages(request.tools),
41
+ ...request.messages,
42
+ ];
43
+ },
44
+ };
45
+ }
46
+ export function renderPromptTemplate(template, variables, options = {}) {
47
+ return template.replace(/\{\{\s*([A-Za-z0-9_]+)\s*\}\}/g, (match, name) => {
48
+ if (!Object.prototype.hasOwnProperty.call(variables, name)) {
49
+ if (options.missing === "preserve")
50
+ return match;
51
+ throw new Error(`Missing prompt template variable: ${name}`);
52
+ }
53
+ return templateValue(variables[name]);
54
+ });
55
+ }
56
+ export async function assembleProviderInput(options) {
57
+ const inputBuilder = options.inputBuilder ?? createDefaultInputBuilder();
58
+ const baseContext = {
59
+ sessionId: options.sessionId,
60
+ runId: options.runId,
61
+ metadata: options.metadata,
62
+ signal: options.signal,
63
+ };
64
+ const messages = await inputBuilder.build(options.input, { ...options, ...baseContext });
65
+ const context = await resolveContextProviders({
66
+ providers: options.contextProviders,
67
+ messages,
68
+ middleware: options.middleware,
69
+ ...baseContext,
70
+ });
71
+ const promptBuilder = options.promptBuilder ?? createDefaultPromptBuilder();
72
+ const promptRequest = options.middleware
73
+ ? await options.middleware.run("prompt_build", {
74
+ messages,
75
+ context,
76
+ skills: options.skills,
77
+ tools: options.tools,
78
+ metadata: options.metadata,
79
+ signal: options.signal,
80
+ })
81
+ : {
82
+ messages,
83
+ context,
84
+ skills: options.skills,
85
+ tools: options.tools,
86
+ metadata: options.metadata,
87
+ signal: options.signal,
88
+ };
89
+ const providerMessages = await promptBuilder.build({ ...promptRequest, tools: options.tools });
90
+ return {
91
+ model: options.model,
92
+ messages: providerMessages,
93
+ tools: options.tools,
94
+ context,
95
+ options: options.providerOptions,
96
+ metadata: options.metadata,
97
+ signal: options.signal,
98
+ };
99
+ }
100
+ function inputMessages(input) {
101
+ if (typeof input === "string")
102
+ return [textMessage("user", input)];
103
+ if ("role" in input)
104
+ return [input];
105
+ return [...input];
106
+ }
107
+ function instructionMessages(value, label) {
108
+ const items = typeof value === "string" ? [value] : value ?? [];
109
+ return items.map((text) => textMessage("system", `${label}:\n${text}`));
110
+ }
111
+ function customInstructionMessages(value) {
112
+ if (!value)
113
+ return [];
114
+ if (typeof value === "string")
115
+ return [textMessage("system", value)];
116
+ const items = Array.isArray(value) ? value : [value];
117
+ return items.map((item) => textMessage("system", item.label ? `${item.label}:\n${item.text}` : item.text, item.metadata));
118
+ }
119
+ function summaryMessages(summaries) {
120
+ return (summaries ?? []).map((summary) => {
121
+ if (typeof summary === "string")
122
+ return textMessage("system", `Summary:\n${summary}`);
123
+ const content = typeof summary.content === "string" ? [{ type: "text", text: summary.content }] : summary.content;
124
+ return { role: "system", content, metadata: summary.metadata };
125
+ });
126
+ }
127
+ async function attachmentMessages(context) {
128
+ const messages = [];
129
+ for (const attachment of context.attachments ?? []) {
130
+ if (attachment.content) {
131
+ messages.push({ role: "user", content: attachment.content, metadata: attachmentMetadata(attachment) });
132
+ continue;
133
+ }
134
+ if (attachment.text !== undefined) {
135
+ messages.push(textMessage("user", attachment.name ? `Attachment ${attachment.name}:\n${attachment.text}` : attachment.text, attachmentMetadata(attachment)));
136
+ continue;
137
+ }
138
+ if (attachment.uri)
139
+ messages.push(await resourceMessage(attachment.uri, context, attachment));
140
+ }
141
+ for (const uri of context.resourceUris ?? [])
142
+ messages.push(await resourceMessage(uri, context));
143
+ return messages;
144
+ }
145
+ async function resourceMessage(uri, context, attachment) {
146
+ if (!context.resourceLoader)
147
+ throw new Error(`Resource loader required for ${uri}`);
148
+ const text = await loadTextResource(context.resourceLoader, uri, {
149
+ signal: context.signal,
150
+ metadata: context.metadata,
151
+ });
152
+ const label = attachment?.name ?? uri;
153
+ return textMessage("user", `Resource ${label}:\n${text}`, attachmentMetadata({ ...attachment, uri }));
154
+ }
155
+ function toolResultMessages(results) {
156
+ return (results ?? []).map((result) => ({
157
+ role: "tool",
158
+ content: [{
159
+ type: "tool_result",
160
+ toolCallId: result.toolCallId,
161
+ name: result.name,
162
+ result: result.value,
163
+ error: result.error,
164
+ }, ...(result.content ?? [])],
165
+ metadata: result.metadata,
166
+ }));
167
+ }
168
+ function textMessage(role, text, metadata) {
169
+ return { role, content: [{ type: "text", text }], metadata };
170
+ }
171
+ function contextMessages(context) {
172
+ return (context ?? []).map((block) => textMessage("system", `${block.title ? `${block.title}:\n` : "Context:\n"}${blockText(block)}`, block.metadata));
173
+ }
174
+ function skillMessages(skills) {
175
+ return (skills ?? [])
176
+ .filter((skill) => skill.instructions)
177
+ .map((skill) => textMessage("system", `Skill ${skill.name}:\n${skill.instructions}`, skill.metadata));
178
+ }
179
+ function toolMessages(tools) {
180
+ if (!tools?.length)
181
+ return [];
182
+ return [textMessage("system", `Available tools:\n${tools.map((tool) => `- ${tool.name}${tool.description ? `: ${tool.description}` : ""}`).join("\n")}`)];
183
+ }
184
+ function blockText(block) {
185
+ if (typeof block.content === "string")
186
+ return block.content;
187
+ return block.content.map((part) => {
188
+ if (part.type === "text" || part.type === "thinking")
189
+ return part.text;
190
+ if (part.type === "tool_result")
191
+ return JSON.stringify(part.result ?? part.error ?? null);
192
+ if (part.type === "tool_call")
193
+ return `${part.name}(${JSON.stringify(part.arguments)})`;
194
+ return part.url ?? part.mimeType ?? "[image]";
195
+ }).join("\n");
196
+ }
197
+ function templateValue(value) {
198
+ if (typeof value === "string")
199
+ return value;
200
+ if (typeof value === "number" || typeof value === "boolean" || value === null)
201
+ return String(value);
202
+ return JSON.stringify(sortJson(value));
203
+ }
204
+ function sortJson(value) {
205
+ if (!value || typeof value !== "object")
206
+ return value;
207
+ if (Array.isArray(value))
208
+ return value.map(sortJson);
209
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, sortJson(value[key])]));
210
+ }
211
+ function throwIfAborted(signal) {
212
+ if (signal?.aborted)
213
+ throw new Error("Context resolution aborted");
214
+ }
215
+ function attachmentMetadata(attachment) {
216
+ if (!attachment)
217
+ return undefined;
218
+ return {
219
+ ...attachment.metadata,
220
+ ...(attachment.name ? { name: attachment.name } : {}),
221
+ ...(attachment.uri ? { uri: attachment.uri } : {}),
222
+ ...(attachment.mediaType ? { mediaType: attachment.mediaType } : {}),
223
+ };
224
+ }
225
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1,28 @@
1
+ import type { JsonObject } from "./contracts.js";
2
+ export type ManifestContributionKind = "provider" | "model" | "tool" | "contextProvider" | "skill" | "command" | "agent" | "inputBuilder" | "promptBuilder" | "compactionStrategy" | "retryPolicy" | "storeFactory" | "resourceLoader" | "settingsProvider" | "credentialResolver" | "providerPackage" | "authMethod" | "providerRequestPolicy" | "systemPromptContribution";
3
+ export interface ManifestContributionDeclaration {
4
+ readonly kind: ManifestContributionKind;
5
+ readonly name: string;
6
+ readonly module?: string;
7
+ readonly exportName?: string;
8
+ readonly configKey?: string;
9
+ readonly resource?: string;
10
+ readonly metadata?: JsonObject;
11
+ }
12
+ export interface ManifestResourceDeclaration {
13
+ readonly uri: string;
14
+ readonly mediaType?: string;
15
+ readonly purpose?: "manifest" | "prompt" | "skill" | "package" | string;
16
+ readonly metadata?: JsonObject;
17
+ }
18
+ export interface PrismManifest {
19
+ readonly name: string;
20
+ readonly version?: string;
21
+ readonly description?: string;
22
+ readonly configDefaults?: JsonObject;
23
+ readonly contributions?: readonly ManifestContributionDeclaration[];
24
+ readonly resources?: readonly ManifestResourceDeclaration[];
25
+ readonly metadata?: JsonObject;
26
+ }
27
+ export declare function definePrismManifest(manifest: PrismManifest): PrismManifest;
28
+ export declare function parsePrismManifest(value: unknown): PrismManifest;
@@ -0,0 +1,108 @@
1
+ import { assertJsonObject, isJsonObject } from "./config.js";
2
+ export function definePrismManifest(manifest) {
3
+ return parsePrismManifest(manifest);
4
+ }
5
+ export function parsePrismManifest(value) {
6
+ if (!isRecord(value))
7
+ throw new Error("manifest must be an object");
8
+ const manifest = value;
9
+ const name = readRequiredString(manifest, "name");
10
+ const parsed = {
11
+ name,
12
+ ...readOptionalString(manifest, "version"),
13
+ ...readOptionalString(manifest, "description"),
14
+ ...readOptionalJsonObject(manifest, "configDefaults"),
15
+ contributions: readContributions(manifest.contributions),
16
+ resources: readResources(manifest.resources),
17
+ ...readOptionalJsonObject(manifest, "metadata"),
18
+ };
19
+ return parsed;
20
+ }
21
+ function isRecord(value) {
22
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23
+ }
24
+ function readContributions(value) {
25
+ if (value === undefined)
26
+ return undefined;
27
+ if (!Array.isArray(value))
28
+ throw new Error("manifest.contributions must be an array");
29
+ return value.map((item, index) => {
30
+ assertJsonObject(item, `manifest.contributions[${index}]`);
31
+ const contribution = item;
32
+ return {
33
+ kind: readKind(contribution.kind, index),
34
+ name: readRequiredString(contribution, "name", `manifest.contributions[${index}].name`),
35
+ ...readOptionalString(contribution, "module", `manifest.contributions[${index}].module`),
36
+ ...readOptionalString(contribution, "exportName", `manifest.contributions[${index}].exportName`),
37
+ ...readOptionalString(contribution, "configKey", `manifest.contributions[${index}].configKey`),
38
+ ...readOptionalString(contribution, "resource", `manifest.contributions[${index}].resource`),
39
+ ...readOptionalJsonObject(contribution, "metadata", `manifest.contributions[${index}].metadata`),
40
+ };
41
+ });
42
+ }
43
+ function readResources(value) {
44
+ if (value === undefined)
45
+ return undefined;
46
+ if (!Array.isArray(value))
47
+ throw new Error("manifest.resources must be an array");
48
+ return value.map((item, index) => {
49
+ assertJsonObject(item, `manifest.resources[${index}]`);
50
+ const resource = item;
51
+ return {
52
+ uri: readRequiredString(resource, "uri", `manifest.resources[${index}].uri`),
53
+ ...readOptionalString(resource, "mediaType", `manifest.resources[${index}].mediaType`),
54
+ ...readOptionalString(resource, "purpose", `manifest.resources[${index}].purpose`),
55
+ ...readOptionalJsonObject(resource, "metadata", `manifest.resources[${index}].metadata`),
56
+ };
57
+ });
58
+ }
59
+ function readKind(value, index) {
60
+ const kinds = new Set([
61
+ "provider",
62
+ "model",
63
+ "tool",
64
+ "contextProvider",
65
+ "skill",
66
+ "command",
67
+ "agent",
68
+ "inputBuilder",
69
+ "promptBuilder",
70
+ "compactionStrategy",
71
+ "retryPolicy",
72
+ "storeFactory",
73
+ "resourceLoader",
74
+ "settingsProvider",
75
+ "credentialResolver",
76
+ "providerPackage",
77
+ "authMethod",
78
+ "providerRequestPolicy",
79
+ "systemPromptContribution",
80
+ ]);
81
+ if (typeof value !== "string" || !kinds.has(value)) {
82
+ throw new Error(`manifest.contributions[${index}].kind must be a known contribution kind`);
83
+ }
84
+ return value;
85
+ }
86
+ function readRequiredString(record, key, label = `manifest.${key}`) {
87
+ const value = record[key];
88
+ if (typeof value !== "string" || value.length === 0)
89
+ throw new Error(`${label} must be a non-empty string`);
90
+ return value;
91
+ }
92
+ function readOptionalString(record, key, label = `manifest.${key}`) {
93
+ const value = record[key];
94
+ if (value === undefined)
95
+ return {};
96
+ if (typeof value !== "string")
97
+ throw new Error(`${label} must be a string`);
98
+ return { [key]: value };
99
+ }
100
+ function readOptionalJsonObject(record, key, label = `manifest.${key}`) {
101
+ const value = record[key];
102
+ if (value === undefined)
103
+ return {};
104
+ if (!isJsonObject(value))
105
+ throw new Error(`${label} must be a JSON object`);
106
+ return { [key]: value };
107
+ }
108
+ //# sourceMappingURL=manifests.js.map
@@ -0,0 +1,15 @@
1
+ import type { ExtensionEvent } from "./contracts.js";
2
+ export type MiddlewareHookName = "provider_request" | "input_assembly" | "prompt_build" | "context" | "tool_call" | "tool_result" | "retry" | "compaction" | "session_start" | "session_shutdown";
3
+ export type MiddlewareNext<T> = (value: T) => Promise<T>;
4
+ export type Middleware<T = unknown> = (value: T, next: MiddlewareNext<T>) => T | Promise<T>;
5
+ export interface MiddlewareRegistryOptions {
6
+ readonly errorPolicy?: "event" | "throw";
7
+ readonly secrets?: readonly (string | undefined)[];
8
+ readonly onError?: (event: ExtensionEvent) => void | Promise<void>;
9
+ }
10
+ export interface MiddlewareRegistry {
11
+ use<T>(hook: MiddlewareHookName | string, middleware: Middleware<T>): () => void;
12
+ run<T>(hook: MiddlewareHookName | string, value: T): Promise<T>;
13
+ list(hook: MiddlewareHookName | string): readonly Middleware[];
14
+ }
15
+ export declare function createMiddlewareRegistry(options?: MiddlewareRegistryOptions): MiddlewareRegistry;
@@ -0,0 +1,49 @@
1
+ import { errorToErrorInfo } from "./redaction.js";
2
+ function middlewareError(error, hook, secrets) {
3
+ return { type: "extension_error", extension: `middleware:${hook}`, error: errorToErrorInfo(error, secrets) };
4
+ }
5
+ export function createMiddlewareRegistry(options = {}) {
6
+ const byHook = new Map();
7
+ const errorPolicy = options.errorPolicy ?? "event";
8
+ const secrets = options.secrets ?? [];
9
+ return {
10
+ use(hook, middleware) {
11
+ const list = byHook.get(hook) ?? [];
12
+ list.push(middleware);
13
+ byHook.set(hook, list);
14
+ return () => {
15
+ const next = (byHook.get(hook) ?? []).filter((item) => item !== middleware);
16
+ if (next.length === 0)
17
+ byHook.delete(hook);
18
+ else
19
+ byHook.set(hook, next);
20
+ };
21
+ },
22
+ async run(hook, value) {
23
+ let current = value;
24
+ for (const middleware of byHook.get(hook) ?? []) {
25
+ try {
26
+ let calledNext = false;
27
+ const next = async (nextValue) => {
28
+ calledNext = true;
29
+ current = nextValue;
30
+ return current;
31
+ };
32
+ const result = await middleware(current, next);
33
+ if (!calledNext)
34
+ current = result;
35
+ }
36
+ catch (error) {
37
+ if (errorPolicy === "throw")
38
+ throw error;
39
+ await options.onError?.(middlewareError(error, hook, secrets));
40
+ }
41
+ }
42
+ return current;
43
+ },
44
+ list(hook) {
45
+ return [...(byHook.get(hook) ?? [])];
46
+ },
47
+ };
48
+ }
49
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1,6 @@
1
+ import type { AIProvider, ProviderEvent, ProviderRequest } from "./contracts.js";
2
+ export interface MockProviderOptions {
3
+ readonly id?: string;
4
+ readonly onRequest?: (request: ProviderRequest) => void;
5
+ }
6
+ export declare function createMockProvider(events?: readonly ProviderEvent[], options?: MockProviderOptions): AIProvider;
@@ -0,0 +1,14 @@
1
+ export function createMockProvider(events = [{ type: "done" }], options = {}) {
2
+ return {
3
+ id: options.id ?? "mock",
4
+ async *generate(request) {
5
+ options.onRequest?.(request);
6
+ for (const event of events) {
7
+ if (request.signal?.aborted)
8
+ throw request.signal.reason;
9
+ yield event;
10
+ }
11
+ },
12
+ };
13
+ }
14
+ //# sourceMappingURL=mock-provider.js.map
@@ -0,0 +1,8 @@
1
+ import type { ModelConfig } from "./contracts.js";
2
+ export interface ModelRegistry {
3
+ register(model: ModelConfig): void;
4
+ get(provider: string, model: string): ModelConfig | undefined;
5
+ resolve(provider: string, model: string): ModelConfig;
6
+ list(): readonly ModelConfig[];
7
+ }
8
+ export declare function createModelRegistry(models?: readonly ModelConfig[]): ModelRegistry;
package/dist/models.js ADDED
@@ -0,0 +1,25 @@
1
+ export function createModelRegistry(models = []) {
2
+ const byId = new Map();
3
+ const key = (provider, model) => `${provider}\0${model}`;
4
+ const registry = {
5
+ register(model) {
6
+ byId.set(key(model.provider, model.model), model);
7
+ },
8
+ get(provider, model) {
9
+ return byId.get(key(provider, model));
10
+ },
11
+ resolve(provider, model) {
12
+ const config = byId.get(key(provider, model));
13
+ if (!config)
14
+ throw new Error(`Unknown model: ${provider}/${model}`);
15
+ return config;
16
+ },
17
+ list() {
18
+ return [...byId.values()];
19
+ },
20
+ };
21
+ for (const model of models)
22
+ registry.register(model);
23
+ return registry;
24
+ }
25
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1,9 @@
1
+ import { type ConfigLayer } from "../config.js";
2
+ export interface NodeConfigFile {
3
+ readonly name: string;
4
+ readonly path: string;
5
+ readonly optional?: boolean;
6
+ }
7
+ export declare function defaultUserConfigPath(appName?: string): string;
8
+ export declare function readConfigFile(path: string): Promise<ConfigLayer["config"]>;
9
+ export declare function loadConfigFiles(files: readonly NodeConfigFile[]): Promise<ConfigLayer[]>;
@@ -0,0 +1,51 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { assertJsonObject } from "../config.js";
5
+ export function defaultUserConfigPath(appName = "prism") {
6
+ return join(homedir(), ".config", appName, "config.json");
7
+ }
8
+ export async function readConfigFile(path) {
9
+ let text;
10
+ try {
11
+ text = await readFile(path, "utf8");
12
+ }
13
+ catch (error) {
14
+ throw new Error(`Failed to read config ${path}: ${errorMessage(error)}`);
15
+ }
16
+ let parsed;
17
+ try {
18
+ parsed = JSON.parse(text);
19
+ }
20
+ catch (error) {
21
+ throw new Error(`Invalid JSON config ${path}: ${errorMessage(error)}`);
22
+ }
23
+ try {
24
+ assertJsonObject(parsed, `config ${path}`);
25
+ }
26
+ catch (error) {
27
+ throw new Error(errorMessage(error));
28
+ }
29
+ return parsed;
30
+ }
31
+ export async function loadConfigFiles(files) {
32
+ const layers = [];
33
+ for (const file of files) {
34
+ try {
35
+ layers.push({ name: file.name, config: await readConfigFile(file.path) });
36
+ }
37
+ catch (error) {
38
+ if (file.optional && isMissingFile(error))
39
+ continue;
40
+ throw error;
41
+ }
42
+ }
43
+ return layers;
44
+ }
45
+ function isMissingFile(error) {
46
+ return error instanceof Error && error.message.includes("ENOENT");
47
+ }
48
+ function errorMessage(error) {
49
+ return error instanceof Error ? error.message : String(error);
50
+ }
51
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,17 @@
1
+ import type { SessionEntry, SessionStore } from "../contracts.js";
2
+ export interface JsonlSessionStoreOptions {
3
+ readonly path: string;
4
+ readonly createDirectory?: boolean;
5
+ }
6
+ export interface SessionEntryParseError {
7
+ readonly line: number;
8
+ readonly message: string;
9
+ readonly raw?: string;
10
+ }
11
+ export interface SessionEntryReadResult {
12
+ readonly entries: SessionEntry[];
13
+ readonly errors: SessionEntryParseError[];
14
+ }
15
+ export declare function createJsonlSessionStore(pathOrOptions: string | JsonlSessionStoreOptions): SessionStore;
16
+ /** Read a JSONL session file and return both valid entries and per-line parse errors. */
17
+ export declare function readJsonlSessionEntries(path: string): Promise<SessionEntryReadResult>;