@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,225 @@
1
+ /**
2
+ * mikan extension system, v1.
3
+ *
4
+ * Extensions are ES modules that export an `activate` function (either as
5
+ * the default export or a named `activate` export, optionally wrapped in an
6
+ * object that also carries a `name`). `activate` receives a
7
+ * {@link MikanExtensionApi} and registers hooks and tools.
8
+ *
9
+ * ```js
10
+ * // extensions/audit.mjs
11
+ * export default function activate(api) {
12
+ * api.on("tool_call", ({ toolName, args }) => {
13
+ * if (toolName === "bash" && String(args.command).includes("rm -rf /")) {
14
+ * return { block: true, reason: "destructive command" };
15
+ * }
16
+ * });
17
+ * }
18
+ * ```
19
+ *
20
+ * Hooks run in registration order. For hooks with results, the first
21
+ * non-undefined result wins (v1 semantics; later versions may merge).
22
+ * Hook errors are logged and never crash a run.
23
+ */
24
+ import type { AgentMessage, AgentTool, ThinkingLevel } from "@earendil-works/pi-agent-core";
25
+ import type { Api, ImageContent, Model, TextContent } from "@earendil-works/pi-ai";
26
+ import type { MikanSkill } from "../skills.js";
27
+ import type { CompactionEntry } from "../types.js";
28
+ export interface BeforeAgentStartHookEvent {
29
+ prompt: string;
30
+ images?: ImageContent[];
31
+ systemPrompt: string;
32
+ }
33
+ export interface BeforeAgentStartHookResult {
34
+ /** Replace the system prompt for this turn. */
35
+ systemPrompt?: string;
36
+ }
37
+ export interface ToolCallHookEvent {
38
+ toolCallId: string;
39
+ toolName: string;
40
+ args: unknown;
41
+ }
42
+ export interface ToolCallHookResult {
43
+ /** Block the tool call; the model receives an error tool result instead. */
44
+ block?: boolean;
45
+ reason?: string;
46
+ }
47
+ export interface ToolResultHookEvent {
48
+ toolCallId: string;
49
+ toolName: string;
50
+ args: unknown;
51
+ content: (TextContent | ImageContent)[];
52
+ isError: boolean;
53
+ }
54
+ export interface MessageEndHookEvent {
55
+ message: AgentMessage;
56
+ }
57
+ export interface TurnEndHookEvent {
58
+ messages: AgentMessage[];
59
+ }
60
+ export interface SessionCompactHookEvent {
61
+ entry: CompactionEntry;
62
+ reason: "threshold" | "overflow" | "manual";
63
+ }
64
+ /** Map of hook names to handler signatures. */
65
+ export interface MikanHookMap {
66
+ before_agent_start: (event: BeforeAgentStartHookEvent) => BeforeAgentStartHookResult | undefined | void | Promise<BeforeAgentStartHookResult | undefined | void>;
67
+ tool_call: (event: ToolCallHookEvent) => ToolCallHookResult | undefined | void | Promise<ToolCallHookResult | undefined | void>;
68
+ tool_result: (event: ToolResultHookEvent) => void | Promise<void>;
69
+ message_end: (event: MessageEndHookEvent) => void | Promise<void>;
70
+ turn_end: (event: TurnEndHookEvent) => void | Promise<void>;
71
+ session_compact: (event: SessionCompactHookEvent) => void | Promise<void>;
72
+ }
73
+ export type MikanHookName = keyof MikanHookMap;
74
+ /**
75
+ * A schedule contributed by an extension. Fires an autonomous agent run in
76
+ * this conversation with `text` as the task prompt (the run does not inherit
77
+ * conversation history — write `text` self-contained).
78
+ */
79
+ export type ExtensionScheduleSpec = {
80
+ type: "periodic";
81
+ /** Cron expression (croner syntax). */
82
+ schedule: string;
83
+ /** IANA timezone, e.g. "Asia/Taipei". */
84
+ timezone: string;
85
+ text: string;
86
+ /** Target platform; optional when only one platform is running. */
87
+ platform?: string;
88
+ } | {
89
+ type: "one-shot";
90
+ /** ISO 8601 timestamp with offset. */
91
+ at: string;
92
+ text: string;
93
+ platform?: string;
94
+ };
95
+ export interface ExtensionScheduleInfo {
96
+ /** Extension-chosen schedule name. */
97
+ name: string;
98
+ spec: ExtensionScheduleSpec;
99
+ }
100
+ /**
101
+ * Event-file payload the harness hands to the embedder's schedule store.
102
+ * Mirrors mikan's event-file shape; `platform` may be omitted when the
103
+ * embedder runs a single platform.
104
+ */
105
+ export interface ExtensionSchedulePayload {
106
+ type: "one-shot" | "periodic";
107
+ conversationId: string;
108
+ text: string;
109
+ platform?: string;
110
+ at?: string;
111
+ schedule?: string;
112
+ timezone?: string;
113
+ }
114
+ /**
115
+ * Persistence backend for extension schedules, injected by the embedder
116
+ * (mikan backs this with event files watched by its EventsWatcher).
117
+ * Filenames are fully qualified by the harness (`ext-<slug>-<name>.json`).
118
+ */
119
+ export interface ExtensionScheduleStore {
120
+ write(filename: string, payload: ExtensionSchedulePayload): Promise<void>;
121
+ delete(filename: string): Promise<boolean>;
122
+ /** List all schedule files, harness filters by ownership prefix. */
123
+ list(): Promise<Array<{
124
+ filename: string;
125
+ payload: ExtensionSchedulePayload;
126
+ }>>;
127
+ }
128
+ /**
129
+ * Host services injected into extensions by the embedder. All fields are
130
+ * optional: the corresponding api surface throws an informative error when
131
+ * the running context does not provide the service.
132
+ */
133
+ export interface ExtensionHostServices {
134
+ /** State dir for per-extension data dirs; defaults to `~/.mikan`. */
135
+ stateDir?: string;
136
+ /** Schedule persistence; enables `api.schedules`. */
137
+ scheduleStore?: ExtensionScheduleStore;
138
+ /** Post a message to a conversation without an agent run; enables `api.notify`. */
139
+ postMessage?: (conversationId: string, text: string, platform?: string) => Promise<void>;
140
+ /** Resolve read-only secrets for an extension slug; enables `api.secrets`. */
141
+ resolveSecrets?: (slug: string) => Record<string, string>;
142
+ }
143
+ /**
144
+ * Optional `manifest.json` next to a directory-form extension's entrypoint.
145
+ * `name` is the display name only; the slug (data dir, secrets, schedule
146
+ * ownership) always derives from the install path so identity is
147
+ * admin-controlled and stable across manifest edits.
148
+ */
149
+ export interface ExtensionManifest {
150
+ name?: string;
151
+ version?: string;
152
+ description?: string;
153
+ }
154
+ /** API handed to an extension's `activate` function. */
155
+ export interface MikanExtensionApi {
156
+ /** Register a hook handler. */
157
+ on<T extends MikanHookName>(hook: T, handler: MikanHookMap[T]): void;
158
+ /** Contribute an additional agent tool. */
159
+ registerTool(tool: AgentTool): void;
160
+ /** Extension-scoped logging that lands in mikan's structured log. */
161
+ log(message: string): void;
162
+ /** Context about the conversation this harness instance serves. */
163
+ readonly context: {
164
+ readonly conversationId: string;
165
+ readonly workspaceDir: string;
166
+ readonly model: Model<Api>;
167
+ readonly thinkingLevel: ThinkingLevel;
168
+ };
169
+ /** Host-only filesystem locations owned by this extension. */
170
+ readonly paths: {
171
+ /**
172
+ * Per-extension data directory under the state dir
173
+ * (`<stateDir>/extension-data/<slug>`), created on first access.
174
+ * Host-only: never mounted into sandbox containers.
175
+ */
176
+ readonly dataDir: string;
177
+ };
178
+ /**
179
+ * Read-only secrets from the embedder's vault
180
+ * (mikan: `<stateDir>/vaults/extensions/<slug>/env`).
181
+ */
182
+ readonly secrets: {
183
+ get(key: string): string | undefined;
184
+ /** Secret names only, never values. */
185
+ list(): string[];
186
+ };
187
+ /**
188
+ * Named schedules owned by this extension + conversation. Backed by the
189
+ * embedder's schedule store; in mikan these become event files that fire
190
+ * autonomous agent runs (hot-reloaded, persisted across restarts).
191
+ */
192
+ readonly schedules: {
193
+ /** Create or replace a named schedule. */
194
+ upsert(name: string, spec: ExtensionScheduleSpec): Promise<void>;
195
+ /** Delete a named schedule. Returns false when it did not exist. */
196
+ delete(name: string): Promise<boolean>;
197
+ /** Schedules owned by this extension in this conversation. */
198
+ list(): Promise<ExtensionScheduleInfo[]>;
199
+ };
200
+ /**
201
+ * Post text into this conversation without triggering an agent run.
202
+ * Available when the embedder provides platform messaging.
203
+ */
204
+ notify(text: string): Promise<void>;
205
+ }
206
+ export type MikanExtensionActivate = (api: MikanExtensionApi) => void | Promise<void>;
207
+ export interface MikanExtensionModule {
208
+ name?: string;
209
+ activate: MikanExtensionActivate;
210
+ }
211
+ export interface LoadedExtension {
212
+ name: string;
213
+ path: string;
214
+ /** Filesystem-safe identifier used for data dirs, secrets, and schedules. */
215
+ slug: string;
216
+ version?: string;
217
+ description?: string;
218
+ /** Skills discovered under the extension's `skills/` directory. */
219
+ skills: MikanSkill[];
220
+ }
221
+ export interface ExtensionLoadError {
222
+ path: string;
223
+ error: string;
224
+ }
225
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/harness/extensions/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/harness/extensions/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * mikan extension system, v1.\n *\n * Extensions are ES modules that export an `activate` function (either as\n * the default export or a named `activate` export, optionally wrapped in an\n * object that also carries a `name`). `activate` receives a\n * {@link MikanExtensionApi} and registers hooks and tools.\n *\n * ```js\n * // extensions/audit.mjs\n * export default function activate(api) {\n * api.on(\"tool_call\", ({ toolName, args }) => {\n * if (toolName === \"bash\" && String(args.command).includes(\"rm -rf /\")) {\n * return { block: true, reason: \"destructive command\" };\n * }\n * });\n * }\n * ```\n *\n * Hooks run in registration order. For hooks with results, the first\n * non-undefined result wins (v1 semantics; later versions may merge).\n * Hook errors are logged and never crash a run.\n */\nimport type { AgentMessage, AgentTool, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, ImageContent, Model, TextContent } from \"@earendil-works/pi-ai\";\nimport type { MikanSkill } from \"../skills.js\";\nimport type { CompactionEntry } from \"../types.js\";\n\nexport interface BeforeAgentStartHookEvent {\n prompt: string;\n images?: ImageContent[];\n systemPrompt: string;\n}\n\nexport interface BeforeAgentStartHookResult {\n /** Replace the system prompt for this turn. */\n systemPrompt?: string;\n}\n\nexport interface ToolCallHookEvent {\n toolCallId: string;\n toolName: string;\n args: unknown;\n}\n\nexport interface ToolCallHookResult {\n /** Block the tool call; the model receives an error tool result instead. */\n block?: boolean;\n reason?: string;\n}\n\nexport interface ToolResultHookEvent {\n toolCallId: string;\n toolName: string;\n args: unknown;\n content: (TextContent | ImageContent)[];\n isError: boolean;\n}\n\nexport interface MessageEndHookEvent {\n message: AgentMessage;\n}\n\nexport interface TurnEndHookEvent {\n messages: AgentMessage[];\n}\n\nexport interface SessionCompactHookEvent {\n entry: CompactionEntry;\n reason: \"threshold\" | \"overflow\" | \"manual\";\n}\n\n/** Map of hook names to handler signatures. */\nexport interface MikanHookMap {\n before_agent_start: (\n event: BeforeAgentStartHookEvent,\n ) =>\n | BeforeAgentStartHookResult\n | undefined\n | void\n | Promise<BeforeAgentStartHookResult | undefined | void>;\n tool_call: (\n event: ToolCallHookEvent,\n ) => ToolCallHookResult | undefined | void | Promise<ToolCallHookResult | undefined | void>;\n tool_result: (event: ToolResultHookEvent) => void | Promise<void>;\n message_end: (event: MessageEndHookEvent) => void | Promise<void>;\n turn_end: (event: TurnEndHookEvent) => void | Promise<void>;\n session_compact: (event: SessionCompactHookEvent) => void | Promise<void>;\n}\n\nexport type MikanHookName = keyof MikanHookMap;\n\n// ── v2: schedules ────────────────────────────────────────────────────────────\n\n/**\n * A schedule contributed by an extension. Fires an autonomous agent run in\n * this conversation with `text` as the task prompt (the run does not inherit\n * conversation history — write `text` self-contained).\n */\nexport type ExtensionScheduleSpec =\n | {\n type: \"periodic\";\n /** Cron expression (croner syntax). */\n schedule: string;\n /** IANA timezone, e.g. \"Asia/Taipei\". */\n timezone: string;\n text: string;\n /** Target platform; optional when only one platform is running. */\n platform?: string;\n }\n | {\n type: \"one-shot\";\n /** ISO 8601 timestamp with offset. */\n at: string;\n text: string;\n platform?: string;\n };\n\nexport interface ExtensionScheduleInfo {\n /** Extension-chosen schedule name. */\n name: string;\n spec: ExtensionScheduleSpec;\n}\n\n/**\n * Event-file payload the harness hands to the embedder's schedule store.\n * Mirrors mikan's event-file shape; `platform` may be omitted when the\n * embedder runs a single platform.\n */\nexport interface ExtensionSchedulePayload {\n type: \"one-shot\" | \"periodic\";\n conversationId: string;\n text: string;\n platform?: string;\n at?: string;\n schedule?: string;\n timezone?: string;\n}\n\n// ── v2: embedder-injected services ───────────────────────────────────────────\n\n/**\n * Persistence backend for extension schedules, injected by the embedder\n * (mikan backs this with event files watched by its EventsWatcher).\n * Filenames are fully qualified by the harness (`ext-<slug>-<name>.json`).\n */\nexport interface ExtensionScheduleStore {\n write(filename: string, payload: ExtensionSchedulePayload): Promise<void>;\n delete(filename: string): Promise<boolean>;\n /** List all schedule files, harness filters by ownership prefix. */\n list(): Promise<Array<{ filename: string; payload: ExtensionSchedulePayload }>>;\n}\n\n/**\n * Host services injected into extensions by the embedder. All fields are\n * optional: the corresponding api surface throws an informative error when\n * the running context does not provide the service.\n */\nexport interface ExtensionHostServices {\n /** State dir for per-extension data dirs; defaults to `~/.mikan`. */\n stateDir?: string;\n /** Schedule persistence; enables `api.schedules`. */\n scheduleStore?: ExtensionScheduleStore;\n /** Post a message to a conversation without an agent run; enables `api.notify`. */\n postMessage?: (conversationId: string, text: string, platform?: string) => Promise<void>;\n /** Resolve read-only secrets for an extension slug; enables `api.secrets`. */\n resolveSecrets?: (slug: string) => Record<string, string>;\n}\n\n// ── v2: manifest ─────────────────────────────────────────────────────────────\n\n/**\n * Optional `manifest.json` next to a directory-form extension's entrypoint.\n * `name` is the display name only; the slug (data dir, secrets, schedule\n * ownership) always derives from the install path so identity is\n * admin-controlled and stable across manifest edits.\n */\nexport interface ExtensionManifest {\n name?: string;\n version?: string;\n description?: string;\n}\n\n/** API handed to an extension's `activate` function. */\nexport interface MikanExtensionApi {\n /** Register a hook handler. */\n on<T extends MikanHookName>(hook: T, handler: MikanHookMap[T]): void;\n /** Contribute an additional agent tool. */\n registerTool(tool: AgentTool): void;\n /** Extension-scoped logging that lands in mikan's structured log. */\n log(message: string): void;\n /** Context about the conversation this harness instance serves. */\n readonly context: {\n readonly conversationId: string;\n readonly workspaceDir: string;\n readonly model: Model<Api>;\n readonly thinkingLevel: ThinkingLevel;\n };\n /** Host-only filesystem locations owned by this extension. */\n readonly paths: {\n /**\n * Per-extension data directory under the state dir\n * (`<stateDir>/extension-data/<slug>`), created on first access.\n * Host-only: never mounted into sandbox containers.\n */\n readonly dataDir: string;\n };\n /**\n * Read-only secrets from the embedder's vault\n * (mikan: `<stateDir>/vaults/extensions/<slug>/env`).\n */\n readonly secrets: {\n get(key: string): string | undefined;\n /** Secret names only, never values. */\n list(): string[];\n };\n /**\n * Named schedules owned by this extension + conversation. Backed by the\n * embedder's schedule store; in mikan these become event files that fire\n * autonomous agent runs (hot-reloaded, persisted across restarts).\n */\n readonly schedules: {\n /** Create or replace a named schedule. */\n upsert(name: string, spec: ExtensionScheduleSpec): Promise<void>;\n /** Delete a named schedule. Returns false when it did not exist. */\n delete(name: string): Promise<boolean>;\n /** Schedules owned by this extension in this conversation. */\n list(): Promise<ExtensionScheduleInfo[]>;\n };\n /**\n * Post text into this conversation without triggering an agent run.\n * Available when the embedder provides platform messaging.\n */\n notify(text: string): Promise<void>;\n}\n\nexport type MikanExtensionActivate = (api: MikanExtensionApi) => void | Promise<void>;\n\nexport interface MikanExtensionModule {\n name?: string;\n activate: MikanExtensionActivate;\n}\n\nexport interface LoadedExtension {\n name: string;\n path: string;\n /** Filesystem-safe identifier used for data dirs, secrets, and schedules. */\n slug: string;\n version?: string;\n description?: string;\n /** Skills discovered under the extension's `skills/` directory. */\n skills: MikanSkill[];\n}\n\nexport interface ExtensionLoadError {\n path: string;\n error: string;\n}\n"]}
@@ -0,0 +1,16 @@
1
+ /** Idle timeout applied to HTTP headers/body when none is configured. */
2
+ export declare const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 300000;
3
+ /**
4
+ * Parse an idle-timeout setting into milliseconds.
5
+ *
6
+ * Accepts a non-negative number of milliseconds or its string form;
7
+ * `"disabled"` (case-insensitive) yields `0`. Returns `undefined` for
8
+ * anything unparseable so callers can fall back to the default.
9
+ */
10
+ export declare function parseHttpIdleTimeoutMs(value: unknown): number | undefined;
11
+ /**
12
+ * Install the global HTTP dispatcher and fetch. A timeout of `0` disables
13
+ * idle timeouts. Safe to call more than once; the last call wins.
14
+ */
15
+ export declare function configureHttpDispatcher(timeoutMs?: number): void;
16
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/harness/http.ts"],"names":[],"mappings":"AAmBA,yEAAyE;AACzE,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAKpD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAWzE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,MAAqC,GAAG,IAAI,CA2B9F"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Global HTTP dispatcher configuration for the mikan harness.
3
+ *
4
+ * mikan is a long-running headless process whose LLM traffic goes through
5
+ * global `fetch`. Node's built-in fetch ignores `HTTP_PROXY`/`HTTPS_PROXY`/
6
+ * `NO_PROXY` and offers no idle-timeout control, so a proxied deployment
7
+ * cannot reach providers and a silently stalled streaming response would
8
+ * hang a session without ever erroring (auto-retry never kicks in).
9
+ *
10
+ * `configureHttpDispatcher` installs undici's `EnvHttpProxyAgent` as the
11
+ * global dispatcher (proxy support via the standard env vars) with
12
+ * headers/body idle timeouts, and swaps global `fetch` to undici's so both
13
+ * share one implementation. A caller that deliberately replaced `fetch`
14
+ * after module load is left alone.
15
+ *
16
+ * Design adapted from pi-coding-agent's http-dispatcher.
17
+ */
18
+ import * as undici from "undici";
19
+ /** Idle timeout applied to HTTP headers/body when none is configured. */
20
+ export const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 300_000;
21
+ const originalGlobalFetch = globalThis.fetch;
22
+ let installedGlobalFetch;
23
+ /**
24
+ * Parse an idle-timeout setting into milliseconds.
25
+ *
26
+ * Accepts a non-negative number of milliseconds or its string form;
27
+ * `"disabled"` (case-insensitive) yields `0`. Returns `undefined` for
28
+ * anything unparseable so callers can fall back to the default.
29
+ */
30
+ export function parseHttpIdleTimeoutMs(value) {
31
+ if (typeof value === "string") {
32
+ const trimmed = value.trim();
33
+ if (trimmed.toLowerCase() === "disabled")
34
+ return 0;
35
+ if (trimmed.length === 0)
36
+ return undefined;
37
+ return parseHttpIdleTimeoutMs(Number(trimmed));
38
+ }
39
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
40
+ return undefined;
41
+ }
42
+ return Math.floor(value);
43
+ }
44
+ /**
45
+ * Install the global HTTP dispatcher and fetch. A timeout of `0` disables
46
+ * idle timeouts. Safe to call more than once; the last call wins.
47
+ */
48
+ export function configureHttpDispatcher(timeoutMs = DEFAULT_HTTP_IDLE_TIMEOUT_MS) {
49
+ const normalizedTimeoutMs = parseHttpIdleTimeoutMs(timeoutMs);
50
+ if (normalizedTimeoutMs === undefined) {
51
+ throw new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);
52
+ }
53
+ undici.setGlobalDispatcher(new undici.EnvHttpProxyAgent({
54
+ allowH2: false,
55
+ bodyTimeout: normalizedTimeoutMs,
56
+ headersTimeout: normalizedTimeoutMs,
57
+ }));
58
+ // Node's built-in fetch uses its own bundled undici and never sees the
59
+ // dispatcher installed above, so global fetch must be swapped to undici's.
60
+ const shouldInstallGlobals = installedGlobalFetch === undefined
61
+ ? globalThis.fetch === originalGlobalFetch
62
+ : globalThis.fetch === installedGlobalFetch;
63
+ if (shouldInstallGlobals) {
64
+ // `install` swaps global fetch to undici's; it only exists in undici >= 7,
65
+ // whose types aren't guaranteed here, so access it defensively and no-op
66
+ // on older undici (runtime behavior unchanged from the original `?.` call).
67
+ undici.install?.();
68
+ installedGlobalFetch = globalThis.fetch;
69
+ }
70
+ }
71
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/harness/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,yEAAyE;AACzE,MAAM,CAAC,MAAM,4BAA4B,GAAG,OAAO,CAAC;AAEpD,MAAM,mBAAmB,GAAG,UAAU,CAAC,KAAK,CAAC;AAC7C,IAAI,oBAAyD,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,OAAO,CAAC,WAAW,EAAE,KAAK,UAAU;YAAE,OAAO,CAAC,CAAC;QACnD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAC3C,OAAO,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACtE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,SAAS,GAAW,4BAA4B;IACtF,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAC9D,IAAI,mBAAmB,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,CAAC,mBAAmB,CACxB,IAAI,MAAM,CAAC,iBAAiB,CAAC;QAC3B,OAAO,EAAE,KAAK;QACd,WAAW,EAAE,mBAAmB;QAChC,cAAc,EAAE,mBAAmB;KACpC,CAAC,CACH,CAAC;IAEF,uEAAuE;IACvE,2EAA2E;IAC3E,MAAM,oBAAoB,GACxB,oBAAoB,KAAK,SAAS;QAChC,CAAC,CAAC,UAAU,CAAC,KAAK,KAAK,mBAAmB;QAC1C,CAAC,CAAC,UAAU,CAAC,KAAK,KAAK,oBAAoB,CAAC;IAChD,IAAI,oBAAoB,EAAE,CAAC;QACzB,2EAA2E;QAC3E,yEAAyE;QACzE,4EAA4E;QAC3E,MAAmC,CAAC,OAAO,EAAE,EAAE,CAAC;QACjD,oBAAoB,GAAG,UAAU,CAAC,KAAK,CAAC;IAC1C,CAAC;AACH,CAAC","sourcesContent":["/**\n * Global HTTP dispatcher configuration for the mikan harness.\n *\n * mikan is a long-running headless process whose LLM traffic goes through\n * global `fetch`. Node's built-in fetch ignores `HTTP_PROXY`/`HTTPS_PROXY`/\n * `NO_PROXY` and offers no idle-timeout control, so a proxied deployment\n * cannot reach providers and a silently stalled streaming response would\n * hang a session without ever erroring (auto-retry never kicks in).\n *\n * `configureHttpDispatcher` installs undici's `EnvHttpProxyAgent` as the\n * global dispatcher (proxy support via the standard env vars) with\n * headers/body idle timeouts, and swaps global `fetch` to undici's so both\n * share one implementation. A caller that deliberately replaced `fetch`\n * after module load is left alone.\n *\n * Design adapted from pi-coding-agent's http-dispatcher.\n */\nimport * as undici from \"undici\";\n\n/** Idle timeout applied to HTTP headers/body when none is configured. */\nexport const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 300_000;\n\nconst originalGlobalFetch = globalThis.fetch;\nlet installedGlobalFetch: typeof globalThis.fetch | undefined;\n\n/**\n * Parse an idle-timeout setting into milliseconds.\n *\n * Accepts a non-negative number of milliseconds or its string form;\n * `\"disabled\"` (case-insensitive) yields `0`. Returns `undefined` for\n * anything unparseable so callers can fall back to the default.\n */\nexport function parseHttpIdleTimeoutMs(value: unknown): number | undefined {\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (trimmed.toLowerCase() === \"disabled\") return 0;\n if (trimmed.length === 0) return undefined;\n return parseHttpIdleTimeoutMs(Number(trimmed));\n }\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n return undefined;\n }\n return Math.floor(value);\n}\n\n/**\n * Install the global HTTP dispatcher and fetch. A timeout of `0` disables\n * idle timeouts. Safe to call more than once; the last call wins.\n */\nexport function configureHttpDispatcher(timeoutMs: number = DEFAULT_HTTP_IDLE_TIMEOUT_MS): void {\n const normalizedTimeoutMs = parseHttpIdleTimeoutMs(timeoutMs);\n if (normalizedTimeoutMs === undefined) {\n throw new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);\n }\n\n undici.setGlobalDispatcher(\n new undici.EnvHttpProxyAgent({\n allowH2: false,\n bodyTimeout: normalizedTimeoutMs,\n headersTimeout: normalizedTimeoutMs,\n }),\n );\n\n // Node's built-in fetch uses its own bundled undici and never sees the\n // dispatcher installed above, so global fetch must be swapped to undici's.\n const shouldInstallGlobals =\n installedGlobalFetch === undefined\n ? globalThis.fetch === originalGlobalFetch\n : globalThis.fetch === installedGlobalFetch;\n if (shouldInstallGlobals) {\n // `install` swaps global fetch to undici's; it only exists in undici >= 7,\n // whose types aren't guaranteed here, so access it defensively and no-op\n // on older undici (runtime behavior unchanged from the original `?.` call).\n (undici as { install?: () => void }).install?.();\n installedGlobalFetch = globalThis.fetch;\n }\n}\n"]}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * mikan agent harness.
3
+ *
4
+ * mikan's own harness engineering layer, built directly on pi-agent-core
5
+ * (agent loop, compaction, context building) and pi-ai (providers, models,
6
+ * auth). See `src/harness/README.md` for the architecture.
7
+ */
8
+ export { FileCredentialStore, defaultAuthPath } from "./auth.js";
9
+ export { DEFAULT_HTTP_IDLE_TIMEOUT_MS, configureHttpDispatcher, parseHttpIdleTimeoutMs, } from "./http.js";
10
+ export { MikanModels, defaultModelsJsonPath, type CreateMikanModelsOptions } from "./models.js";
11
+ export { SessionStore, loadSessionFileEntries, parseSessionFileEntries } from "./session-store.js";
12
+ export { MikanAgentSession, type CompactionReason, type HarnessEvent, type HarnessEventListener, type MikanAgentSessionOptions, } from "./runner.js";
13
+ export { formatSkillsForPrompt, loadSkillsFromDir, parseFrontmatter, type LoadSkillsResult, type MikanSkill, type SkillDiagnostic, } from "./skills.js";
14
+ export { DEFAULT_BUDGET_SETTINGS, DEFAULT_EVENT_BUDGET, DEFAULT_RETRY_SETTINGS, resolveHarnessSettings, type BudgetSettings, type CompactionSettings, type HarnessSettings, type RetrySettings, } from "./settings.js";
15
+ export { ExtensionRegistry } from "./extensions/registry.js";
16
+ export { defaultExtensionDirs, extensionSlug, loadExtensions, type LoadExtensionsOptions, type LoadExtensionsResult, } from "./extensions/loader.js";
17
+ export type { BeforeAgentStartHookEvent, BeforeAgentStartHookResult, ExtensionHostServices, ExtensionLoadError, ExtensionManifest, ExtensionScheduleInfo, ExtensionSchedulePayload, ExtensionScheduleSpec, ExtensionScheduleStore, LoadedExtension, MessageEndHookEvent, MikanExtensionActivate, MikanExtensionApi, MikanExtensionModule, MikanHookMap, MikanHookName, SessionCompactHookEvent, ToolCallHookEvent, ToolCallHookResult, ToolResultHookEvent, TurnEndHookEvent, } from "./extensions/types.js";
18
+ export { CURRENT_SESSION_VERSION, type BranchSummaryEntry, type CompactionEntry, type CustomEntry, type CustomMessageEntry, type SessionContext, type SessionEntry, type SessionFileEntry, type SessionHeader, type SessionInfoEntry, type SessionMessageEntry, } from "./types.js";
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/harness/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AACnG,OAAO,EACL,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,uBAAuB,EACvB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * mikan agent harness.
3
+ *
4
+ * mikan's own harness engineering layer, built directly on pi-agent-core
5
+ * (agent loop, compaction, context building) and pi-ai (providers, models,
6
+ * auth). See `src/harness/README.md` for the architecture.
7
+ */
8
+ export { FileCredentialStore, defaultAuthPath } from "./auth.js";
9
+ export { DEFAULT_HTTP_IDLE_TIMEOUT_MS, configureHttpDispatcher, parseHttpIdleTimeoutMs, } from "./http.js";
10
+ export { MikanModels, defaultModelsJsonPath } from "./models.js";
11
+ export { SessionStore, loadSessionFileEntries, parseSessionFileEntries } from "./session-store.js";
12
+ export { MikanAgentSession, } from "./runner.js";
13
+ export { formatSkillsForPrompt, loadSkillsFromDir, parseFrontmatter, } from "./skills.js";
14
+ export { DEFAULT_BUDGET_SETTINGS, DEFAULT_EVENT_BUDGET, DEFAULT_RETRY_SETTINGS, resolveHarnessSettings, } from "./settings.js";
15
+ export { ExtensionRegistry } from "./extensions/registry.js";
16
+ export { defaultExtensionDirs, extensionSlug, loadExtensions, } from "./extensions/loader.js";
17
+ export { CURRENT_SESSION_VERSION, } from "./types.js";
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/harness/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAiC,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AACnG,OAAO,EACL,iBAAiB,GAKlB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,GAIjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,GAKvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,cAAc,GAGf,MAAM,wBAAwB,CAAC;AAwBhC,OAAO,EACL,uBAAuB,GAWxB,MAAM,YAAY,CAAC","sourcesContent":["/**\n * mikan agent harness.\n *\n * mikan's own harness engineering layer, built directly on pi-agent-core\n * (agent loop, compaction, context building) and pi-ai (providers, models,\n * auth). See `src/harness/README.md` for the architecture.\n */\nexport { FileCredentialStore, defaultAuthPath } from \"./auth.js\";\nexport {\n DEFAULT_HTTP_IDLE_TIMEOUT_MS,\n configureHttpDispatcher,\n parseHttpIdleTimeoutMs,\n} from \"./http.js\";\nexport { MikanModels, defaultModelsJsonPath, type CreateMikanModelsOptions } from \"./models.js\";\nexport { SessionStore, loadSessionFileEntries, parseSessionFileEntries } from \"./session-store.js\";\nexport {\n MikanAgentSession,\n type CompactionReason,\n type HarnessEvent,\n type HarnessEventListener,\n type MikanAgentSessionOptions,\n} from \"./runner.js\";\nexport {\n formatSkillsForPrompt,\n loadSkillsFromDir,\n parseFrontmatter,\n type LoadSkillsResult,\n type MikanSkill,\n type SkillDiagnostic,\n} from \"./skills.js\";\nexport {\n DEFAULT_BUDGET_SETTINGS,\n DEFAULT_EVENT_BUDGET,\n DEFAULT_RETRY_SETTINGS,\n resolveHarnessSettings,\n type BudgetSettings,\n type CompactionSettings,\n type HarnessSettings,\n type RetrySettings,\n} from \"./settings.js\";\nexport { ExtensionRegistry } from \"./extensions/registry.js\";\nexport {\n defaultExtensionDirs,\n extensionSlug,\n loadExtensions,\n type LoadExtensionsOptions,\n type LoadExtensionsResult,\n} from \"./extensions/loader.js\";\nexport type {\n BeforeAgentStartHookEvent,\n BeforeAgentStartHookResult,\n ExtensionHostServices,\n ExtensionLoadError,\n ExtensionManifest,\n ExtensionScheduleInfo,\n ExtensionSchedulePayload,\n ExtensionScheduleSpec,\n ExtensionScheduleStore,\n LoadedExtension,\n MessageEndHookEvent,\n MikanExtensionActivate,\n MikanExtensionApi,\n MikanExtensionModule,\n MikanHookMap,\n MikanHookName,\n SessionCompactHookEvent,\n ToolCallHookEvent,\n ToolCallHookResult,\n ToolResultHookEvent,\n TurnEndHookEvent,\n} from \"./extensions/types.js\";\nexport {\n CURRENT_SESSION_VERSION,\n type BranchSummaryEntry,\n type CompactionEntry,\n type CustomEntry,\n type CustomMessageEntry,\n type SessionContext,\n type SessionEntry,\n type SessionFileEntry,\n type SessionHeader,\n type SessionInfoEntry,\n type SessionMessageEntry,\n} from \"./types.js\";\n"]}
@@ -0,0 +1,34 @@
1
+ import { type Api, type AuthResult, type Model, type Models } from "@earendil-works/pi-ai";
2
+ /** Default location of mikan's models.json. */
3
+ export declare function defaultModelsJsonPath(): string;
4
+ export interface CreateMikanModelsOptions {
5
+ authPath?: string;
6
+ modelsJsonPath?: string;
7
+ }
8
+ /**
9
+ * Model catalog backed by pi-ai's `Models`. Exposes the lookup and auth
10
+ * operations mikan needs; streaming goes through {@link MikanModels.models}.
11
+ */
12
+ export declare class MikanModels {
13
+ /** Underlying pi-ai collection, for streaming/completion calls. */
14
+ readonly models: Models;
15
+ private loadError;
16
+ private constructor();
17
+ static create(options?: CreateMikanModelsOptions): MikanModels;
18
+ /** Error from loading models.json, if any. Built-in models stay available. */
19
+ getError(): string | undefined;
20
+ /** All known models (built-in plus custom). */
21
+ getAll(): Model<Api>[];
22
+ /** Find a model by provider and id. */
23
+ find(provider: string, modelId: string): Model<Api> | undefined;
24
+ /** Models whose provider auth currently resolves (API key, OAuth, or ambient). */
25
+ getAvailable(): Promise<Model<Api>[]>;
26
+ /** Resolve request auth for a model. Undefined when unconfigured. */
27
+ getAuth(model: Model<Api>): Promise<AuthResult | undefined>;
28
+ /**
29
+ * Resolve an API key for a provider. Convenience for call sites that only
30
+ * need a bearer key (for example pi-agent-core's compat stream function).
31
+ */
32
+ getApiKeyForProvider(provider: string): Promise<string | undefined>;
33
+ }
34
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/harness/models.ts"],"names":[],"mappings":"AA6BA,OAAO,EAEL,KAAK,GAAG,EACR,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,MAAM,EAIZ,MAAM,uBAAuB,CAAC;AAoD/B,+CAA+C;AAC/C,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AA8GD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,SAAS,CAAqB;IAEtC,OAAO,eAGN;IAED,MAAM,CAAC,MAAM,CAAC,OAAO,GAAE,wBAA6B,GAAG,WAAW,CAwBjE;IAED,8EAA8E;IAC9E,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7B;IAED,+CAA+C;IAC/C,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAErB;IAED,uCAAuC;IACvC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAE9D;IAED,kFAAkF;IAC5E,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAkB1C;IAED,qEAAqE;IACrE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAE1D;IAED;;;OAGG;IACG,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CASxE;CACF"}