@oharness/engine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/dist/agent/agent.d.ts +196 -0
  2. package/dist/agent/agent.js +758 -0
  3. package/dist/agent/agent.js.map +1 -0
  4. package/dist/agent/compaction.d.ts +68 -0
  5. package/dist/agent/compaction.js +179 -0
  6. package/dist/agent/compaction.js.map +1 -0
  7. package/dist/agent/hooks.d.ts +77 -0
  8. package/dist/agent/hooks.js +152 -0
  9. package/dist/agent/hooks.js.map +1 -0
  10. package/dist/agent/memory.d.ts +45 -0
  11. package/dist/agent/memory.js +147 -0
  12. package/dist/agent/memory.js.map +1 -0
  13. package/dist/agent/overflow.d.ts +35 -0
  14. package/dist/agent/overflow.js +69 -0
  15. package/dist/agent/overflow.js.map +1 -0
  16. package/dist/agent/permissions.d.ts +181 -0
  17. package/dist/agent/permissions.js +289 -0
  18. package/dist/agent/permissions.js.map +1 -0
  19. package/dist/agent/prompt.d.ts +25 -0
  20. package/dist/agent/prompt.js +63 -0
  21. package/dist/agent/prompt.js.map +1 -0
  22. package/dist/agent/session.d.ts +108 -0
  23. package/dist/agent/session.js +231 -0
  24. package/dist/agent/session.js.map +1 -0
  25. package/dist/agent/settings.d.ts +37 -0
  26. package/dist/agent/settings.js +113 -0
  27. package/dist/agent/settings.js.map +1 -0
  28. package/dist/agent/skills.d.ts +58 -0
  29. package/dist/agent/skills.js +225 -0
  30. package/dist/agent/skills.js.map +1 -0
  31. package/dist/agent/store.d.ts +308 -0
  32. package/dist/agent/store.js +596 -0
  33. package/dist/agent/store.js.map +1 -0
  34. package/dist/agent/subagent.d.ts +44 -0
  35. package/dist/agent/subagent.js +138 -0
  36. package/dist/agent/subagent.js.map +1 -0
  37. package/dist/agent/titles.d.ts +8 -0
  38. package/dist/agent/titles.js +23 -0
  39. package/dist/agent/titles.js.map +1 -0
  40. package/dist/agent/workspace.d.ts +60 -0
  41. package/dist/agent/workspace.js +156 -0
  42. package/dist/agent/workspace.js.map +1 -0
  43. package/dist/artifacts/publish.d.ts +94 -0
  44. package/dist/artifacts/publish.js +104 -0
  45. package/dist/artifacts/publish.js.map +1 -0
  46. package/dist/artifacts/store.d.ts +324 -0
  47. package/dist/artifacts/store.js +500 -0
  48. package/dist/artifacts/store.js.map +1 -0
  49. package/dist/auth/index.d.ts +13 -0
  50. package/dist/auth/index.js +10 -0
  51. package/dist/auth/index.js.map +1 -0
  52. package/dist/auth/manager.d.ts +83 -0
  53. package/dist/auth/manager.js +266 -0
  54. package/dist/auth/manager.js.map +1 -0
  55. package/dist/auth/oauth.d.ts +83 -0
  56. package/dist/auth/oauth.js +327 -0
  57. package/dist/auth/oauth.js.map +1 -0
  58. package/dist/auth/providers/account.d.ts +59 -0
  59. package/dist/auth/providers/account.js +282 -0
  60. package/dist/auth/providers/account.js.map +1 -0
  61. package/dist/auth/providers/anthropic.d.ts +24 -0
  62. package/dist/auth/providers/anthropic.js +209 -0
  63. package/dist/auth/providers/anthropic.js.map +1 -0
  64. package/dist/auth/providers/generic.d.ts +57 -0
  65. package/dist/auth/providers/generic.js +155 -0
  66. package/dist/auth/providers/generic.js.map +1 -0
  67. package/dist/auth/providers/official.d.ts +3 -0
  68. package/dist/auth/providers/official.js +90 -0
  69. package/dist/auth/providers/official.js.map +1 -0
  70. package/dist/auth/providers/ottoport.d.ts +3 -0
  71. package/dist/auth/providers/ottoport.js +60 -0
  72. package/dist/auth/providers/ottoport.js.map +1 -0
  73. package/dist/auth/store.d.ts +22 -0
  74. package/dist/auth/store.js +138 -0
  75. package/dist/auth/store.js.map +1 -0
  76. package/dist/auth/types.d.ts +167 -0
  77. package/dist/auth/types.js +16 -0
  78. package/dist/auth/types.js.map +1 -0
  79. package/dist/config.d.ts +197 -0
  80. package/dist/config.js +195 -0
  81. package/dist/config.js.map +1 -0
  82. package/dist/core/errors.d.ts +46 -0
  83. package/dist/core/errors.js +83 -0
  84. package/dist/core/errors.js.map +1 -0
  85. package/dist/core/tokens.d.ts +12 -0
  86. package/dist/core/tokens.js +56 -0
  87. package/dist/core/tokens.js.map +1 -0
  88. package/dist/core/types.d.ts +91 -0
  89. package/dist/core/types.js +49 -0
  90. package/dist/core/types.js.map +1 -0
  91. package/dist/harness.d.ts +302 -0
  92. package/dist/harness.js +695 -0
  93. package/dist/harness.js.map +1 -0
  94. package/dist/index.d.ts +32 -0
  95. package/dist/index.js +21 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/mcp/client.d.ts +55 -0
  98. package/dist/mcp/client.js +199 -0
  99. package/dist/mcp/client.js.map +1 -0
  100. package/dist/mcp/index.d.ts +13 -0
  101. package/dist/mcp/index.js +8 -0
  102. package/dist/mcp/index.js.map +1 -0
  103. package/dist/mcp/manager.d.ts +77 -0
  104. package/dist/mcp/manager.js +325 -0
  105. package/dist/mcp/manager.js.map +1 -0
  106. package/dist/mcp/oauth.d.ts +63 -0
  107. package/dist/mcp/oauth.js +302 -0
  108. package/dist/mcp/oauth.js.map +1 -0
  109. package/dist/mcp/protocol.d.ts +130 -0
  110. package/dist/mcp/protocol.js +14 -0
  111. package/dist/mcp/protocol.js.map +1 -0
  112. package/dist/mcp/registry.d.ts +52 -0
  113. package/dist/mcp/registry.js +100 -0
  114. package/dist/mcp/registry.js.map +1 -0
  115. package/dist/mcp/registry.json +293 -0
  116. package/dist/mcp/secrets.d.ts +20 -0
  117. package/dist/mcp/secrets.js +75 -0
  118. package/dist/mcp/secrets.js.map +1 -0
  119. package/dist/mcp/transport.d.ts +51 -0
  120. package/dist/mcp/transport.js +158 -0
  121. package/dist/mcp/transport.js.map +1 -0
  122. package/dist/paths.d.ts +37 -0
  123. package/dist/paths.js +63 -0
  124. package/dist/paths.js.map +1 -0
  125. package/dist/plugins.d.ts +55 -0
  126. package/dist/plugins.js +201 -0
  127. package/dist/plugins.js.map +1 -0
  128. package/dist/providers/builtin.d.ts +23 -0
  129. package/dist/providers/builtin.js +141 -0
  130. package/dist/providers/builtin.js.map +1 -0
  131. package/dist/providers/catalog.d.ts +129 -0
  132. package/dist/providers/catalog.js +254 -0
  133. package/dist/providers/catalog.js.map +1 -0
  134. package/dist/providers/catalog.json +472 -0
  135. package/dist/providers/discovery.d.ts +16 -0
  136. package/dist/providers/discovery.js +161 -0
  137. package/dist/providers/discovery.js.map +1 -0
  138. package/dist/providers/http.d.ts +24 -0
  139. package/dist/providers/http.js +139 -0
  140. package/dist/providers/http.js.map +1 -0
  141. package/dist/providers/index.d.ts +10 -0
  142. package/dist/providers/index.js +8 -0
  143. package/dist/providers/index.js.map +1 -0
  144. package/dist/providers/piai.d.ts +124 -0
  145. package/dist/providers/piai.js +551 -0
  146. package/dist/providers/piai.js.map +1 -0
  147. package/dist/providers/registry.d.ts +65 -0
  148. package/dist/providers/registry.js +195 -0
  149. package/dist/providers/registry.js.map +1 -0
  150. package/dist/providers/resilient.d.ts +46 -0
  151. package/dist/providers/resilient.js +117 -0
  152. package/dist/providers/resilient.js.map +1 -0
  153. package/dist/providers/types.d.ts +182 -0
  154. package/dist/providers/types.js +50 -0
  155. package/dist/providers/types.js.map +1 -0
  156. package/dist/schedule/cron.d.ts +35 -0
  157. package/dist/schedule/cron.js +125 -0
  158. package/dist/schedule/cron.js.map +1 -0
  159. package/dist/schedule/scheduler.d.ts +87 -0
  160. package/dist/schedule/scheduler.js +237 -0
  161. package/dist/schedule/scheduler.js.map +1 -0
  162. package/dist/storage/kv.d.ts +56 -0
  163. package/dist/storage/kv.js +173 -0
  164. package/dist/storage/kv.js.map +1 -0
  165. package/dist/storage/migrate.d.ts +11 -0
  166. package/dist/storage/migrate.js +93 -0
  167. package/dist/storage/migrate.js.map +1 -0
  168. package/dist/storage/project.d.ts +9 -0
  169. package/dist/storage/project.js +57 -0
  170. package/dist/storage/project.js.map +1 -0
  171. package/dist/storage/records.d.ts +32 -0
  172. package/dist/storage/records.js +48 -0
  173. package/dist/storage/records.js.map +1 -0
  174. package/dist/sync/client.d.ts +79 -0
  175. package/dist/sync/client.js +118 -0
  176. package/dist/sync/client.js.map +1 -0
  177. package/dist/sync/mirror.d.ts +85 -0
  178. package/dist/sync/mirror.js +389 -0
  179. package/dist/sync/mirror.js.map +1 -0
  180. package/dist/sync/protocol.d.ts +67 -0
  181. package/dist/sync/protocol.js +16 -0
  182. package/dist/sync/protocol.js.map +1 -0
  183. package/dist/sync/settings.d.ts +56 -0
  184. package/dist/sync/settings.js +60 -0
  185. package/dist/sync/settings.js.map +1 -0
  186. package/dist/tools/builtin/artifact.d.ts +16 -0
  187. package/dist/tools/builtin/artifact.js +134 -0
  188. package/dist/tools/builtin/artifact.js.map +1 -0
  189. package/dist/tools/builtin/bash.d.ts +3 -0
  190. package/dist/tools/builtin/bash.js +142 -0
  191. package/dist/tools/builtin/bash.js.map +1 -0
  192. package/dist/tools/builtin/fs.d.ts +19 -0
  193. package/dist/tools/builtin/fs.js +280 -0
  194. package/dist/tools/builtin/fs.js.map +1 -0
  195. package/dist/tools/builtin/index.d.ts +22 -0
  196. package/dist/tools/builtin/index.js +42 -0
  197. package/dist/tools/builtin/index.js.map +1 -0
  198. package/dist/tools/builtin/mcp-resource.d.ts +3 -0
  199. package/dist/tools/builtin/mcp-resource.js +220 -0
  200. package/dist/tools/builtin/mcp-resource.js.map +1 -0
  201. package/dist/tools/builtin/memory.d.ts +10 -0
  202. package/dist/tools/builtin/memory.js +76 -0
  203. package/dist/tools/builtin/memory.js.map +1 -0
  204. package/dist/tools/builtin/recall.d.ts +13 -0
  205. package/dist/tools/builtin/recall.js +163 -0
  206. package/dist/tools/builtin/recall.js.map +1 -0
  207. package/dist/tools/builtin/search.d.ts +3 -0
  208. package/dist/tools/builtin/search.js +240 -0
  209. package/dist/tools/builtin/search.js.map +1 -0
  210. package/dist/tools/builtin/skill.d.ts +10 -0
  211. package/dist/tools/builtin/skill.js +46 -0
  212. package/dist/tools/builtin/skill.js.map +1 -0
  213. package/dist/tools/builtin/task.d.ts +9 -0
  214. package/dist/tools/builtin/task.js +68 -0
  215. package/dist/tools/builtin/task.js.map +1 -0
  216. package/dist/tools/builtin/todo.d.ts +20 -0
  217. package/dist/tools/builtin/todo.js +63 -0
  218. package/dist/tools/builtin/todo.js.map +1 -0
  219. package/dist/tools/define.d.ts +19 -0
  220. package/dist/tools/define.js +39 -0
  221. package/dist/tools/define.js.map +1 -0
  222. package/dist/tools/index.d.ts +7 -0
  223. package/dist/tools/index.js +5 -0
  224. package/dist/tools/index.js.map +1 -0
  225. package/dist/tools/registry.d.ts +39 -0
  226. package/dist/tools/registry.js +101 -0
  227. package/dist/tools/registry.js.map +1 -0
  228. package/dist/tools/types.d.ts +112 -0
  229. package/dist/tools/types.js +22 -0
  230. package/dist/tools/types.js.map +1 -0
  231. package/dist/util/id.d.ts +9 -0
  232. package/dist/util/id.js +19 -0
  233. package/dist/util/id.js.map +1 -0
  234. package/dist/util/json.d.ts +25 -0
  235. package/dist/util/json.js +100 -0
  236. package/dist/util/json.js.map +1 -0
  237. package/dist/util/jwt.d.ts +74 -0
  238. package/dist/util/jwt.js +177 -0
  239. package/dist/util/jwt.js.map +1 -0
  240. package/dist/util/logger.d.ts +13 -0
  241. package/dist/util/logger.js +59 -0
  242. package/dist/util/logger.js.map +1 -0
  243. package/dist/util/queue.d.ts +26 -0
  244. package/dist/util/queue.js +106 -0
  245. package/dist/util/queue.js.map +1 -0
  246. package/dist/util/schema.d.ts +17 -0
  247. package/dist/util/schema.js +98 -0
  248. package/dist/util/schema.js.map +1 -0
  249. package/dist/util/shell.d.ts +20 -0
  250. package/dist/util/shell.js +24 -0
  251. package/dist/util/shell.js.map +1 -0
  252. package/official.json +4 -0
  253. package/package.json +38 -0
  254. package/skills/artifact-authoring/SKILL.md +81 -0
  255. package/skills/canvas/SKILL.md +85 -0
  256. package/skills/skill-authoring/SKILL.md +85 -0
@@ -0,0 +1,83 @@
1
+ export class HarnessError extends Error {
2
+ code;
3
+ retryable;
4
+ cause;
5
+ constructor(message, opts = {}) {
6
+ super(message);
7
+ this.name = new.target.name;
8
+ this.code = opts.code ?? "harness_error";
9
+ this.retryable = opts.retryable ?? false;
10
+ this.cause = opts.cause;
11
+ }
12
+ }
13
+ export class ConfigError extends HarnessError {
14
+ constructor(message, cause) {
15
+ super(message, { code: "config_error", cause });
16
+ }
17
+ }
18
+ export class ProviderError extends HarnessError {
19
+ status;
20
+ provider;
21
+ constructor(provider, message, opts = {}) {
22
+ super(message, {
23
+ code: "provider_error",
24
+ retryable: opts.retryable ?? isRetryableStatus(opts.status),
25
+ cause: opts.cause,
26
+ });
27
+ this.provider = provider;
28
+ this.status = opts.status;
29
+ }
30
+ }
31
+ export class ToolError extends HarnessError {
32
+ toolName;
33
+ constructor(toolName, message, cause) {
34
+ super(message, { code: "tool_error", cause });
35
+ this.toolName = toolName;
36
+ }
37
+ }
38
+ export class PermissionDeniedError extends HarnessError {
39
+ constructor(message) {
40
+ super(message, { code: "permission_denied" });
41
+ }
42
+ }
43
+ export class McpError extends HarnessError {
44
+ server;
45
+ constructor(server, message, cause) {
46
+ super(message, { code: "mcp_error", cause });
47
+ this.server = server;
48
+ }
49
+ }
50
+ /**
51
+ * The server answered 401: it has an identity to check and we have not proved
52
+ * one. Distinct from `McpError` because it is not a failure to be reported —
53
+ * it is the start of a login, and the caller needs the challenge to begin it.
54
+ */
55
+ export class McpAuthRequiredError extends McpError {
56
+ /** The `WWW-Authenticate` header, which carries where to go discover auth. */
57
+ challenge;
58
+ url;
59
+ constructor(server, url, challenge) {
60
+ super(server, "authorization required", undefined);
61
+ this.url = url;
62
+ if (challenge !== undefined)
63
+ this.challenge = challenge;
64
+ }
65
+ }
66
+ export function isRetryableStatus(status) {
67
+ if (status === undefined)
68
+ return false;
69
+ return status === 408 || status === 409 || status === 429 || status >= 500;
70
+ }
71
+ export function errorMessage(err) {
72
+ if (err instanceof Error)
73
+ return err.message;
74
+ if (typeof err === "string")
75
+ return err;
76
+ try {
77
+ return JSON.stringify(err);
78
+ }
79
+ catch {
80
+ return String(err);
81
+ }
82
+ }
83
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,YAAa,SAAQ,KAAK;IAC5B,IAAI,CAAS;IACb,SAAS,CAAU;IACV,KAAK,CAAW;IAElC,YACE,OAAe,EACf,OAAgE,EAAE;QAElE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,eAAe,CAAC;QACzC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC;QACzC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,YAAY;IAC3C,YAAY,OAAe,EAAE,KAAe;QAC1C,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,YAAY;IACpC,MAAM,CAAU;IAChB,QAAQ,CAAS;IAE1B,YACE,QAAgB,EAChB,OAAe,EACf,OAAkE,EAAE;QAEpE,KAAK,CAAC,OAAO,EAAE;YACb,IAAI,EAAE,gBAAgB;YACtB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3D,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,SAAU,SAAQ,YAAY;IAChC,QAAQ,CAAS;IAE1B,YAAY,QAAgB,EAAE,OAAe,EAAE,KAAe;QAC5D,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,YAAY;IACrD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAChD,CAAC;CACF;AAED,MAAM,OAAO,QAAS,SAAQ,YAAY;IAC/B,MAAM,CAAS;IAExB,YAAY,MAAc,EAAE,OAAe,EAAE,KAAe;QAC1D,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,oBAAqB,SAAQ,QAAQ;IAChD,8EAA8E;IACrE,SAAS,CAAU;IACnB,GAAG,CAAS;IAErB,YAAY,MAAc,EAAE,GAAW,EAAE,SAAkB;QACzD,KAAK,CAAC,MAAM,EAAE,wBAAwB,EAAE,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,SAAS,KAAK,SAAS;YAAE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC1D,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAAC,MAA0B;IAC1D,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACvC,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,IAAI,GAAG,YAAY,KAAK;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC7C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACxC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;AACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ContentBlock, Message, ToolSchema } from "./types.ts";
2
+ export declare function estimateStringTokens(s: string): number;
3
+ export declare function estimateBlockTokens(block: ContentBlock): number;
4
+ export declare function estimateJsonTokens(value: unknown): number;
5
+ export declare function estimateMessageTokens(message: Message): number;
6
+ export declare function estimateMessagesTokens(messages: Message[]): number;
7
+ export declare function estimateToolsTokens(tools: ToolSchema[]): number;
8
+ export declare function estimateRequestTokens(input: {
9
+ system?: string;
10
+ messages: Message[];
11
+ tools?: ToolSchema[];
12
+ }): number;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Cheap, provider-independent token estimate.
3
+ *
4
+ * We deliberately do not ship a tokenizer: every provider tokenizes
5
+ * differently and the harness only needs an estimate good enough to decide
6
+ * *when* to compact. Real numbers come back from the provider in `Usage` and
7
+ * override these estimates once a turn completes.
8
+ */
9
+ const CHARS_PER_TOKEN = 3.6;
10
+ /** Rough overhead per message envelope / per tool-call wrapper. */
11
+ const MESSAGE_OVERHEAD = 4;
12
+ const IMAGE_TOKENS = 1_600;
13
+ export function estimateStringTokens(s) {
14
+ return Math.ceil(s.length / CHARS_PER_TOKEN);
15
+ }
16
+ export function estimateBlockTokens(block) {
17
+ switch (block.type) {
18
+ case "text":
19
+ return estimateStringTokens(block.text);
20
+ case "thinking":
21
+ return estimateStringTokens(block.thinking);
22
+ case "image":
23
+ return IMAGE_TOKENS;
24
+ case "tool_call":
25
+ return MESSAGE_OVERHEAD + estimateStringTokens(block.name) + estimateJsonTokens(block.input);
26
+ case "tool_result":
27
+ return (MESSAGE_OVERHEAD +
28
+ block.content.reduce((sum, b) => sum + estimateBlockTokens(b), 0));
29
+ }
30
+ }
31
+ export function estimateJsonTokens(value) {
32
+ try {
33
+ return estimateStringTokens(JSON.stringify(value) ?? "");
34
+ }
35
+ catch {
36
+ return 0;
37
+ }
38
+ }
39
+ export function estimateMessageTokens(message) {
40
+ return (MESSAGE_OVERHEAD + message.content.reduce((sum, b) => sum + estimateBlockTokens(b), 0));
41
+ }
42
+ export function estimateMessagesTokens(messages) {
43
+ return messages.reduce((sum, m) => sum + estimateMessageTokens(m), 0);
44
+ }
45
+ export function estimateToolsTokens(tools) {
46
+ return tools.reduce((sum, t) => sum +
47
+ estimateStringTokens(t.name) +
48
+ estimateStringTokens(t.description) +
49
+ estimateJsonTokens(t.inputSchema), 0);
50
+ }
51
+ export function estimateRequestTokens(input) {
52
+ return ((input.system ? estimateStringTokens(input.system) : 0) +
53
+ estimateMessagesTokens(input.messages) +
54
+ (input.tools ? estimateToolsTokens(input.tools) : 0));
55
+ }
56
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/core/tokens.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,mEAAmE;AACnE,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,YAAY,GAAG,KAAK,CAAC;AAE3B,MAAM,UAAU,oBAAoB,CAAC,CAAS;IAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAmB;IACrD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM;YACT,OAAO,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1C,KAAK,UAAU;YACb,OAAO,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC9C,KAAK,OAAO;YACV,OAAO,YAAY,CAAC;QACtB,KAAK,WAAW;YACd,OAAO,gBAAgB,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/F,KAAK,aAAa;YAChB,OAAO,CACL,gBAAgB;gBAChB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAClE,CAAC;IACN,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,CAAC;QACH,OAAO,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO,CACL,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CACvF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAmB;IACxD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAmB;IACrD,OAAO,KAAK,CAAC,MAAM,CACjB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CACT,GAAG;QACH,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5B,oBAAoB,CAAC,CAAC,CAAC,WAAW,CAAC;QACnC,kBAAkB,CAAC,CAAC,CAAC,WAAW,CAAC,EACnC,CAAC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAIrC;IACC,OAAO,CACL,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvD,sBAAsB,CAAC,KAAK,CAAC,QAAQ,CAAC;QACtC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACrD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Provider-neutral conversation types.
3
+ *
4
+ * Everything the harness stores, persists and replays is expressed in these
5
+ * types. Provider adapters translate them to/from wire formats. This is what
6
+ * makes mid-session model switching possible: history never carries a
7
+ * provider-specific shape.
8
+ */
9
+ export type Role = "user" | "assistant";
10
+ export interface TextBlock {
11
+ type: "text";
12
+ text: string;
13
+ }
14
+ /** Reasoning/thinking content. `signature` is opaque provider state (Anthropic). */
15
+ export interface ThinkingBlock {
16
+ type: "thinking";
17
+ thinking: string;
18
+ signature?: string;
19
+ /** True when the provider only gave us a redacted/encrypted blob. */
20
+ redacted?: boolean;
21
+ }
22
+ export interface ImageBlock {
23
+ type: "image";
24
+ /** e.g. "image/png" */
25
+ mimeType: string;
26
+ /** base64, no data: prefix */
27
+ data: string;
28
+ }
29
+ export interface ToolCallBlock {
30
+ type: "tool_call";
31
+ /** Harness-owned id. Stable across providers for a given session. */
32
+ id: string;
33
+ name: string;
34
+ input: unknown;
35
+ }
36
+ export interface ToolResultBlock {
37
+ type: "tool_result";
38
+ toolCallId: string;
39
+ /**
40
+ * Kept alongside the id because some providers (Gemini) key tool results by
41
+ * function name rather than by call id.
42
+ */
43
+ toolName: string;
44
+ content: Array<TextBlock | ImageBlock>;
45
+ isError?: boolean;
46
+ }
47
+ export type ContentBlock = TextBlock | ThinkingBlock | ImageBlock | ToolCallBlock | ToolResultBlock;
48
+ export interface Message {
49
+ role: Role;
50
+ content: ContentBlock[];
51
+ /** Bookkeeping that never reaches the model. */
52
+ meta?: MessageMeta;
53
+ }
54
+ export interface MessageMeta {
55
+ id?: string;
56
+ timestamp?: number;
57
+ /** Model that produced this assistant message, for audit after switching. */
58
+ model?: string;
59
+ provider?: string;
60
+ usage?: Usage;
61
+ stopReason?: StopReason;
62
+ /** Set on summary messages produced by compaction. */
63
+ compacted?: boolean;
64
+ /** Marks synthetic messages injected by the harness, not by the user. */
65
+ synthetic?: boolean;
66
+ [key: string]: unknown;
67
+ }
68
+ export interface Usage {
69
+ inputTokens: number;
70
+ outputTokens: number;
71
+ cacheReadTokens?: number;
72
+ cacheWriteTokens?: number;
73
+ reasoningTokens?: number;
74
+ }
75
+ export type StopReason = "end_turn" | "tool_use" | "max_tokens" | "stop_sequence" | "refusal" | "aborted" | "error";
76
+ /** JSON Schema subset we pass around. Intentionally loose. */
77
+ export type JSONSchema = Record<string, unknown>;
78
+ /** Tool description as handed to a provider. */
79
+ export interface ToolSchema {
80
+ name: string;
81
+ description: string;
82
+ inputSchema: JSONSchema;
83
+ }
84
+ export declare function text(s: string): TextBlock;
85
+ export declare function userMessage(content: string | ContentBlock[]): Message;
86
+ export declare function assistantMessage(content: ContentBlock[], meta?: MessageMeta): Message;
87
+ /** Concatenated plain text of a message, ignoring thinking and tool blocks. */
88
+ export declare function messageText(message: Message): string;
89
+ export declare function toolCallsOf(message: Message): ToolCallBlock[];
90
+ export declare function emptyUsage(): Usage;
91
+ export declare function addUsage(a: Usage, b: Usage | undefined): Usage;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Provider-neutral conversation types.
3
+ *
4
+ * Everything the harness stores, persists and replays is expressed in these
5
+ * types. Provider adapters translate them to/from wire formats. This is what
6
+ * makes mid-session model switching possible: history never carries a
7
+ * provider-specific shape.
8
+ */
9
+ // ---------------------------------------------------------------------------
10
+ // Helpers
11
+ // ---------------------------------------------------------------------------
12
+ export function text(s) {
13
+ return { type: "text", text: s };
14
+ }
15
+ export function userMessage(content) {
16
+ return {
17
+ role: "user",
18
+ content: typeof content === "string" ? [text(content)] : content,
19
+ meta: { timestamp: Date.now() },
20
+ };
21
+ }
22
+ export function assistantMessage(content, meta) {
23
+ return { role: "assistant", content, meta: { timestamp: Date.now(), ...meta } };
24
+ }
25
+ /** Concatenated plain text of a message, ignoring thinking and tool blocks. */
26
+ export function messageText(message) {
27
+ return message.content
28
+ .filter((b) => b.type === "text")
29
+ .map((b) => b.text)
30
+ .join("");
31
+ }
32
+ export function toolCallsOf(message) {
33
+ return message.content.filter((b) => b.type === "tool_call");
34
+ }
35
+ export function emptyUsage() {
36
+ return { inputTokens: 0, outputTokens: 0 };
37
+ }
38
+ export function addUsage(a, b) {
39
+ if (!b)
40
+ return a;
41
+ return {
42
+ inputTokens: a.inputTokens + b.inputTokens,
43
+ outputTokens: a.outputTokens + b.outputTokens,
44
+ cacheReadTokens: (a.cacheReadTokens ?? 0) + (b.cacheReadTokens ?? 0),
45
+ cacheWriteTokens: (a.cacheWriteTokens ?? 0) + (b.cacheWriteTokens ?? 0),
46
+ reasoningTokens: (a.reasoningTokens ?? 0) + (b.reasoningTokens ?? 0),
47
+ };
48
+ }
49
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsGH,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,UAAU,IAAI,CAAC,CAAS;IAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAgC;IAC1D,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO;QAChE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;KAChC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAuB,EAAE,IAAkB;IAC1E,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC;AAClF,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,OAAO,OAAO,CAAC,OAAO;SACnB,MAAM,CAAC,CAAC,CAAC,EAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;SAChD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAsB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,CAAQ,EAAE,CAAoB;IACrD,IAAI,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACjB,OAAO;QACL,WAAW,EAAE,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;QAC1C,YAAY,EAAE,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY;QAC7C,eAAe,EAAE,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;QACpE,gBAAgB,EAAE,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC;QACvE,eAAe,EAAE,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;KACrE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,302 @@
1
+ import { AuthManager } from "./auth/manager.ts";
2
+ import type { AuthProvider, AuthStatus, AuthorizeResult } from "./auth/index.ts";
3
+ import { Agent } from "./agent/agent.ts";
4
+ import type { AgentEvent, AgentOptions } from "./agent/agent.ts";
5
+ import { HookRegistry } from "./agent/hooks.ts";
6
+ import type { AuditEntry, PermissionPrompt } from "./agent/permissions.ts";
7
+ import { Session } from "./agent/session.ts";
8
+ import { SessionStore } from "./agent/store.ts";
9
+ import type { SessionMeta } from "./agent/store.ts";
10
+ import { SubagentRegistry } from "./agent/subagent.ts";
11
+ import { SkillRegistry } from "./agent/skills.ts";
12
+ import { SettingsStore } from "./agent/settings.ts";
13
+ import type { WorkspacePolicy } from "./agent/workspace.ts";
14
+ import { MemoryStore } from "./agent/memory.ts";
15
+ import type { HarnessConfig } from "./config.ts";
16
+ import type { PluginDefinition } from "./plugins.ts";
17
+ import { McpManager } from "./mcp/manager.ts";
18
+ import { Scheduler } from "./schedule/scheduler.ts";
19
+ import type { McpServerStatus } from "./mcp/manager.ts";
20
+ import { ProviderRegistry } from "./providers/registry.ts";
21
+ import type { Catalog, CatalogProvider } from "./providers/catalog.ts";
22
+ import type { ModelSpec } from "./providers/types.ts";
23
+ import { ToolRegistry } from "./tools/registry.ts";
24
+ import type { Tool } from "./tools/types.ts";
25
+ import type { Logger, LogSink } from "./util/logger.ts";
26
+ /** Whether decisions are recorded, where else, and whose call that is. */
27
+ export interface AuditStatus {
28
+ on: boolean;
29
+ /** The extra file, as configured — usually relative to the project. */
30
+ file?: string;
31
+ /** The same path resolved, for showing somebody where to look. */
32
+ path?: string;
33
+ source: "user" | "project";
34
+ }
35
+ export interface HarnessOptions {
36
+ cwd?: string;
37
+ config?: HarnessConfig;
38
+ permissionPrompt?: PermissionPrompt;
39
+ /** Extra tools registered on top of the builtins. */
40
+ tools?: Tool[];
41
+ /** Extra auth providers, e.g. a subscription vendor with your own client id. */
42
+ authProviders?: AuthProvider[];
43
+ logger?: Logger;
44
+ /**
45
+ * Where diagnostics go, when the default stderr is the wrong place.
46
+ *
47
+ * A full-screen frontend owns the terminal: a line written straight to
48
+ * stderr lands on top of the frame it is drawing, which is not a rendering
49
+ * bug the frontend can fix from its side. The level stays the engine's
50
+ * decision; only the destination moves.
51
+ */
52
+ logSink?: LogSink;
53
+ /** Skip session persistence entirely (useful in tests and embedded use). */
54
+ ephemeral?: boolean;
55
+ }
56
+ /**
57
+ * Top-level facade: owns providers, tools, MCP connections, hooks and
58
+ * subagents, and hands out `Agent` instances bound to a `Session`.
59
+ *
60
+ * Construct it with `Harness.create()` rather than `new`, because MCP
61
+ * connection and config loading are async.
62
+ */
63
+ export declare class Harness {
64
+ readonly cwd: string;
65
+ readonly config: HarnessConfig;
66
+ readonly providers: ProviderRegistry;
67
+ readonly tools: ToolRegistry;
68
+ readonly hooks: HookRegistry;
69
+ readonly subagents: SubagentRegistry;
70
+ readonly skills: SkillRegistry;
71
+ readonly memory: MemoryStore;
72
+ readonly settings: SettingsStore;
73
+ readonly workspace: WorkspacePolicy;
74
+ readonly mcp: McpManager;
75
+ readonly store: SessionStore;
76
+ readonly auth: AuthManager;
77
+ readonly catalog: Catalog;
78
+ readonly scheduler: Scheduler;
79
+ private readonly ephemeral;
80
+ /** Mirrors this project's transcripts, when sync is on and signed in. */
81
+ private mirror;
82
+ private syncState;
83
+ /** Active declarative plugin bundles, in their effective override order. */
84
+ readonly plugins: PluginDefinition[];
85
+ readonly logger: Logger;
86
+ private readonly options;
87
+ private projectInstructions?;
88
+ private constructor();
89
+ static create(opts?: HarnessOptions): Promise<Harness>;
90
+ /**
91
+ * Begin mirroring, if this machine is configured and signed in for it.
92
+ *
93
+ * Every reason not to is a normal state rather than an error — not signed
94
+ * in, switched off, this one repository excluded — so nothing here logs a
95
+ * failure for them. Only an actual attempt that goes wrong is worth a line.
96
+ */
97
+ private startSync;
98
+ /**
99
+ * The roots this machine was told to allow, as opposed to the ones it
100
+ * worked out.
101
+ *
102
+ * `workspace.writableRoots` is the sum of a choice and a derivation: what
103
+ * the config named, plus every skill and agent directory the installed
104
+ * plugins contributed. Only the first half is editable, and telling them
105
+ * apart is the difference between a settings row that works and one whose
106
+ * changes come back on the next launch.
107
+ */
108
+ configuredWritableRoots(): string[];
109
+ /**
110
+ * Replace the roots this machine allows writes to.
111
+ *
112
+ * Takes effect on the next launch rather than now: the workspace policy is
113
+ * built once and handed to every tool, and swapping it under a turn already
114
+ * in flight would let a command that was checked against one answer run
115
+ * against another.
116
+ */
117
+ setWritableRoots(roots: string[]): Promise<string[]>;
118
+ /**
119
+ * Whether permission decisions are being recorded, and who decided that.
120
+ *
121
+ * Recording is on unless somebody turned it off: the trail is a handful of
122
+ * short lines per turn, it never leaves the machine, and the state where it
123
+ * is missing is exactly the state where it turns out to have been wanted.
124
+ *
125
+ * The source travels with the answer for the same reason sync carries a
126
+ * reason: a merged config cannot tell a value the user chose from one the
127
+ * repository imposed, and only the first can be changed from here. A switch
128
+ * offered over the second would appear to work and come back on the next
129
+ * launch, which is worse than no switch at all.
130
+ */
131
+ auditStatus(): Promise<AuditStatus>;
132
+ /**
133
+ * Start or stop recording permission decisions, and remember the choice.
134
+ *
135
+ * Only the recording is a choice here. Where an extra copy is written is
136
+ * `auditLog`, and that stays where somebody typed it: a switch that also
137
+ * deleted a configured path would turn "stop recording for now" into
138
+ * "forget where my collector reads from".
139
+ *
140
+ * On is written as the *absence* of the key, because on is the default and a
141
+ * config file should say what somebody decided, not restate what they left
142
+ * alone. Takes effect on the sessions already open — see `equip`.
143
+ */
144
+ setAudit(enabled: boolean): Promise<AuditStatus>;
145
+ /** A session's permission trail, oldest first. Empty for an ephemeral one. */
146
+ decisions(sessionId: string): Promise<AuditEntry[]>;
147
+ /**
148
+ * Push whatever is waiting, now.
149
+ *
150
+ * The mirror pushes on its own — this is for the person who wants to know it
151
+ * has happened before closing the laptop, which is not a question a
152
+ * background timer can answer. False means there was nothing to push it
153
+ * through: off, excluded, or not signed in.
154
+ */
155
+ syncNow(): Promise<boolean>;
156
+ /**
157
+ * The OHarness account access token, if signed in.
158
+ *
159
+ * Only `official` is asked. Other gateway entries in the catalog hold keys
160
+ * to *their* vendor, not to an OHarness account, and handing one of those to
161
+ * the artifact API would authenticate as nobody — the 401 that follows is a
162
+ * far worse way to find out than not trying.
163
+ *
164
+ * Public because publishing an artifact needs it too, and a second copy of
165
+ * this rule in the server package would be a second place to get it wrong.
166
+ */
167
+ accountToken(): Promise<string | undefined>;
168
+ /**
169
+ * Whether transcripts are leaving this machine, and why not when they are
170
+ * not.
171
+ *
172
+ * The reason is carried rather than collapsed to a boolean because "you
173
+ * turned this off" and "you are not signed in" look identical from outside
174
+ * and need opposite advice.
175
+ */
176
+ syncStatus(): {
177
+ on: boolean;
178
+ reason?: string;
179
+ url?: string;
180
+ };
181
+ /**
182
+ * Turn sync on or off now, and remember the choice.
183
+ *
184
+ * Written to the user's config rather than held in memory, because a switch
185
+ * that forgets on restart is not a switch — someone who turned sync off did
186
+ * not mean "until the next launch". Stopping aborts the poll in flight, so
187
+ * the connection does not outlive the decision.
188
+ */
189
+ setSyncEnabled(enabled: boolean): Promise<void>;
190
+ /** Connect an MCP server at runtime and expose its tools immediately. */
191
+ addMcpServer(name: string, config: NonNullable<HarnessConfig["mcpServers"]>[string]): Promise<McpServerStatus>;
192
+ /**
193
+ * Begin an OAuth login for a connector that asked for one.
194
+ *
195
+ * The connector does not have to be connected — a server that answered 401
196
+ * is exactly the case this exists for. On success the server is reconnected,
197
+ * so the tools appear without the user doing anything else.
198
+ */
199
+ mcpLogin(name: string): Promise<AuthorizeResult>;
200
+ /** Forget a connector's credential. It will ask again on the next connect. */
201
+ mcpLogout(name: string): Promise<boolean>;
202
+ removeMcpServer(name: string): Promise<void>;
203
+ mcpStatus(): McpServerStatus[];
204
+ authStatus(): Promise<AuthStatus[]>;
205
+ /** Providers that can actually authenticate right now. */
206
+ configuredProviders(): Promise<Set<string>>;
207
+ /**
208
+ * Ask providers which models they actually serve, and persist the result to
209
+ * the user catalog so the next run starts with a current list.
210
+ */
211
+ refreshModels(providerId?: string): Promise<ModelSpec[]>;
212
+ /** Merge discovered models into the user catalog on disk. */
213
+ private saveDiscovered;
214
+ /**
215
+ * Re-scan the skill directories.
216
+ *
217
+ * Skills are ordinary markdown on disk and the agent can write them, so
218
+ * without this an authored skill sits unusable until the next restart —
219
+ * which breaks the one loop that would let the agent improve itself.
220
+ */
221
+ reloadSkills(): Promise<number>;
222
+ /** Providers declared by the catalog, for `/models` and login hints. */
223
+ listCatalogProviders(): CatalogProvider[];
224
+ listModels(configuredOnly?: boolean): ModelSpec[];
225
+ listSessions(limit?: number): Promise<SessionMeta[]>;
226
+ /** Start a fresh session. */
227
+ createSession(overrides?: {
228
+ model?: string;
229
+ title?: string;
230
+ }): Session;
231
+ /**
232
+ * Give a session the machinery that outlives it: where remembered approvals
233
+ * are written, and where decisions are recorded.
234
+ */
235
+ private auditQueue;
236
+ /**
237
+ * The file the queue has already made a directory for.
238
+ *
239
+ * A path rather than a flag, because recording can be switched on and off
240
+ * while sessions are open: a boolean would remember that *some* directory
241
+ * exists and let the first write to a new one ENOENT into a log line.
242
+ */
243
+ private auditReadyFor?;
244
+ private equip;
245
+ /**
246
+ * Write one trail entry: to the session's own log, and to the configured
247
+ * file when there is one.
248
+ *
249
+ * Fire-and-forget so recording never delays or fails a tool call, but
250
+ * chained: concurrent appends of separate lines can interleave and a
251
+ * half-written record is worse than none. The chain also carries the
252
+ * one-time mkdir for the file sink — without it every write ENOENTs into a
253
+ * log line and the trail is silently empty.
254
+ *
255
+ * This is the one place this harness parts company with a stricter reading
256
+ * of the same idea, where a decision that cannot be recorded is a decision
257
+ * that does not happen. That trade buys an audit you can rely on at the cost
258
+ * of a tool call that fails because a disk did; here the tool call wins, and
259
+ * a failed write is a warning in the log rather than a refusal. Anything
260
+ * that needs the stronger guarantee needs this to be awaited on the call
261
+ * path, not just louder.
262
+ */
263
+ private record;
264
+ /**
265
+ * Branch a session. Omit `keepMessages` to branch from where it stands, or
266
+ * pass a count to rewind the branch to an earlier point.
267
+ */
268
+ forkSession(id: string, opts?: {
269
+ keepMessages?: number;
270
+ title?: string;
271
+ model?: string;
272
+ }): Promise<Session | undefined>;
273
+ deleteSession(id: string): Promise<boolean>;
274
+ /**
275
+ * Delete every session recorded in one tree.
276
+ *
277
+ * The directory itself is never touched — this throws away what the harness
278
+ * wrote about the work, not the work. Returns the ids, because whoever asked
279
+ * is probably holding some of them open.
280
+ */
281
+ deleteSessionsIn(cwd: string): Promise<string[]>;
282
+ renameSession(id: string, title: string): Promise<boolean>;
283
+ /** Reload a persisted session by id; returns undefined if it is unknown. */
284
+ resumeSession(id: string, model?: string): Promise<Session | undefined>;
285
+ /** Build an agent bound to a session, wired with everything the harness owns. */
286
+ agent(session: Session, overrides?: Partial<AgentOptions>): Agent;
287
+ /**
288
+ * One-shot convenience: run a prompt in a new session and stream events.
289
+ * For multi-turn use, keep a `Session` and reuse the agent.
290
+ */
291
+ run(prompt: string, opts?: {
292
+ model?: string;
293
+ signal?: AbortSignal;
294
+ }): AsyncGenerator<AgentEvent, void, void>;
295
+ close(): Promise<void>;
296
+ /**
297
+ * First model whose provider has credentials. Only the cheap synchronous
298
+ * check runs here — a subscription-only provider is picked up once the
299
+ * caller has awaited `configuredProviders()`.
300
+ */
301
+ private defaultModel;
302
+ }