Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8b67fd2
feat(canvas): build and securely deliver cloud artifacts
k11kirky Aug 3, 2026
623ab63
refactor(canvas): first-class canvases over the new PostHog canvas API
k11kirky Aug 3, 2026
cd0e11b
refactor(canvas): simplify-pass cleanups on the client remodel
k11kirky Aug 3, 2026
4d3d617
fix(auth): bump OAUTH_SCOPE_VERSION for the new canvas scope
k11kirky Aug 3, 2026
532f5ae
feat(canvas): let the agent resolve or create the target canvas
k11kirky Aug 3, 2026
3cfc9ca
fix(canvas): stop "Generating" from outliving the agent's turn on clo…
k11kirky Aug 3, 2026
fea79b2
style: apply Biome formatting to canvas view and prompt-builder test
k11kirky Aug 3, 2026
7d34651
fix(canvas): derive build elapsed time during render instead of via e…
k11kirky Aug 3, 2026
d564757
fix(canvas): client races surfaced by review — star order, eviction, …
k11kirky Aug 3, 2026
612a3e2
fix(canvas): bind artifact bridge to its document
k11kirky Aug 3, 2026
4a882a7
fix(canvas): open local canvas artifact links
k11kirky Aug 3, 2026
eb61013
fix(canvas): reconcile latest space layout contracts
k11kirky Aug 3, 2026
d961e40
fix(canvas): avoid stored metadata during target selection
k11kirky Aug 3, 2026
149d8b5
chore(visual): update storybook baselines
k11kirky Aug 3, 2026
b8744e9
fix(canvas): render migrated freeform canvases
k11kirky Aug 3, 2026
957523d
fix(canvas): harden artifact lifecycle and client state
k11kirky Aug 3, 2026
260bae2
fix(canvas): guard version reverts against stale state
k11kirky Aug 3, 2026
6857662
fix(canvas): consume paginated version history
k11kirky Aug 3, 2026
42da7a4
fix(canvas): restore spaces activity header
k11kirky Aug 3, 2026
2fe715c
test(canvas): update channel home hook mock
k11kirky Aug 3, 2026
0d1d80c
fix(visual): restore current loops baselines
k11kirky Aug 3, 2026
3bb510a
fix(artifacts): mark uploaded deliverables as agent output
k11kirky Aug 3, 2026
eace0cf
fix(agent): type artifact upload provenance
k11kirky Aug 3, 2026
828a131
fix(agent): constrain artifact source provenance
k11kirky Aug 3, 2026
63cb76d
fix(canvas): align startup and artifact source contracts
k11kirky Aug 3, 2026
2796941
fix(canvas): align task filing call signature
k11kirky Aug 3, 2026
aa85fdb
refactor(canvas): apply simplify-pass cleanups
k11kirky Aug 3, 2026
2f8aeeb
fix(desktop): reconcile canvas port with imported tree
k11kirky Aug 3, 2026
25006c0
fix(canvas): constrain artifact frame navigation
k11kirky Aug 3, 2026
73aeccc
fix(canvas): enforce artifact security boundaries
k11kirky Aug 3, 2026
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
1 change: 1 addition & 0 deletions products/desktop/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,4 @@ apps/mobile/ROADMAP.md
# to the PostHog Visual Review product; the committed baseline is the signed
# hash manifest apps/code/snapshots.yml.
apps/code/.storybook/__snapshots__/
dump.rdb
5 changes: 5 additions & 0 deletions products/desktop/apps/code/src/renderer/di/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import "reflect-metadata";
import { useDevFlagsStore } from "@features/dev-toolbar/devFlagsStore";
import { TypedContainer } from "@inversifyjs/strongly-typed";
import type { TrpcRouter } from "@main/trpc/router";
import { canvasApplicationModule } from "@posthog/core/canvas/canvas.module";
import {
CLOUD_TASK_CLIENT,
type CloudTaskClient,
Expand Down Expand Up @@ -426,6 +427,10 @@ container.bind(SKILLS_WORKSPACE_CLIENT).toConstantValue({

// sessions (cloud-artifact + title-generator)
container.load(sessionsModule);

// canvas generation orchestration (deps: task service, model resolver, title
// generator — all renderer-bound; persistence effects come in via its gateway)
container.load(canvasApplicationModule);
container
.bind(CLOUD_ARTIFACT_READ_FILE_AS_BASE64)
.toConstantValue((filePath: string) =>
Expand Down
12 changes: 8 additions & 4 deletions products/desktop/apps/web/src/web-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import {
type IAuthSessionStore,
type IAuthTokenCipher,
} from "@posthog/core/auth/identifiers";
import { canvasCoreModule } from "@posthog/core/canvas/canvas.module";
import {
canvasApplicationModule,
canvasCoreModule,
} from "@posthog/core/canvas/canvas.module";
import { taskThreadCoreModule } from "@posthog/core/canvas/taskThread.module";
import type { CloudTaskService } from "@posthog/core/cloud-task/cloud-task";
import { cloudTaskModule } from "@posthog/core/cloud-task/cloud-task.module";
Expand Down Expand Up @@ -484,10 +487,11 @@ container.bind(CLOUD_TASK_AUTH).toDynamicValue((ctx) => ({
}));

// ── Canvas / Channels: host-agnostic dashboard + freeform canvas services ──
// They only need AuthService + fetch (they reach the PostHog desktop_file_system
// API), so the web host binds them by loading the same core module desktop does;
// the web host router forwards its canvas routers to these.
// They only need AuthService + fetch (they reach the PostHog canvases and
// task_channels APIs), so the web host binds them by loading the same core
// module desktop does; the web host router forwards its canvas routers to these.
container.load(canvasCoreModule);
container.load(canvasApplicationModule);
container.load(taskThreadCoreModule);

// SessionService is built from host-agnostic deps (host tRPC client + UI
Expand Down
3 changes: 2 additions & 1 deletion products/desktop/apps/web/src/web-host-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,8 @@ export const webHostRouter = router({
browserTabs: browserTabsRouter,
// Canvas / Channels: real host-router routers over the host-agnostic canvas
// core services (bound via canvasCoreModule in web-container), which reach the
// PostHog desktop_file_system API through authenticatedFetch — no Node backend.
// PostHog canvases + task_channels APIs through authenticatedFetch — no Node
// backend.
canvasData: canvasDataRouter,
canvasTemplates: canvasTemplatesRouter,
channelTasks: channelTasksRouter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,13 @@ describe("uploadArtifactTool", () => {

expect(result.isError).toBeUndefined();
expect(prepareTaskArtifactUploads).toHaveBeenCalledWith("task-1", "run-1", [
{ name: "report.csv", type: "output", size: 7, content_type: "text/csv" },
{
name: "report.csv",
type: "output",
source: "agent_output",
size: 7,
content_type: "text/csv",
},
]);
expect(fetch).toHaveBeenCalledWith(
"https://storage.example/upload",
Expand All @@ -80,6 +86,7 @@ describe("uploadArtifactTool", () => {
expect.objectContaining({
id: "artifact-1",
type: "output",
source: "agent_output",
storage_path: "tasks/artifacts/report.csv",
}),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export const uploadArtifactTool = defineLocalTool({
{
name,
type: "output",
source: "agent_output",
size: fileStat.size,
content_type: contentType,
},
Expand Down Expand Up @@ -111,6 +112,7 @@ export const uploadArtifactTool = defineLocalTool({
id: upload.id,
name,
type: "output",
source: "agent_output",
storage_path: upload.storage_path,
content_type: contentType,
},
Expand Down
5 changes: 5 additions & 0 deletions products/desktop/packages/agent/src/posthog-api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { StoredLogEntry } from "@posthog/shared";
import packageJson from "../package.json" with { type: "json" };
import type {
ArtifactSource,
ArtifactType,
PostHogAPIConfig,
StoredEntry,
Expand All @@ -17,6 +18,7 @@ const DEFAULT_USER_AGENT = `posthog/agent.hog.dev; version: ${packageJson.versio
export interface TaskArtifactUploadPayload {
name: string;
type: ArtifactType;
source?: ArtifactSource;
content: string;
/** Encoding of `content`. With "base64" the backend stores the decoded bytes. */
content_encoding?: "utf-8" | "base64";
Expand All @@ -26,6 +28,7 @@ export interface TaskArtifactUploadPayload {
export interface TaskArtifactPrepareUploadPayload {
name: string;
type: ArtifactType;
source?: ArtifactSource;
size: number;
content_type?: string;
}
Expand All @@ -34,6 +37,7 @@ export interface PreparedTaskArtifactUpload {
id: string;
name: string;
type: ArtifactType;
source?: ArtifactSource;
size: number;
content_type?: string;
storage_path: string;
Expand All @@ -51,6 +55,7 @@ export interface TaskArtifactFinalizeUploadPayload {
id: string;
name: string;
type: ArtifactType;
source?: ArtifactSource;
storage_path: string;
content_type?: string;
}
Expand Down
4 changes: 1 addition & 3 deletions products/desktop/packages/agent/src/server/agent-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1575,9 +1575,7 @@ export class AgentServer {
return null;
}),
]);
this.taskRepositories =
preTask?.repositories ??
(preTask?.repository ? [preTask.repository] : []);
this.taskRepositories = preTask?.repository ? [preTask.repository] : [];

this.prewarmedRun =
(preTaskRun?.state as Record<string, unknown> | undefined)?.prewarmed ===
Expand Down
1 change: 1 addition & 0 deletions products/desktop/packages/agent/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
import type { EffortLevel } from "@posthog/shared/domain-types";

export type {
ArtifactSource,
ArtifactType,
PostHogAPIConfig,
Task,
Expand Down
Loading
Loading