@pen.dev/cli 0.3.9 → 0.3.10
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/browserAll-DN_YxOXQ.mjs +2 -0
- package/dist/esm-BHQtsEyo.mjs +2 -0
- package/dist/{esm-DBgQcoAH.mjs → esm-BYcFG9-N.mjs} +12 -12
- package/dist/index.mjs +2 -2
- package/dist/init-C4ANyG-9.mjs +2 -0
- package/dist/out/mcp-server-darwin-arm64 +0 -0
- package/dist/out/mcp-server-darwin-x64 +0 -0
- package/dist/out/mcp-server-linux-arm64 +0 -0
- package/dist/out/mcp-server-linux-x64 +0 -0
- package/dist/out/mcp-server-windows-arm64.exe +0 -0
- package/dist/out/mcp-server-windows-x64.exe +0 -0
- package/dist/out/skills/pen-dev/SKILL.md +3 -1
- package/dist/out/skills/pen-dev/pen-schema.md +14 -2
- package/dist/out/skills/pen-dev/whiteboard.md +120 -0
- package/dist/validate-response-DHB60j_7.mjs +3 -0
- package/dist/webworkerAll-FVvp_NgY.mjs +2 -0
- package/package.json +6 -4
- package/dist/browserAll-D_luQzBO.mjs +0 -2
- package/dist/emscripten-module.browser-F76W5DM6-CQ3fNT5V.mjs +0 -5147
- package/dist/emscripten-module.browser-XIKQQPVU-C295tmz_.mjs +0 -2160
- package/dist/esm-D7vjDQPJ.mjs +0 -2
- package/dist/ffi-CUJpv82f.mjs +0 -2
- package/dist/ffi-Cplg1Nas.mjs +0 -2
- package/dist/init-B5EVeDge.mjs +0 -2
- package/dist/validate-response-CezyBuEO.mjs +0 -3
- package/dist/webworkerAll-BPqqt3nL.mjs +0 -2
- /package/dist/{html-BzzLf-XM.mjs → html-C5EUiP3B.mjs} +0 -0
- /package/dist/{module-ES6BEMUI-2G5oIxui.mjs → module-ES6BEMUI-fiUywq2c.mjs} +0 -0
- /package/dist/{module-asyncify-2EFITU5U-CqIYQibj.mjs → module-asyncify-2EFITU5U-Ck30SKgw.mjs} +0 -0
- /package/dist/{standalone-BxPYxoeE.mjs → standalone-D4MlQZsr.mjs} +0 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{C as e,O as t,S as n,_ as r,c as i,d as a,f as o,g as s,h as c,l,m as u,o as d,p as f,s as p,u as m,v as h,w as g}from"./index.mjs";t.add(g),t.add(e),t.add(s),t.add(n),t.add(c),t.add(u),t.add(f),t.add(d),t.add(p),t.add(m),t.add(i),t.add(l),t.add(a),t.add(o),t.add(r),t.add(h);export{};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pen-dev
|
|
3
|
-
description: Create high-quality visual designs — websites, app screens, dashboards, slides, marketing materials, social media graphics on the pen.dev canvas. Use when the task involves generating designs on the canvas.
|
|
3
|
+
description: Create high-quality visual designs — websites, app screens, dashboards, slides, marketing materials, social media graphics on the pen.dev canvas — or use the canvas as a whiteboard to research, plan, and compare with live browser nodes. Use when the task involves generating designs or working out a task on the canvas.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# pen.dev
|
|
@@ -16,6 +16,7 @@ pen.dev is an infinite canvas design tool with nested object hierarchy.
|
|
|
16
16
|
| `generate` | Using the `Generate` function: AI and stock images, SVG artwork, and transforming an image already in the document. | [generate.md](./generate.md) |
|
|
17
17
|
| `components` | Learn how to use components and instances in .pen files. | [components.md](./guide/components.md) |
|
|
18
18
|
| `scripts-and-shaders` | Learn how to use scripts and shaders on the pen.dev canvas. | [scripts-and-shaders.md](./scripts-and-shaders.md) |
|
|
19
|
+
| `whiteboard` | Research, evaluation, and planning work done on the canvas with live `browser` nodes: competitor and vendor comparisons, meeting prep, briefs, schedules. The deliverable is information for the user, not a product design. Required when the user asks you to research, compare, evaluate, plan, or prep something. | [whiteboard.md](./whiteboard.md) |
|
|
19
20
|
| `code` | Generating code from .pen files. | [code.md](./guide/code.md) |
|
|
20
21
|
| `design-system` | Composing screens with design system components. | [design-system.md](./guide/design-system.md) |
|
|
21
22
|
| `landing-page` | Designing landing pages and promotional websites. | [landing-page.md](./guide/landing-page.md) |
|
|
@@ -30,6 +31,7 @@ pen.dev is an infinite canvas design tool with nested object hierarchy.
|
|
|
30
31
|
- Favor copying existing content and updating the copied content later, rather than generating new content.
|
|
31
32
|
- When creating new variables make sure you are not accidentally overwriting any existing design.
|
|
32
33
|
- User may ask for technical modifications like removing, moving, re-ordering, clearing, and copying objects/variables, or just ask questions. Only do what's requested and nothing more.
|
|
34
|
+
- When the user asks you to research, compare, evaluate, plan, or prep something (competitors, vendors, a meeting, a schedule, a trip), the deliverable is information laid out for them, not an app or website about the topic. Read [whiteboard.md](./whiteboard.md) and work with live `browser` nodes instead of designing a product.
|
|
33
35
|
- pen.dev is a collaborative multiplayer environment: the document can change while you work, so the state you remember may be stale. If a node is missing or no longer matches what you expected, re-read instead of recreating it, and don't undo changes the user made in the meantime.
|
|
34
36
|
- When adding more content to a frame make sure the frame has the right layout, or is big enough to fit the new content. Resize the frame if necessary. There is no scrolling and the entire content should always be visible on the canvas.
|
|
35
37
|
- Place components at the top and your screens below, growing to the right and down.
|
|
@@ -32,6 +32,8 @@ export type SizingBehavior = string;
|
|
|
32
32
|
/** Position relative to parent. X right, Y down. IGNORED when parent uses flex layout. */
|
|
33
33
|
export interface Position { x?: number; y?: number; }
|
|
34
34
|
export interface Size { width?: NumberOrVariable | SizingBehavior; height?: NumberOrVariable | SizingBehavior; }
|
|
35
|
+
/** Affine matrix [a, b, c, d, tx, ty]. */
|
|
36
|
+
export type AffineTransform = [number, number, number, number, number, number];
|
|
35
37
|
export type BlendMode = 'normal' | 'darken' | 'multiply' | 'linearBurn' | 'colorBurn' | 'light' | 'screen' | 'linearDodge' | 'colorDodge' | 'overlay' | 'softLight' | 'hardLight' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity';
|
|
36
38
|
export type Fill = ColorOrVariable | {
|
|
37
39
|
type: "color";
|
|
@@ -52,7 +54,17 @@ size?: { width?: NumberOrVariable; height?: NumberOrVariable };
|
|
|
52
54
|
/** Degrees CCW (0° up, 90° left, 180° down). */
|
|
53
55
|
rotation?: NumberOrVariable;
|
|
54
56
|
colors?: { color: ColorOrVariable; position: NumberOrVariable }[];
|
|
55
|
-
} | /** Image fill. URL is relative to the .pen file, e.g. `./image.jpg`. */ {
|
|
57
|
+
} | /** Image fill. URL is relative to the .pen file, e.g. `./image.jpg`. */ {
|
|
58
|
+
type: "image";
|
|
59
|
+
enabled?: BooleanOrVariable;
|
|
60
|
+
blendMode?: BlendMode;
|
|
61
|
+
opacity?: NumberOrVariable;
|
|
62
|
+
url?: string;
|
|
63
|
+
/** Default 'cover'. */
|
|
64
|
+
mode?: "cover" | "contain" | "stretch";
|
|
65
|
+
/** Crops the image. Maps normalized image coordinates (0..1 across its width and height) into the crop's 0..1 box, so [2, 0, 0, 1, -1, 0] is the right half. The mode fits the crop into the shape like a whole image, and cover keeps it inside the image. Defaults to identity, no crop. */
|
|
66
|
+
transform?: AffineTransform;
|
|
67
|
+
} | /** Shader fill. URL points to a WebGL 1.0 (#version 100) fragment shader file, relative to the .pen file, e.g. `./effect.glsl`. Uniforms are described via `@directive` annotations inside block comments in the shader source. A `vec2` uniform annotated with `@resolution` is auto-bound to the fill size in pixels. Other uniforms' user-set values are stored in `uniforms`. */ {
|
|
56
68
|
type: "shader";
|
|
57
69
|
enabled?: BooleanOrVariable;
|
|
58
70
|
blendMode?: BlendMode;
|
|
@@ -211,5 +223,5 @@ export interface Ref extends Entity {
|
|
|
211
223
|
}
|
|
212
224
|
export type Child = Frame | Group | Rectangle | Ellipse | Path | Polygon | Text | Note | Prompt | Context | Icon | Script | Browser | Ref;
|
|
213
225
|
export type IdPath = string;
|
|
214
|
-
export interface Document { version: "2.
|
|
226
|
+
export interface Document { version: "2.20"; themes?: { [key: string /** RegEx: [^:]+ */]: string[] }; imports?: { [key: string]: string /** Value: relative URI of imported .pen file. Key: short alias. */ }; variables?: { [key: string /** RegEx: [^:]+ */]: { type: "boolean"; value: BooleanOrVariable | { value: BooleanOrVariable; theme?: Theme }[] } | { type: "color"; value: ColorOrVariable | { value: ColorOrVariable; theme?: Theme }[] } | { type: "number"; value: NumberOrVariable | { value: NumberOrVariable; theme?: Theme }[] } | { type: "string"; value: StringOrVariable | { value: StringOrVariable; theme?: Theme }[] } }; children: (Frame | Group | Rectangle | Ellipse | Polygon | Path | Text | Note | Context | Prompt | Icon | Script | Browser | Ref)[]; }
|
|
215
227
|
```
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Whiteboarding: research and planning on the canvas
|
|
2
|
+
|
|
3
|
+
Read this when the deliverable is information for the user, not a product. `browser` nodes put real web pages on the canvas, the `browser` tool drives them, and `execute` lays out what you learn next to them. The canvas works like a team whiteboard: the user watches the work happen and keeps the result.
|
|
4
|
+
|
|
5
|
+
## When this applies
|
|
6
|
+
|
|
7
|
+
Whiteboard when the user wants a task done and shown, not a UI designed:
|
|
8
|
+
|
|
9
|
+
- "Research our three main competitors' pricing and put it side by side."
|
|
10
|
+
- "Evaluate these vendors for our CRM migration and recommend one."
|
|
11
|
+
- "Prep me for tomorrow's meeting with Acme: what they do, recent news, who we're meeting."
|
|
12
|
+
- "Find a venue for the 40-person offsite in Berlin in May and draft the agenda."
|
|
13
|
+
- "Summarize what these five articles say about the EU AI Act."
|
|
14
|
+
- "Plan a 4-day trip to Lisbon in October on a 1500 EUR budget."
|
|
15
|
+
|
|
16
|
+
Signals: research, compare, evaluate, plan, prep, find, decide, summarize, shortlist, schedule, budget. No mention of screens, apps, websites, or landing pages.
|
|
17
|
+
|
|
18
|
+
Do NOT design an app, dashboard, or website about the topic. A request to evaluate vendors is not a request for a procurement tool. If it is genuinely unclear, ask one question rather than guess the expensive option.
|
|
19
|
+
|
|
20
|
+
## Building blocks
|
|
21
|
+
|
|
22
|
+
- `browser` node: a live page on the canvas. `Insert(parent, {type: "browser", name, url, width, height})`. The user can scroll, click, and sign in inside it.
|
|
23
|
+
- `browser` tool: pass the node's id as `nodeId`. `load-page` navigates; `return-screenshot` and `return-element` (with a focused `querySelector`) read the page back; `cdp` acts inside it; `screenshot-to-canvas` copies a region into the document.
|
|
24
|
+
- Canvas artifacts: frames, text, tables, `icon` nodes, and `note` nodes (a sticky note with `content`, `width`, `height`).
|
|
25
|
+
- `get_app_state` shows existing browser nodes and the user's selection. If the user already opened a page or picked an element, use it (`target: "selection"`) instead of opening another.
|
|
26
|
+
|
|
27
|
+
The `browser` tool is desktop-only. Elsewhere, browse with whatever tools you have and still build the board as described here.
|
|
28
|
+
|
|
29
|
+
## The loop
|
|
30
|
+
|
|
31
|
+
1. **Brief on the board first.** One `execute`: a root `Board` frame with the title, goal, constraints, and open questions. Keep `placeholder: true` while filling.
|
|
32
|
+
2. **Open sources.** One browser node per source in a `Sources` row, named after the source. Put the query in the URL where the site supports it. Two or three sources at a time.
|
|
33
|
+
3. **Orient, then extract.** `return-screenshot` first. Then `cdp` `Runtime.evaluate` with `returnByValue: true` to pull a structured array (`{name, price, plan, url}`) in one call, or `return-element` on a specific section. Use `Input.dispatchMouseEvent`, `Input.insertText`, and `Input.dispatchKeyEvent` for searches, filters, cookie banners, and pagination; locate targets with `DOM.querySelector` and `DOM.getBoxModel`. A click that navigates returns once the page has loaded.
|
|
34
|
+
4. **Write findings as you go.** After each source, add its results next to it. Partial results are useful; the user is watching.
|
|
35
|
+
5. **Synthesize.** A separate frame with the deliverable: comparison matrix, recommendation, brief, agenda, itinerary. This is what the user reads first.
|
|
36
|
+
6. **Hand back the user's decisions** (budget trade-offs, final pick, dates) as an `Open questions` note. Do not decide for them.
|
|
37
|
+
7. **Verify** with `Get` and `ctx.problems`, one `TakeScreenshot` of the synthesis, then clear `placeholder`.
|
|
38
|
+
|
|
39
|
+
## Rules for the board
|
|
40
|
+
|
|
41
|
+
- Only write what you read on a page. Never invent prices, plans, dates, names, or figures. If a source gave nothing, say so on the board.
|
|
42
|
+
- Every fact carries its source: site name with `href` to the page, plus the date checked for anything that changes (prices, availability, headcount).
|
|
43
|
+
- Separate facts from judgment. Mark estimates and opinions ("est.", "recommended").
|
|
44
|
+
- Keep the browser nodes when done, scrolled to the relevant part. They are the evidence.
|
|
45
|
+
- Readable at canvas zoom: body 14-16px, headings 20-28px, cards 320-480px wide, wrapped text with `textGrowth: "fixed-width"`. Rows and short phrases, not paragraphs.
|
|
46
|
+
- Tables for anything comparable (vendors, plans, options), cards for entities with several attributes (a company, a venue), a column per day or phase for schedules, `note` nodes for caveats and questions.
|
|
47
|
+
- Plain style: light background, one accent color, one font. No style archetypes, hero sections, nav bars, or buttons. No `clip: true`, no fixed screen width; the board grows as `fit_content`.
|
|
48
|
+
- Copy real visuals (a pricing table, a map, a chart from a report) with `screenshot-to-canvas` on a `query` target instead of redrawing them.
|
|
49
|
+
|
|
50
|
+
## Safety and consent
|
|
51
|
+
|
|
52
|
+
- Never log in, enter personal or payment details, purchase, book, sign up, or submit forms on the user's behalf. Stop where the only remaining step is theirs and say so.
|
|
53
|
+
- Browser nodes share one browser session. If a site needs an account, ask the user to sign in inside the node, then continue.
|
|
54
|
+
- Re-read a node before acting in it; the user may have moved on. Do not navigate away from a page they are looking at without saying so.
|
|
55
|
+
- Do not send Escape through `cdp`; the editor intercepts it.
|
|
56
|
+
|
|
57
|
+
## Layout
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
Board (frame, vertical, gap 40, padding 48)
|
|
61
|
+
├── Brief: title, goal, constraints, open questions
|
|
62
|
+
├── Sources (horizontal, gap 32): browser nodes, 640-900 wide, 600-800 tall
|
|
63
|
+
├── Findings (horizontal, gap 32): one column per source or topic
|
|
64
|
+
└── Synthesis (horizontal, gap 24): matrix, recommendation, plan, budget, decisions
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Place boards with `FindEmptySpace` at the document root.
|
|
68
|
+
|
|
69
|
+
## Example: "Compare Linear, Jira, and Shortcut for a 30-person team"
|
|
70
|
+
|
|
71
|
+
Brief and first sources:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
const pos = FindEmptySpace({width: 2400, height: 1600, padding: 120})
|
|
75
|
+
boardId = Insert(document, {type: "frame", name: "Issue tracker evaluation", x: pos.x, y: pos.y, layout: "vertical", gap: 40, padding: 48, fill: "#FAFAF7", placeholder: true})
|
|
76
|
+
briefId = Insert(boardId, {type: "frame", name: "Brief", layout: "vertical", gap: 8, width: 720})
|
|
77
|
+
Insert(briefId, {type: "text", name: "Title", content: "Issue tracker for a 30-person team", fontFamily: "Inter", fontSize: 28, fontWeight: "bold", fill: "#111111"})
|
|
78
|
+
Insert(briefId, {type: "text", name: "Constraints", textGrowth: "fixed-width", width: "fill_container", content: "30 seats · GitHub integration required · SSO preferred · budget under 400 EUR/month", fontFamily: "Inter", fontSize: 15, fill: "#444444"})
|
|
79
|
+
sourcesId = Insert(boardId, {type: "frame", name: "Sources", gap: 32})
|
|
80
|
+
linearId = Insert(sourcesId, {type: "browser", name: "Linear pricing", url: "https://linear.app/pricing", width: 800, height: 700})
|
|
81
|
+
jiraId = Insert(sourcesId, {type: "browser", name: "Jira pricing", url: "https://www.atlassian.com/software/jira/pricing", width: 800, height: 700})
|
|
82
|
+
findingsId = Insert(boardId, {type: "frame", name: "Findings", gap: 32})
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Extract the plans as data:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{"action": "cdp", "nodeId": "<linearId>", "method": "Runtime.evaluate", "params": {"returnByValue": true, "expression": "[...document.querySelectorAll('h3')].map(h => ({name: h.innerText.trim(), price: h.parentElement?.innerText.match(/\\$\\d+[^\\n]*/)?.[0] ?? '', sso: /SSO|SAML/i.test(h.parentElement?.innerText ?? '')}))"}}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Write the findings in the next `execute`, transcribing the values you just read into a literal array, then cite the source:
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
const plans = [
|
|
95
|
+
{name: "Free", seat: "$0", total: "$0", sso: "No"},
|
|
96
|
+
{name: "Basic", seat: "$8", total: "$240", sso: "No"},
|
|
97
|
+
{name: "Business", seat: "$14", total: "$420", sso: "Yes"},
|
|
98
|
+
]
|
|
99
|
+
const row = (parent, cells, bold) => {
|
|
100
|
+
const r = Insert(parent, {type: "frame", name: "Row", gap: 16, width: "fill_container", padding: [8, 0]})
|
|
101
|
+
for (const [i, c] of cells.entries()) Insert(r, {type: "text", name: c, content: c, textGrowth: "fixed-width", width: i === 0 ? 160 : 140, fontFamily: "Inter", fontSize: 14, fontWeight: bold ? "bold" : "normal", fill: "#111111"})
|
|
102
|
+
}
|
|
103
|
+
linearColId = Insert(findingsId, {type: "frame", name: "Linear", layout: "vertical", gap: 4, width: 620, placeholder: true})
|
|
104
|
+
Insert(linearColId, {type: "text", name: "Heading", content: "Linear", fontFamily: "Inter", fontSize: 20, fontWeight: "bold", fill: "#111111"})
|
|
105
|
+
row(linearColId, ["Plan", "Per seat", "30 seats", "SSO"], true)
|
|
106
|
+
for (const p of plans) row(linearColId, [p.name, p.seat, p.total, p.sso])
|
|
107
|
+
Insert(linearColId, {type: "text", name: "Source", content: "linear.app/pricing, checked 28 Sep 2026", href: "https://linear.app/pricing", fontFamily: "Inter", fontSize: 12, fill: "#777777"})
|
|
108
|
+
Update(linearColId, {placeholder: false})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Finish with the synthesis: a comparison matrix across all three, a recommendation card with the reasoning, a monthly cost line, and an `Open questions` note. Screenshot the synthesis and clear the board's `placeholder`.
|
|
112
|
+
|
|
113
|
+
## Antipatterns
|
|
114
|
+
|
|
115
|
+
- Designing a product about the topic.
|
|
116
|
+
- Filling cards with plausible data you did not read on a page.
|
|
117
|
+
- Dumping raw DOM or whole result lists. Extract, select, then write the rows that matter.
|
|
118
|
+
- Holding everything for one final `execute`. The board should grow as you work.
|
|
119
|
+
- Deleting the browser nodes once you have the numbers.
|
|
120
|
+
- Purchasing, booking, signing up, or submitting anything.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{$ as e,Q as t,U as n,W as r,X as i,Z as a,it as o,nt as s,rt as c,tt as l}from"./index.mjs";var u=class e extends o{constructor(e){super(),this.typeUrl=``,this.value=new Uint8Array,s.util.initPartial(e,this)}toJson(e){if(this.typeUrl===``)return{};let t=this.typeUrlToName(this.typeUrl),n=(e?.typeRegistry)?.findMessage(t);if(!n)throw Error(`cannot encode message google.protobuf.Any to JSON: "${this.typeUrl}" is not in the type registry`);let r=n.fromBinary(this.value).toJson(e);return(t.startsWith(`google.protobuf.`)||r===null||Array.isArray(r)||typeof r!=`object`)&&(r={value:r}),r[`@type`]=this.typeUrl,r}fromJson(e,t){if(e===null||Array.isArray(e)||typeof e!=`object`)throw Error(`cannot decode message google.protobuf.Any from JSON: expected object but got ${e===null?`null`:Array.isArray(e)?`array`:typeof e}`);if(Object.keys(e).length==0)return this;let n=e[`@type`];if(typeof n!=`string`||n==``)throw Error(`cannot decode message google.protobuf.Any from JSON: "@type" is empty`);let r=this.typeUrlToName(n),i=(t?.typeRegistry)?.findMessage(r);if(!i)throw Error(`cannot decode message google.protobuf.Any from JSON: ${n} is not in the type registry`);let a;if(r.startsWith(`google.protobuf.`)&&Object.prototype.hasOwnProperty.call(e,`value`))a=i.fromJson(e.value,t);else{let n=Object.assign({},e);delete n[`@type`],a=i.fromJson(n,t)}return this.packFrom(a),this}packFrom(e){this.value=e.toBinary(),this.typeUrl=this.typeNameToUrl(e.getType().typeName)}unpackTo(e){return this.is(e.getType())?(e.fromBinary(this.value),!0):!1}unpack(e){if(this.typeUrl===``)return;let t=e.findMessage(this.typeUrlToName(this.typeUrl));if(t)return t.fromBinary(this.value)}is(e){if(this.typeUrl===``)return!1;let t=this.typeUrlToName(this.typeUrl),n=``;return n=typeof e==`string`?e:e.typeName,t===n}typeNameToUrl(e){return`type.googleapis.com/${e}`}typeUrlToName(e){if(!e.length)throw Error(`invalid type url: ${e}`);let t=e.lastIndexOf(`/`),n=t>=0?e.substring(t+1):e;if(!n.length)throw Error(`invalid type url: ${e}`);return n}static pack(t){let n=new e;return n.packFrom(t),n}static fromBinary(t,n){return new e().fromBinary(t,n)}static fromJson(t,n){return new e().fromJson(t,n)}static fromJsonString(t,n){return new e().fromJsonString(t,n)}static equals(t,n){return s.util.equals(e,t,n)}};u.runtime=s,u.typeName=`google.protobuf.Any`,u.fields=s.util.newFieldList(()=>[{no:1,name:`type_url`,kind:`scalar`,T:9},{no:2,name:`value`,kind:`scalar`,T:12}]);function ee(e){let t;return t=typeof e==`object`&&`getType`in e?e.toBinary():typeof e==`string`?new TextEncoder().encode(e):e instanceof Uint8Array?e:new Uint8Array(e),c.enc(t).replace(/=+$/,``)}function te(t,n,r){try{let e=c.dec(t);return n?n.fromBinary(e,r):e}catch(t){throw i.from(t,e.DataLoss)}}function d(...e){let t=new Headers;for(let n of e)n.forEach((e,n)=>{t.append(n,e)});return t}function f(...e){let t=new AbortController,n=e.filter(e=>e!==void 0).concat(t.signal);for(let e of n){if(e.aborted){r.apply(e);break}e.addEventListener(`abort`,r)}function r(){t.signal.aborted||t.abort(m(this));for(let e of n)e.removeEventListener(`abort`,r)}return t}function p(t){let n=new AbortController,r=()=>{n.abort(new i(`the operation timed out`,e.DeadlineExceeded))},a;return t!==void 0&&(t<=0?r():a=setTimeout(r,t)),{signal:n.signal,cleanup:()=>clearTimeout(a)}}function m(e){if(!e.aborted)return;if(e.reason!==void 0)return e.reason;let t=Error(`This operation was aborted`);return t.name=`AbortError`,t}function ne(){return{get(e){return e.id in this?this[e.id]:e.defaultValue},set(e,t){return this[e.id]=t,this},delete(e){return delete this[e.id],this}}}const re=128;function h(e){let t=new Headers,n=new TextDecoder().decode(e).split(`\r
|
|
3
|
+
`);for(let e of n){if(e===``)continue;let n=e.indexOf(`:`);if(n>0){let r=e.substring(0,n).trim(),i=e.substring(n+1).trim();t.append(r,i)}}return t}function ie(e){let t=[];return e.forEach((e,n)=>{t.push(`${n}: ${e}\r\n`)}),new TextEncoder().encode(t.join(``))}function ae(){return{serialize:ie,parse:h}}const g=`Content-Type`,_=`Grpc-Encoding`,v=`Grpc-Accept-Encoding`,y=`Grpc-Timeout`,b=`Grpc-Status`,x=`Grpc-Message`,S=`Grpc-Status-Details-Bin`,C=`User-Agent`,w=`X-User-Agent`,oe=/^application\/grpc-web(-text)?(?:\+(?:(json)(?:; ?charset=utf-?8)?|proto))?$/i,T=`application/grpc-web+proto`,E=`application/grpc-web+json`;function se(e){let t=e?.match(oe);if(t)return{text:!!t[1],binary:!t[2]}}var D=class e extends o{constructor(e){super(),this.code=0,this.message=``,this.details=[],s.util.initPartial(e,this)}static fromBinary(t,n){return new e().fromBinary(t,n)}static fromJson(t,n){return new e().fromJson(t,n)}static fromJsonString(t,n){return new e().fromJsonString(t,n)}static equals(t,n){return s.util.equals(e,t,n)}};D.runtime=s,D.typeName=`google.rpc.Status`,D.fields=s.util.newFieldList(()=>[{no:1,name:`code`,kind:`scalar`,T:5},{no:2,name:`message`,kind:`scalar`,T:9},{no:3,name:`details`,kind:`message`,T:u,repeated:!0}]);const ce=`0`;function le(e,t){if(t){if(e.set(b,t.code.toString(10)),e.set(x,encodeURIComponent(t.rawMessage)),t.details.length>0){let n=new D({code:t.code,message:t.rawMessage,details:t.details.map(e=>`getType`in e?u.pack(e):new u({typeUrl:`type.googleapis.com/${e.type}`,value:e.value}))});e.set(S,ee(n))}}else e.set(b,`0`);return e}function O(t){let n=t.get(S);if(n!=null){let e=te(n,D);if(e.code==0)return;let r=new i(e.message,e.code,t);return r.details=e.details.map(e=>({type:e.typeUrl.substring(e.typeUrl.lastIndexOf(`/`)+1),value:e.value})),r}let r=t.get(b);if(r!=null){if(r===`0`)return;let n=parseInt(r,10);return n in e?new i(decodeURIComponent(t.get(x)??``),n,t):new i(`invalid grpc-status: ${r}`,e.Internal,t)}}function ue(e,t,n){let r=typeof t==`string`?t:t.typeName,i=typeof n==`string`?n:n.name;return e.toString().replace(/\/?$/,`/${r}/${i}`)}function k(e,t){return t instanceof e?t:new e(t)}function A(e,t){function n(t){return t.done===!0?t:{done:t.done,value:k(e,t.value)}}return{[Symbol.asyncIterator](){let e=t[Symbol.asyncIterator](),r={next:()=>e.next().then(n)};return e.throw!==void 0&&(r.throw=t=>e.throw(t).then(n)),e.return!==void 0&&(r.return=t=>e.return(t).then(n)),r}}}function j(e,t){return t?.concat().reverse().reduce((e,t)=>t(e),e)??e}function M(e){let t=Object.assign({},e);return t.ignoreUnknownFields??=!0,t}function de(e,t,n,r){let i=N(P(e.I,t),r),a=N(F(e.I,n),r),o=N(P(e.O,t),r),s=N(F(e.O,n),r);return{getI(e){return e?i:a},getO(e){return e?o:s}}}function fe(e,t,n,r){let i=t?P(e.I,r):F(e.I,n);return{parse:(t?P(e.O,r):F(e.O,n)).parse,serialize:i.serialize}}function N(e,t){return{serialize(n){let i=e.serialize(n);return r(t.writeMaxBytes,i.byteLength),i},parse(r){return n(t.readMaxBytes,r.byteLength,!0),e.parse(r)}}}function P(t,n){return{parse(r){try{return t.fromBinary(r,n)}catch(t){throw new i(`parse binary: ${t instanceof Error?t.message:String(t)}`,e.Internal)}},serialize(t){try{return t.toBinary(n)}catch(t){throw new i(`serialize binary: ${t instanceof Error?t.message:String(t)}`,e.Internal)}}}}function F(t,n){let r=n?.textEncoder??new TextEncoder,a=n?.textDecoder??new TextDecoder,o=M(n);return{parse(n){try{let e=a.decode(n);return t.fromJsonString(e,o)}catch(t){throw i.from(t,e.InvalidArgument)}},serialize(t){try{let e=t.toJsonString(o);return r.encode(e)}catch(t){throw i.from(t,e.Internal)}}}}const pe=/^application\/(connect\+)?(?:(json)(?:; ?charset=utf-?8)?|(proto))$/i,me=/^application\/(?:json(?:; ?charset=utf-?8)?|proto)$/i,he=/^application\/connect\+?(?:json(?:; ?charset=utf-?8)?|proto)$/i,I=`application/proto`,L=`application/json`,R=`application/connect+proto`,z=`application/connect+json`;function B(e){let t=e?.match(pe);if(t)return{stream:!!t[1],binary:!!t[3]}}function ge(e){switch(e){case`proto`:return{stream:!1,binary:!0};case`json`:return{stream:!1,binary:!1};default:return}}var _e=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols==`function`)for(var i=0,r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]]);return n};function V(e,t,n){if(t&&new Headers(t).forEach((e,t)=>n.metadata.append(t,e)),typeof e!=`object`||!e||Array.isArray(e))throw n;let r=n.code;`code`in e&&typeof e.code==`string`&&(r=a(e.code)??r);let o=e.message;if(o!=null&&typeof o!=`string`)throw n;let s=new i(o??``,r,t);if(`details`in e&&Array.isArray(e.details))for(let t of e.details){if(typeof t!=`object`||!t||Array.isArray(t)||typeof t.type!=`string`||typeof t.value!=`string`)throw n;try{s.details.push({type:t.type,value:c.dec(t.value),debug:t.debug})}catch{throw n}}return s}function ve(e,t,n){let r;try{r=JSON.parse(new TextDecoder().decode(e))}catch{throw n}return V(r,t,n)}function H(e,n){let r={code:t(e.code)};return e.rawMessage.length>0&&(r.message=e.rawMessage),e.details.length>0&&(r.details=e.details.map(e=>{if(`getType`in e){let t={type:e.getType().typeName,value:e.toBinary()};try{t.debug=e.toJson(n)}catch{}return t}return e}).map(e=>{var{value:t}=e,n=_e(e,[`value`]);return Object.assign(Object.assign({},n),{value:c.enc(t).replace(/=+$/,``)})})),r}function ye(t,n){let r=new TextEncoder;try{let e=H(t,n),i=JSON.stringify(e);return r.encode(i)}catch(t){throw new i(`failed to serialize Connect Error: ${t instanceof Error?t.message:String(t)}`,e.Internal)}}const be=2;function U(t){let n=new i(`invalid end stream`,e.Unknown),r;try{r=JSON.parse(typeof t==`string`?t:new TextDecoder().decode(t))}catch{throw n}if(typeof r!=`object`||!r||Array.isArray(r))throw n;let a=new Headers;if(`metadata`in r){if(typeof r.metadata!=`object`||r.metadata==null||Array.isArray(r.metadata))throw n;for(let[e,t]of Object.entries(r.metadata)){if(!Array.isArray(t)||t.some(e=>typeof e!=`string`))throw n;for(let n of t)a.append(e,n)}}return{metadata:a,error:`error`in r&&r.error!=null?V(r.error,a,n):void 0}}function xe(e,t,n){let r={};t!==void 0&&(r.error=H(t,n),e=d(e,t.metadata));let i=!1,a={};return e.forEach((e,t)=>{i=!0,a[t]=[e]}),i&&(r.metadata=a),r}function Se(t){let n=new TextEncoder;return{serialize(r){try{let e=xe(r.metadata,r.error,t),i=JSON.stringify(e);return n.encode(i)}catch(t){throw new i(`failed to serialize EndStreamResponse: ${t instanceof Error?t.message:String(t)}`,e.Internal)}},parse(t){try{return U(t)}catch(t){throw new i(`failed to parse EndStreamResponse: ${t instanceof Error?t.message:String(t)}`,e.InvalidArgument)}}}}const W=`Content-Type`,G=`Content-Length`,K=`Content-Encoding`,q=`Connect-Content-Encoding`,J=`Accept-Encoding`,Y=`Connect-Accept-Encoding`,X=`Connect-Timeout-Ms`,Z=`Connect-Protocol-Version`,Q=`User-Agent`;function Ce(t){switch(t){case 400:return e.Internal;case 401:return e.Unauthenticated;case 403:return e.PermissionDenied;case 404:return e.Unimplemented;case 429:return e.Unavailable;case 502:return e.Unavailable;case 503:return e.Unavailable;case 504:return e.Unavailable;default:return e.Unknown}}function we(t){switch(t){case e.Canceled:return 499;case e.Unknown:return 500;case e.InvalidArgument:return 400;case e.DeadlineExceeded:return 504;case e.NotFound:return 404;case e.AlreadyExists:return 409;case e.PermissionDenied:return 403;case e.ResourceExhausted:return 429;case e.FailedPrecondition:return 400;case e.Aborted:return 409;case e.OutOfRange:return 400;case e.Unimplemented:return 501;case e.Internal:return 500;case e.Unavailable:return 503;case e.DataLoss:return 500;case e.Unauthenticated:return 401;default:return 500}}const $=`connect`,Te=`encoding`,Ee=`compression`,De=`base64`,Oe=`message`;function ke(e){let t=new Headers,n=new Headers;return e.forEach((e,r)=>{r.toLowerCase().startsWith(`trailer-`)?n.append(r.substring(8),e):t.append(r,e)}),[t,n]}function Ae(e,t){let n=new Headers(e);return t.forEach((e,t)=>{n.append(`trailer-${t}`,e)}),n}function je(t){let n=t.get(Z);if(n===null)throw new i(`missing required header: set ${Z} to "1"`,e.InvalidArgument);if(n!==`1`)throw new i(`${Z} must be "1": got "${n}"`,e.InvalidArgument)}function Me(t){let n=t.get($);if(n===null)throw new i(`missing required parameter: set ${$} to "v1"`,e.InvalidArgument);if(n!==`v1`)throw new i(`${$} must be "v1": got "${n}"`,e.InvalidArgument)}function Ne(e,t,n,r,i){let a=new Headers(r??{});return n!==void 0&&a.set(X,`${n}`),a.set(W,e==l.Unary?t?I:L:t?R:z),a.set(Z,`1`),i&&!a.has(Q)&&a.set(Q,`connect-es/1.7.0`),a}function Pe(e,t,n,r,i,a,o){let s=Ne(e,t,n,r,o);if(a!=null){let t=e==l.Unary?K:q;s.set(t,a.name)}if(i.length>0){let t=e==l.Unary?J:Y;s.set(t,i.map(e=>e.name).join(`,`))}return s}function Fe(t,n,r,a){let o=a.get(W),s=B(o);if(r!==200){let e=new i(`HTTP ${r}`,Ce(r),a);if(t==l.Unary&&s&&!s.binary)return{isUnaryError:!0,unaryError:e};throw e}let c={binary:n,stream:t!==l.Unary};if(s?.binary!==c.binary||s.stream!==c.stream)throw new i(`unsupported content type ${o}`,s===void 0?e.Unknown:e.Internal,a);return{isUnaryError:!1}}function Ie(t,n,r,a,o){let s,c=o.get(t==l.Unary?K:q);if(c!=null&&c.toLowerCase()!==`identity`&&(s=n.find(e=>e.name===c),!s))throw new i(`unsupported response encoding "${c}"`,e.Internal,o);return Object.assign({compression:s},Fe(t,r,a,o))}function Le(e,t){return t?c.enc(e).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``):encodeURIComponent(new TextDecoder().decode(e))}function Re(e,t,n){let r=`?connect=v1`,i=e.header.get(W);i?.indexOf(`application/`)===0&&(r+=`&encoding=`+encodeURIComponent(i.slice(12)));let a=e.header.get(K);a!==null&&a!==`identity`&&(r+=`&compression=`+encodeURIComponent(a),n=!0),n&&(r+=`&base64=1`),r+=`&message=`+Le(t,n);let o=e.url+r,s=new Headers(e.header);return[Z,W,G,K,J].forEach(e=>s.delete(e)),Object.assign(Object.assign({},e),{init:Object.assign(Object.assign({},e.init),{method:`GET`}),url:o,header:s})}function ze(e){let t=j(e.next,e.interceptors),[n,r,i]=Ve(e);return t(Object.assign(Object.assign({},e.req),{message:k(e.req.method.I,e.req.message),signal:n})).then(e=>(i(),e),r)}function Be(e){let t=j(e.next,e.interceptors),[n,r,i]=Ve(e),a=Object.assign(Object.assign({},e.req),{message:A(e.req.method.I,e.req.message),signal:n}),o=!1;return n.addEventListener(`abort`,function(){var t,n;let r=e.req.message[Symbol.asyncIterator]();o||(t=r.throw)==null||t.call(r,this.reason).catch(()=>{}),(n=r.return)==null||n.call(r).catch(()=>{})}),t(a).then(e=>Object.assign(Object.assign({},e),{message:{[Symbol.asyncIterator](){let t=e.message[Symbol.asyncIterator]();return{next(){return t.next().then(e=>(e.done==1&&(o=!0,i()),e),r)}}}}}),r)}function Ve(e){let{signal:t,cleanup:n}=p(e.timeoutMs),r=f(e.signal,t);return[r.signal,function(e){let a=i.from(t.aborted?m(t):e);return r.abort(a),n(),Promise.reject(a)},function(){n(),r.abort()}]}function He(t,n){let r=O(t);if(r)throw n.forEach((e,t)=>{r.metadata.append(t,e)}),r;if(!n.has(b)&&!t.has(b))throw new i(`protocol error: missing status`,e.Internal)}function Ue(e,t,n,r){let i=new Headers(n??{});i.set(g,e?T:E),i.set(`X-Grpc-Web`,`1`);let a=i.get(C)??i.get(w)??`connect-es/1.7.0`;return i.set(w,a),r&&i.set(C,a),t!==void 0&&i.set(y,`${t}m`),i}function We(e,t,n,r,i,a){let o=Ue(e,t,n,a);return i!=null&&o.set(_,i.name),r.length>0&&o.set(v,r.map(e=>e.name).join(`,`)),o}function Ge(t){switch(t){case 400:return e.Internal;case 401:return e.Unauthenticated;case 403:return e.PermissionDenied;case 404:return e.Unimplemented;case 429:return e.Unavailable;case 502:return e.Unavailable;case 503:return e.Unavailable;case 504:return e.Unavailable;default:return e.Unknown}}function Ke(e,t){if(e>=200&&e<300)return{foundStatus:t.has(b),headerError:O(t)};throw new i(decodeURIComponent(t.get(x)??`HTTP ${e}`),Ge(e),t)}function qe(t,n,r){let{foundStatus:a,headerError:o}=Ke(n,r),s,c=r.get(_);if(c!==null&&c.toLowerCase()!==`identity`&&(s=t.find(e=>e.name===c),!s))throw new i(`unsupported response encoding "${c}"`,e.Internal,r);return{foundStatus:a,compression:s,headerError:o}}export{le as $,Se as A,I as B,W as C,J as D,X as E,ye as F,de as G,B as H,z as I,k as J,M as K,R as L,U as M,V as N,G as O,ve as P,ce as Q,he as R,we as S,q as T,ge as U,me as V,fe as W,ue as X,A as Y,O as Z,Ae as _,d as _t,We as a,g as at,Te as b,ze as c,y as ct,Ie as d,re as dt,E as et,Ne as f,h as ft,ke as g,m as gt,Me as h,f as ht,Ue as i,v as it,be as j,K as k,Re as l,C as lt,je as m,p as mt,qe as n,oe as nt,He as o,_ as ot,Pe as p,ne as pt,j as q,Ge as r,se as rt,Be as s,b as st,Ke as t,T as tt,Fe as u,ae as ut,De as v,Y as w,Oe as x,Ee as y,L as z};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pen.dev/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"description": "CLI tool for running the pen.dev AI agent manipulating .pen design files",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -35,11 +35,13 @@
|
|
|
35
35
|
"author": "High Agency, Inc.",
|
|
36
36
|
"license": "UNLICENSED",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@anthropic-ai/claude-agent-sdk": "^0.3.
|
|
39
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
38
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.284",
|
|
39
|
+
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
40
40
|
"@inquirer/prompts": "^8.3.0",
|
|
41
|
+
"@jitl/quickjs-wasmfile-release-asyncify": "^0.32.0",
|
|
42
|
+
"@jitl/quickjs-wasmfile-release-sync": "^0.32.0",
|
|
41
43
|
"@node-ipc/node-ipc": "^11.0.3",
|
|
42
|
-
"@openai/codex-sdk": "^0.
|
|
44
|
+
"@openai/codex-sdk": "^0.159.2",
|
|
43
45
|
"eventemitter3": "^5.0.1",
|
|
44
46
|
"semver": "^7.7.4",
|
|
45
47
|
"sharp": "^0.34.5",
|