@koda-sl/baker-bridge 0.68.1 → 0.68.3
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/README.md +20 -5
- package/dist/hono/agent.d.ts.map +1 -1
- package/dist/hono/agent.js +4 -23
- package/dist/hono/agent.js.map +1 -1
- package/dist/hono/agent.test.js +69 -50
- package/dist/hono/agent.test.js.map +1 -1
- package/dist/hono/bridge-job.d.ts.map +1 -1
- package/dist/hono/bridge-job.js +8 -2
- package/dist/hono/bridge-job.js.map +1 -1
- package/dist/hono/bridge-job.test.js +3 -12
- package/dist/hono/bridge-job.test.js.map +1 -1
- package/dist/hono/openrouter-session.d.ts +29 -0
- package/dist/hono/openrouter-session.d.ts.map +1 -0
- package/dist/hono/openrouter-session.js +48 -0
- package/dist/hono/openrouter-session.js.map +1 -0
- package/dist/hono/openrouter-session.test.d.ts +2 -0
- package/dist/hono/openrouter-session.test.d.ts.map +1 -0
- package/dist/hono/openrouter-session.test.js +37 -0
- package/dist/hono/openrouter-session.test.js.map +1 -0
- package/dist/hono/slash-command-allowlist.d.ts +5 -0
- package/dist/hono/slash-command-allowlist.d.ts.map +1 -0
- package/dist/hono/slash-command-allowlist.js +42 -0
- package/dist/hono/slash-command-allowlist.js.map +1 -0
- package/dist/hono/slash-command-allowlist.test.d.ts +2 -0
- package/dist/hono/slash-command-allowlist.test.d.ts.map +1 -0
- package/dist/hono/slash-command-allowlist.test.js +44 -0
- package/dist/hono/slash-command-allowlist.test.js.map +1 -0
- package/dist/hono/slash-commands.d.ts +2 -0
- package/dist/hono/slash-commands.d.ts.map +1 -1
- package/dist/hono/slash-commands.js +4 -0
- package/dist/hono/slash-commands.js.map +1 -1
- package/package.json +5 -6
- package/dist/hono/plugins.d.ts +0 -3
- package/dist/hono/plugins.d.ts.map +0 -1
- package/dist/hono/plugins.js +0 -7
- package/dist/hono/plugins.js.map +0 -1
- package/dist/hono/plugins.test.d.ts +0 -2
- package/dist/hono/plugins.test.d.ts.map +0 -1
- package/dist/hono/plugins.test.js +0 -98
- package/dist/hono/plugins.test.js.map +0 -1
- package/plugins/reports/.claude-plugin/plugin.json +0 -7
- package/plugins/reports/skills/build/SKILL.md +0 -73
- package/plugins/reports/skills/build/references/report-contracts.md +0 -103
- package/plugins/reports/skills/build/scripts/report-paths.mjs +0 -19
- package/plugins/reports/skills/build/scripts/scaffold-report.mjs +0 -108
- package/plugins/reports/skills/build/templates/report-definition.md +0 -22
- package/plugins/reports/skills/build/templates/report-index.html +0 -20
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# Report Contracts
|
|
2
|
-
|
|
3
|
-
Use this reference when creating or repairing Baker company Reports.
|
|
4
|
-
|
|
5
|
-
## Ownership
|
|
6
|
-
|
|
7
|
-
- Convex owns Report lifecycle and dashboard listing state.
|
|
8
|
-
- Scaffold owns report files and Nitro runtime behavior.
|
|
9
|
-
- The sandbox supervisor builds `reports` through the locked `reports-build` wrapper and serves promoted built Nitro output on port `3001`; do not use `nitro dev` for Reports.
|
|
10
|
-
- Dashboard owns visibility and links to the sandbox `reportsHost`.
|
|
11
|
-
- V1 reports are internal dashboard/sandbox live assets, not public generated-site deployment output.
|
|
12
|
-
|
|
13
|
-
## Required files
|
|
14
|
-
|
|
15
|
-
For slug `{slug}`:
|
|
16
|
-
|
|
17
|
-
```text
|
|
18
|
-
reports/server/routes/reports/data/{slug}.get.ts
|
|
19
|
-
reports/public/{slug}/index.html
|
|
20
|
-
reports/public/{slug}/_definition.md
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Slug format: lowercase alphanumeric words separated by hyphens.
|
|
24
|
-
|
|
25
|
-
## `_definition.md`
|
|
26
|
-
|
|
27
|
-
Frontmatter is the metadata contract consumed by watcher/upsert.
|
|
28
|
-
|
|
29
|
-
```markdown
|
|
30
|
-
---
|
|
31
|
-
title: "Campaign Performance Weekly"
|
|
32
|
-
description: "Weekly spend, conversions, and cost per lead by campaign"
|
|
33
|
-
status: draft
|
|
34
|
-
---
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Allowed statuses: `draft`, `active`, `error`, `archived`. Optional `errorMessage` is surfaced with error report definitions.
|
|
38
|
-
|
|
39
|
-
Keep frontmatter minimal and put business context, data-source notes, refresh notes, evolution, and source breadcrumbs in the Markdown body. Set `status: active` only when the endpoint, dashboard, metadata, and live smoke test are ready.
|
|
40
|
-
|
|
41
|
-
## Endpoint pattern
|
|
42
|
-
|
|
43
|
-
Default to `runReportBaker(event, args)` so `?fresh=true` maps to Baker `--no-cache`.
|
|
44
|
-
|
|
45
|
-
```ts
|
|
46
|
-
import { defineHandler } from "nitro";
|
|
47
|
-
import { runReportBaker } from "../../../utils/baker.ts";
|
|
48
|
-
|
|
49
|
-
export default defineHandler(async (event) => {
|
|
50
|
-
const start = Date.now();
|
|
51
|
-
const result = await runReportBaker<Row[]>(event, ["ads", "google", "query", "--preset", "campaign-performance"]);
|
|
52
|
-
|
|
53
|
-
if (!result.ok) {
|
|
54
|
-
return { ok: false, error: result.error };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
ok: true,
|
|
59
|
-
data: result.data,
|
|
60
|
-
meta: { durationMs: Date.now() - start, cached: result.cached ?? false },
|
|
61
|
-
};
|
|
62
|
-
});
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
For multi-call orchestration, read `freshRequested(event)` once and pass `{ noCache }` to every cacheable Baker call. Do not pass `noCache` to Baker commands that do not support `--no-cache`. Refresh invalidation is whole-report: `/reports/{slug}/?fresh=true` propagates to same-origin `/reports/data/{slug}` fetches, and Baker CLI cache is bypassed with `--no-cache`; HTTP responses remain `no-store`.
|
|
66
|
-
|
|
67
|
-
Google Ads query rows arrive from Baker CLI with flat dotted keys such as `campaign.name`, `campaign.advertising_channel_type`, `metrics.cost_micros`, and `segments.conversion_action_name`. `runReportBaker` preserves those flat keys and explicitly adds nested aliases for compatibility with existing reports. In new or repaired Google Ads report endpoints, adapt rows with `googleAdsRow(raw)` from `reports/server/utils/googleAdsRow.ts` before returning report data; the adapter preserves the input row as `row.raw`. Do not use top-level aliases such as `row.name` or `row.spend`; derive those explicitly from the Google Ads fields.
|
|
68
|
-
|
|
69
|
-
## HTML dashboard pattern
|
|
70
|
-
|
|
71
|
-
The page is served by the generic route at `/reports/{slug}/`, which injects a whole-report Refresh control. Keep dashboard JS simple:
|
|
72
|
-
|
|
73
|
-
- Fetch `/reports/data/{slug}` without manually appending `fresh=true`.
|
|
74
|
-
- Let the injected bootstrap propagate `?fresh=true` from the page URL to same-origin report fetches.
|
|
75
|
-
- Do not implement a second custom refresh button unless the user explicitly asks for custom UX.
|
|
76
|
-
- Keep chart data available in tables for accessibility.
|
|
77
|
-
|
|
78
|
-
## Validation
|
|
79
|
-
|
|
80
|
-
Run from the scaffold harness root:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
pnpm run verify
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Do not invoke `__tooling__/lefthook/base/validate-reports.mjs` directly. `pnpm run verify` is the supported contract and runs report validation with the correct working directory, plus typecheck and Nitro build checks.
|
|
87
|
-
|
|
88
|
-
The report validator checks report slug shape, `_definition.md` frontmatter/status, required dashboard files, active report endpoints, and legacy dashboard fetches. Legacy `/reports/{slug}` data fetches/routes must be fixed manually to use `/reports/data/{slug}`. The validator reports these issues but does not mutate source files or execute report data endpoints.
|
|
89
|
-
|
|
90
|
-
Before marking a new or active report done, smoke-test the built runtime:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
node __tooling__/scripts/smoke-reports-runtime.mjs --slug {slug}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
In a running company sandbox, the supervisor serves Reports at port `3001`, so direct probes are also valid:
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
curl -fsS http://localhost:3001/reports/{slug}/ >/tmp/report.html
|
|
100
|
-
curl -fsS http://localhost:3001/reports/data/{slug} | tee /tmp/report-data.json
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Endpoint `{ "ok": false, ... }`, visible dashboard error cards, failed Baker CLI calls, provider API errors, or smoke script failures are blocking. Fix the endpoint/query and rerun the smoke test before claiming success.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
const REPORT_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
2
|
-
|
|
3
|
-
function titleFromSlug(slug) {
|
|
4
|
-
return slug.replace(/-/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function paths(slug) {
|
|
8
|
-
return {
|
|
9
|
-
definition: `reports/public/${slug}/_definition.md`,
|
|
10
|
-
dashboard: `reports/public/${slug}/index.html`,
|
|
11
|
-
endpoint: `reports/server/routes/reports/data/${slug}.get.ts`,
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const ReportFileContract = {
|
|
16
|
-
isValidSlug: (slug) => REPORT_SLUG_RE.test(slug),
|
|
17
|
-
titleFromSlug,
|
|
18
|
-
paths,
|
|
19
|
-
};
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { dirname, join, resolve } from "node:path";
|
|
3
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
-
import { ReportFileContract } from "./report-paths.mjs";
|
|
5
|
-
|
|
6
|
-
function endpointTemplate() {
|
|
7
|
-
return `import { defineHandler } from "nitro";
|
|
8
|
-
import { runReportBaker } from "../../../utils/baker.ts";
|
|
9
|
-
|
|
10
|
-
export default defineHandler(async (event) => {
|
|
11
|
-
const start = Date.now();
|
|
12
|
-
|
|
13
|
-
// TODO: replace with the Baker command for this report.
|
|
14
|
-
// runReportBaker maps ?fresh=true to Baker --no-cache for commands that support it.
|
|
15
|
-
const result = await runReportBaker(event, ["TODO", "replace", "with", "baker", "args"]);
|
|
16
|
-
|
|
17
|
-
if (!result.ok) {
|
|
18
|
-
return { ok: false, error: result.error };
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
ok: true,
|
|
23
|
-
data: result.data,
|
|
24
|
-
meta: {
|
|
25
|
-
durationMs: Date.now() - start,
|
|
26
|
-
cached: result.cached ?? false,
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
});
|
|
30
|
-
`;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
34
|
-
|
|
35
|
-
function readTemplate(name) {
|
|
36
|
-
return readFileSync(resolve(scriptDir, "..", "templates", name), "utf8");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const TEMPLATE_TOKEN_RE = /__[A-Z0-9_]+__/g;
|
|
40
|
-
|
|
41
|
-
function renderTemplate(template, values) {
|
|
42
|
-
let rendered = template;
|
|
43
|
-
for (const [key, value] of Object.entries(values)) {
|
|
44
|
-
rendered = rendered.replaceAll(`__${key.toUpperCase()}__`, value);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const unresolved = rendered.match(TEMPLATE_TOKEN_RE);
|
|
48
|
-
if (unresolved) {
|
|
49
|
-
throw new Error(`Unresolved template token(s): ${[...new Set(unresolved)].join(", ")}`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return rendered;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function pageTemplate(slug, title) {
|
|
56
|
-
return renderTemplate(readTemplate("report-index.html"), { slug, title });
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function definitionTemplate(slug, title, today = new Date().toISOString().slice(0, 10)) {
|
|
60
|
-
return renderTemplate(readTemplate("report-definition.md"), { slug, title, today });
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function createReportFiles(slug, projectRoot = process.cwd()) {
|
|
64
|
-
if (!ReportFileContract.isValidSlug(slug)) {
|
|
65
|
-
throw new Error(`Invalid slug "${slug}". Must match /^[a-z0-9]+(-[a-z0-9]+)*$/`);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const paths = ReportFileContract.paths(slug);
|
|
69
|
-
const pageDir = join(projectRoot, "reports", "public", slug);
|
|
70
|
-
const dashboardPath = join(pageDir, "index.html");
|
|
71
|
-
const endpointPath = resolve(projectRoot, paths.endpoint);
|
|
72
|
-
const definitionPath = resolve(projectRoot, paths.definition);
|
|
73
|
-
|
|
74
|
-
if (existsSync(pageDir)) {
|
|
75
|
-
throw new Error(`Dashboard page already exists: ${pageDir}`);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (existsSync(endpointPath)) {
|
|
79
|
-
throw new Error(`Endpoint already exists: ${endpointPath}`);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const title = ReportFileContract.titleFromSlug(slug);
|
|
83
|
-
|
|
84
|
-
mkdirSync(pageDir, { recursive: true });
|
|
85
|
-
mkdirSync(dirname(endpointPath), { recursive: true });
|
|
86
|
-
writeFileSync(dashboardPath, pageTemplate(slug, title));
|
|
87
|
-
writeFileSync(definitionPath, definitionTemplate(slug, title));
|
|
88
|
-
writeFileSync(endpointPath, endpointTemplate());
|
|
89
|
-
|
|
90
|
-
return { slug, files: [endpointPath, dashboardPath, definitionPath] };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const isDirectRun = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
94
|
-
if (isDirectRun) {
|
|
95
|
-
const slug = process.argv[2];
|
|
96
|
-
|
|
97
|
-
if (!slug) {
|
|
98
|
-
console.error("Usage: node scaffold-report.mjs <slug>");
|
|
99
|
-
process.exit(1);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
try {
|
|
103
|
-
process.stdout.write(`${JSON.stringify(createReportFiles(slug), null, 2)}\n`);
|
|
104
|
-
} catch (error) {
|
|
105
|
-
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
106
|
-
process.exit(1);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "__TITLE__"
|
|
3
|
-
description: ""
|
|
4
|
-
status: draft
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Why This Report Exists
|
|
8
|
-
|
|
9
|
-
TODO: describe the question this report answers and the decision it supports.
|
|
10
|
-
|
|
11
|
-
## Data and Refresh
|
|
12
|
-
|
|
13
|
-
- **Data endpoint**: TODO: list the Baker commands or local data sources used by `/reports/data/__SLUG__`.
|
|
14
|
-
- **Refresh policy**: manual via the injected Refresh control using `?fresh=true`; smoke with the built Reports runtime before marking active.
|
|
15
|
-
|
|
16
|
-
## Evolution
|
|
17
|
-
|
|
18
|
-
- __TODAY__: created
|
|
19
|
-
|
|
20
|
-
## Sources
|
|
21
|
-
|
|
22
|
-
- TODO: link to personas, campaigns, audits, competitors, or docs that motivated this report.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>__TITLE__</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<main>
|
|
10
|
-
<h1>__TITLE__</h1>
|
|
11
|
-
<p>
|
|
12
|
-
TODO: replace this placeholder with the real Report Dashboard authored for this company.
|
|
13
|
-
</p>
|
|
14
|
-
<p>
|
|
15
|
-
Fetch report data from <code>/reports/data/__SLUG__</code>. The reports runtime serves this file at
|
|
16
|
-
<code>/reports/__SLUG__/</code> and injects the refresh control.
|
|
17
|
-
</p>
|
|
18
|
-
</main>
|
|
19
|
-
</body>
|
|
20
|
-
</html>
|