@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,98 @@
1
+ import { z } from "zod";
2
+ /** Convert a zod schema to a JSON Schema object suitable for tool definitions. */
3
+ export function zodToJsonSchema(schema) {
4
+ const raw = z.toJSONSchema(schema, { target: "draft-7", io: "input" });
5
+ return normalizeObjectSchema(raw);
6
+ }
7
+ /**
8
+ * Every provider expects a top-level object schema for tool inputs, and every
9
+ * provider chokes on `$schema`/`$id` at the top level of a function parameter.
10
+ */
11
+ export function normalizeObjectSchema(schema) {
12
+ const { $schema, $id, ...rest } = schema;
13
+ void $schema;
14
+ void $id;
15
+ if (rest["type"] === undefined && rest["properties"] === undefined) {
16
+ return { type: "object", properties: {}, ...rest };
17
+ }
18
+ if (rest["type"] === "object" && rest["properties"] === undefined) {
19
+ rest["properties"] = {};
20
+ }
21
+ return rest;
22
+ }
23
+ /**
24
+ * Gemini accepts only a subset of OpenAPI 3.0 schema. Strip what it rejects
25
+ * rather than letting the request 400.
26
+ */
27
+ const GEMINI_ALLOWED = new Set([
28
+ "type",
29
+ "format",
30
+ "description",
31
+ "nullable",
32
+ "enum",
33
+ "maxItems",
34
+ "minItems",
35
+ "properties",
36
+ "required",
37
+ "items",
38
+ "anyOf",
39
+ "propertyOrdering",
40
+ ]);
41
+ export function sanitizeForGemini(schema) {
42
+ return walk(schema);
43
+ function walk(node) {
44
+ if (Array.isArray(node))
45
+ return node.map(walk);
46
+ if (node === null || typeof node !== "object")
47
+ return node;
48
+ const src = node;
49
+ const out = {};
50
+ // `oneOf`/`allOf` are unsupported; the closest legal construct is anyOf.
51
+ const union = src["oneOf"] ?? src["allOf"];
52
+ if (union && !src["anyOf"])
53
+ out["anyOf"] = walk(union);
54
+ for (const [key, value] of Object.entries(src)) {
55
+ if (!GEMINI_ALLOWED.has(key))
56
+ continue;
57
+ if (key === "properties" && value && typeof value === "object") {
58
+ const props = {};
59
+ for (const [pk, pv] of Object.entries(value)) {
60
+ props[pk] = walk(pv);
61
+ }
62
+ out["properties"] = props;
63
+ continue;
64
+ }
65
+ out[key] = walk(value);
66
+ }
67
+ // Gemini requires `type` on object nodes that declare properties.
68
+ if (out["properties"] && !out["type"])
69
+ out["type"] = "object";
70
+ if (out["items"] && !out["type"])
71
+ out["type"] = "array";
72
+ return out;
73
+ }
74
+ }
75
+ /**
76
+ * OpenAI strict function calling requires `additionalProperties: false` and
77
+ * every property listed in `required`. We only apply it when asked, because it
78
+ * also forbids optional fields.
79
+ */
80
+ export function toStrictOpenAiSchema(schema) {
81
+ return walk(schema);
82
+ function walk(node) {
83
+ if (Array.isArray(node))
84
+ return node.map(walk);
85
+ if (node === null || typeof node !== "object")
86
+ return node;
87
+ const src = node;
88
+ const out = {};
89
+ for (const [key, value] of Object.entries(src))
90
+ out[key] = walk(value);
91
+ if (out["type"] === "object" && out["properties"]) {
92
+ out["additionalProperties"] = false;
93
+ out["required"] = Object.keys(out["properties"]);
94
+ }
95
+ return out;
96
+ }
97
+ }
98
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/util/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Which shell to run a command string through.
3
+ *
4
+ * The harness hands the model's command to a shell rather than parsing it
5
+ * itself — pipes, redirects and quoting are the model's to use. That means
6
+ * picking a shell per platform: `bash -c` simply does not exist on a stock
7
+ * Windows install, so every shell-backed feature was silently unavailable
8
+ * there.
9
+ */
10
+ export interface ShellCommand {
11
+ command: string;
12
+ args: string[];
13
+ }
14
+ /**
15
+ * `SHELL` is honoured on POSIX so a user on zsh/fish gets their own
16
+ * environment; `ComSpec` is the Windows equivalent.
17
+ */
18
+ export declare function shellFor(script: string): ShellCommand;
19
+ /** True when the platform's shell is cmd.exe rather than a POSIX shell. */
20
+ export declare function isWindowsShell(): boolean;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * `SHELL` is honoured on POSIX so a user on zsh/fish gets their own
3
+ * environment; `ComSpec` is the Windows equivalent.
4
+ */
5
+ export function shellFor(script) {
6
+ if (process.platform === "win32") {
7
+ const comspec = process.env["ComSpec"] ?? "cmd.exe";
8
+ // PowerShell needs a different invocation than cmd, and `-Command` is the
9
+ // only form that accepts a full script string.
10
+ if (/powershell|pwsh/i.test(comspec)) {
11
+ return { command: comspec, args: ["-NoProfile", "-Command", script] };
12
+ }
13
+ return { command: comspec, args: ["/d", "/s", "/c", script] };
14
+ }
15
+ const shell = process.env["SHELL"];
16
+ // Fall back to bash rather than sh: the tool descriptions promise bash
17
+ // syntax, and a login shell may be something that cannot run it.
18
+ return { command: shell && shell.trim() !== "" ? shell : "/bin/bash", args: ["-c", script] };
19
+ }
20
+ /** True when the platform's shell is cmd.exe rather than a POSIX shell. */
21
+ export function isWindowsShell() {
22
+ return process.platform === "win32" && !/powershell|pwsh/i.test(process.env["ComSpec"] ?? "");
23
+ }
24
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/util/shell.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAc;IACrC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC;QACpD,0EAA0E;QAC1E,+CAA+C;QAC/C,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACrC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC;QACxE,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;IAChE,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACnC,uEAAuE;IACvE,iEAAiE;IACjE,OAAO,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;AAC/F,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,cAAc;IAC5B,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;AAChG,CAAC"}
package/official.json ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "supabaseUrl": "https://xuqupogshrptlyrbcgne.supabase.co",
3
+ "supabaseAnonKey": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inh1cXVwb2dzaHJwdGx5cmJjZ25lIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDI2MzY3ODEsImV4cCI6MjA1ODIxMjc4MX0.aSmArTFk0hgMdaueEULtceSzCKfC8mOSLNhNSeLojUo"
4
+ }
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@oharness/engine",
3
+ "version": "0.1.0",
4
+ "description": "The agent loop, tool execution, context management and permissions. No frontend, no transport.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "engines": {
8
+ "node": ">=22.6.0"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "oharness-source": "./src/index.ts",
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "./*.ts": {
19
+ "oharness-source": "./src/*.ts",
20
+ "types": "./dist/*.d.ts",
21
+ "default": "./dist/*.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "skills",
27
+ "official.json"
28
+ ],
29
+ "scripts": {
30
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && cp src/providers/catalog.json dist/providers/catalog.json && cp src/mcp/registry.json dist/mcp/registry.json",
31
+ "prepack": "node scripts/write-official.mjs",
32
+ "postpack": "node scripts/write-official.mjs --clean"
33
+ },
34
+ "dependencies": {
35
+ "@earendil-works/pi-ai": "^0.84.3",
36
+ "zod": "^4.1.5"
37
+ }
38
+ }
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: artifact-authoring
3
+ description: Making and revising artifacts — which kind to use, what an HTML artifact is allowed to contain, and when writing a file is the better answer.
4
+ ---
5
+
6
+ # Authoring artifacts
7
+
8
+ An artifact is something the user **looks at**: a chart, a rendered page, a
9
+ document being iterated on. It is not a file. If the thing you are making is
10
+ source code, a config, or anything the user will keep and edit, use `write` —
11
+ artifacts live in memory and disappear when the process does.
12
+
13
+ ## The one rule that will otherwise waste a turn
14
+
15
+ **An HTML artifact must be a single self-contained file.** It is served into a
16
+ sandbox whose policy is `default-src 'none'`, so:
17
+
18
+ - `<script src="https://cdn…">` — **blocked**. React, Vue, Tailwind, Chart.js,
19
+ D3 or anything else from a CDN will not load, and the page renders blank.
20
+ - `<link rel="stylesheet" href="https://…">` — **blocked**. So are remote
21
+ fonts and remote images.
22
+ - `fetch()`, `XMLHttpRequest`, `WebSocket` — **blocked**. An artifact cannot
23
+ reach the network, including the harness that served it.
24
+ - JSX/TSX — there is no build step, and the usual workaround (Babel from a CDN)
25
+ is blocked by the first rule.
26
+
27
+ Nothing warns you when this happens. The artifact stores fine, publishes fine,
28
+ and shows an empty rectangle.
29
+
30
+ What *does* work, and is enough for most things worth looking at:
31
+
32
+ - Inline `<style>` and inline `<script>` — both run.
33
+ - Plain DOM, canvas, SVG, CSS animation, CSS grid.
34
+ - `data:` URIs for images and fonts.
35
+ - Any data the page needs, written into the file as a literal.
36
+
37
+ Draw charts by emitting SVG or by drawing to a `<canvas>` in inline script.
38
+ That is a few dozen lines, and it always renders.
39
+
40
+ ## Canvases
41
+
42
+ `text/canvas+html` makes a board of artboards the user can select, edit and save
43
+ back. It has enough rules of its own to be its own skill — read **canvas**
44
+ before writing one.
45
+
46
+ ## Choosing a kind
47
+
48
+ Set `mime` to match what you actually wrote:
49
+
50
+ | You are making | `mime` |
51
+ | --- | --- |
52
+ | A layout the user will want to nudge by hand | `text/canvas+html` (see the canvas skill) |
53
+ | A rendered page or interactive widget | `text/html` |
54
+ | A diagram or chart with no interaction | `image/svg+xml` |
55
+ | Prose, a report, notes | `text/markdown` |
56
+ | Data or source to be read, not run | `application/json`, `text/plain` |
57
+
58
+ Prefer `image/svg+xml` over `text/html` when nothing needs to be clickable: it
59
+ renders everywhere, including places an HTML artifact only gets a summary line.
60
+
61
+ ## Revising
62
+
63
+ Reuse the same `id` to revise. That keeps one artifact with a version history
64
+ rather than filling the panel with near-duplicates, and it keeps any link that
65
+ was already shared pointing at the same place.
66
+
67
+ Send the **complete** new content every time — there is no patching.
68
+
69
+ Choose an id that describes the thing (`sales-chart`, `onboarding-flow`), not
70
+ the moment (`chart-v2`, `chart-final`). The version number is kept for you.
71
+
72
+ ## What publishing does
73
+
74
+ Publishing copies the artifact to the website and returns a URL. Two things
75
+ follow that are worth telling the user:
76
+
77
+ - The link serves the revision that was **published**, not the latest one.
78
+ Revise five times without republishing and the recipient still sees the
79
+ first. The panel shows this, and offers to update the link.
80
+ - Publishing needs an account, and the content leaves the machine. Do not
81
+ publish anything containing credentials, private paths, or customer data.
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: canvas
3
+ description: Create a canvas: a pan/zoom board of `<artboard>` blocks the user can select, edit and save back as their own revision. Use for mockups, screen flows, dashboards, landing pages, posters — any layout better nudged by hand. Write only the artboards; the editor is the harness's.
4
+ ---
5
+
6
+ # Canvases
7
+
8
+ A canvas is the one artifact the user can edit back. Write it with
9
+ `artifact_write` and `mime: text/canvas+html`.
10
+
11
+ ## Write the artboards, nothing else
12
+
13
+ The stage, the zoom, the selection outline, the properties panel, undo and Save
14
+ all come from the harness. You supply an optional `<style>` and a list of
15
+ artboards — no `<html>`, no `<head>`, no viewport, no pan/zoom code. Writing
16
+ your own editor means two editors fighting over the same clicks, and it costs
17
+ you the whole artifact size budget.
18
+
19
+ ```html
20
+ <style>
21
+ .screen { font: 15px/1.5 ui-sans-serif, system-ui, sans-serif; padding: 24px; }
22
+ .screen h2 { margin: 0 0 8px; font-size: 22px; }
23
+ .muted { color: #71717a; }
24
+ </style>
25
+
26
+ <artboard title="Empty state" width="390" height="600">
27
+ <div class="screen">
28
+ <h2>No projects yet</h2>
29
+ <p class="muted">Create one to get started.</p>
30
+ </div>
31
+ </artboard>
32
+
33
+ <artboard title="With projects" width="390" height="600">
34
+ <div class="screen">
35
+ <h2>Projects</h2>
36
+ <p class="muted">3 active</p>
37
+ </div>
38
+ </artboard>
39
+ ```
40
+
41
+ - `title`, `width` and `height` are the only attributes that mean anything.
42
+ Position is not one of them: boards are packed and wrapped for you, in the
43
+ order you wrote them. Put related states next to each other.
44
+ - The leading `<style>` is shared by every board and survives every save.
45
+ **Style your own classes.** A `*` or a bare `h2` selector reaches inside every
46
+ artboard at once — occasionally what you want, usually a surprise.
47
+ - Everything in [artifact-authoring](../artifact-authoring/SKILL.md) still
48
+ applies: one self-contained document, no CDN, no fetch, `data:` URIs for
49
+ images.
50
+
51
+ ## Sizes worth reaching for
52
+
53
+ | Artboard | width x height |
54
+ | --- | --- |
55
+ | Phone screen | 390 x 844, or 390 x 600 for a crop |
56
+ | Tablet | 834 x 1112 |
57
+ | Desktop app or landing page | 1440 x 1024 |
58
+ | Poster / flyer (A4 at 96dpi) | 794 x 1123 |
59
+ | Social card | 1200 x 630 |
60
+
61
+ A flow is one artboard per state. A document is one tall artboard, not five
62
+ stacked ones.
63
+
64
+ ## What happens after you hand it over
65
+
66
+ **Their edits are real revisions.** A save writes a new version authored by
67
+ them, on top of yours. Revising the same id afterwards replaces what they
68
+ changed — nothing is lost, the earlier version is still in the history, and the
69
+ tool receipt tells you when it has just happened. When it does: say so, read
70
+ the version back with `artifact_read`, and fold their changes in rather than
71
+ silently reverting them.
72
+
73
+ **Saving needs a frontend that offers it.** A canvas opened in its own tab, or
74
+ published to the website, still pans and zooms but has no Save — there is no
75
+ session behind it to write a revision to. It is a fine thing to share, and a
76
+ poor place to ask someone to make changes.
77
+
78
+ ## When not to reach for this
79
+
80
+ - The thing must *run* — a working widget, a simulation, a chart with
81
+ interaction. That is a `text/html` artifact.
82
+ - Nothing needs to be clickable and nobody will nudge it. An `image/svg+xml`
83
+ artifact renders in more places, including ones a canvas only gets a summary
84
+ line in.
85
+ - The user will keep and edit the result as a file. Use `write`.
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: skill-authoring
3
+ description: Writing a SKILL.md — the frontmatter, where skills are discovered, and what makes a description one that actually gets matched.
4
+ ---
5
+
6
+ # Writing a skill
7
+
8
+ A skill is packaged instructions loaded on demand. Its **description** sits in
9
+ the system prompt of every request; its **body** is only loaded when a task
10
+ matches. That split is the whole point, and it drives every rule below.
11
+
12
+ ## The file
13
+
14
+ One directory, one `SKILL.md`:
15
+
16
+ ```
17
+ my-skill/
18
+ SKILL.md
19
+ scripts/check.py ← optional, referenced from the body by relative path
20
+ reference/api.md
21
+ ```
22
+
23
+ ```markdown
24
+ ---
25
+ name: my-skill
26
+ description: One line. This is the only thing seen before the skill is loaded.
27
+ ---
28
+
29
+ # My skill
30
+
31
+ The instructions.
32
+ ```
33
+
34
+ `description` is required — a skill without one can never be selected, and is
35
+ skipped with a warning. `name` defaults to the directory name.
36
+
37
+ Relative paths in the body resolve against the skill's own directory, and the
38
+ files in it are listed when the skill loads, so `run scripts/check.py` is a
39
+ usable instruction rather than a dead reference.
40
+
41
+ ## Where they go
42
+
43
+ | Location | Scope |
44
+ | --- | --- |
45
+ | `<project>/.oharness/skills/` | This repository. Overrides the two below. |
46
+ | `~/.oharness/skills/` | This user, every project. |
47
+ | shipped with the harness | Built-in. Overridden by either of the above. |
48
+
49
+ Same name in two places: the more specific one wins. That is how a repository
50
+ pins its own version of a skill without anyone editing a global file.
51
+
52
+ Writing a `SKILL.md` into one of those directories registers it **immediately**
53
+ — there is no restart. Authoring a skill for yourself mid-task and then using
54
+ it in the same session works.
55
+
56
+ ## Writing a description that gets matched
57
+
58
+ This is where most skills fail. The description is matched against a task
59
+ before anything else is known, so it has to name the situation, not the skill.
60
+
61
+ - **Weak:** "Helper for deployments." — matches nothing in particular.
62
+ - **Better:** "Deploying to Railway: which service takes which variables, and
63
+ the migration order that avoids downtime."
64
+
65
+ Name the concrete nouns someone would use for the task. Avoid "helps you",
66
+ "utilities for", and anything that describes the file rather than the job.
67
+
68
+ ## Writing the body
69
+
70
+ Write it for someone competent who has not seen this system. That means:
71
+
72
+ - Say **why**, not only what. A rule with a reason survives a refactor; a bare
73
+ instruction gets dropped the first time it is inconvenient.
74
+ - Put the thing that will otherwise be got wrong at the top, not in a section
75
+ near the end.
76
+ - Prefer a short table over a long list of prose alternatives.
77
+ - Do not restate what any competent model already knows. Every line you add is
78
+ read on every use of the skill; earn it.
79
+
80
+ ## When *not* to write a skill
81
+
82
+ If the knowledge is a hard constraint that must always hold — an API that will
83
+ reject a call, a policy that will block a write — it belongs in the relevant
84
+ tool's description, not a skill. Skills are opt-in and may not be installed;
85
+ a tool description is seen every time.