Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .github/workflows/cli-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- name: Install
run: pnpm install --frozen-lockfile

- name: Lint (TypeScript)
- name: Lint
run: |
pnpm --filter @autodraw/core run lint
pnpm --filter @maelstromlab/autodraw run lint
Expand All @@ -55,8 +55,5 @@ jobs:
- name: Test @maelstromlab/autodraw
run: pnpm --filter @maelstromlab/autodraw run test

- name: Build @autodraw/core
run: pnpm --filter @autodraw/core run build

- name: Build @maelstromlab/autodraw
run: pnpm --filter @maelstromlab/autodraw run build
4 changes: 4 additions & 0 deletions .github/workflows/web-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ jobs:
- name: Install
run: pnpm install --frozen-lockfile

# @autodraw/core resolves to dist/; astro check needs it (see AGENTS.md).
- name: Build @autodraw/core
run: pnpm --filter @autodraw/core run build

- name: Format
run: pnpm --filter web format

Expand Down
6 changes: 3 additions & 3 deletions apps/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
"prepublishOnly": "pnpm run build",
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsup && oclif manifest",
"postpack": "oclif manifest",
"lint": "tsc -p tsconfig.json --noEmit",
"typecheck": "tsc -p tsconfig.json --noEmit",
"test": "vitest run"
"lint": "pnpm --filter @autodraw/core run build && tsc -p tsconfig.json --noEmit",
"typecheck": "pnpm --filter @autodraw/core run build && tsc -p tsconfig.json --noEmit",
"test": "pnpm --filter @autodraw/core run build && vitest run"
},
"dependencies": {
"@oclif/core": "^4.2.10",
Expand Down
8 changes: 3 additions & 5 deletions apps/editor/src/editor/onboarding/AgentGetStartedPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Self-contained styling so it reads clearly inside the onboarding dialog and on any canvas theme.
*/

import { Bot, Copy } from "lucide-react";
import { Bot, Clipboard, ClipboardCheck } from "lucide-react";
import type { CSSProperties, ReactNode } from "react";
import { useCallback, useState } from "react";
import * as SimpleIcons from "simple-icons";
Expand Down Expand Up @@ -148,11 +148,9 @@ function CopyableRow({ row }: { row: AgentGetStartedCopyRow }) {
aria-label={done ? "Copied" : `Copy: ${row.id}`}
>
{done ? (
<span className="font-mono text-[10px] font-medium uppercase tracking-wide text-emerald-400">
Copied
</span>
<ClipboardCheck className="size-4 text-emerald-400" strokeWidth={2.25} aria-hidden />
) : (
<Copy className="size-4" strokeWidth={2.25} aria-hidden />
<Clipboard className="size-4" strokeWidth={2.25} aria-hidden />
)}
</button>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/editor/src/editor/onboarding/OnboardingDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function OnboardingDialog() {
>
<DialogContent
className="flex w-[calc(100%-2rem)] max-w-2xl flex-col gap-0 border-0 bg-transparent p-3 shadow-none sm:max-w-2xl"
hideClose={false}
hideClose
>
<DialogTitle className="sr-only">Connect your agent</DialogTitle>
<ConnectStep onDone={close} />
Expand Down
58 changes: 45 additions & 13 deletions apps/web/worker/diagramService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,11 @@ async function createDiagram(request: Request, env: AutodrawWorkerEnv): Promise<
const tokenHash = await sha256Hex(editToken);
const createdAt = new Date().toISOString();

await env.DIAGRAMS!.put(r2Key(id), text, {
const bucket = env.DIAGRAMS;
if (!bucket) {
return errorResponse("Diagram storage not configured", 503);
}
await bucket.put(r2Key(id), text, {
httpMetadata: { contentType: "application/json; charset=utf-8" },
customMetadata: { editTokenHash: tokenHash, createdAt },
});
Expand All @@ -139,7 +143,11 @@ async function createDiagram(request: Request, env: AutodrawWorkerEnv): Promise<
}

async function getDiagram(env: AutodrawWorkerEnv, id: string): Promise<Response> {
const obj = await env.DIAGRAMS!.get(r2Key(id));
const bucket = env.DIAGRAMS;
if (!bucket) {
return errorResponse("Diagram storage not configured", 503);
}
const obj = await bucket.get(r2Key(id));
if (!obj) {
return errorResponse("Not found", 404);
}
Expand All @@ -162,7 +170,11 @@ async function putDiagram(request: Request, env: AutodrawWorkerEnv, id: string):
);
}

const head = await env.DIAGRAMS!.head(r2Key(id));
const bucket = env.DIAGRAMS;
if (!bucket) {
return errorResponse("Diagram storage not configured", 503);
}
const head = await bucket.head(r2Key(id));
if (!head) {
return errorResponse("Not found", 404);
}
Expand All @@ -188,7 +200,7 @@ async function putDiagram(request: Request, env: AutodrawWorkerEnv, id: string):
}

const createdAt = head.customMetadata?.createdAt ?? new Date().toISOString();
await env.DIAGRAMS!.put(r2Key(id), text, {
await bucket.put(r2Key(id), text, {
httpMetadata: { contentType: "application/json; charset=utf-8" },
customMetadata: { editTokenHash: tokenHash, createdAt },
});
Expand All @@ -205,7 +217,11 @@ async function deleteDiagram(
if (!token) {
return errorResponse("Missing edit token", 401);
}
const head = await env.DIAGRAMS!.head(r2Key(id));
const bucket = env.DIAGRAMS;
if (!bucket) {
return errorResponse("Diagram storage not configured", 503);
}
const head = await bucket.head(r2Key(id));
if (!head) {
return errorResponse("Not found", 404);
}
Expand All @@ -214,7 +230,7 @@ async function deleteDiagram(
if (!expected || tokenHash !== expected) {
return errorResponse("Invalid edit token", 403);
}
await env.DIAGRAMS!.delete(r2Key(id));
await bucket.delete(r2Key(id));
return jsonResponse({ ok: true });
}

Expand All @@ -228,7 +244,11 @@ export async function loadDiagramJson(
if (!diagramStorageConfigured(env)) {
return { ok: false, error: "Diagram storage not configured", status: 503 };
}
const head = await env.DIAGRAMS!.head(r2Key(id));
const bucket = env.DIAGRAMS;
if (!bucket) {
return { ok: false, error: "Diagram storage not configured", status: 503 };
}
const head = await bucket.head(r2Key(id));
if (!head) {
return { ok: false, error: "Not found", status: 404 };
}
Expand All @@ -242,7 +262,7 @@ export async function loadDiagramJson(
return { ok: false, error: "Invalid edit token", status: 403 };
}
}
const obj = await env.DIAGRAMS!.get(r2Key(id));
const obj = await bucket.get(r2Key(id));
if (!obj) {
return { ok: false, error: "Not found", status: 404 };
}
Expand All @@ -258,7 +278,11 @@ export async function saveDiagramJson(
if (!diagramStorageConfigured(env)) {
return { ok: false, error: "Diagram storage not configured", status: 503 };
}
const head = await env.DIAGRAMS!.head(r2Key(id));
const bucket = env.DIAGRAMS;
if (!bucket) {
return { ok: false, error: "Diagram storage not configured", status: 503 };
}
const head = await bucket.head(r2Key(id));
if (!head) {
return { ok: false, error: "Not found", status: 404 };
}
Expand All @@ -276,7 +300,7 @@ export async function saveDiagramJson(
}
const normalized = serializeDiagram(doc);
const createdAt = head.customMetadata?.createdAt ?? new Date().toISOString();
await env.DIAGRAMS!.put(r2Key(id), normalized, {
await bucket.put(r2Key(id), normalized, {
httpMetadata: { contentType: "application/json; charset=utf-8" },
customMetadata: { editTokenHash: tokenHash, createdAt },
});
Expand Down Expand Up @@ -304,7 +328,11 @@ export async function createDiagramFromObject(
const editToken = newEditToken();
const tokenHash = await sha256Hex(editToken);
const createdAt = new Date().toISOString();
await env.DIAGRAMS!.put(r2Key(id), text, {
const bucket = env.DIAGRAMS;
if (!bucket) {
return { ok: false, error: "Diagram storage not configured", status: 503 };
}
await bucket.put(r2Key(id), text, {
httpMetadata: { contentType: "application/json; charset=utf-8" },
customMetadata: { editTokenHash: tokenHash, createdAt },
});
Expand All @@ -319,7 +347,11 @@ export async function deleteDiagramByToken(
if (!diagramStorageConfigured(env)) {
return { ok: false, error: "Diagram storage not configured", status: 503 };
}
const head = await env.DIAGRAMS!.head(r2Key(id));
const bucket = env.DIAGRAMS;
if (!bucket) {
return { ok: false, error: "Diagram storage not configured", status: 503 };
}
const head = await bucket.head(r2Key(id));
if (!head) {
return { ok: false, error: "Not found", status: 404 };
}
Expand All @@ -328,6 +360,6 @@ export async function deleteDiagramByToken(
if (!expected || tokenHash !== expected) {
return { ok: false, error: "Invalid edit token", status: 403 };
}
await env.DIAGRAMS!.delete(r2Key(id));
await bucket.delete(r2Key(id));
return { ok: true };
}
1 change: 0 additions & 1 deletion apps/web/worker/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { withCors } from "./cors.js";
import { handleDiagramApi } from "./diagramService.js";
import { handleMcpRequest } from "./mcpHandler.js";
import type { AutodrawWorkerEnv, ExecutionContext } from "./types.js";
Expand Down
2 changes: 1 addition & 1 deletion apps/web/worker/mcpHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from "@autodraw/core";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
import { CfWorkerJsonSchemaValidator } from "@modelcontextprotocol/sdk/validation/cfworker.js";
import { CfWorkerJsonSchemaValidator } from "@modelcontextprotocol/sdk/validation/cfworker";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { corsOptionsResponse, withCors } from "./cors.js";
import {
Expand Down
5 changes: 5 additions & 0 deletions apps/web/worker/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/** Static assets binding (Workers + Assets). */
export interface Fetcher {
fetch(input: Request | string, init?: RequestInit): Promise<Response>;
}

/** Minimal R2 typing for the diagram Worker (no `@cloudflare/workers-types` required for `astro check`). */
export interface R2Object {
customMetadata?: Record<string, string>;
Expand Down
Loading