Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
2768798
feat(canvas): plan-mode context creation with a channel feed
adamleithp Jul 12, 2026
26f7087
fix(canvas): derive 'created this context' feed row from the channel row
adamleithp Jul 12, 2026
8e706ae
fix(canvas): address review findings on context creation flow
adamleithp Jul 12, 2026
d596afe
better new context dialog
adamleithp Jul 13, 2026
14ef73f
collapsible contexts in nav
adamleithp Jul 13, 2026
77ae9db
bring in changes from ux-threads-slacck branch for last turn in threa…
adamleithp Jul 13, 2026
9913fb8
load thread only after everything is loaded (show skeleton first)
adamleithp Jul 13, 2026
ddf5256
fake thread message composer
adamleithp Jul 13, 2026
5ef66af
more fake composer + reference to context.md file allowed, more menti…
adamleithp Jul 13, 2026
d15eb04
more fake composer + reference to tasks
adamleithp Jul 13, 2026
79a3f7c
reply to thread added to fake composer, working
adamleithp Jul 13, 2026
6cd84d7
in channel, force cloud, remove input choice
adamleithp Jul 13, 2026
cfde5b2
badges, better links in thread item
adamleithp Jul 13, 2026
cc22baf
tighten thread item + mention link spacing
adamleithp Jul 13, 2026
b051f44
feat(canvas): experimental thread/feed/inbox tweaks
adamleithp Jul 14, 2026
5d1a626
fix(canvas): drop duplicate model key after rebase
adamleithp Jul 14, 2026
f69d1ef
fix(canvas): thread dock never starts a run on a runless task
adamleithp Jul 14, 2026
e3c7e98
fix(canvas): keep generate() resolving on late failures
adamleithp Jul 14, 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
52 changes: 52 additions & 0 deletions packages/api-client/src/posthog-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ import type {
ActionabilityJudgmentArtefact,
AvailableSuggestedReviewer,
AvailableSuggestedReviewersResponse,
ChannelFeedMessage,
ChannelFeedMessageEvent,
CodeReferenceArtefact,
CommitArtefact,
CommitDiffResponse,
Expand Down Expand Up @@ -2467,6 +2469,56 @@ export class PostHogAPIClient {
return (await response.json()) as TaskChannel;
}

// A channel's system-announcement feed (context created, CONTEXT.md being
// built), chronological. Durable + team-visible, rendered alongside task cards.
async getChannelFeed(channelId: string): Promise<ChannelFeedMessage[]> {
const teamId = await this.getTeamId();
const urlPath = `/api/projects/${teamId}/task_channels/${channelId}/feed/`;
const response = await this.api.fetcher.fetch({
method: "get",
url: new URL(`${this.api.baseUrl}${urlPath}`),
path: urlPath,
});
if (!response.ok) {
throw new Error(`Failed to fetch channel feed: ${response.statusText}`);
}
return (await response.json()) as ChannelFeedMessage[];
}

// Post a system announcement into a channel's feed. The row is authored by the
// system; the server records the requester as `author` for "Adam …" rendering.
async postChannelFeedMessage(
channelId: string,
input: {
event: ChannelFeedMessageEvent;
payload?: Record<string, unknown>;
// Optional explicit timestamp (ISO) so a burst of announcements orders
// deterministically instead of racing on server insert time.
createdAt?: string;
},
): Promise<ChannelFeedMessage> {
const teamId = await this.getTeamId();
const urlPath = `/api/projects/${teamId}/task_channels/${channelId}/feed/`;
const response = await this.api.fetcher.fetch({
method: "post",
url: new URL(`${this.api.baseUrl}${urlPath}`),
path: urlPath,
overrides: {
body: JSON.stringify({
event: input.event,
payload: input.payload ?? {},
...(input.createdAt ? { created_at: input.createdAt } : {}),
}),
},
});
if (!response.ok) {
throw new Error(
`Failed to post channel feed message: ${response.statusText}`,
);
}
return (await response.json()) as ChannelFeedMessage;
}

// Mentions of the current user across task threads, newest first.
async getTaskMentions(options?: { since?: string }): Promise<TaskMention[]> {
const teamId = await this.getTeamId();
Expand Down
21 changes: 21 additions & 0 deletions packages/shared/src/domain-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,27 @@ export interface TaskChannel {
created_by?: UserBasic | null;
}

/** Lifecycle events a client may post into a channel's feed. */
export type ChannelFeedMessageEvent = "context_md_building";

/**
* A durable, team-visible "PostHog agent" announcement in a channel's feed —
* rendered alongside task cards (e.g. "Adam created this context"). `author` is
* the user whose action produced the row; `author_kind` says who authored it.
* `payload` carries structured event data (e.g. `{ context_name }`) so rendering
* survives renames.
*/
export interface ChannelFeedMessage {
id: string;
channel: string;
author?: UserBasic | null;
author_kind: "human" | "system" | "agent";
event: ChannelFeedMessageEvent | string;
payload: Record<string, unknown>;
content: string;
created_at: string;
}

/**
* One human message in a task's thread. Thread messages never reach the agent
* unless the task author forwards one, which stamps the forwarded_* fields.
Expand Down
Loading
Loading