Surfaces the assign/milestone mutations end-to-end so they're usable in-app and by the agent — the rest of #24. Agent path: - propose_change tool + system prompt now accept `assignee` (login/null) and `milestone` (id/null). ProposeChangeArgs + proposalsFor extended: a new ProposalContext (current assignee/milestone + milestones list) lets a proposal skip no-ops and label the milestone. ChangeProposal gains an always-present `summary` (plan is now label-only) — chat-panel, use-chat, and the model executor render `summary`, so non-label proposals display correctly. Dialog path: - Client `listCollaborators()` (prepends the repo owner — /collaborators omits them, so a solo-owner repo still has an assignable person). New `gitea:collaborators` bridge. The Adjust dialog gains Assignee + Milestone pickers (current values from the reconciled backlog); pending assign/remilestone changes flow through the existing apply path. Tests: +4 core (assign/milestone proposals with no-op skip; collaborators owner-prepend + no-double-add). 138 core green; core + desktop typecheck clean; 14 fixture e2e green; live-backlog now drives the pickers on real data. Fixed stale P2 refs in live-backlog (P2 is shipped → correctly off the runway). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
56 lines
2.8 KiB
TypeScript
56 lines
2.8 KiB
TypeScript
import { contextBridge, ipcRenderer } from 'electron'
|
|
|
|
const api = {
|
|
platform: process.platform,
|
|
gitea: {
|
|
/** Whether the main process has a gitea token + target repo configured. */
|
|
status: () => ipcRenderer.invoke('gitea:status'),
|
|
/** The last persisted snapshot, for instant boot before the fresh reconcile. */
|
|
boot: () => ipcRenderer.invoke('gitea:boot'),
|
|
/** Full read of the managed repo — every issue + milestone. */
|
|
reconcile: () => ipcRenderer.invoke('gitea:reconcile'),
|
|
/** One issue by index, normalized (or null if unconfigured). */
|
|
getIssue: (index: number) => ipcRenderer.invoke('gitea:getIssue', index),
|
|
/** Apply an estimate/priority change (the write path); resolves to the plan + fresh issue. */
|
|
applyChange: (change: unknown) => ipcRenderer.invoke('gitea:applyChange', change),
|
|
/** File a set of captured issues with their est/* + p/* labels. */
|
|
createIssues: (issues: unknown) => ipcRenderer.invoke('gitea:createIssues', issues),
|
|
/** Assignable people (repo collaborators) for the assignee picker. */
|
|
collaborators: () => ipcRenderer.invoke('gitea:collaborators'),
|
|
},
|
|
pmstate: {
|
|
/** Read the directive ledger from the pm-state repo. */
|
|
directives: () => ipcRenderer.invoke('pmstate:directives'),
|
|
/** Read the capacity config from the pm-state repo. */
|
|
capacity: () => ipcRenderer.invoke('pmstate:capacity'),
|
|
},
|
|
config: {
|
|
/** The saved config (never the token) — null when unset. */
|
|
get: () => ipcRenderer.invoke('config:get'),
|
|
/** Validate a token + repo before saving. */
|
|
test: (cfg: unknown) => ipcRenderer.invoke('config:test', cfg),
|
|
/** Save config (token encrypted in main); takes effect without restart. */
|
|
set: (cfg: unknown) => ipcRenderer.invoke('config:set', cfg),
|
|
/** Forget the saved config. */
|
|
clear: () => ipcRenderer.invoke('config:clear'),
|
|
},
|
|
model: {
|
|
/** Whether a model endpoint is configured (else the UI keeps the scripted Reginald). */
|
|
status: () => ipcRenderer.invoke('model:status'),
|
|
/** One agent turn: messages in, Reginald's prose + the tools it consulted out. */
|
|
chat: (messages: unknown) => ipcRenderer.invoke('model:chat', messages),
|
|
/** Subscribe to streamed prose tokens for the in-flight turn; returns an unsubscribe. */
|
|
onToken: (cb: (delta: string) => void) => {
|
|
const listener = (_e: unknown, delta: string) => cb(delta)
|
|
ipcRenderer.on('model:chat:token', listener)
|
|
return () => ipcRenderer.removeListener('model:chat:token', listener)
|
|
},
|
|
/** Decompose a braindump into a proposed issue set (capture_work). */
|
|
capture: (braindump: string) => ipcRenderer.invoke('model:capture', braindump),
|
|
},
|
|
}
|
|
|
|
export type CommiteaApi = typeof api
|
|
|
|
contextBridge.exposeInMainWorld('commitea', api)
|