Skip to content

Kody v2026.07.30

Latest

Choose a tag to compare

@kody-bot kody-bot released this 30 Jul 13:02
06aa3d7

Kody v2026.07.30

This release reshapes how packages work and how fast they run. The package model is now static-first — two simple rules replace a tangle of invocation paths — and hosted package apps moved to their own origin so community code can never touch your session. On the performance side, execute latency got a hard look: cold-isolate dispatch dropped ~1.5 seconds, sequential storage round trips came off the hot path, and every execute now reports phase-level timings so you can see exactly where time goes.

New

  • A simpler, faster package model — two rules, not five. When you know a package's name at write time, import fn from 'kody:@scope/pkg/export' is now the default: typed, publish-verified, and essentially free per call. When the name is data or you need the target's own runtime, packages.invoke({ kodyId, exportName, params }) is the one dynamic primitive — keyless for lean/ephemeral calls, keyed with an idempotencyKey for durable exactly-once dispatch. Legacy surfaces (packages.invokeChecked, packages.check, dynamic import("kody:@…")) still work but are deprecated everywhere Kody's agent guidance talks to you. All agent-facing instructions, MCP tool descriptions, and docs now teach the two-rule model consistently. (#1045, #1046)

  • Static import calls are now metered. Every call through a statically imported package export emits a non-blocking usage event with the caller, callee package, duration, and outcome — so package reuse shows up on your admin usage charts the same way dynamic invocations always have. (#1047)

  • Hosted package apps now run on a separate origin (kodyapps.dev). Community package code executed on the app origin could read your session cookie or fetch your account data with credentials: 'include'. Package apps now live on their own registrable domain: credentials are stripped from every forwarded request and WebSocket upgrade, and same-origin browser attacks are structurally impossible. Package search, identity parsing, and hosted URLs all follow the new origin. A hotfix and a follow-up fixed a production outage where deploying the new domain accidentally detached heykody.dev and disabled the workers.dev trigger — both are now guarded so a deploy can never drop a domain again. (#1013, #1015, #1016, #1017, #1025)

  • Optional pre-exec TypeScript checks for execute. A feature-flagged LanguageService check type-checks your ad hoc execute modules — including kody:@ static imports — before bundling and sandbox execution, catching type errors before the run starts. Default off, with a per-user override available. (#1029)

  • Execute now reports phase-level Server-Timing. Every execute response carries serverTiming entries for typecheck, bundle, and run phases — and the run phase is further split into hydrate, provider-assembly, and sandbox sub-spans. When a run feels slow, you can see exactly which phase owns the latency directly from the tool response. (#1034, #1036)

  • Package-storage audit route for admins. GET /admin/package-storage-audit.json gives a read-only, platform-wide view of legacy storage buckets, ambient storage imports, and orphaned inventory rows — the report that gates the ongoing cleanup of old package storage layouts. (#1030)

Improved

  • Cold-isolate dispatch is ~1.5 seconds faster. The first kody.* capability call inside a fresh isolate was paying for lazy module evaluation of ~500 modules; the hot path now skips that and lands in the same ~40ms band as warm calls. Sequential storage round trips were also cut from the execute hot path — package invocations that stacked 600ms–1.9s of platform overhead now resolve in tens of milliseconds on the lean path. (#1042, #1035, #1046)

  • Scheduled jobs are safer and self-healing. Due jobs are now atomically claimed with expiring leases so two workers can't double-run the same occurrence, transient failures retry with exponential backoff, and each occurrence is deduplicated by a {jobId, scheduledFor} key. Kody also now detects silently dead scheduled jobs — schedules whose alarms stopped firing without any error — and re-arms them automatically. (#1012, #1041)

  • Package delete now cleans up everything it owns. Deleting a package previously orphaned durable storage buckets, app-scoped values, and job scratch state. It now clears every package-owned bucket with per-bucket error tolerance and removes app-scoped values alongside secrets — and app-scoped values are keyed by package id only, so non-package contexts can no longer mint storage buckets under arbitrary keys. Package publish artifact rebuilds also moved to throwaway isolates so large packages can't hit memory limits during rebuild. (#1022, #1026, #1028)

  • Storage entitlement checks are accurate across all buckets. Quota enforcement now aggregates every inventoried storage bucket — including the current bucket before async registration finishes — instead of silently under-counting. Estimates fail closed if any bucket is unreadable, and a bounded retry protects against transient flakes during package deletions. (#1010, #1030)

  • Homepage is ~75% lighter and scores 100 across every PageSpeed category. Route-level code splitting, lazy Sentry, and image optimization cut the critical-path weight from 937KB to a fraction; the hero PNG alone was 339KB. Every remaining PageSpeed audit is now green — doctype fixed (no more quirks mode), CSS inlined for first paint, meta descriptions added, CSP allowlisted for Cloudflare's analytics beacon, and color contrast raised above the AA threshold. (#1021, #1027)

  • Import boundaries are now enforced by lint. The MCP layer can no longer reach into app-layer modules, and the package registry can no longer import MCP internals — a custom lint rule catches static, dynamic, and test-mock imports alike. Six compatibility re-export shims left from the extraction were removed so the coupling can't quietly return. (#1014, #1018)

  • Client route state is deduplicated. Five hand-rolled delete-confirmation flows now share one createDoubleCheck helper, and Account Secrets moved to the shared list/detail route helper with nested-path support — no URL changes. (#1011)

  • OAuth connect helpers extracted and tested. The 2,000-line connect-oauth route was split into a pure-helper module with full characterization tests, and client/server secret normalization now has parity tests so the two sides can't silently drift. (#1019)

  • Docs audited against reality. Every markdown file was checked against current code — wrong ports, stale migration references, contradictory setup instructions, and duplicated architecture docs were corrected. The disaster-recovery runbook now records which Cloudflare resources are intentionally kept on the old account so a future cleanup can't delete live backups. (#1023, #1020, #1043)

Fixed

  • Execute hangs past 90 seconds are gone, and stranded runs self-heal. The sandbox timeout only applied inside the dynamic worker, so evaluate() could hang indefinitely on the host side — leaving runs stuck for hours with no terminal record. There's now a host-side deadline racing the worker evaluation, timed-out queued evaluations are aborted so they can't start late, and outbound fetches have a default timeout. Stranded running rows are marked terminal instead of waiting 24 hours. (#1039)

  • Package service caller mistakes no longer open Sentry issues. When an agent called a package service without a package_id or with an unknown package, the error looked like a platform bug. Those are now classified as caller errors and filtered from Sentry. (#1038)