Skip to content

Commit f2cfd34

Browse files
authored
fix: guard formatMeta against non-number cost_usd + fix stale docs (#121)
* fix: guard formatMeta against non-number cost_usd + fix stale docs formatMeta was doing an unsafe cast to number on cost_usd — if the agent sends a string or null it would crash with toFixed is not a function. added a typeof check before calling toFixed. also updated CONTRIBUTING.md: - fixed references to drafts-menu.tsx → export-menu.tsx (the actual file) - fixed scenario list: sale → sales, added missing operations/education/creator/video * fix: add next/ prefix to CONTRIBUTING.md paths
1 parent 532bc39 commit f2cfd34

2 files changed

Lines changed: 15 additions & 15 deletions

File tree

CONTRIBUTING.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ This guide tells you exactly where to look for each type of contribution and wha
1212

1313
| If you want to… | You're really adding | Where it lives | Ship size |
1414
|---|---|---|---|
15-
| Make HTML Anything render a new kind of artifact (an invoice, a job posting, an iOS Settings screen…) | a **Skill** | [`src/lib/templates/skills/<your-skill>/`](src/lib/templates/skills/) | one folder, ~3 files |
16-
| Hook up a new coding-agent CLI | an **Agent adapter** | [`src/lib/agents/argv.ts`](src/lib/agents/argv.ts) + [`src/lib/agents/detect.ts`](src/lib/agents/detect.ts) | ~10 lines in one array |
17-
| Add a new export target (WeChat Channels, Douyin captions, Notion, …) | an **Export adapter** | [`src/components/drafts-menu.tsx`](src/components/drafts-menu.tsx) + helper under `src/lib/export/` | one component + one helper |
18-
| Add a feature, fix a bug, refactor the streaming parser | code | `src/app/`, `src/lib/`, `src/components/` | normal PR |
15+
| Make HTML Anything render a new kind of artifact (an invoice, a job posting, an iOS Settings screen…) | a **Skill** | [`next/src/lib/templates/skills/<your-skill>/`](next/src/lib/templates/skills/) | one folder, ~3 files |
16+
| Hook up a new coding-agent CLI | an **Agent adapter** | [`next/src/lib/agents/argv.ts`](next/src/lib/agents/argv.ts) + [`next/src/lib/agents/detect.ts`](next/src/lib/agents/detect.ts) | ~10 lines in one array |
17+
| Add a new export target (WeChat Channels, Douyin captions, Notion, …) | an **Export adapter** | [`next/src/components/export-menu.tsx`](next/src/components/export-menu.tsx) + helper under `next/src/lib/export/` | one component + one helper |
18+
| Add a feature, fix a bug, refactor the streaming parser | code | `next/src/app/`, `next/src/lib/`, `next/src/components/` | normal PR |
1919
| Improve docs, port a section into another language, fix typos | docs | `README.md`, `README.zh-CN.md`, this file | one PR |
2020

2121
If you're not sure which bucket your idea is in, [open an issue first](https://github.com/nexu-io/html-anything/issues/new) and we'll point you at the right surface.
@@ -42,12 +42,12 @@ Before you push, make sure you have **at least one coding-agent CLI logged in**
4242

4343
## Adding a new Skill
4444

45-
A skill is a folder under [`src/lib/templates/skills/`](src/lib/templates/skills/) with a `SKILL.md` at the root, following Claude Code's [`SKILL.md` convention][skill] plus a small extended frontmatter that the picker reads. **No registration step.** Drop the folder in, restart `pnpm dev`, the picker shows it.
45+
A skill is a folder under [`next/src/lib/templates/skills/`](next/src/lib/templates/skills/) with a `SKILL.md` at the root, following Claude Code's [`SKILL.md` convention][skill] plus a small extended frontmatter that the picker reads. **No registration step.** Drop the folder in, restart `pnpm dev`, the picker shows it.
4646

4747
### Skill folder layout
4848

4949
```text
50-
src/lib/templates/skills/your-skill/
50+
next/src/lib/templates/skills/your-skill/
5151
├── SKILL.md # required — prompt body + frontmatter
5252
├── example.html # required — what the agent should produce, hand-authored
5353
├── assets/ # optional — fonts, images, reusable CSS, layout fragments
@@ -104,20 +104,20 @@ example_prompt: |
104104
3. **Hard constraints exist and are specific.** Vague directives ("use modern typography") are not constraints. Real ones look like "Inter 96 / 64 / 40 / 24 / 16 px, 8 px grid, max two weights per slide".
105105
4. **No `lorem ipsum`** anywhere in the example. If the example uses placeholder data, it must be plausibly-real placeholder data.
106106
5. **Slug uses ASCII lowercase with dashes**`deck-swiss-international`, `social-x-post-card`. Mirror the 75 existing folders.
107-
6. **If you vendored work from another repo**, the original `LICENSE` and authorship attribution have to ship inside your skill folder. Example: `src/lib/templates/skills/deck-guizang-editorial/LICENSE` preserves the original op7418 license verbatim.
107+
6. **If you vendored work from another repo**, the original `LICENSE` and authorship attribution have to ship inside your skill folder. Example: `next/src/lib/templates/skills/deck-guizang-editorial/LICENSE` preserves the original op7418 license verbatim.
108108

109109
### Picker grouping
110110

111111
The picker organizes skills along two axes. Pick values that already exist where possible — only introduce a new value if your skill genuinely doesn't fit:
112112

113113
- **`mode`**`prototype` · `deck` · `frame` · `social` · `office` · `doc` · `mockup` · `vfx`.
114-
- **`scenario`**`design` · `marketing` · `engineering` · `product` · `finance` · `hr` · `sale` · `personal`.
114+
- **`scenario`**`design` · `marketing` · `engineering` · `product` · `finance` · `hr` · `sales` · `personal` · `operations` · `education` · `creator` · `video`.
115115

116116
---
117117

118118
## Adding a new coding-agent CLI
119119

120-
Hooking up a new agent (e.g. some new shop's `foo-coder` CLI) is one entry in [`src/lib/agents/argv.ts`](src/lib/agents/argv.ts):
120+
Hooking up a new agent (e.g. some new shop's `foo-coder` CLI) is one entry in [`next/src/lib/agents/argv.ts`](next/src/lib/agents/argv.ts):
121121

122122
```ts
123123
{
@@ -133,7 +133,7 @@ Hooking up a new agent (e.g. some new shop's `foo-coder` CLI) is one entry in [`
133133
}
134134
```
135135

136-
That's it. `/api/agents` will detect it on `PATH`, the top-bar picker shows it, the chat path works through the same SSE pipeline. If the CLI emits **typed events** (like Claude Code's `--output-format stream-json`), add a parser in [`src/lib/agents/invoke.ts`](src/lib/agents/invoke.ts) and set `stream: 'claude-stream-json'`.
136+
That's it. `/api/agents` will detect it on `PATH`, the top-bar picker shows it, the chat path works through the same SSE pipeline. If the CLI emits **typed events** (like Claude Code's `--output-format stream-json`), add a parser in [`next/src/lib/agents/invoke.ts`](next/src/lib/agents/invoke.ts) and set `stream: 'claude-stream-json'`.
137137

138138
### Bar for merging an agent adapter
139139

@@ -146,7 +146,7 @@ That's it. `/api/agents` will detect it on `PATH`, the top-bar picker shows it,
146146

147147
## Adding a new export target
148148

149-
Export targets live in two places: a helper under `src/lib/export/` that produces the bytes (string for `.html`, Blob for `.png`, `ClipboardItem` for paste), and a menu entry in [`src/components/drafts-menu.tsx`](src/components/drafts-menu.tsx) that wires it into the UI.
149+
Export targets live in two places: a helper under `next/src/lib/export/` that produces the bytes (string for `.html`, Blob for `.png`, `ClipboardItem` for paste), and a menu entry in [`next/src/components/export-menu.tsx`](next/src/components/export-menu.tsx) that wires it into the UI.
150150

151151
### Bar for merging an export target
152152

@@ -166,8 +166,8 @@ We're not pedantic about formatting (Prettier on save is fine), but two rules ar
166166
Beyond that:
167167

168168
- **Don't narrate.** No `// import the module`, no `// loop through items`. If the code reads obviously, the comment is noise. Save comments for non-obvious intent or constraints the code can't express.
169-
- **TypeScript for `src/`.** No new top-level `.js` files unless there's a compelling reason.
170-
- **No new top-level dependencies** without a paragraph in the PR description on what we get vs. what bytes we ship. The dep list in [`package.json`](package.json) is small on purpose.
169+
- **TypeScript for `next/src/`.** No new top-level `.js` files unless there's a compelling reason.
170+
- **No new top-level dependencies** without a paragraph in the PR description on what we get vs. what bytes we ship. The dep list in [`next/package.json`](next/package.json) is small on purpose.
171171
- **Run `pnpm build`** before pushing structural changes. Type errors block merge.
172172

173173
---
@@ -236,6 +236,6 @@ The repo ships two languages at parity: English (`README.md`, `CONTRIBUTING.md`)
236236

237237
By contributing, you agree your contribution is licensed under the [Apache-2.0 License](LICENSE) of this repository.
238238

239-
Vendored work retains its original license and authorship attribution — see each `src/lib/templates/skills/<skill>/` folder's own `LICENSE` / `README.md` for what it inherits from upstream. The most prominent example is [`src/lib/templates/skills/deck-guizang-editorial/`](src/lib/templates/skills/deck-guizang-editorial/), which retains the original license and authorship attribution to [op7418](https://github.com/op7418).
239+
Vendored work retains its original license and authorship attribution — see each `next/src/lib/templates/skills/<skill>/` folder's own `LICENSE` / `README.md` for what it inherits from upstream. The most prominent example is [`next/src/lib/templates/skills/deck-guizang-editorial/`](next/src/lib/templates/skills/deck-guizang-editorial/), which retains the original license and authorship attribution to [op7418](https://github.com/op7418).
240240

241241
[skill]: https://docs.anthropic.com/en/docs/claude-code/skills

next/src/lib/use-convert.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ function formatMeta(key: string, value: unknown): string {
294294
if (key === "session") return `session = ${value}`;
295295
if (key === "cwd") return `cwd = ${value}`;
296296
if (key === "duration_ms") return `duration = ${value} ms`;
297-
if (key === "cost_usd") return `cost ≈ $${(value as number).toFixed(4)}`;
297+
if (key === "cost_usd" && typeof value === "number") return `cost ≈ $${value.toFixed(4)}`;
298298
if (key === "result") return `result = ${value}`;
299299
if (key === "rate_limit" && value && typeof value === "object") {
300300
const r = value as { status?: string; rateLimitType?: string };

0 commit comments

Comments
 (0)