@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.
- package/dist/agent/agent.d.ts +196 -0
- package/dist/agent/agent.js +758 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/compaction.d.ts +68 -0
- package/dist/agent/compaction.js +179 -0
- package/dist/agent/compaction.js.map +1 -0
- package/dist/agent/hooks.d.ts +77 -0
- package/dist/agent/hooks.js +152 -0
- package/dist/agent/hooks.js.map +1 -0
- package/dist/agent/memory.d.ts +45 -0
- package/dist/agent/memory.js +147 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/overflow.d.ts +35 -0
- package/dist/agent/overflow.js +69 -0
- package/dist/agent/overflow.js.map +1 -0
- package/dist/agent/permissions.d.ts +181 -0
- package/dist/agent/permissions.js +289 -0
- package/dist/agent/permissions.js.map +1 -0
- package/dist/agent/prompt.d.ts +25 -0
- package/dist/agent/prompt.js +63 -0
- package/dist/agent/prompt.js.map +1 -0
- package/dist/agent/session.d.ts +108 -0
- package/dist/agent/session.js +231 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/agent/settings.d.ts +37 -0
- package/dist/agent/settings.js +113 -0
- package/dist/agent/settings.js.map +1 -0
- package/dist/agent/skills.d.ts +58 -0
- package/dist/agent/skills.js +225 -0
- package/dist/agent/skills.js.map +1 -0
- package/dist/agent/store.d.ts +308 -0
- package/dist/agent/store.js +596 -0
- package/dist/agent/store.js.map +1 -0
- package/dist/agent/subagent.d.ts +44 -0
- package/dist/agent/subagent.js +138 -0
- package/dist/agent/subagent.js.map +1 -0
- package/dist/agent/titles.d.ts +8 -0
- package/dist/agent/titles.js +23 -0
- package/dist/agent/titles.js.map +1 -0
- package/dist/agent/workspace.d.ts +60 -0
- package/dist/agent/workspace.js +156 -0
- package/dist/agent/workspace.js.map +1 -0
- package/dist/artifacts/publish.d.ts +94 -0
- package/dist/artifacts/publish.js +104 -0
- package/dist/artifacts/publish.js.map +1 -0
- package/dist/artifacts/store.d.ts +324 -0
- package/dist/artifacts/store.js +500 -0
- package/dist/artifacts/store.js.map +1 -0
- package/dist/auth/index.d.ts +13 -0
- package/dist/auth/index.js +10 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/manager.d.ts +83 -0
- package/dist/auth/manager.js +266 -0
- package/dist/auth/manager.js.map +1 -0
- package/dist/auth/oauth.d.ts +83 -0
- package/dist/auth/oauth.js +327 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/providers/account.d.ts +59 -0
- package/dist/auth/providers/account.js +282 -0
- package/dist/auth/providers/account.js.map +1 -0
- package/dist/auth/providers/anthropic.d.ts +24 -0
- package/dist/auth/providers/anthropic.js +209 -0
- package/dist/auth/providers/anthropic.js.map +1 -0
- package/dist/auth/providers/generic.d.ts +57 -0
- package/dist/auth/providers/generic.js +155 -0
- package/dist/auth/providers/generic.js.map +1 -0
- package/dist/auth/providers/official.d.ts +3 -0
- package/dist/auth/providers/official.js +90 -0
- package/dist/auth/providers/official.js.map +1 -0
- package/dist/auth/providers/ottoport.d.ts +3 -0
- package/dist/auth/providers/ottoport.js +60 -0
- package/dist/auth/providers/ottoport.js.map +1 -0
- package/dist/auth/store.d.ts +22 -0
- package/dist/auth/store.js +138 -0
- package/dist/auth/store.js.map +1 -0
- package/dist/auth/types.d.ts +167 -0
- package/dist/auth/types.js +16 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/config.d.ts +197 -0
- package/dist/config.js +195 -0
- package/dist/config.js.map +1 -0
- package/dist/core/errors.d.ts +46 -0
- package/dist/core/errors.js +83 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/tokens.d.ts +12 -0
- package/dist/core/tokens.js +56 -0
- package/dist/core/tokens.js.map +1 -0
- package/dist/core/types.d.ts +91 -0
- package/dist/core/types.js +49 -0
- package/dist/core/types.js.map +1 -0
- package/dist/harness.d.ts +302 -0
- package/dist/harness.js +695 -0
- package/dist/harness.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +55 -0
- package/dist/mcp/client.js +199 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/index.d.ts +13 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/manager.d.ts +77 -0
- package/dist/mcp/manager.js +325 -0
- package/dist/mcp/manager.js.map +1 -0
- package/dist/mcp/oauth.d.ts +63 -0
- package/dist/mcp/oauth.js +302 -0
- package/dist/mcp/oauth.js.map +1 -0
- package/dist/mcp/protocol.d.ts +130 -0
- package/dist/mcp/protocol.js +14 -0
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/registry.d.ts +52 -0
- package/dist/mcp/registry.js +100 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/registry.json +293 -0
- package/dist/mcp/secrets.d.ts +20 -0
- package/dist/mcp/secrets.js +75 -0
- package/dist/mcp/secrets.js.map +1 -0
- package/dist/mcp/transport.d.ts +51 -0
- package/dist/mcp/transport.js +158 -0
- package/dist/mcp/transport.js.map +1 -0
- package/dist/paths.d.ts +37 -0
- package/dist/paths.js +63 -0
- package/dist/paths.js.map +1 -0
- package/dist/plugins.d.ts +55 -0
- package/dist/plugins.js +201 -0
- package/dist/plugins.js.map +1 -0
- package/dist/providers/builtin.d.ts +23 -0
- package/dist/providers/builtin.js +141 -0
- package/dist/providers/builtin.js.map +1 -0
- package/dist/providers/catalog.d.ts +129 -0
- package/dist/providers/catalog.js +254 -0
- package/dist/providers/catalog.js.map +1 -0
- package/dist/providers/catalog.json +472 -0
- package/dist/providers/discovery.d.ts +16 -0
- package/dist/providers/discovery.js +161 -0
- package/dist/providers/discovery.js.map +1 -0
- package/dist/providers/http.d.ts +24 -0
- package/dist/providers/http.js +139 -0
- package/dist/providers/http.js.map +1 -0
- package/dist/providers/index.d.ts +10 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/piai.d.ts +124 -0
- package/dist/providers/piai.js +551 -0
- package/dist/providers/piai.js.map +1 -0
- package/dist/providers/registry.d.ts +65 -0
- package/dist/providers/registry.js +195 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/resilient.d.ts +46 -0
- package/dist/providers/resilient.js +117 -0
- package/dist/providers/resilient.js.map +1 -0
- package/dist/providers/types.d.ts +182 -0
- package/dist/providers/types.js +50 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/schedule/cron.d.ts +35 -0
- package/dist/schedule/cron.js +125 -0
- package/dist/schedule/cron.js.map +1 -0
- package/dist/schedule/scheduler.d.ts +87 -0
- package/dist/schedule/scheduler.js +237 -0
- package/dist/schedule/scheduler.js.map +1 -0
- package/dist/storage/kv.d.ts +56 -0
- package/dist/storage/kv.js +173 -0
- package/dist/storage/kv.js.map +1 -0
- package/dist/storage/migrate.d.ts +11 -0
- package/dist/storage/migrate.js +93 -0
- package/dist/storage/migrate.js.map +1 -0
- package/dist/storage/project.d.ts +9 -0
- package/dist/storage/project.js +57 -0
- package/dist/storage/project.js.map +1 -0
- package/dist/storage/records.d.ts +32 -0
- package/dist/storage/records.js +48 -0
- package/dist/storage/records.js.map +1 -0
- package/dist/sync/client.d.ts +79 -0
- package/dist/sync/client.js +118 -0
- package/dist/sync/client.js.map +1 -0
- package/dist/sync/mirror.d.ts +85 -0
- package/dist/sync/mirror.js +389 -0
- package/dist/sync/mirror.js.map +1 -0
- package/dist/sync/protocol.d.ts +67 -0
- package/dist/sync/protocol.js +16 -0
- package/dist/sync/protocol.js.map +1 -0
- package/dist/sync/settings.d.ts +56 -0
- package/dist/sync/settings.js +60 -0
- package/dist/sync/settings.js.map +1 -0
- package/dist/tools/builtin/artifact.d.ts +16 -0
- package/dist/tools/builtin/artifact.js +134 -0
- package/dist/tools/builtin/artifact.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +3 -0
- package/dist/tools/builtin/bash.js +142 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/fs.d.ts +19 -0
- package/dist/tools/builtin/fs.js +280 -0
- package/dist/tools/builtin/fs.js.map +1 -0
- package/dist/tools/builtin/index.d.ts +22 -0
- package/dist/tools/builtin/index.js +42 -0
- package/dist/tools/builtin/index.js.map +1 -0
- package/dist/tools/builtin/mcp-resource.d.ts +3 -0
- package/dist/tools/builtin/mcp-resource.js +220 -0
- package/dist/tools/builtin/mcp-resource.js.map +1 -0
- package/dist/tools/builtin/memory.d.ts +10 -0
- package/dist/tools/builtin/memory.js +76 -0
- package/dist/tools/builtin/memory.js.map +1 -0
- package/dist/tools/builtin/recall.d.ts +13 -0
- package/dist/tools/builtin/recall.js +163 -0
- package/dist/tools/builtin/recall.js.map +1 -0
- package/dist/tools/builtin/search.d.ts +3 -0
- package/dist/tools/builtin/search.js +240 -0
- package/dist/tools/builtin/search.js.map +1 -0
- package/dist/tools/builtin/skill.d.ts +10 -0
- package/dist/tools/builtin/skill.js +46 -0
- package/dist/tools/builtin/skill.js.map +1 -0
- package/dist/tools/builtin/task.d.ts +9 -0
- package/dist/tools/builtin/task.js +68 -0
- package/dist/tools/builtin/task.js.map +1 -0
- package/dist/tools/builtin/todo.d.ts +20 -0
- package/dist/tools/builtin/todo.js +63 -0
- package/dist/tools/builtin/todo.js.map +1 -0
- package/dist/tools/define.d.ts +19 -0
- package/dist/tools/define.js +39 -0
- package/dist/tools/define.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +39 -0
- package/dist/tools/registry.js +101 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +112 -0
- package/dist/tools/types.js +22 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/util/id.d.ts +9 -0
- package/dist/util/id.js +19 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/json.d.ts +25 -0
- package/dist/util/json.js +100 -0
- package/dist/util/json.js.map +1 -0
- package/dist/util/jwt.d.ts +74 -0
- package/dist/util/jwt.js +177 -0
- package/dist/util/jwt.js.map +1 -0
- package/dist/util/logger.d.ts +13 -0
- package/dist/util/logger.js +59 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/queue.d.ts +26 -0
- package/dist/util/queue.js +106 -0
- package/dist/util/queue.js.map +1 -0
- package/dist/util/schema.d.ts +17 -0
- package/dist/util/schema.js +98 -0
- package/dist/util/schema.js.map +1 -0
- package/dist/util/shell.d.ts +20 -0
- package/dist/util/shell.js +24 -0
- package/dist/util/shell.js.map +1 -0
- package/official.json +4 -0
- package/package.json +38 -0
- package/skills/artifact-authoring/SKILL.md +81 -0
- package/skills/canvas/SKILL.md +85 -0
- 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.
|