Skip to content

Releases: gemstack-land/the-framework

@gemstack/the-framework@1.4.2

Choose a tag to compare

@github-actions github-actions released this 27 Jul 02:21
4a43429

Patch Changes

  • d8daf7d: A daemon restart no longer risks double-assigning a queue entry (#1268): the drain's pin now rides the suspended-run record and is handed back on resume, so the resumed run re-emits its claim whether or not the meta replay kept it.

@gemstack/the-framework@1.4.1

Choose a tag to compare

@github-actions github-actions released this 27 Jul 01:44
69fffaa

Patch Changes

  • c53b802: The sessions rail is honest about cloud runs (#1263, #1264): a finished Run on: Claude web session reads "in cloud" instead of "done" (its local process ended at the hand-off; the cloud session keeps working and opens its own PR), rows carry a cloud glyph for web sessions, and a web run's row names its agent again (claude-web is still Claude).
  • 13024b3: "Spin up agents working on the AI queue" now does what it says (#1204): the drain routine's Run now fires a drain-only sweep, which fans out to the concurrency setting, one agent per open queue entry, instead of starting a single agent on the first entry. An empty queue is reported on the card rather than the click being borrowed for a rotation job.
  • 13024b3: Fix a pinned queue entry being handed out to a second agent (#1253). The routine's drain pins lived only in the daemon's memory, so a hands-off web run (whose local process ends at the hand-off while the cloud session still works the entry) and a daemon restart both put the entry back on the market, fanning it out again and opening duplicate PRs. The pinned entry now travels to the run's meta (--queue-entry, like --ticket), and the sweep derives durable claims from the metas: a live run holds its entry, a finished one holds it while its PR is open, and failed/stopped runs release it.
  • 0bc296a: Fix the session view crashing (Base UI error #31) on multi-app repos once the preview URL clears, e.g. right after Stop session: the session menu's "Serve which app" submenu label was missing its menu-group wrapper.

@gemstack/the-framework@1.4.0

Choose a tag to compare

@github-actions github-actions released this 26 Jul 23:16
8272cbd

Minor Changes

  • 10b50ef: Rework the Overview's Agents card around the sessions working right now.

    The Recent column is gone — finished sessions already live in the sidebar's session list, so the card kept only the live half — and with it the per-column "Current" eyebrow: "Agents currently working" now reads as a one-liner right next to the card's title. The card also moves up from its slot below Routine work to sit beside the Human Queue, on top of the AI Queue, so what needs you, who is on it, and what the AI takes up next share one row. DashboardData.recentAgents, which existed only to feed the removed column, is dropped from the dashboard payload.

  • 422351c: A parked Claude web question can now be answered from the dashboard. The run view renders the bridge's question as real choices: pick one, confirm the send, and the browser extension types that label into the session's composer and submits it. The pick is deliberately narrow and reversible: the daemon only queues a label of the currently parked question (never free text), the send is a second explicit click, a queued pick can be withdrawn until the extension collects it over the new GET /_bridge/answer, and the extension reports what its delivery did back over POST /_bridge/answered, so the dashboard shows queued, sent, or failed with the reason. The transcript mirror also now keeps the newest text when a page exceeds the mirror cap, instead of sending the rendered system prompt and cutting off the session's actual activity.

  • 422351c: The browser bridge now publishes which cloud sessions are worth watching, at GET /_bridge/sessions, so the extension can open a pinned background tab for each instead of only working while somebody happens to be looking at claude.ai. Recency is the whole filter and has to be: a web run ends at its hand-off, so every one of them reads done whether its session is parked on a question or finished an hour ago, and there is no read-back that would say which. Capped at three, twelve hours back, newest first.

  • 422351c: The browser bridge now mirrors what a Claude web session is saying, not just the question it is parked on. The extension reads the transcript from the session page and posts what changed to POST /_bridge/events, keyed by each message's position so the same message arriving on every DOM change replaces rather than repeats. The run view renders it under the cloud notice. It is a mirror of another product's page rather than a run log of our own: no tool calls, no timings, and nothing arrives while the tab is closed.

  • 422351c: A Claude web run can now show the question its cloud session is parked on, instead of leaving it stranded on claude.ai. A browser extension running in the user's own session reports the question to a new opt-in /_bridge/question endpoint, and the run view renders it. The question is keyed by cloud session id, which a web run already carries, so it lands on the right run even though the run itself ended at the hand-off. Off unless the bridge preference is set, and the route authenticates with its own bearer token rather than the non-loopback guard, since it is the one route meant to be reached from another origin. The first slice was read only; answering from the dashboard ships alongside in this release.

  • 79d1689: Re-skin the dashboard onto the landing page's Everforest identity (IBM Plex Sans, warm dark palette, squarer corners) and rename the two queues to "Human Queue" and "AI Queue" so the dashboard and the-framework.ai read as one product.

  • 23385a1: Dashboard: remove the top navbar and move its chrome into the sidebar (brand, a prominent Overview, an expandable Projects nav, and the Local/theme/notifications/Settings controls in a footer). Add a project / session breadcrumb and an always-available session-details disclosure (agent + spend) to the session toolbar, and fold the toolbar's actions (GitHub, folder, editor, Serve, Stop, Remove worktree, Delete, Open session) into a single overflow menu. Polish the Recents rail: themed scrollbar, a sticky label with a scroll-driven fade, lighter weights, and a hover marquee for long titles. Stop the toolbar flickering on session navigation (keep-previous on the git status / GitHub reads). Add an opt-in pnpm dev:daemon so the dev server can start runs by proxying to the daemon.

  • 46fc0c6: Rework the dashboard Overview around what matters at a glance (#1139).

    Usage moves to the top as the first thing you see. The two cross-project queues now sit side by side: a Human Queue ("Agents awaiting your approval, review, or input") and an AI Queue ("Tasks AI will work on next"), the latter showing every queued item in full as bullet points rather than collapsing to "+N more". A new Agents view lists the sessions working now and the ones just finished in two columns — Current and Recent — each row clickable straight into its session and dated in plain language ("22s ago", "2w ago") with the exact moment on hover. Hot tickets narrows to the three lanes worth surfacing — In progress, AI Queue (tickets an open TODO_AGENTS.md entry links to), and High priority — in a two-column layout.

    The redundant cards are gone: the KPI tiles, run outcomes, the projects table, and the "Overview" title with its tagline. Session activity is removed for now, to return later.

  • ef0d941: Add a "Hot tickets" overview to the dashboard.

    The Overview now has a cross-project glance at the tickets that matter right now, in three lanes: In progress (tickets the agent has planned or spiked), Up next (high priority, not started yet), and Queued (the rest of the open backlog). Each row names its project and jumps into it when selected.

    It pools every project's tickets/, so it is a projection of the same files the agent plans from, polled so it stays live. Empty lanes collapse to a single header line, so an import-heavy repo where everything sits queued still reads as designed.

  • 2c1e6d4: Start a run with no project, in a neutral scratch directory.

    A "topic" run starts project-less: it spawns in a neutral scratch dir under the config home with no repo or worktree, so the agent has no code to touch. This is the "ask a question, plan, or draft a ticket without a repo" path. It still produces the normal run lifecycle (events.jsonl, run.json, settle) inside the scratch dir.

    A new sendStartTopic RPC starts one beside the project-scoped sendStart, keeping the home-default behavior untouched. The scratch dir is retained on failure or stop and removed on a clean finish, mirroring the worktree retention rule. The UI for it is tracked separately.

  • 4dc9c40: fix(the-framework): carry the ticket and backlog format specs in the run's system channel (#1163): both were pointed at as node_modules/@gemstack/the-framework/prompts/*.md, a path that only resolves when the framework is a root dependency of the repo it works on, so the agent was told to follow a format it could not open. The spec still ships with the package and is never written into the user's repo (#674), it is just handed over rather than left to be found. The two unused TICKETING_FORMAT_FILE / TODO_FORMAT_FILE path constants go with it, along with the files entries that published the specs for them.

  • bdefcd9: Remove the [Quick wins] preset (#773). It harvested .plan.md companions and appended the quick ones to TODO_AGENTS.md, a step the triage pair ([Do quick-win work] / [Do consensual work], #891/#892) already covers by reading tickets/*.md directly — so the auto-PM rotation now triages straight from tickets rather than harvesting an intermediate plan first, and the launcher no longer offers the button.

  • f674fbc: Add a repos-directory preference with an opt-in auto-grant (#1123): a root directory the project-registration flow will default into, plus an off-by-default toggle that auto-adds every git repo directly inside it on daemon boot.

  • 91a23ff: Routine work: a Concurrent agents setting (default 2, up to 10) for how many agents the routine keeps going at once. A sweep now tops a project up in one tick, so one click of "Trigger routine now" against a standing queue fans out that many sessions at once, each pinned to its own queue entry.

  • ab64c85: Give every routine on the Overview its own checkbox, so the scheduled sweep can be narrowed to the routines you actually want it spending quota on. Unticking is what gets saved (autoPmOptOut), so every routine stays on by default and one added by a later version runs without anyone re-visiting the setting. An unticked draining routine stands the sweep down rather than falling through to the rotation, and an unticked maintenance sweep leaves its calendar untouched so it still comes due once it is ticked back on.

  • 95f54a5: Show the routine work on the Overview: the jobs the idle sweep fires (drain the queue, harvest quick-wins, triage, spike & plan, the maintenance sweep), each with a "Run now" button that starts it against a project immediately, plus the single auto-run checkbox that says when the next sweep is due. The list is the daemon's own job table rather than a copy, so the two cannot drift.

  • cc8af7c: "Run on: Claude web" is a real run target now, not a placeholder. Picking it hands the session to Claude Code on the web on your own account: the work runs on Anthropic's infrastructure at no local CPU cost, does its own git worktree and opens its own pull request, and the run view links straight to the session plus the claude --teleport command that pulls it back to this machine. Also available as framework run --run-on web.

    This is a hand-off rather than a streamed run, and deliberately so: a cloud session exposes no read-back API of any kind, so following the work happens on claude.ai or through the branch it pushes. Nothing here drives the claude.ai UI — it goes through the CLI's own --cloud flag, with the same subscription auth every other target uses.

  • f423571: feat(the-framework): record...

Read more

@gemstack/the-framework@1.3.0

Choose a tag to compare

@github-actions github-actions released this 24 Jul 09:38
5abc227

Minor Changes

  • a6983a7: Reclaim a session's worktree once its work has landed.

    A run that failed or was stopped keeps its checkout so you can read what it was holding, and nothing ever took those back, so a machine accumulated one full checkout per such session forever. The daemon now sweeps the registered projects every ten minutes and removes the checkouts whose branch has landed.

    Only the checkout goes. The branch, its commits, and the session's row and replayable log are kept, so everything this reclaims is a git worktree add away. That is what makes it safe to do without asking.

    A branch counts as landed on either of two signals, because neither alone is enough. git branch --merged is the stronger one, since it proves the commits are reachable from the local base, but it only holds for a merge that kept them: a squash or rebase merge rewrites the commits, so the branch never becomes an ancestor and the signal never fires. A merged PR closes that gap. A closed-unmerged PR does not count as landed, since the checkout of rejected work is the one you are most likely to still want.

    The sweep is conservative wherever the answer is unclear: a live run keeps its checkout, and so does a branch that no longer exists or one whose state cannot be read.

    framework worktrees sweep runs the same pass on demand, next to the existing prune (which removes every checkout whose session is no longer running, landed or not).

  • a82411e: Print the commands and the version on bare framework too (#312).

    #312 describes what $ framework should do, and two of its items were already built: the convenience command list and the version footer with the npm "up to date" check. Both lived only in ensureDaemonCmd, the framework --daemon path. Bare framework, the command the issue is actually about, foregrounds the dashboard instead and printed two lines: the URL and "Ctrl+C to stop".

    Both paths now print one shared footer, so the version you are running is visible from the command people actually type, and so is a newer release when there is one.

    The update line is not awaited before the static lines. #312 asks for the static info first, and the foreground path blocks on the server until it is signalled, so anything held back until after the registry call would never have been printed there at all. The check keeps its existing 2.5s cap and stays silent when npm is unreachable.

    The foreground footer drops the framework stop line, which stops a detached dashboard; that path tells you Ctrl+C instead.

  • aa349a4: Manage saved devices from the settings page.

    Adding and removing a device already worked, but only from the composer's "Run on" menu, and the composer only exists on a project launcher. From the Overview or the settings page there was no way to manage the roster at all. The settings page now has a Devices section listing each saved device with its origin and online/offline status, an Add device button, and a remove per row. The "Run on" picker still lists devices, because choosing a run target is a per-run act; which devices exist is configuration.

    Removing a device from settings clears the run target when that device was the one selected, the same guard the composer already applied, so a run can never point at a device that is no longer saved.

    The section states that devices are saved in the browser rather than on the server: unlike every other setting on the page, a device carries a token, so it stays in this browser's storage and never reaches the daemon.

  • afa43b1: Configure the Discord bot and webhook from the dashboard (#1095).

    Both Discord credentials were daemon environment variables and nothing else, so enabling Discord meant editing the daemon's environment and restarting it. That made it the one onboarding step you could not finish in the product: the #958 checklist could tell you the daemon had no token, and then only tell you to go elsewhere.

    The setup dialogs now take the credential. It is stored in the registry file at the same tier as the daemon token (#1051): top level, never in preferences, so it cannot reach the browser bundle or a per-project override. The file is written owner-only. The daemon rebuilds its Discord services on the save, so the bot connects and the notification watchers start without a restart.

    The value only ever moves inward. There is no read that returns a credential: the dashboard is told which ones exist and where each came from, which is the presence-only contract onNotifyChannels has had since #948. A stored credential shows as saved, with Replace and Remove rather than a field holding a secret.

    An environment variable still wins over a stored value, and the dialog says so instead of offering an edit the daemon would shadow. That is how a container, a systemd unit or a shared box keeps configuring the daemon it runs.

    The bell, the settings rows and the checklist now read this from one shared value rather than three independent polls, so saving a credential in one place settles all of them at once.

  • e0517cf: The end-of-session handoff happens by itself: Push branch and Open PR are now checkboxes, ticked by default.

    They used to be two buttons on a finished session, and the code was explicit that they should stay clicks, on the grounds that publishing the agent's work under your name is your call. In practice that meant a click per session for the thing you almost always want, and when nobody clicked, the work stayed on a local branch nobody was told about.

    The call is still yours, it is just made once instead of every time. The two controls are now pre-commitments in the session action bar: whatever is still ticked when the session settles happens on its own. Leave them alone and it is zero-config. Untick either one while the session runs to opt out, and the old button comes back, so the deliberate path is never lost. A failure falls back to the button too, with git's or gh's own reason beside it.

    The pair is not independent, because gh will not open a PR for a branch the remote has never seen: ticking Open PR arms the push, and unticking Push branch unticks the PR.

    The PR is opened as a draft, so firing on every session does not put a review request in anyone's inbox. That needed one change elsewhere: the interventions queue skipped every draft, on the grounds that a draft is not asking for review. For a PR the framework opened for itself that reasoning inverts, since then nothing would tell you the work exists at all. The queue now lists a draft on a the-framework/* branch and still skips drafts opened by hand.

    New per-project preferences autoPushBranch and autoOpenPr set where the boxes start; both default on. The CLI has --no-auto-push-branch and --no-auto-open-pr, which travel as explicit --no-* flags for the same reason the repo-config toggles do: these default on, so silence would re-arm them.

    The handoff runs after the on-before-mergeable quality pass, so anything that pass committed is included, and it commits the session's own pending work first, which teardown would otherwise only do after the run process had exited. It declines rather than acting on a stopped run, a branch that is gone, a session that committed nothing, a repo with no remote, and a branch that already has a PR.

Patch Changes

  • f1cab24: Fix two faults in opening a session's pull request, both found by driving the handoff against a real GitHub remote rather than a stubbed one.

    The PR base was a tracking ref, so opening a PR failed outright. RunHandoff.base holds what detectBase reads out of refs/remotes/origin/HEAD, which is origin/main. That is correct for the two things the field is otherwise used for, since the commit range and the merged check are both asking git about a remote-tracking ref. It is not a thing you can open a PR against: gh pr create --base origin/main is rejected with Base ref must be a branch. The name is now converted at the gh boundary, leaving the field as the git ref it is. This affected the manual Open PR button too, on any repo whose default branch is discovered through origin/HEAD.

    The "this branch already has a PR" guard could be defeated by a cold cache. The check read through the dashboard's cached PR lookup, which answers prPending rather than yes-or-no while it refreshes. "Not known yet" therefore read as "no PR", and a second handoff for the same branch went ahead and tried to open another one; only gh refusing the duplicate stopped it. The handoff now takes the uncached lookup and waits for a real answer. It runs once, at the end of a session, so it can afford to.

  • 2f8908c: Make the settings page obey the same run-option rules as the launcher (#958).

    The settings page rendered the run options as flat, independently checkable boxes, while the launcher has real rules between them. So the page could show an option checked that the launcher shows off, and allowed combinations that mean nothing: Eco under Vanilla (nothing left to trim), Browser on Codex (inert, the browser rides Claude Code's MCP config), Auto maintenance without Post-merge cleanup, and anything under Transparent, which overrides the lot.

    The table and its rules moved out of the composer into one module both surfaces render, so a rule cannot hold in one place and not the other. A row the rules disable is greyed and shows why, rather than disappearing, since the settings page is where you go to look for a setting. checked is now the effective value everywhere, so no surface claims an option is on while the run ignores it.

    Two smaller cases of the same thing: the notification rows now show the delivery capability the bell already showed (browser permission blocked, DISCORD_WEBHOOK / DISCORD_BOT_TOKEN unset), and the spend offset is bounded to the same range as its slider and the sanitizer, instead of accepting a value that w...

Read more

@gemstack/the-framework@1.2.0

Choose a tag to compare

@github-actions github-actions released this 23 Jul 22:12
fa743d9

Minor Changes

  • b2d23ed: Rename the package from @gemstack/framework to @gemstack/the-framework, and the CLI command from framework to the-framework (#1071), for consistency with the product name The Framework.

    Shipped as a new package name rather than a break in the old one: @gemstack/framework keeps resolving and is deprecated with a pointer here, so nothing installed today stops working. Update installs to @gemstack/the-framework and invocations to the-framework.

  • 61451a1: Dashboard: the session page says its branch once. The handoff card that repeated the branch name under the action bar is gone; its verdict ("2 commits · 0 files", "no changes", "branch gone") and its Push branch / Open PR buttons now ride in the branch row itself, and clicking that row expands the commits and changed files. A live session's Changes panel folds into the same row: the file count sits beside the branch, the rows open underneath.

  • ecf2ce4: feat(framework): context fragment lists the recorded conversations (#683)

    Adds .the-framework/conversations/**.md to CONTEXT_DOCS, so a run is told to read the human conversations (Discord/chat turns) that earlier runs committed there. A read-only pointer, like tickets/ and TODO_AGENTS.md, so it stays out of the merge-update set. The path is pinned by a test to the canonical THE_FRAMEWORK_DIR/CONVERSATIONS_DIR constants so it cannot drift from where runs actually commit.

  • 053db85: feat(framework): context fragment points the knowledge base at a knowledge-base/ folder (#683)

    Splits the flat KNOWLEDGE-BASE.md into knowledge-base/FACTS.md and knowledge-base/INSIGHTS.md, and moves DECISIONS.md and MARKET_RESEARCH.md under knowledge-base/, with a knowledge-base/**.md catch-all. The on-before-mergeable prompt and the Market research preset name the same paths.

  • 7c70533: Dashboard: the session log reads like a conversation. Your prompt is its own YOU row and the agent's turn is AGENT, so a message is no longer echoed twice — the redundant You: … log line is gone and the first prompt and every follow-up now read the same way.

    Both your prompts and the agent's replies render as Markdown (headings, bold, lists, code, links), at the log's own density. A short message renders inline; a long one collapses to its first line with a chevron and expands in place on click, so the log stays scannable without hiding the text.

    Also: the sessions rail's home row is now "New session" (a launcher) instead of "Live", and a session's id is always offered for copy in the toolbar (the exact string --resume takes), beside the existing copy-branch action.

  • a1552ac: feat(framework): remote-daemon lane, non-loopback bind guarded by a shared token (#1051)

    framework --daemon --host <addr> binds the dashboard daemon to a non-loopback address so a device you own can reach it. Because a daemon that spawns processes is code execution for anyone who finds the port, a non-loopback bind generates and persists a shared token (crypto.randomBytes(32), a top-level Registry.daemonToken, never a preference and never shipped to the browser bundle), and one guard fronts every route (static bundle, /_telefunc, /browser): a request needs a valid fw_daemon cookie or a matching ?token=, else 401, compared with crypto.timingSafeEqual. A valid ?token= sets an HttpOnly; SameSite=Strict cookie and 302s to the clean path, so one cookie rides the RPC, the live-events Channel, and the MJPEG screencast alike. A loopback bind generates nothing and the guard is a no-op, so the local zero-config path is byte-identical. The CLI prints a loud warning and the token URL on any non-loopback bind. Composes with (does not replace) the existing CSRF origin check.

  • 3166507: Devices: online/offline status and remove-device in the "Run on" gear (#1072).

    Each saved-device row in the gear gains a remove (X) control that drops the device; if the removed device was the selected run target, the selection clears back to a driver target. The gear device rows and the connection indicator now show a green (online) / grey (offline) reachability dot, and an offline row is muted and labelled. The device tokens stay browser-side (per #1052), so the browser hands the local daemon each device's {url, token} and the daemon does a cookie'd GET /_relay/ping to report reachable or not; a short client poll drives the dots. The new ping endpoint is cookie-guarded (401 without) and starts nothing.

  • 969b9bb: Dashboard launcher and rail UX pass:

    • The prompt editor and its run controls are grouped into one rounded "composer box"; the editor loses its own border and focus ring, and the placeholder and typed text get roomier padding.
    • The submit button is a single arrow icon that stays hidden until the prompt has text, then fades in and slides into place, pushing the model select over smoothly (a spinner shows while starting or sending).
    • The agent/model select sits just left of the submit button, borderless, with the model shown as selected (the default reads "Default", no separator dot).
    • Presets is a borderless slash icon, the options gear is borderless with a smaller count badge, and all controls share one height.
    • "Open in editor" moved out of the options gear onto the workspace editor button, which now opens the checkout and picks the preferred editor.
    • The right rail holds one fixed width for every tab (no expand on Views/Browser).
    • The sessions rail: "New session" is now "New", the "Sessions" heading is replaced by a "Recents" label over the list, the agent logo is smaller, and rows clear the scrollbar.
    • The session toolbar drops the copy-branch and copy-session-id buttons, and the branch dirty/clean indicator sits closer to the branch name.
  • f20add1: Dashboard: the session view holds still. A run ending used to swap the whole page for a different one — the action bar blanked, the output was replaced by "Loading session…", the run overview disappeared and the composer was rebuilt. Live and finished are now the same view, so only what the bar, feed and composer say changes. The action bar is one row at any width (the branch truncates, the least important facts drop out, the buttons never wrap under it), and the composer no longer vanishes on a session that ended without a resumable id: it stays and starts a new session instead.

  • 85c5f73: Onboarding checklist and a settings page (#958).

    The Overview gains an Onboarding section: add a project (one click for the directory the server runs in), fill the AI task queue, fill tickets/ (with an "Import tickets from GitHub" button), add the Discord bot, turn on browser notifications, and add Discord notifications. Every step's done-state is derived from a real fact (a registered project, a non-empty queue, a ticket on disk, a granted browser permission, credentials the daemon holds), so a step cannot be ticked by clicking it, and one done outside the dashboard shows up done. It can be dismissed, which hides it only on the Overview.

    Settings now have a page of their own at /settings, reachable from the header, collecting what was spread across the header menus: appearance and editor, agent / model / run-on, run options, eco, notifications, and automation. The Onboarding checklist lives there too and is not dismissible, which is what dismissing it on the Overview points you to.

    Supporting changes: onDashboard's per-project rollup carries hasTickets, a new onOnboarding read offers the server's working directory as a first project (gated on the same wiring as adding projects, so a public host discloses nothing), and onboardingDismissed joins the preferences.

  • d3cd883: Custom presets can now be saved to a project, not just to you. When you create a preset with a project open, a "Save to" choice lets you keep it private (as before) or commit it into the repo's .the-framework/custom-presets.json, so everyone who clones the project gets it. Shared presets show up in their own "Project presets" group in the Presets menu and under / in the editor, and delete from there. Personal presets still live in your home config and follow you across every project.

  • 30e94f9: feat(framework): run a session on a connected device via a server-side relay (#1067, slice 1)

    Picking a saved device in the "Run on" gear now makes it a true run target: you stay on this dashboard, submit, and the session runs on the remote device and streams its events back into the current run view. A device row no longer navigates the browser; it selects the device in place (the token stays a per-browser secret, memory-only, never persisted).

    Under the hood the local daemon relays the run: it POSTs the run to the remote daemon's new /_relay/start (authenticating with the device token as the fw_daemon cookie, no Origin) and fetch-streams the remote's /_relay/events back into the local run view over the normal same-origin channel. The browser never talks cross-origin and the token never leaves the two daemons. Both /_relay/* endpoints are fronted by the same #1051 token guard.

    Slice 1 is submit + live events. The remote run executes in the device's own home checkout, and the diff, PR, push/handoff, and browser screencast panels show a "not available for remote runs yet" placeholder; those (and per-project remote targeting) land in later slices.

  • 38ef437: A run started on a connected device is now a true peer: its file reads, diffs, git status, worktree, run-handoff, live steering, and push/open-PR all work by relaying each run-scoped RPC to the device over the #1051 token cookie, keyed by a durable per-run marker on the local daemon; push and PR run on the device's own checkout. The run view's diff and handoff panels are no longer suppressed for remote runs (#1067, slice 2). The browser preview stays local-only for now (slice 3).

  • 1c8d520: A run relayed to a connected device (#1067) now appears in ...

Read more

@gemstack/mcp@0.5.0

Choose a tag to compare

@github-actions github-actions released this 23 Jul 21:57
5a692bf

Minor Changes

  • 9258b84: Remove the dead Mcp server registry and correct the docs to the real mounting API.

    @gemstack/mcp exported Mcp.web() / Mcp.local() / Mcp.getWebServers() / Mcp.getLocalServers(), backed by a store on the __gemstack_mcp_servers__ global. Nothing in the repo ever read that store: no package, no example, no runtime path. Six README and docs pages nevertheless presented Mcp.web(path, ServerClass) as the way to mount a server, so anyone following them registered into a map nobody read, got no error, and got no working endpoint.

    Removed: Mcp, McpWebEntry, McpWebBuilder, and the global store. The real, already-working mounts are unchanged: createMcpHttpHandler(server) for raw node:http / Express / Connect (main entry), createWebRequestHandler(server) for Fetch-style hosts and startStdio(server) for stdio (both from @gemstack/mcp/runtime). Note the shape difference the old docs hid: these take a server instance, not a class.

    @gemstack/mcp takes a minor rather than a major: it is pre-1.0, where a breaking removal is conventionally a minor, and no working code can be relying on the removed surface since nothing ever consumed it. The connector packages take a patch: their published READMEs (and, for @gemstack/mcp-connectors, the mountConnectors JSDoc that ships in its .d.ts) carried the false mount snippet, so the corrected text is worth a release.

@gemstack/mcp-connectors@0.2.2

Choose a tag to compare

@github-actions github-actions released this 23 Jul 21:57
5a692bf

Patch Changes

  • 9258b84: Remove the dead Mcp server registry and correct the docs to the real mounting API.

    @gemstack/mcp exported Mcp.web() / Mcp.local() / Mcp.getWebServers() / Mcp.getLocalServers(), backed by a store on the __gemstack_mcp_servers__ global. Nothing in the repo ever read that store: no package, no example, no runtime path. Six README and docs pages nevertheless presented Mcp.web(path, ServerClass) as the way to mount a server, so anyone following them registered into a map nobody read, got no error, and got no working endpoint.

    Removed: Mcp, McpWebEntry, McpWebBuilder, and the global store. The real, already-working mounts are unchanged: createMcpHttpHandler(server) for raw node:http / Express / Connect (main entry), createWebRequestHandler(server) for Fetch-style hosts and startStdio(server) for stdio (both from @gemstack/mcp/runtime). Note the shape difference the old docs hid: these take a server instance, not a class.

    @gemstack/mcp takes a minor rather than a major: it is pre-1.0, where a breaking removal is conventionally a minor, and no working code can be relying on the removed surface since nothing ever consumed it. The connector packages take a patch: their published READMEs (and, for @gemstack/mcp-connectors, the mountConnectors JSDoc that ships in its .d.ts) carried the false mount snippet, so the corrected text is worth a release.

  • Updated dependencies [9258b84]

    • @gemstack/mcp@0.5.0

@gemstack/mcp-connector-google-drive@0.2.2

Choose a tag to compare

@github-actions github-actions released this 23 Jul 21:57
5a692bf

Patch Changes

  • 9258b84: Remove the dead Mcp server registry and correct the docs to the real mounting API.

    @gemstack/mcp exported Mcp.web() / Mcp.local() / Mcp.getWebServers() / Mcp.getLocalServers(), backed by a store on the __gemstack_mcp_servers__ global. Nothing in the repo ever read that store: no package, no example, no runtime path. Six README and docs pages nevertheless presented Mcp.web(path, ServerClass) as the way to mount a server, so anyone following them registered into a map nobody read, got no error, and got no working endpoint.

    Removed: Mcp, McpWebEntry, McpWebBuilder, and the global store. The real, already-working mounts are unchanged: createMcpHttpHandler(server) for raw node:http / Express / Connect (main entry), createWebRequestHandler(server) for Fetch-style hosts and startStdio(server) for stdio (both from @gemstack/mcp/runtime). Note the shape difference the old docs hid: these take a server instance, not a class.

    @gemstack/mcp takes a minor rather than a major: it is pre-1.0, where a breaking removal is conventionally a minor, and no working code can be relying on the removed surface since nothing ever consumed it. The connector packages take a patch: their published READMEs (and, for @gemstack/mcp-connectors, the mountConnectors JSDoc that ships in its .d.ts) carried the false mount snippet, so the corrected text is worth a release.

  • Updated dependencies [9258b84]

    • @gemstack/mcp@0.5.0
    • @gemstack/mcp-connectors@0.2.2

@gemstack/mcp-connector-github@0.2.2

Choose a tag to compare

@github-actions github-actions released this 23 Jul 21:57
5a692bf

Patch Changes

  • 9258b84: Remove the dead Mcp server registry and correct the docs to the real mounting API.

    @gemstack/mcp exported Mcp.web() / Mcp.local() / Mcp.getWebServers() / Mcp.getLocalServers(), backed by a store on the __gemstack_mcp_servers__ global. Nothing in the repo ever read that store: no package, no example, no runtime path. Six README and docs pages nevertheless presented Mcp.web(path, ServerClass) as the way to mount a server, so anyone following them registered into a map nobody read, got no error, and got no working endpoint.

    Removed: Mcp, McpWebEntry, McpWebBuilder, and the global store. The real, already-working mounts are unchanged: createMcpHttpHandler(server) for raw node:http / Express / Connect (main entry), createWebRequestHandler(server) for Fetch-style hosts and startStdio(server) for stdio (both from @gemstack/mcp/runtime). Note the shape difference the old docs hid: these take a server instance, not a class.

    @gemstack/mcp takes a minor rather than a major: it is pre-1.0, where a breaking removal is conventionally a minor, and no working code can be relying on the removed surface since nothing ever consumed it. The connector packages take a patch: their published READMEs (and, for @gemstack/mcp-connectors, the mountConnectors JSDoc that ships in its .d.ts) carried the false mount snippet, so the corrected text is worth a release.

  • Updated dependencies [9258b84]

    • @gemstack/mcp@0.5.0
    • @gemstack/mcp-connectors@0.2.2

@gemstack/ai-sdk@0.6.1

Choose a tag to compare

@github-actions github-actions released this 23 Jul 21:57
5a692bf

Patch Changes

  • cd121f4: fix(ai-sdk): a store whose unscoped list() hides other users' threads no longer fails open on resume-by-id

    The #984 owner check settles ownership from ConversationStoreListEntry.userId, falling back to an unscoped store.list() when the caller's scoped listing does not hold the thread. A thread missing from that unscoped listing was read as "no owner recorded" and allowed, which is right for a pre-#984 ownerless row but wrong for a store whose list() with no user id returns nothing. Such a store implements list(userId) correctly and is fully owner-aware, and a cross-user resume was still allowed.

    The unscoped listing reporting nothing at all, while the store demonstrably holds rows (the caller has threads of their own, or the target thread has messages), now proves the listing is not enumerating the backend, and the resume is refused with ConversationOwnershipError.

    Deliberately unchanged: a listing that reports rows but not this one stays permissive, since an absent thread and a partial listing are indistinguishable there. Ownerless legacy threads on a store that enumerates normally stay resumable, with or without a user on the run, and a store that omits userId from its entries keeps its old permissive behavior.

    ConversationStore gains no members. The listing contract the check depends on is now documented on the interface itself, where an implementer sees it, rather than only on the entry type's userId field.

  • 780ef3e: Internal: the provider layer no longer carries four copies of the same code. Every adapter builds its SDK client through one shared lazyClient() helper, the five pure OpenAI-compatible providers (xai, groq, deepseek, ollama, azure) come from one factory, and the Anthropic stream-event mapping is shared with Bedrock instead of being inlined twice.

    Two side effects worth naming. A first client build is now memoised as a promise, so two concurrent calls share one client rather than racing to construct two, and a failed dynamic import no longer caches. And XaiProvider.name and friends are typed string rather than the literal 'xai', matching the ProviderFactory contract they are consumed through.

    All public exports keep their names, constructor signatures, and default base URLs.

  • 23c1fb7: CachedSubAgentRunStore.load() now returns null (not undefined) when a CacheAdapter resolves undefined on a miss, matching CachedAgentRunStore.load(). The CacheAdapter contract already declares Promise<T | null>, so adapters that honour it are unaffected; adapters that resolve undefined now get the documented null.

    Internal: both run-store families now share one storage implementation. All public exports (InMemoryAgentRunStore, CachedAgentRunStore, newAgentRunId, InMemorySubAgentRunStore, CachedSubAgentRunStore and their types) keep the same shape.