@geminixiang/mikan 0.5.2 → 1.0.0-beta.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 (208) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +3 -3
  3. package/dist/adapter.d.ts +1 -1
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js.map +1 -1
  6. package/dist/adapters/shared.js +2 -2
  7. package/dist/adapters/shared.js.map +1 -1
  8. package/dist/agent.d.ts +11 -2
  9. package/dist/agent.d.ts.map +1 -1
  10. package/dist/agent.js +211 -119
  11. package/dist/agent.js.map +1 -1
  12. package/dist/commands/admin.d.ts.map +1 -1
  13. package/dist/commands/admin.js +1 -5
  14. package/dist/commands/admin.js.map +1 -1
  15. package/dist/commands/auto-reply.d.ts +3 -0
  16. package/dist/commands/auto-reply.d.ts.map +1 -1
  17. package/dist/commands/auto-reply.js +3 -0
  18. package/dist/commands/auto-reply.js.map +1 -1
  19. package/dist/commands/model.d.ts +2 -3
  20. package/dist/commands/model.d.ts.map +1 -1
  21. package/dist/commands/model.js +1 -4
  22. package/dist/commands/model.js.map +1 -1
  23. package/dist/commands/new.d.ts.map +1 -1
  24. package/dist/commands/new.js +1 -5
  25. package/dist/commands/new.js.map +1 -1
  26. package/dist/commands/registry.d.ts.map +1 -1
  27. package/dist/commands/registry.js +2 -5
  28. package/dist/commands/registry.js.map +1 -1
  29. package/dist/commands/types.d.ts +6 -2
  30. package/dist/commands/types.d.ts.map +1 -1
  31. package/dist/commands/types.js.map +1 -1
  32. package/dist/config.d.ts +42 -1
  33. package/dist/config.d.ts.map +1 -1
  34. package/dist/config.js +93 -7
  35. package/dist/config.js.map +1 -1
  36. package/dist/events.d.ts +0 -1
  37. package/dist/events.d.ts.map +1 -1
  38. package/dist/events.js +1 -6
  39. package/dist/events.js.map +1 -1
  40. package/dist/execution-resolver.d.ts.map +1 -1
  41. package/dist/execution-resolver.js +9 -6
  42. package/dist/execution-resolver.js.map +1 -1
  43. package/dist/harness/auth.d.ts +16 -0
  44. package/dist/harness/auth.d.ts.map +1 -0
  45. package/dist/harness/auth.js +86 -0
  46. package/dist/harness/auth.js.map +1 -0
  47. package/dist/harness/extensions/loader.d.ts +43 -0
  48. package/dist/harness/extensions/loader.d.ts.map +1 -0
  49. package/dist/harness/extensions/loader.js +325 -0
  50. package/dist/harness/extensions/loader.js.map +1 -0
  51. package/dist/harness/extensions/registry.d.ts +23 -0
  52. package/dist/harness/extensions/registry.d.ts.map +1 -0
  53. package/dist/harness/extensions/registry.js +45 -0
  54. package/dist/harness/extensions/registry.js.map +1 -0
  55. package/dist/harness/extensions/types.d.ts +225 -0
  56. package/dist/harness/extensions/types.d.ts.map +1 -0
  57. package/dist/harness/extensions/types.js +2 -0
  58. package/dist/harness/extensions/types.js.map +1 -0
  59. package/dist/harness/http.d.ts +16 -0
  60. package/dist/harness/http.d.ts.map +1 -0
  61. package/dist/harness/http.js +71 -0
  62. package/dist/harness/http.js.map +1 -0
  63. package/dist/harness/index.d.ts +19 -0
  64. package/dist/harness/index.d.ts.map +1 -0
  65. package/dist/harness/index.js +18 -0
  66. package/dist/harness/index.js.map +1 -0
  67. package/dist/harness/models.d.ts +34 -0
  68. package/dist/harness/models.d.ts.map +1 -0
  69. package/dist/harness/models.js +248 -0
  70. package/dist/harness/models.js.map +1 -0
  71. package/dist/harness/runner.d.ts +124 -0
  72. package/dist/harness/runner.d.ts.map +1 -0
  73. package/dist/harness/runner.js +436 -0
  74. package/dist/harness/runner.js.map +1 -0
  75. package/dist/harness/session-store.d.ts +77 -0
  76. package/dist/harness/session-store.d.ts.map +1 -0
  77. package/dist/harness/session-store.js +248 -0
  78. package/dist/harness/session-store.js.map +1 -0
  79. package/dist/harness/settings.d.ts +47 -0
  80. package/dist/harness/settings.d.ts.map +1 -0
  81. package/dist/harness/settings.js +29 -0
  82. package/dist/harness/settings.js.map +1 -0
  83. package/dist/harness/skills.d.ts +54 -0
  84. package/dist/harness/skills.d.ts.map +1 -0
  85. package/dist/harness/skills.js +203 -0
  86. package/dist/harness/skills.js.map +1 -0
  87. package/dist/harness/types.d.ts +32 -0
  88. package/dist/harness/types.d.ts.map +1 -0
  89. package/dist/harness/types.js +2 -0
  90. package/dist/harness/types.js.map +1 -0
  91. package/dist/index.d.ts +1 -0
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +1 -0
  94. package/dist/index.js.map +1 -1
  95. package/dist/log.d.ts.map +1 -1
  96. package/dist/log.js +11 -14
  97. package/dist/log.js.map +1 -1
  98. package/dist/main.js +67 -8
  99. package/dist/main.js.map +1 -1
  100. package/dist/model-registry.d.ts +2 -2
  101. package/dist/model-registry.d.ts.map +1 -1
  102. package/dist/model-registry.js.map +1 -1
  103. package/dist/provisioner.d.ts +1 -4
  104. package/dist/provisioner.d.ts.map +1 -1
  105. package/dist/provisioner.js +3 -8
  106. package/dist/provisioner.js.map +1 -1
  107. package/dist/runtime/agent-run-controller.d.ts.map +1 -1
  108. package/dist/runtime/agent-run-controller.js +6 -3
  109. package/dist/runtime/agent-run-controller.js.map +1 -1
  110. package/dist/runtime/conversation-runtime.js +1 -1
  111. package/dist/runtime/conversation-runtime.js.map +1 -1
  112. package/dist/runtime/types.d.ts +4 -3
  113. package/dist/runtime/types.d.ts.map +1 -1
  114. package/dist/runtime/types.js.map +1 -1
  115. package/dist/sandbox/container.d.ts +1 -0
  116. package/dist/sandbox/container.d.ts.map +1 -1
  117. package/dist/sandbox/container.js +2 -2
  118. package/dist/sandbox/container.js.map +1 -1
  119. package/dist/sandbox/host.d.ts.map +1 -1
  120. package/dist/sandbox/host.js +0 -4
  121. package/dist/sandbox/host.js.map +1 -1
  122. package/dist/sandbox/image.d.ts.map +1 -1
  123. package/dist/sandbox/image.js +0 -3
  124. package/dist/sandbox/image.js.map +1 -1
  125. package/dist/sandbox/index.d.ts.map +1 -1
  126. package/dist/sandbox/index.js +4 -1
  127. package/dist/sandbox/index.js.map +1 -1
  128. package/dist/sandbox/types.d.ts +2 -2
  129. package/dist/sandbox/types.d.ts.map +1 -1
  130. package/dist/sandbox/types.js.map +1 -1
  131. package/dist/sessions/agent-memory-file-manager.d.ts.map +1 -1
  132. package/dist/sessions/agent-memory-file-manager.js +8 -8
  133. package/dist/sessions/agent-memory-file-manager.js.map +1 -1
  134. package/dist/sessions/metadata.js +2 -2
  135. package/dist/sessions/metadata.js.map +1 -1
  136. package/dist/sessions/store.d.ts +3 -3
  137. package/dist/sessions/store.d.ts.map +1 -1
  138. package/dist/sessions/store.js +17 -43
  139. package/dist/sessions/store.js.map +1 -1
  140. package/dist/sessions/types.d.ts +1 -1
  141. package/dist/sessions/types.d.ts.map +1 -1
  142. package/dist/sessions/types.js.map +1 -1
  143. package/dist/store.d.ts +1 -0
  144. package/dist/store.d.ts.map +1 -1
  145. package/dist/store.js +18 -11
  146. package/dist/store.js.map +1 -1
  147. package/dist/tools/edit.d.ts.map +1 -1
  148. package/dist/tools/edit.js +1 -3
  149. package/dist/tools/edit.js.map +1 -1
  150. package/dist/tools/event.d.ts.map +1 -1
  151. package/dist/tools/event.js +7 -74
  152. package/dist/tools/event.js.map +1 -1
  153. package/dist/tools/read.d.ts.map +1 -1
  154. package/dist/tools/read.js +1 -3
  155. package/dist/tools/read.js.map +1 -1
  156. package/dist/tools/write.d.ts.map +1 -1
  157. package/dist/tools/write.js +3 -7
  158. package/dist/tools/write.js.map +1 -1
  159. package/dist/trigger.d.ts +2 -0
  160. package/dist/trigger.d.ts.map +1 -1
  161. package/dist/trigger.js +7 -13
  162. package/dist/trigger.js.map +1 -1
  163. package/dist/types.d.ts +21 -0
  164. package/dist/types.d.ts.map +1 -1
  165. package/dist/types.js.map +1 -1
  166. package/dist/vault/index.d.ts.map +1 -1
  167. package/dist/vault/index.js +7 -1
  168. package/dist/vault/index.js.map +1 -1
  169. package/dist/web/admin/portal.d.ts +1 -1
  170. package/dist/web/admin/portal.d.ts.map +1 -1
  171. package/dist/web/admin/portal.js +394 -73
  172. package/dist/web/admin/portal.js.map +1 -1
  173. package/dist/web/admin/provider-models.d.ts +2 -2
  174. package/dist/web/admin/provider-models.d.ts.map +1 -1
  175. package/dist/web/admin/provider-models.js +4 -2
  176. package/dist/web/admin/provider-models.js.map +1 -1
  177. package/dist/web/admin/store.d.ts.map +1 -1
  178. package/dist/web/admin/store.js +3 -12
  179. package/dist/web/admin/store.js.map +1 -1
  180. package/dist/web/admin/types.d.ts +7 -5
  181. package/dist/web/admin/types.d.ts.map +1 -1
  182. package/dist/web/admin/types.js.map +1 -1
  183. package/dist/web/login/oauth.d.ts.map +1 -1
  184. package/dist/web/login/oauth.js +41 -23
  185. package/dist/web/login/oauth.js.map +1 -1
  186. package/dist/web/login/store.d.ts +0 -4
  187. package/dist/web/login/store.d.ts.map +1 -1
  188. package/dist/web/login/store.js +3 -16
  189. package/dist/web/login/store.js.map +1 -1
  190. package/dist/web/server.js +2 -2
  191. package/dist/web/server.js.map +1 -1
  192. package/dist/web/session-view/portal.d.ts.map +1 -1
  193. package/dist/web/session-view/portal.js +5 -16
  194. package/dist/web/session-view/portal.js.map +1 -1
  195. package/dist/web/session-view/service.js +7 -13
  196. package/dist/web/session-view/service.js.map +1 -1
  197. package/dist/web/session-view/store.d.ts.map +1 -1
  198. package/dist/web/session-view/store.js +2 -7
  199. package/dist/web/session-view/store.js.map +1 -1
  200. package/dist/web/token-store.d.ts +2 -8
  201. package/dist/web/token-store.d.ts.map +1 -1
  202. package/dist/web/token-store.js +11 -12
  203. package/dist/web/token-store.js.map +1 -1
  204. package/package.json +6 -3
  205. package/dist/context.d.ts +0 -2
  206. package/dist/context.d.ts.map +0 -1
  207. package/dist/context.js +0 -2
  208. package/dist/context.js.map +0 -1
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Model catalog for the mikan harness.
3
+ *
4
+ * Wraps pi-ai's `Models` collection: all built-in providers are registered
5
+ * with credentials resolved through mikan's auth.json, and custom providers
6
+ * or overrides can be added via a `models.json` file
7
+ * (`~/.mikan/models.json` by default).
8
+ *
9
+ * models.json subset supported by mikan:
10
+ *
11
+ * ```jsonc
12
+ * {
13
+ * "providers": {
14
+ * "my-provider": {
15
+ * "api": "openai-completions", // required when models are listed
16
+ * "baseUrl": "http://host/v1",
17
+ * "apiKey": "literal-key", // optional; auth.json / MY_PROVIDER_API_KEY otherwise
18
+ * "headers": { },
19
+ * "compat": { },
20
+ * "models": [{ "id": "m", "name": "M", "input": ["text"], "reasoning": false }]
21
+ * },
22
+ * "anthropic": { "baseUrl": "https://proxy.example/v1" } // override built-in provider
23
+ * }
24
+ * }
25
+ * ```
26
+ */
27
+ import { existsSync, readFileSync } from "fs";
28
+ import { homedir } from "os";
29
+ import { join } from "path";
30
+ import { createProvider, } from "@earendil-works/pi-ai";
31
+ import { builtinModels } from "@earendil-works/pi-ai/providers/all";
32
+ import { anthropicMessagesApi } from "@earendil-works/pi-ai/api/anthropic-messages.lazy";
33
+ import { azureOpenAIResponsesApi } from "@earendil-works/pi-ai/api/azure-openai-responses.lazy";
34
+ import { googleGenerativeAIApi } from "@earendil-works/pi-ai/api/google-generative-ai.lazy";
35
+ import { mistralConversationsApi } from "@earendil-works/pi-ai/api/mistral-conversations.lazy";
36
+ import { openAICompletionsApi } from "@earendil-works/pi-ai/api/openai-completions.lazy";
37
+ import { openAIResponsesApi } from "@earendil-works/pi-ai/api/openai-responses.lazy";
38
+ import { defaultAuthPath, FileCredentialStore } from "./auth.js";
39
+ const CUSTOM_API_STREAMS = {
40
+ "anthropic-messages": anthropicMessagesApi,
41
+ "azure-openai-responses": azureOpenAIResponsesApi,
42
+ "google-generative-ai": googleGenerativeAIApi,
43
+ "mistral-conversations": mistralConversationsApi,
44
+ "openai-completions": openAICompletionsApi,
45
+ "openai-responses": openAIResponsesApi,
46
+ };
47
+ const DEFAULT_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
48
+ const DEFAULT_CONTEXT_WINDOW = 128000;
49
+ const DEFAULT_MAX_TOKENS = 16384;
50
+ /** Default location of mikan's models.json. */
51
+ export function defaultModelsJsonPath() {
52
+ return join(homedir(), ".mikan", "models.json");
53
+ }
54
+ function parseModelsJson(path) {
55
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
56
+ if (!parsed || typeof parsed !== "object") {
57
+ throw new Error("models.json must be a JSON object");
58
+ }
59
+ const providers = parsed.providers;
60
+ if (providers === undefined)
61
+ return undefined;
62
+ if (!providers || typeof providers !== "object" || Array.isArray(providers)) {
63
+ throw new Error('models.json "providers" must be an object');
64
+ }
65
+ for (const [name, config] of Object.entries(providers)) {
66
+ if (!config || typeof config !== "object") {
67
+ throw new Error(`models.json provider "${name}" must be an object`);
68
+ }
69
+ const models = config.models;
70
+ if (models !== undefined) {
71
+ if (!Array.isArray(models)) {
72
+ throw new Error(`models.json provider "${name}" models must be an array`);
73
+ }
74
+ const api = config.api;
75
+ if (typeof api !== "string" || !(api in CUSTOM_API_STREAMS)) {
76
+ throw new Error(`models.json provider "${name}" needs an "api" of: ${Object.keys(CUSTOM_API_STREAMS).join(", ")}`);
77
+ }
78
+ for (const model of models) {
79
+ if (!model || typeof model !== "object" || typeof model.id !== "string") {
80
+ throw new Error(`models.json provider "${name}" has a model without a string "id"`);
81
+ }
82
+ }
83
+ }
84
+ }
85
+ return parsed;
86
+ }
87
+ function envVarNameFor(providerName) {
88
+ return `${providerName.replace(/[^a-zA-Z0-9]+/g, "_").toUpperCase()}_API_KEY`;
89
+ }
90
+ function buildCustomProvider(providerName, config) {
91
+ const api = config.api;
92
+ const displayName = config.name ?? providerName;
93
+ const envVar = envVarNameFor(providerName);
94
+ const models = (config.models ?? []).map((modelConfig) => {
95
+ const model = {
96
+ id: modelConfig.id,
97
+ name: modelConfig.name ?? modelConfig.id,
98
+ api: (modelConfig.api ?? api),
99
+ provider: providerName,
100
+ baseUrl: modelConfig.baseUrl ?? config.baseUrl ?? "",
101
+ reasoning: modelConfig.reasoning ?? false,
102
+ input: modelConfig.input ?? ["text"],
103
+ cost: modelConfig.cost ?? DEFAULT_COST,
104
+ contextWindow: modelConfig.contextWindow ?? DEFAULT_CONTEXT_WINDOW,
105
+ maxTokens: modelConfig.maxTokens ?? DEFAULT_MAX_TOKENS,
106
+ };
107
+ if (modelConfig.thinkingLevelMap)
108
+ model.thinkingLevelMap = modelConfig.thinkingLevelMap;
109
+ if (modelConfig.headers ?? config.headers) {
110
+ model.headers = { ...config.headers, ...modelConfig.headers };
111
+ }
112
+ const compat = modelConfig.compat ?? config.compat;
113
+ if (compat)
114
+ model.compat = compat;
115
+ return model;
116
+ });
117
+ return createProvider({
118
+ id: providerName,
119
+ name: displayName,
120
+ baseUrl: config.baseUrl,
121
+ headers: config.headers,
122
+ auth: {
123
+ apiKey: {
124
+ name: `${displayName} API key`,
125
+ resolve: async ({ ctx, credential }) => {
126
+ const key = (credential?.type === "api_key" ? credential.key : undefined) ??
127
+ config.apiKey ??
128
+ (await ctx.env(envVar));
129
+ if (!key)
130
+ return undefined;
131
+ const source = credential?.type === "api_key" && credential.key
132
+ ? "auth.json"
133
+ : config.apiKey
134
+ ? "models.json"
135
+ : envVar;
136
+ return { auth: { apiKey: key }, source };
137
+ },
138
+ },
139
+ },
140
+ models,
141
+ api: CUSTOM_API_STREAMS[api](),
142
+ });
143
+ }
144
+ /** Rebuild a built-in provider with overridden model base URLs / compat. */
145
+ function overrideBuiltinProvider(provider, config) {
146
+ const models = provider.getModels().map((model) => {
147
+ const overridden = Object.assign({}, model);
148
+ if (config.baseUrl)
149
+ overridden.baseUrl = config.baseUrl;
150
+ if (config.compat)
151
+ overridden.compat = config.compat;
152
+ return overridden;
153
+ });
154
+ return {
155
+ ...provider,
156
+ getModels: () => models,
157
+ };
158
+ }
159
+ /**
160
+ * Model catalog backed by pi-ai's `Models`. Exposes the lookup and auth
161
+ * operations mikan needs; streaming goes through {@link MikanModels.models}.
162
+ */
163
+ export class MikanModels {
164
+ constructor(models, loadError) {
165
+ this.models = models;
166
+ this.loadError = loadError;
167
+ }
168
+ static create(options = {}) {
169
+ const authPath = options.authPath ?? defaultAuthPath();
170
+ const modelsJsonPath = options.modelsJsonPath ?? defaultModelsJsonPath();
171
+ const models = builtinModels({ credentials: new FileCredentialStore(authPath) });
172
+ let loadError;
173
+ if (existsSync(modelsJsonPath)) {
174
+ try {
175
+ const config = parseModelsJson(modelsJsonPath);
176
+ for (const [providerName, providerConfig] of Object.entries(config?.providers ?? {})) {
177
+ if (providerConfig.models && providerConfig.models.length > 0) {
178
+ models.setProvider(buildCustomProvider(providerName, providerConfig));
179
+ }
180
+ else if (providerConfig.baseUrl || providerConfig.compat) {
181
+ const builtin = models.getProvider(providerName);
182
+ if (builtin) {
183
+ models.setProvider(overrideBuiltinProvider(builtin, providerConfig));
184
+ }
185
+ }
186
+ }
187
+ }
188
+ catch (err) {
189
+ loadError = `Failed to load ${modelsJsonPath}: ${err instanceof Error ? err.message : String(err)}`;
190
+ }
191
+ }
192
+ return new MikanModels(models, loadError);
193
+ }
194
+ /** Error from loading models.json, if any. Built-in models stay available. */
195
+ getError() {
196
+ return this.loadError;
197
+ }
198
+ /** All known models (built-in plus custom). */
199
+ getAll() {
200
+ return [...this.models.getModels()];
201
+ }
202
+ /** Find a model by provider and id. */
203
+ find(provider, modelId) {
204
+ return this.models.getModel(provider, modelId);
205
+ }
206
+ /** Models whose provider auth currently resolves (API key, OAuth, or ambient). */
207
+ async getAvailable() {
208
+ const byProvider = new Map();
209
+ for (const model of this.models.getModels()) {
210
+ const group = byProvider.get(model.provider) ?? [];
211
+ group.push(model);
212
+ byProvider.set(model.provider, group);
213
+ }
214
+ const available = [];
215
+ for (const group of byProvider.values()) {
216
+ try {
217
+ const auth = await this.models.getAuth(group[0]);
218
+ if (auth)
219
+ available.push(...group);
220
+ }
221
+ catch {
222
+ // Auth resolution failure (e.g. expired OAuth) — treat as unavailable.
223
+ }
224
+ }
225
+ return available;
226
+ }
227
+ /** Resolve request auth for a model. Undefined when unconfigured. */
228
+ getAuth(model) {
229
+ return this.models.getAuth(model);
230
+ }
231
+ /**
232
+ * Resolve an API key for a provider. Convenience for call sites that only
233
+ * need a bearer key (for example pi-agent-core's compat stream function).
234
+ */
235
+ async getApiKeyForProvider(provider) {
236
+ const model = this.models.getModels(provider)[0];
237
+ if (!model)
238
+ return undefined;
239
+ try {
240
+ const auth = await this.models.getAuth(model);
241
+ return auth?.auth.apiKey;
242
+ }
243
+ catch {
244
+ return undefined;
245
+ }
246
+ }
247
+ }
248
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/harness/models.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model catalog for the mikan harness.\n *\n * Wraps pi-ai's `Models` collection: all built-in providers are registered\n * with credentials resolved through mikan's auth.json, and custom providers\n * or overrides can be added via a `models.json` file\n * (`~/.mikan/models.json` by default).\n *\n * models.json subset supported by mikan:\n *\n * ```jsonc\n * {\n * \"providers\": {\n * \"my-provider\": {\n * \"api\": \"openai-completions\", // required when models are listed\n * \"baseUrl\": \"http://host/v1\",\n * \"apiKey\": \"literal-key\", // optional; auth.json / MY_PROVIDER_API_KEY otherwise\n * \"headers\": { },\n * \"compat\": { },\n * \"models\": [{ \"id\": \"m\", \"name\": \"M\", \"input\": [\"text\"], \"reasoning\": false }]\n * },\n * \"anthropic\": { \"baseUrl\": \"https://proxy.example/v1\" } // override built-in provider\n * }\n * }\n * ```\n */\nimport { existsSync, readFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { join } from \"path\";\nimport {\n createProvider,\n type Api,\n type AuthResult,\n type Model,\n type Models,\n type MutableModels,\n type Provider,\n type ProviderStreams,\n} from \"@earendil-works/pi-ai\";\nimport { builtinModels } from \"@earendil-works/pi-ai/providers/all\";\nimport { anthropicMessagesApi } from \"@earendil-works/pi-ai/api/anthropic-messages.lazy\";\nimport { azureOpenAIResponsesApi } from \"@earendil-works/pi-ai/api/azure-openai-responses.lazy\";\nimport { googleGenerativeAIApi } from \"@earendil-works/pi-ai/api/google-generative-ai.lazy\";\nimport { mistralConversationsApi } from \"@earendil-works/pi-ai/api/mistral-conversations.lazy\";\nimport { openAICompletionsApi } from \"@earendil-works/pi-ai/api/openai-completions.lazy\";\nimport { openAIResponsesApi } from \"@earendil-works/pi-ai/api/openai-responses.lazy\";\nimport { defaultAuthPath, FileCredentialStore } from \"./auth.js\";\n\nconst CUSTOM_API_STREAMS: Record<string, () => ProviderStreams> = {\n \"anthropic-messages\": anthropicMessagesApi,\n \"azure-openai-responses\": azureOpenAIResponsesApi,\n \"google-generative-ai\": googleGenerativeAIApi,\n \"mistral-conversations\": mistralConversationsApi,\n \"openai-completions\": openAICompletionsApi,\n \"openai-responses\": openAIResponsesApi,\n};\n\nconst DEFAULT_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\nconst DEFAULT_CONTEXT_WINDOW = 128000;\nconst DEFAULT_MAX_TOKENS = 16384;\n\ninterface CustomModelConfig {\n id: string;\n name?: string;\n api?: string;\n baseUrl?: string;\n reasoning?: boolean;\n input?: (\"text\" | \"image\")[];\n cost?: { input: number; output: number; cacheRead: number; cacheWrite: number };\n contextWindow?: number;\n maxTokens?: number;\n thinkingLevelMap?: Model<Api>[\"thinkingLevelMap\"];\n headers?: Record<string, string>;\n compat?: unknown;\n}\n\ninterface CustomProviderConfig {\n name?: string;\n api?: string;\n baseUrl?: string;\n apiKey?: string;\n headers?: Record<string, string>;\n compat?: unknown;\n models?: CustomModelConfig[];\n}\n\ninterface ModelsJsonConfig {\n providers: Record<string, CustomProviderConfig>;\n}\n\n/** Default location of mikan's models.json. */\nexport function defaultModelsJsonPath(): string {\n return join(homedir(), \".mikan\", \"models.json\");\n}\n\nfunction parseModelsJson(path: string): ModelsJsonConfig | undefined {\n const parsed: unknown = JSON.parse(readFileSync(path, \"utf-8\"));\n if (!parsed || typeof parsed !== \"object\") {\n throw new Error(\"models.json must be a JSON object\");\n }\n const providers = (parsed as { providers?: unknown }).providers;\n if (providers === undefined) return undefined;\n if (!providers || typeof providers !== \"object\" || Array.isArray(providers)) {\n throw new Error('models.json \"providers\" must be an object');\n }\n for (const [name, config] of Object.entries(providers)) {\n if (!config || typeof config !== \"object\") {\n throw new Error(`models.json provider \"${name}\" must be an object`);\n }\n const models = (config as CustomProviderConfig).models;\n if (models !== undefined) {\n if (!Array.isArray(models)) {\n throw new Error(`models.json provider \"${name}\" models must be an array`);\n }\n const api = (config as CustomProviderConfig).api;\n if (typeof api !== \"string\" || !(api in CUSTOM_API_STREAMS)) {\n throw new Error(\n `models.json provider \"${name}\" needs an \"api\" of: ${Object.keys(CUSTOM_API_STREAMS).join(\", \")}`,\n );\n }\n for (const model of models) {\n if (!model || typeof model !== \"object\" || typeof model.id !== \"string\") {\n throw new Error(`models.json provider \"${name}\" has a model without a string \"id\"`);\n }\n }\n }\n }\n return parsed as ModelsJsonConfig;\n}\n\nfunction envVarNameFor(providerName: string): string {\n return `${providerName.replace(/[^a-zA-Z0-9]+/g, \"_\").toUpperCase()}_API_KEY`;\n}\n\nfunction buildCustomProvider(providerName: string, config: CustomProviderConfig): Provider {\n const api = config.api!;\n const displayName = config.name ?? providerName;\n const envVar = envVarNameFor(providerName);\n const models = (config.models ?? []).map((modelConfig): Model<Api> => {\n const model: Model<Api> = {\n id: modelConfig.id,\n name: modelConfig.name ?? modelConfig.id,\n api: (modelConfig.api ?? api) as Api,\n provider: providerName,\n baseUrl: modelConfig.baseUrl ?? config.baseUrl ?? \"\",\n reasoning: modelConfig.reasoning ?? false,\n input: modelConfig.input ?? [\"text\"],\n cost: modelConfig.cost ?? DEFAULT_COST,\n contextWindow: modelConfig.contextWindow ?? DEFAULT_CONTEXT_WINDOW,\n maxTokens: modelConfig.maxTokens ?? DEFAULT_MAX_TOKENS,\n };\n if (modelConfig.thinkingLevelMap) model.thinkingLevelMap = modelConfig.thinkingLevelMap;\n if (modelConfig.headers ?? config.headers) {\n model.headers = { ...config.headers, ...modelConfig.headers };\n }\n const compat = modelConfig.compat ?? config.compat;\n if (compat) model.compat = compat as Model<Api>[\"compat\"];\n return model;\n });\n\n return createProvider({\n id: providerName,\n name: displayName,\n baseUrl: config.baseUrl,\n headers: config.headers,\n auth: {\n apiKey: {\n name: `${displayName} API key`,\n resolve: async ({ ctx, credential }) => {\n const key =\n (credential?.type === \"api_key\" ? credential.key : undefined) ??\n config.apiKey ??\n (await ctx.env(envVar));\n if (!key) return undefined;\n const source =\n credential?.type === \"api_key\" && credential.key\n ? \"auth.json\"\n : config.apiKey\n ? \"models.json\"\n : envVar;\n return { auth: { apiKey: key }, source };\n },\n },\n },\n models,\n api: CUSTOM_API_STREAMS[api](),\n });\n}\n\n/** Rebuild a built-in provider with overridden model base URLs / compat. */\nfunction overrideBuiltinProvider(provider: Provider, config: CustomProviderConfig): Provider {\n const models = provider.getModels().map((model): Model<Api> => {\n const overridden: Model<Api> = Object.assign({}, model);\n if (config.baseUrl) overridden.baseUrl = config.baseUrl;\n if (config.compat) overridden.compat = config.compat as Model<Api>[\"compat\"];\n return overridden;\n });\n return {\n ...provider,\n getModels: () => models,\n };\n}\n\nexport interface CreateMikanModelsOptions {\n authPath?: string;\n modelsJsonPath?: string;\n}\n\n/**\n * Model catalog backed by pi-ai's `Models`. Exposes the lookup and auth\n * operations mikan needs; streaming goes through {@link MikanModels.models}.\n */\nexport class MikanModels {\n /** Underlying pi-ai collection, for streaming/completion calls. */\n readonly models: Models;\n private loadError: string | undefined;\n\n private constructor(models: MutableModels, loadError: string | undefined) {\n this.models = models;\n this.loadError = loadError;\n }\n\n static create(options: CreateMikanModelsOptions = {}): MikanModels {\n const authPath = options.authPath ?? defaultAuthPath();\n const modelsJsonPath = options.modelsJsonPath ?? defaultModelsJsonPath();\n const models = builtinModels({ credentials: new FileCredentialStore(authPath) });\n\n let loadError: string | undefined;\n if (existsSync(modelsJsonPath)) {\n try {\n const config = parseModelsJson(modelsJsonPath);\n for (const [providerName, providerConfig] of Object.entries(config?.providers ?? {})) {\n if (providerConfig.models && providerConfig.models.length > 0) {\n models.setProvider(buildCustomProvider(providerName, providerConfig));\n } else if (providerConfig.baseUrl || providerConfig.compat) {\n const builtin = models.getProvider(providerName);\n if (builtin) {\n models.setProvider(overrideBuiltinProvider(builtin, providerConfig));\n }\n }\n }\n } catch (err) {\n loadError = `Failed to load ${modelsJsonPath}: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n return new MikanModels(models, loadError);\n }\n\n /** Error from loading models.json, if any. Built-in models stay available. */\n getError(): string | undefined {\n return this.loadError;\n }\n\n /** All known models (built-in plus custom). */\n getAll(): Model<Api>[] {\n return [...this.models.getModels()];\n }\n\n /** Find a model by provider and id. */\n find(provider: string, modelId: string): Model<Api> | undefined {\n return this.models.getModel(provider, modelId);\n }\n\n /** Models whose provider auth currently resolves (API key, OAuth, or ambient). */\n async getAvailable(): Promise<Model<Api>[]> {\n const byProvider = new Map<string, Model<Api>[]>();\n for (const model of this.models.getModels()) {\n const group = byProvider.get(model.provider) ?? [];\n group.push(model);\n byProvider.set(model.provider, group);\n }\n\n const available: Model<Api>[] = [];\n for (const group of byProvider.values()) {\n try {\n const auth = await this.models.getAuth(group[0]);\n if (auth) available.push(...group);\n } catch {\n // Auth resolution failure (e.g. expired OAuth) — treat as unavailable.\n }\n }\n return available;\n }\n\n /** Resolve request auth for a model. Undefined when unconfigured. */\n getAuth(model: Model<Api>): Promise<AuthResult | undefined> {\n return this.models.getAuth(model);\n }\n\n /**\n * Resolve an API key for a provider. Convenience for call sites that only\n * need a bearer key (for example pi-agent-core's compat stream function).\n */\n async getApiKeyForProvider(provider: string): Promise<string | undefined> {\n const model = this.models.getModels(provider)[0];\n if (!model) return undefined;\n try {\n const auth = await this.models.getAuth(model);\n return auth?.auth.apiKey;\n } catch {\n return undefined;\n }\n }\n}\n"]}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * MikanAgentSession — mikan's agent run loop.
3
+ *
4
+ * Owns a pi-agent-core `Agent` and layers on the behaviors mikan needs for
5
+ * long-lived chat conversations:
6
+ *
7
+ * - message persistence into the conversation's {@link SessionStore}
8
+ * - automatic context compaction (threshold and overflow recovery), using
9
+ * pi-agent-core's compaction pipeline over the session tree
10
+ * - automatic retry with exponential backoff on transient provider errors
11
+ * - extension hook dispatch ({@link ExtensionRegistry})
12
+ *
13
+ * Events mirror the agent's lifecycle events plus `compaction_start/_end`
14
+ * and `auto_retry_start/_end`, preserving the event surface mikan's
15
+ * platform adapters already render.
16
+ */
17
+ import { Agent, type AgentEvent, type AgentMessage, type AgentTool, type ThinkingLevel } from "@earendil-works/pi-agent-core";
18
+ import { type Api, type ImageContent, type Model } from "@earendil-works/pi-ai";
19
+ import type { ExtensionRegistry } from "./extensions/registry.js";
20
+ import type { MikanModels } from "./models.js";
21
+ import { resolveHarnessSettings, type BudgetSettings } from "./settings.js";
22
+ import type { SessionStore } from "./session-store.js";
23
+ export type CompactionReason = "threshold" | "overflow" | "manual";
24
+ interface CompactionResultSummary {
25
+ summary: string;
26
+ firstKeptEntryId: string;
27
+ tokensBefore: number;
28
+ }
29
+ export type HarnessEvent = AgentEvent | {
30
+ type: "compaction_start";
31
+ reason: CompactionReason;
32
+ } | {
33
+ type: "compaction_end";
34
+ reason: CompactionReason;
35
+ result?: CompactionResultSummary;
36
+ aborted: boolean;
37
+ errorMessage?: string;
38
+ } | {
39
+ type: "auto_retry_start";
40
+ attempt: number;
41
+ maxAttempts: number;
42
+ delayMs: number;
43
+ errorMessage: string;
44
+ } | {
45
+ type: "auto_retry_end";
46
+ success: boolean;
47
+ attempt: number;
48
+ finalError?: string;
49
+ } | {
50
+ type: "budget_exceeded";
51
+ /** Which cap was hit, e.g. "cost 2.01 USD > 2 USD limit". */
52
+ reason: string;
53
+ tokens: number;
54
+ costUsd: number;
55
+ llmCalls: number;
56
+ durationMs: number;
57
+ };
58
+ export type HarnessEventListener = (event: HarnessEvent) => void | Promise<void>;
59
+ export interface MikanAgentSessionOptions {
60
+ systemPrompt: string;
61
+ model: Model<Api>;
62
+ thinkingLevel: ThinkingLevel;
63
+ tools: AgentTool[];
64
+ models: MikanModels;
65
+ sessionStore: SessionStore;
66
+ settings?: Parameters<typeof resolveHarnessSettings>[0];
67
+ extensions?: ExtensionRegistry;
68
+ }
69
+ export declare class MikanAgentSession {
70
+ readonly agent: Agent;
71
+ readonly sessionStore: SessionStore;
72
+ private readonly models;
73
+ private readonly settings;
74
+ private readonly extensions;
75
+ private listeners;
76
+ private retryAttempt;
77
+ private overflowRecoveryAttempted;
78
+ private retryAbortController;
79
+ private compactionAbortController;
80
+ private tally;
81
+ private runBudget;
82
+ private budgetExceededReason;
83
+ constructor(options: MikanAgentSessionOptions);
84
+ /** Conversation transcript currently held by the agent. */
85
+ get messages(): AgentMessage[];
86
+ get model(): Model<Api>;
87
+ subscribe(listener: HarnessEventListener): () => void;
88
+ /** Replace the agent transcript from the persisted session tree. */
89
+ reloadFromSession(): number;
90
+ /**
91
+ * Send a user prompt and run the agent loop to completion, including
92
+ * automatic retries and compaction. Resolves when the turn (and any
93
+ * recovery continuations) settles.
94
+ *
95
+ * @param options.budget Per-run resource ceilings that override the session
96
+ * defaults. Autonomous (event / trigger) runs should pass a budget so a
97
+ * runaway loop is stopped even with no human watching.
98
+ */
99
+ prompt(text: string, options?: {
100
+ images?: ImageContent[];
101
+ budget?: BudgetSettings;
102
+ }): Promise<void>;
103
+ /** Abort the active run, pending retry backoff, and in-flight compaction. */
104
+ abort(): void;
105
+ private ensureAuthConfigured;
106
+ private emit;
107
+ private handleAgentEvent;
108
+ /** Fold one assistant turn's usage into the running per-run tally. */
109
+ private recordUsage;
110
+ /** Compare the tally against the run budget; abort the run when a cap is exceeded. */
111
+ private enforceBudget;
112
+ private overBudgetReason;
113
+ private findLastAssistantMessage;
114
+ /** Decide what to do after a run settles. Returns true when the agent should continue. */
115
+ private handlePostRun;
116
+ private handleOverflow;
117
+ private checkThresholdCompaction;
118
+ private runCompaction;
119
+ private isRetryableError;
120
+ private prepareRetry;
121
+ private dropTrailingErrorMessage;
122
+ }
123
+ export {};
124
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/harness/runner.ts"],"names":[],"mappings":"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"}