agents 0.31.0 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/{agent-routing-wS1TimZ_.d.ts → agent-routing-vVMA7m8Y.d.ts} +6 -6
  2. package/dist/agent-routing.d.ts +1 -1
  3. package/dist/agent-tool-types.d.ts +1 -1
  4. package/dist/{agent-tools-Bamxxb6Y.d.ts → agent-tools-gGXXkf1z.d.ts} +2 -2
  5. package/dist/agent-tools.d.ts +1 -1
  6. package/dist/agent-tools.js +0 -1
  7. package/dist/agent-tools.js.map +1 -1
  8. package/dist/browser/ai.js +1 -1
  9. package/dist/browser/tools/ai-sdk.d.ts +66 -1
  10. package/dist/browser/tools/ai-sdk.js +2 -2
  11. package/dist/browser/tools/pi.js +2 -2
  12. package/dist/browser/tools/tanstack-ai.d.ts +2 -2
  13. package/dist/browser/tools/tanstack-ai.js +2 -2
  14. package/dist/browser/tools/tanstack-ai.js.map +1 -1
  15. package/dist/{browser-tool-lGnvEBLJ.js → browser-tool-DRan7Lk6.js} +2 -2
  16. package/dist/{browser-tool-lGnvEBLJ.js.map → browser-tool-DRan7Lk6.js.map} +1 -1
  17. package/dist/catalog-BpOejOsE.js +239 -0
  18. package/dist/catalog-BpOejOsE.js.map +1 -0
  19. package/dist/catalog-BpiVV1OF.d.ts +173 -0
  20. package/dist/chat/index.d.ts +2 -2
  21. package/dist/chat-sdk/index.d.ts +1 -1
  22. package/dist/chat-sdk/index.js +1 -1
  23. package/dist/{client-wn4-yqGz.d.ts → client-eSfgYvd3.d.ts} +2 -2
  24. package/dist/client.d.ts +1 -1
  25. package/dist/{cloudflare-Dzvc7V2N.js → cloudflare-CUUm_9q9.js} +26 -4
  26. package/dist/cloudflare-CUUm_9q9.js.map +1 -0
  27. package/dist/{do-oauth-client-provider-DfsUcpc3.d.ts → do-oauth-client-provider-DtNqv7oj.d.ts} +26 -2
  28. package/dist/{index-YSKgfgg9.d.ts → emitter-BJZtCVjQ.d.ts} +6 -140
  29. package/dist/emitter-DPOVcCln.js +15 -0
  30. package/dist/emitter-DPOVcCln.js.map +1 -0
  31. package/dist/experimental/channels/web/index.js +1 -1
  32. package/dist/harness/container/index.js +0 -1
  33. package/dist/harness/container/index.js.map +1 -1
  34. package/dist/harness/container/runtime/index.js +2 -2
  35. package/dist/harness/opencode/index.js +0 -1
  36. package/dist/harness/opencode/index.js.map +1 -1
  37. package/dist/harness/pi/index.d.ts +11 -4
  38. package/dist/harness/pi/index.js +43 -141
  39. package/dist/harness/pi/index.js.map +1 -1
  40. package/dist/index.d.ts +2 -3
  41. package/dist/index.js +2 -2
  42. package/dist/markdown-BZ-VLtA1.js +86 -0
  43. package/dist/markdown-BZ-VLtA1.js.map +1 -0
  44. package/dist/mcp/client/do-oauth-client-provider.d.ts +4 -2
  45. package/dist/mcp/client/do-oauth-client-provider.js +15 -1
  46. package/dist/mcp/client/do-oauth-client-provider.js.map +1 -1
  47. package/dist/mcp/client/index.d.ts +1 -1
  48. package/dist/mcp/index.d.ts +1 -1
  49. package/dist/mcp/index.js +1 -1
  50. package/dist/models/pi-ai/index.js +129 -2
  51. package/dist/models/pi-ai/index.js.map +1 -1
  52. package/dist/observability/ai/index.js +1 -2
  53. package/dist/observability/ai/index.js.map +1 -1
  54. package/dist/observability/index.d.ts +170 -9
  55. package/dist/observability/index.js +386 -11
  56. package/dist/observability/index.js.map +1 -1
  57. package/dist/react.d.ts +2 -2
  58. package/dist/resource-B59OV2a2.js +325 -0
  59. package/dist/resource-B59OV2a2.js.map +1 -0
  60. package/dist/routing/index.d.ts +1 -1
  61. package/dist/script-CFDLTk5b.d.ts +91 -0
  62. package/dist/script-workspace-BpdAYq1R.d.ts +41 -0
  63. package/dist/serializable.d.ts +1 -1
  64. package/dist/skill-DRBcIBjC.d.ts +221 -0
  65. package/dist/skills/index.d.ts +275 -36
  66. package/dist/skills/index.js +265 -1534
  67. package/dist/skills/index.js.map +1 -1
  68. package/dist/skills/runner.d.ts +37 -0
  69. package/dist/skills/runner.js +912 -0
  70. package/dist/skills/runner.js.map +1 -0
  71. package/dist/skills/tools/ai-sdk.d.ts +36 -0
  72. package/dist/skills/tools/ai-sdk.js +94 -0
  73. package/dist/skills/tools/ai-sdk.js.map +1 -0
  74. package/dist/source-9RQzlEhM.d.ts +112 -0
  75. package/dist/{src-BGolXG_H.js → src-DoGNJ4Ud.js} +4 -5
  76. package/dist/src-DoGNJ4Ud.js.map +1 -0
  77. package/dist/sub-routing.d.ts +1 -1
  78. package/dist/tool-CxKsvxjm.js.map +1 -1
  79. package/dist/tool-DkT_DJBm.js.map +1 -1
  80. package/dist/{tool-helpers-BodWi4gd.js → tool-helpers-BI7ifO2S.js} +1 -2
  81. package/dist/{tool-helpers-BodWi4gd.js.map → tool-helpers-BI7ifO2S.js.map} +1 -1
  82. package/dist/vite.d.ts +2 -2
  83. package/dist/vite.js +10 -258
  84. package/dist/vite.js.map +1 -1
  85. package/dist/voice/index.d.ts +1 -1
  86. package/dist/websockets/index.js +1 -1
  87. package/dist/{websockets-CyoeosdO.js → websockets-C6SJtWCJ.js} +1 -2
  88. package/dist/{websockets-CyoeosdO.js.map → websockets-C6SJtWCJ.js.map} +1 -1
  89. package/dist/workflow-types.d.ts +1 -1
  90. package/dist/workflows.d.ts +1 -1
  91. package/dist/workflows.js +0 -1
  92. package/dist/workflows.js.map +1 -1
  93. package/docs/harnesses/pi.md +9 -3
  94. package/docs/mcp-client.md +23 -1
  95. package/docs/mcp-servers.md +2 -2
  96. package/docs/observability.md +5 -3
  97. package/package.json +24 -15
  98. package/dist/ai-sdk-hW3vntnk.d.ts +0 -72
  99. package/dist/cloudflare-Dzvc7V2N.js.map +0 -1
  100. package/dist/index-iv9FTXX9.d.ts +0 -311
  101. package/dist/skills/compile.d.ts +0 -40
  102. package/dist/skills/compile.js +0 -65
  103. package/dist/skills/compile.js.map +0 -1
  104. package/dist/src-BGolXG_H.js.map +0 -1
  105. package/skills-module.d.ts +0 -22
@@ -1,8 +1,8 @@
1
1
  import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "../../classPrivateFieldGet2-DZBYAB34.js";
2
2
  import { t as _classPrivateMethodInitSpec } from "../../classPrivateMethodInitSpec-qMjJ6sHQ.js";
3
3
  import { t as LifecycleCapability } from "../../capability-DBAKc6UZ.js";
4
- import "../../lifecycle-v1rKHV2C.js";
5
4
  import { isDurableObjectMemoryLimitReset } from "../../retries.js";
5
+ import { i as renderSkillResource, n as formatSkillDiagnostic, r as loadSkillCatalog } from "../../catalog-BpOejOsE.js";
6
6
  import { Type } from "@earendil-works/pi-ai";
7
7
  import { LiveDoc, ROOT_CONVERSATION_ID, watchEvents } from "@earendil-works/pi-durable";
8
8
  import { BACKGROUND_CONTEXT, withAbortSignal } from "@earendil-works/chord/context";
@@ -655,182 +655,84 @@ var PiSessions = class {
655
655
  };
656
656
  //#endregion
657
657
  //#region src/harness/pi/skills.ts
658
- function skillsFingerprint(sources) {
659
- return sources.map((source) => `${source.id}:${source.fingerprint}`).join("|");
660
- }
661
658
  function textResult(text) {
662
659
  return { output: [{
663
660
  type: "text",
664
661
  text
665
662
  }] };
666
663
  }
667
- function attributes(pairs) {
668
- return pairs.filter((pair) => pair[1] !== void 0).map(([key, value]) => ` ${key}="${value.replace(/"/g, """)}"`).join("");
669
- }
670
- function describeResource(resource) {
671
- const details = [
672
- resource.kind,
673
- resource.encoding ?? "text",
674
- resource.mimeType,
675
- resource.size === void 0 ? void 0 : `${resource.size} bytes`
676
- ].filter((value) => value !== void 0);
677
- return `- ${resource.path} (${details.join(", ")})`;
678
- }
679
- function renderSkillContent(skill) {
680
- const resources = skill.content.resources ?? [];
681
- const lines = [`<skill_content${attributes([["name", skill.descriptor.name], ["version", skill.descriptor.version]])}>`, skill.content.body.trim()];
682
- if (resources.length > 0) {
683
- lines.push("<skill_resources>");
684
- for (const resource of resources) lines.push(` <file${attributes([
685
- ["kind", resource.kind],
686
- ["encoding", resource.encoding ?? "text"],
687
- ["size", resource.size === void 0 ? void 0 : String(resource.size)]
688
- ])}>${resource.path}</file>`);
689
- lines.push("</skill_resources>");
690
- }
691
- lines.push("</skill_content>", "");
692
- lines.push(resources.length === 0 ? "No bundled resources." : ["Bundled resources:", ...resources.map(describeResource)].join("\n"));
693
- return lines.join("\n");
664
+ /** A failed tool call: pi sends it to the model as an error result. */
665
+ function errorResult(error) {
666
+ return {
667
+ output: [{
668
+ type: "text",
669
+ text: error.message
670
+ }],
671
+ isError: true
672
+ };
694
673
  }
695
674
  /**
696
- * Resolve `agents/skills` sources into a system-prompt catalog and two
697
- * tools.
698
- *
699
- * The first source to list a name wins, as in `SkillRegistry`. pi-durable
700
- * has no skill concept of its own, so the model activates skills through
701
- * `activate_skill` and reads bundled files through `read_skill_resource` —
702
- * the same tools `@cloudflare/think` offers, so skills authored for one
703
- * framework work in the other.
675
+ * Model-facing tools for a catalog: `activate_skill` and
676
+ * `read_skill_resource`. These match the tools `@cloudflare/think` offers, so
677
+ * a skill behaves the same in both frameworks.
704
678
  */
705
- async function resolveSkillSources(sources) {
706
- const fingerprint = skillsFingerprint(sources);
707
- const warnings = [];
708
- const resolved = /* @__PURE__ */ new Map();
709
- for (const source of sources) {
710
- let descriptors;
711
- try {
712
- descriptors = await source.list();
713
- } catch (error) {
714
- warnings.push(`Skill source "${source.id}" failed to list skills: ${error instanceof Error ? error.message : String(error)}`);
715
- continue;
716
- }
717
- for (const descriptor of descriptors) {
718
- if (resolved.has(descriptor.name)) {
719
- warnings.push(`Skill "${descriptor.name}" from source "${source.id}" is shadowed by an earlier source`);
720
- continue;
721
- }
722
- let content;
723
- try {
724
- content = await source.load(descriptor.name);
725
- } catch (error) {
726
- warnings.push(`Skill "${descriptor.name}" from source "${source.id}" failed to load: ${error instanceof Error ? error.message : String(error)}`);
727
- continue;
728
- }
729
- if (!content) continue;
730
- resolved.set(descriptor.name, {
731
- descriptor,
732
- content,
733
- source
734
- });
735
- }
736
- }
737
- const visible = [...resolved.values()].filter((skill) => skill.descriptor.metadata?.["disable-model-invocation"] !== true);
738
- if (visible.length === 0) return {
739
- fingerprint,
740
- tools: [],
741
- catalog: null,
742
- warnings
743
- };
744
- const names = visible.map((skill) => skill.descriptor.name);
679
+ function skillTools(catalog) {
680
+ const names = catalog.skills.map((entry) => entry.skill.name);
681
+ if (names.length === 0) return [];
745
682
  const nameSchema = Type.Union(names.map((name) => Type.Literal(name)));
746
- const byName = new Map(visible.map((skill) => [skill.descriptor.name, skill]));
747
- const activateSkill = {
683
+ return [{
748
684
  name: "activate_skill",
749
685
  description: "Activate a skill by name. Use this when the user's task matches one of the available skills; the response contains the skill's full instructions.",
750
686
  parameters: Type.Object({ name: nameSchema }),
751
687
  replay: "safe",
752
688
  async execute(input) {
753
- const skill = byName.get(input.name);
754
- return textResult(skill ? renderSkillContent(skill) : `Skill not found: ${input.name}`);
689
+ const activated = catalog.activate(input.name);
690
+ return activated.ok ? textResult(activated.value) : errorResult(activated.error);
755
691
  }
756
- };
757
- const readResource = {
692
+ }, {
758
693
  name: "read_skill_resource",
759
- description: "Read a file bundled with a skill, such as a reference document or template. Provide the skill name and the file's path from the skill's resource list.",
694
+ description: "Read a file bundled with a skill, such as a reference document or template. Provide the skill name and the file's path from the skill's resource list, or a qualified path like skill-name/references/file.md.",
760
695
  parameters: Type.Object({
761
696
  name: Type.Optional(nameSchema),
762
697
  path: Type.String({ minLength: 1 })
763
698
  }),
764
699
  replay: "safe",
765
700
  async execute(input) {
766
- const target = resolveResourceTarget(byName, input.name, input.path);
767
- if (!target) return textResult(`Skill resource not found: ${input.name ? `${input.name}/` : ""}${input.path}`);
768
- const resource = await target.skill.source.readResource?.(target.skill.descriptor.name, target.path).catch(() => null);
769
- if (!resource) return textResult(`Skill resource not found: ${target.skill.descriptor.name}/${target.path}`);
770
- return textResult([
771
- `<skill_resource${attributes([
772
- ["name", target.skill.descriptor.name],
773
- ["path", resource.path],
774
- ["kind", resource.kind],
775
- ["encoding", resource.encoding ?? "text"],
776
- ["mimeType", resource.mimeType]
777
- ])}>`,
778
- resource.content,
779
- "</skill_resource>"
780
- ].join("\n"));
701
+ const read = await catalog.readResource(input.name === void 0 ? { path: input.path } : {
702
+ name: input.name,
703
+ path: input.path
704
+ });
705
+ return read.ok ? textResult(renderSkillResource(read.value)) : errorResult(read.error);
781
706
  }
782
- };
783
- const catalog = [
784
- "Available skills. When a task matches a skill, use activate_skill with its name before proceeding.",
785
- "",
786
- ...visible.map((skill) => `- ${skill.descriptor.name}: ${skill.descriptor.description}`)
787
- ].join("\n");
788
- return {
789
- fingerprint,
790
- tools: [activateSkill, readResource],
791
- catalog,
792
- warnings
793
- };
794
- }
795
- function resolveResourceTarget(byName, name, path) {
796
- if (path.split("/").some((segment) => segment === "..")) return void 0;
797
- if (name !== void 0) {
798
- const skill = byName.get(name);
799
- return skill && hasResource(skill, path) ? {
800
- skill,
801
- path
802
- } : void 0;
803
- }
804
- const [head, ...rest] = path.split("/");
805
- const skill = head === void 0 ? void 0 : byName.get(head);
806
- const relative = rest.join("/");
807
- return skill && relative && hasResource(skill, relative) ? {
808
- skill,
809
- path: relative
810
- } : void 0;
811
- }
812
- function hasResource(skill, path) {
813
- return (skill.content.resources ?? []).some((resource) => resource.path === path);
707
+ }];
814
708
  }
815
709
  /**
816
710
  * `agents/skills` sources as a pi extension, named `agents.skills`: the
817
711
  * activation tools and a `skills` system prompt section. Install it on
818
- * pi's registry in the harness factory.
712
+ * pi's registry in the harness factory. Sources are read once, when the
713
+ * extension is built.
819
714
  *
820
715
  * ```ts
821
- * registry.install(await skills(sources));
716
+ * import * as agentSkills from "agents/skills";
717
+ *
718
+ * registry.install(
719
+ * await skills([agentSkills.workspace(workspace), agentSkills.r2(env.SKILLS)])
720
+ * );
822
721
  * ```
722
+ *
723
+ * @param sources - Skill sources in priority order.
724
+ * @returns The pi extension.
823
725
  */
824
726
  async function skills(sources) {
825
- const resolved = await resolveSkillSources(sources);
826
- for (const warning of resolved.warnings) console.warn(`pi skills: ${warning}`);
827
- const catalog = resolved.catalog;
727
+ const catalog = await loadSkillCatalog(sources);
728
+ for (const diagnostic of catalog.diagnostics) console.warn(`pi skills: ${formatSkillDiagnostic(diagnostic)}`);
729
+ const prompt = catalog.prompt();
828
730
  return {
829
731
  name: "agents.skills",
830
- tools: resolved.tools,
831
- sections: catalog === null ? [] : [{
732
+ tools: skillTools(catalog),
733
+ sections: prompt === null ? [] : [{
832
734
  key: "skills",
833
- render: () => catalog
735
+ render: () => prompt
834
736
  }]
835
737
  };
836
738
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["exhaustive"],"sources":["../../../src/harness/pi/session-store.ts","../../../src/harness/pi/harness.ts","../../../src/harness/pi/skills.ts"],"sourcesContent":["import type { SqliteStorage } from \"@earendil-works/pi-durable/storage/sqlite\";\nimport { openDurableObjectSqliteStorage } from \"@earendil-works/pi-durable/storage/sqlite/cloudflare\";\n\n/**\n * pi's session store on a Durable Object's SQLite database.\n *\n * pi owns its sessions: conversations, entries, tasks, submissions, and\n * documents live in pi's own schema, created and migrated by pi's portable\n * `SqliteStorage` through pi's own Durable Object adapter. The store keeps\n * pi's tables under a prefix, so they cannot collide with the SDK's or the\n * host's tables in the same object.\n *\n * It is the Durable Object counterpart of `agents/sessions` for a harness\n * that brings its own session model, and has nothing pi-harness specific in\n * it: any harness built on pi-durable can open its storage with it.\n */\nexport type PiSessionStoreOptions = {\n /**\n * Prefix for every table and index pi creates. Must not start with `_cf_`,\n * which Durable Objects reserve. Default `pi_`.\n */\n readonly prefix?: string;\n};\n\nconst DEFAULT_PREFIX = \"pi_\";\n\n/** Open pi-durable's storage over this object's SQLite database. */\nexport function openPiSessionStore(\n storage: DurableObjectStorage,\n options: PiSessionStoreOptions = {}\n): Promise<SqliteStorage> {\n const prefix = options.prefix ?? DEFAULT_PREFIX;\n // pi validates the prefix as a SQLite identifier; Durable Objects also\n // reserve `_cf_` in any case, which pi does not know about.\n if (prefix.toLowerCase().startsWith(\"_cf_\")) {\n return Promise.reject(\n new Error(\"The pi session store prefix must not start with _cf_\")\n );\n }\n return openDurableObjectSqliteStorage(storage, { prefix });\n}\n","import type { Api, Model, ModelThinkingLevel } from \"@earendil-works/pi-ai\";\nimport {\n LiveDoc,\n ROOT_CONVERSATION_ID,\n watchEvents,\n type AgentEventStream,\n type Conversation,\n type ConversationId,\n type AgentChange,\n type EntryRecord,\n type Harness,\n type HarnessInspection,\n type ModelRef,\n type SettledSubmissionRecord,\n type TaskId,\n type UserInput,\n type Wake\n} from \"@earendil-works/pi-durable\";\nimport type { SqliteStorage } from \"@earendil-works/pi-durable/storage/sqlite\";\nimport {\n LifecycleCapability,\n type CapabilityStartContext,\n type LifecycleJobContext,\n type LifecycleJobOutcome\n} from \"../../lifecycle\";\nimport { isDurableObjectMemoryLimitReset } from \"../../retries\";\nimport {\n BACKGROUND_CONTEXT,\n withAbortSignal,\n type Context\n} from \"@earendil-works/chord/context\";\nimport { openPiSessionStore } from \"./session-store\";\nimport type {\n PiOperationResult,\n PiPendingOperation,\n PiPromptResponse,\n PiReceipt,\n PiSessionId,\n PiSessionInfo,\n PiSessionOptions,\n PiSubmitOptions\n} from \"./types\";\n\nconst BG = BACKGROUND_CONTEXT;\n\n/** The root session's id. */\nexport const ROOT_SESSION: PiSessionId = String(ROOT_CONVERSATION_ID);\n\n/**\n * The wake timings. They suit a real deployment; only tests change them,\n * with `setWakeTimingForTests`, so a suite does not sit on the real\n * heartbeat.\n *\n * Longest one wake waits on pi. It waits inside an alarm invocation, which\n * has a 15 minute wall-time limit, so a longer run is waited on across\n * several alarms.\n */\nconst WAIT_BUDGET_MS = 10 * 60_000;\n\n/**\n * The wake job's heartbeat while it waits, and how often it re-checks work\n * it cannot wait on, such as background tasks. If the object is evicted, the\n * job is still due and its alarm restarts the object.\n */\nconst HEARTBEAT_MS = 30_000;\n\n/**\n * How often a wait re-reads `pi.wake()` when the factory did not pass\n * `onWake`, so nothing tells the harness when it changes.\n */\nconst POLL_MS = 1_000;\n\n/**\n * The longest a wake job whose dispatch keeps failing waits before it tries\n * again. Its delay starts at the heartbeat and doubles up to this.\n */\nconst MAX_WAKE_BACKOFF_MS = 10 * 60_000;\n\n/**\n * Wake dispatches that failed in a row. Stored, so the backoff holds across\n * restarts, and outside the job: a push that saved it in the job's payload\n * could overwrite a submit's due-now push.\n */\nconst WAKE_ERRORS_KEY = \"pi-harness:wake-errors\";\n\nlet setWakeTiming: (harness: PiHarness, timing: WakeTiming) => void;\n\n/**\n * @internal Shorten a harness's wake timings, so a test suite does not sit\n * on the real heartbeat. Not exported from `agents/harness/pi`.\n */\nexport function setWakeTimingForTests(\n harness: PiHarness,\n timing: WakeTiming\n): void {\n setWakeTiming(harness, timing);\n}\n\nconst WAKE_FN = \"wake\";\n\n/**\n * The one wake job. Before Pi 1.4 there was one per session, with ids\n * `pi-wake:<session>`; a left-over one hands over to this one.\n */\nconst WAKE_JOB_ID = \"pi-wake\";\n\n/**\n * What the factory is handed: the things only the harness can build.\n * Everything else `Harness.open` takes (models, registry, settings, env,\n * onReport) the factory builds itself.\n */\nexport type PiHarnessContext = {\n /** pi's storage over this object's SQLite, its migrations already run. */\n readonly storage: SqliteStorage;\n /** Background context, for the open itself. */\n readonly context: Context;\n /**\n * Pass this to `Harness.open` as its `onWake` option. pi calls it when it\n * next needs to run, and the harness sets this object's alarm for then.\n *\n * With it, pi sets no in-memory timer for a sleeping task (a retry\n * backoff, a poll, a `sleepUntil`), so the object can hibernate until the\n * alarm. Without it the harness still works, but pi's timer keeps the\n * object in memory, and billed, while a task sleeps, and the harness logs\n * a warning when it opens pi.\n *\n * The harness reads pi's wake times against `Date.now()`, so do not pass\n * `now` to `Harness.open`.\n */\n readonly onWake: (wake: Wake) => void;\n};\n\n/**\n * Opens pi's `Harness`. The harness adopts what it returns. Pass `onWake`\n * through to `Harness.open`.\n *\n * ```ts\n * harness: async ({ storage, context, onWake }) => {\n * const registry = createRegistry();\n * registry.install(await skills(sources));\n * return Harness.open(storage, { models, registry, onWake }, context);\n * }\n * ```\n */\nexport type PiHarnessFactory = (\n context: PiHarnessContext\n) => Harness | Promise<Harness>;\n\n/**\n * A model, as pi-ai describes one: `createAI`'s `ai(\"@cf/…\")` returns one.\n *\n * Only its `provider` and `id` are used. pi stores that reference with\n * the session and resolves it, at each request, against the `Models` the\n * factory opened pi with. So the model must be one those `Models` list,\n * and options passed to `ai(id, options)` here, such as `fallback`, are not\n * applied.\n */\nexport type PiModel = Pick<Model<Api>, \"provider\" | \"id\">;\n\n/**\n * Applied to a session the first time it is created. Without a model, a\n * session's generation fails as unanswered until `session.setModel` sets one.\n */\nexport type PiSessionDefaults = {\n /**\n * Model for new sessions, by its `provider` and `id`; it must be on the\n * `Models` the factory opens pi with (see `PiModel`). Change one\n * session's with `session.setModel`.\n */\n readonly model?: PiModel;\n readonly thinkingLevel?: ModelThinkingLevel;\n};\n\n/** How long the wake waits on pi, and how often it checks. */\ntype WakeTiming = {\n /** Longest one wake waits inside an alarm. Default 600_000. */\n readonly waitBudgetMs?: number;\n /** Heartbeat while waiting. Default 30_000. */\n readonly heartbeatMs?: number;\n /** How often a wait re-reads `pi.wake()` without `onWake`. Default 1_000. */\n readonly pollMs?: number;\n};\n\n/** `PiHarness`'s options. Only `harness`, which opens pi, is required. */\nexport type PiHarnessOptions = {\n /** Opens pi's `Harness` over the storage this object prepared. */\n readonly harness: PiHarnessFactory;\n /** What a new session starts with. */\n readonly defaults?: PiSessionDefaults;\n};\n\ntype Opened = {\n readonly pi: Harness;\n readonly storage: SqliteStorage;\n};\n\n/** pi-durable's stored reference to a pi-ai model. */\nfunction modelRef(model: PiModel): ModelRef {\n return { provider: model.provider, modelId: model.id };\n}\n\nfunction conversationId(session: PiSessionId): ConversationId {\n const id = Number(session);\n if (!Number.isSafeInteger(id) || id < 1) {\n throw new Error(`Invalid pi session ${JSON.stringify(session)}`);\n }\n return id as ConversationId;\n}\n\n/** The text of an assistant entry, for an operation's result. */\nfunction assistantText(entry: EntryRecord | undefined): string {\n const message = entry?.model?.[0];\n if (message?.role !== \"assistant\") return \"\";\n return message.content\n .map((part) => (part.type === \"text\" ? part.text : \"\"))\n .join(\"\");\n}\n\nfunction signalContext(signal: AbortSignal | undefined): Context {\n return signal ? withAbortSignal(signal, BG) : BG;\n}\n\n/**\n * pi-durable hosted in a Durable Object, behind a small harness interface:\n * `harness.prompt()`, `harness.sessions`, `harness.session(id)`. How a session reaches a\n * client (sockets, SSE, RPC) is the host's glue, built on `session.events()`.\n *\n * pi owns everything about a run: the transcript, the inbox of steers and\n * follow-ups, generation and tool tasks, retries, crash recovery, and the\n * live view. It keeps all of it in its own tables in this object's SQLite\n * database (see `session-store.ts`).\n *\n * What pi cannot do on a Durable Object is wake itself: its scheduler runs\n * in memory, and an evicted object has no memory. The harness is that wake,\n * with one Lifecycle job driven by `pi.wake()`. Input goes to pi once, in\n * `submit()`, after the job is scheduled. While pi has work running, the\n * job waits on it, rescheduling itself as a heartbeat. While pi's tasks\n * sleep, the job is due when the first one wakes; pi tells the harness\n * through the `onWake` the factory passes to `Harness.open`. When pi has\n * nothing to do, the job completes. An eviction mid-run leaves the job due,\n * so its alarm restarts the object, pi reopens and resumes its own tasks,\n * and the job waits again.\n */\nexport class PiHarness extends LifecycleCapability {\n readonly sessions: PiSessions;\n readonly #options: PiHarnessOptions;\n /** The in-memory wait on pi's running work, inside an alarm's work. */\n #waiting: Promise<void> | undefined;\n /** Resolves the current wait's sleep early: `pi.wake()` changed. */\n #changed: (() => void) | undefined;\n /** Submissions between their wake and pi's admission. */\n #admitting = 0;\n /** Whether pi has called `onWake`, so the factory passed it. */\n #onWakeWired = false;\n #waitBudgetMs = WAIT_BUDGET_MS;\n #heartbeatMs = HEARTBEAT_MS;\n #pollMs = POLL_MS;\n #opening: Promise<Opened> | undefined;\n /** Settles once the last pi that closed on its own has closed. */\n #lastClose: Promise<unknown> = Promise.resolve();\n /** Every pi that has begun closing, on its own or by `dispose()`. */\n readonly #closing = new WeakSet<Harness>();\n\n static {\n setWakeTiming = (harness, timing) => harness.#setWakeTiming(timing);\n }\n\n constructor(options: PiHarnessOptions) {\n super(\"pi-harness\");\n this.#options = options;\n this.sessions = new PiSessions(this);\n }\n\n #setWakeTiming(timing: WakeTiming): void {\n for (const [name, value] of Object.entries(timing)) {\n if (!Number.isFinite(value) || value <= 0) {\n throw new Error(`PiHarness timing.${name} must be a positive number`);\n }\n }\n this.#waitBudgetMs = timing.waitBudgetMs ?? this.#waitBudgetMs;\n this.#heartbeatMs = timing.heartbeatMs ?? this.#heartbeatMs;\n this.#pollMs = timing.pollMs ?? this.#pollMs;\n }\n\n // ── Lifecycle ────────────────────────────────────────────────────────────\n\n override async onStart(_context: CapabilityStartContext): Promise<void> {\n await this.#open();\n }\n\n async onJob(\n context: LifecycleJobContext\n ): Promise<LifecycleJobOutcome | void> {\n if (context.job.fn !== WAKE_FN) return;\n let outcome: LifecycleJobOutcome;\n if (context.job.id !== WAKE_JOB_ID) {\n // A per-session wake from before Pi 1.4: hand over to the one wake.\n await this.#wake();\n outcome = undefined;\n } else {\n outcome = await this.#wakeStep();\n }\n // It got through, so a failing wake's backoff starts over.\n const kv = this.lifecycle.storage.kv;\n if (kv.get(WAKE_ERRORS_KEY) !== undefined) kv.delete(WAKE_ERRORS_KEY);\n return outcome;\n }\n\n /**\n * A wake dispatch that failed through Lifecycle's retries, as when pi\n * cannot be opened. Lifecycle would complete the job, and pi's work would\n * never be woken again, so try again later: at the heartbeat, doubling\n * while the failures continue, up to 10 minutes.\n */\n onJobError(\n context: LifecycleJobContext,\n error: unknown\n ): LifecycleJobOutcome | void {\n if (context.job.fn !== WAKE_FN) return;\n console.error(\n `pi wake job \"${context.job.id}\" failed after ${context.attempt} ` +\n \"attempts; retrying with backoff\",\n error\n );\n this.#wakeError(error);\n const kv = this.lifecycle.storage.kv;\n const errors = (kv.get<number>(WAKE_ERRORS_KEY) ?? 0) + 1;\n kv.put(WAKE_ERRORS_KEY, errors);\n const delay = Math.min(\n this.#heartbeatMs * 2 ** (errors - 1),\n MAX_WAKE_BACKOFF_MS\n );\n return { rescheduleAt: Date.now() + delay };\n }\n\n /** Close pi's in-memory resources. Durable state is untouched. */\n async dispose(): Promise<void> {\n const opening = this.#opening;\n this.#opening = undefined;\n const opened = await opening?.catch(() => undefined);\n // Closing calls #piClosing, which also ends a wait sleeping on this pi.\n await opened?.pi.close(BG);\n }\n\n // ── The harness interface ────────────────────────────────────────────────\n\n /** A handle on one session. No I/O until you call it. */\n session(id: PiSessionId = ROOT_SESSION): PiSession {\n return new PiSession(this, id);\n }\n\n /** Submit a prompt and wait for its answer. */\n prompt(\n input: UserInput,\n options: PiSubmitOptions = {}\n ): Promise<PiPromptResponse> {\n return this.session(options.session).prompt(input, options);\n }\n\n /** Durably submit a prompt. Resolves before the model runs. */\n submit(input: UserInput, options: PiSubmitOptions = {}): Promise<PiReceipt> {\n return this.session(options.session).submit(input, options);\n }\n\n /** Stop one operation, or everything running in a session. */\n abort(\n options: PiSessionOptions & { readonly operationId?: string } = {}\n ): Promise<boolean> {\n return this.session(options.session).abort(options.operationId);\n }\n\n /**\n * Run again the tasks pi's crash-loop guard parked in a session's work.\n * False when nothing was parked.\n */\n retry(options: PiSessionOptions = {}): Promise<boolean> {\n return this.session(options.session).retry();\n }\n\n wait(\n operationId: string,\n options: PiSessionOptions & { readonly signal?: AbortSignal } = {}\n ): Promise<PiOperationResult> {\n return this.session(options.session).wait(operationId, options.signal);\n }\n\n /** The session's active transcript, as pi's entries. */\n messages(options: PiSessionOptions = {}): Promise<EntryRecord[]> {\n return this.session(options.session).messages();\n }\n\n /** Submissions pi has not settled yet, oldest first. */\n async pending(options: PiSessionOptions = {}): Promise<PiPendingOperation[]> {\n const { pi } = await this.#open();\n const id =\n options.session === undefined\n ? undefined\n : conversationId(options.session);\n const inspection = await pi.inspect(BG);\n const parked = await this.#parked(inspection);\n return inspection.submissions.flatMap((record): PiPendingOperation[] => {\n if (record.requestId === undefined) return [];\n if (id !== undefined && record.conversationId !== id) return [];\n let status: PiPendingOperation[\"status\"];\n switch (record.status) {\n case \"queued\":\n status = \"queued\";\n break;\n case \"placed\":\n status = parked.some((task) =>\n task.sessions.has(record.conversationId)\n )\n ? \"parked\"\n : \"running\";\n break;\n case \"done\":\n case \"unanswered\":\n // Settled. pi's inspection holds only unsettled submissions.\n return [];\n default: {\n // A status added by a newer pi: decide what it reports.\n const exhaustive: never = record;\n return exhaustive;\n }\n }\n return [\n {\n operationId: record.requestId,\n session: String(record.conversationId),\n status\n }\n ];\n });\n }\n\n /** The opened pi Harness, for anything the interface does not cover. */\n async pi(): Promise<Harness> {\n return (await this.#open()).pi;\n }\n\n // ── Used by PiSession and PiSessions ─────────────────────────────────────\n\n /** @internal */\n async conversation(session: PiSessionId): Promise<Conversation> {\n const { pi } = await this.#open();\n const conversation = await pi.conversation(conversationId(session), BG);\n if (!conversation) throw new Error(`Unknown pi session ${session}`);\n return conversation;\n }\n\n /** @internal */\n async storage(): Promise<SqliteStorage> {\n return (await this.#open()).storage;\n }\n\n /** @internal */\n async enqueue(\n session: PiSessionId,\n input: UserInput,\n options: PiSubmitOptions\n ): Promise<PiReceipt> {\n const operationId = options.operationId ?? crypto.randomUUID();\n const { storage } = await this.#open();\n const conversation = await this.conversation(session);\n const accepted = await this.#admit(async () => {\n // The one admission. pi deduplicates by request id.\n const accepted =\n (await storage.submissionByRequest(\n conversation.id,\n operationId,\n BG\n )) === undefined;\n await conversation.submit(\n {\n type: \"input\",\n content: input,\n whenBusy: options.whenBusy ?? \"followUp\",\n requestId: operationId,\n ...(options.entry ? { entry: options.entry } : {})\n },\n BG\n );\n return accepted;\n });\n return { operationId, session, accepted };\n }\n\n /** @internal Run again the tasks pi's restart limit parked in a session. */\n async retryParked(session: PiSessionId): Promise<boolean> {\n const { pi } = await this.#open();\n const id = conversationId(session);\n const parked = (await this.#parked(await pi.inspect(BG))).filter((task) =>\n task.sessions.has(id)\n );\n if (parked.length === 0) return false;\n await this.#admit(async () => {\n for (const task of parked) await pi.retryTask(task.id, BG);\n });\n return true;\n }\n\n /** @internal Withdraw a queued input, or abort the run it joined. */\n async withdraw(session: PiSessionId, operationId: string): Promise<boolean> {\n const { pi, storage } = await this.#open();\n const id = conversationId(session);\n const record = await storage.submissionByRequest(id, operationId, BG);\n if (!record || record.status === \"done\" || record.status === \"unanswered\") {\n return false;\n }\n const outcome = await pi.abortSubmission(record.id, BG, id);\n switch (outcome) {\n case \"aborted\":\n return true;\n case \"already_placed\":\n await (await pi.conversation(id, BG))?.abort(BG);\n return true;\n case \"settled\":\n case \"not_found\":\n return false;\n default: {\n // An outcome added by a newer pi: decide whether it withdrew.\n const exhaustive: never = outcome;\n return exhaustive;\n }\n }\n }\n\n /** @internal Wait for pi to settle an operation, by its request id. */\n async settled(\n session: PiSessionId,\n operationId: string,\n signal?: AbortSignal\n ): Promise<PiOperationResult> {\n const conversation = await this.conversation(session);\n const context = signalContext(signal);\n const submission = await this.#findSubmission(\n conversation.id,\n operationId,\n context\n );\n if (!submission) {\n return {\n operationId,\n session,\n status: \"unanswered\",\n reason: \"not_found\"\n };\n }\n return this.#result(\n session,\n operationId,\n await submission.wait(context),\n context\n );\n }\n\n // ── The wake ─────────────────────────────────────────────────────────────\n\n /**\n * Hand pi work inside the wake. The wake is scheduled first, so if the\n * object dies after pi has the work, that job restarts it; while `hand`\n * is in flight the step will not complete. The wake steps again after, so\n * it sees the work even if it just completed.\n */\n async #admit<T>(hand: () => Promise<T>): Promise<T> {\n this.#admitting++;\n let result: T;\n try {\n await this.#wake();\n result = await hand();\n } finally {\n this.#admitting--;\n }\n await this.#wake();\n return result;\n }\n\n /** Schedule the wake job now, or at `time`. */\n #wake(time = Date.now()): Promise<unknown> {\n // A push made while the job is dispatching supersedes that dispatch's\n // outcome, so a submit is never lost to a wake that is completing.\n return this.lifecycle.jobs.push({\n id: WAKE_JOB_ID,\n fn: WAKE_FN,\n time,\n singleflight: true,\n recoveryLoop: true\n });\n }\n\n /** Schedule the wake job for what `pi.wake()` says, if pi needs one. */\n async #wakeFor(wake: Wake): Promise<void> {\n if (wake.active) await this.#wake();\n else if (wake.at !== undefined) await this.#wake(wake.at);\n }\n\n /**\n * pi's `onWake`, handed to the factory. pi calls it after open and\n * whenever `pi.wake()` changes. It must not block, so the job push is\n * left running.\n */\n readonly #onWake = (wake: Wake): void => {\n this.#onWakeWired = true;\n this.#changed?.();\n // A running wait re-reads pi.wake() and steps again when it ends.\n if (this.#waiting) return;\n this.#wakeFor(wake).catch((error: unknown) => this.#wakeError(error));\n };\n\n /**\n * One run of the wake job. It never admits or replays anything: it reads\n * `pi.wake()`, which is all of pi's sessions at once. Running work is\n * waited on; a sleep reschedules the job for when it ends; no work\n * completes the job. pi does all the work in between.\n */\n async #wakeStep(): Promise<LifecycleJobOutcome> {\n const heartbeat = { rescheduleAt: Date.now() + this.#heartbeatMs };\n if (this.#waiting) return heartbeat;\n const { pi } = await this.#open();\n // The alarm may be for a sleeping task: make due ones runnable.\n pi.resume();\n const wake = pi.wake();\n if (wake.active) {\n const wait = this.#waitWhileActive(pi).then(\n (ended) => {\n this.#waiting = undefined;\n // Step again now: pi may be sleeping, or have nothing left. After\n // a failed wait, as when pi's Session fails, the heartbeat that is\n // already due steps instead, so a pi that keeps failing is not\n // reopened in a loop.\n if (ended) void this.#wake();\n },\n (error: unknown) => {\n // A memory-limit reset: the alarm's breaker backs the job off.\n this.#waiting = undefined;\n throw error;\n }\n );\n this.#waiting = wait;\n // The wait runs past this dispatch, inside the alarm's work, so the\n // object stays alive for it, and a memory-limit reset it ends with\n // counts against the alarm's breaker. The heartbeat covers an\n // eviction.\n if (!this.lifecycle.trackAlarmWork(wait)) wait.catch(() => {});\n return heartbeat;\n }\n // A submit between its wake and pi's admission: check again later.\n if (this.#admitting > 0) return heartbeat;\n if (wake.at !== undefined) return { rescheduleAt: wake.at };\n // Nothing to do. A task parked by pi's restart limit is not work: it\n // waits for `retry()`.\n return undefined;\n }\n\n /**\n * Wait while pi has work running, up to the wait budget. With `onWake`, a\n * change ends each sleep early, and so does pi closing; without it, the\n * sleep is `pollMs`. A task sleeping beside the running work, such as a\n * retry backoff, also ends the sleep when it is due, and the wait calls\n * `pi.resume()` to run it: with `onWake`, pi arms no timer for it, and\n * the wake job's alarm is not set for it while the job waits. Whether the\n * wait ended, with pi idle or at the budget, rather than failing. Rejects\n * with a memory-limit reset.\n */\n async #waitWhileActive(pi: Harness): Promise<boolean> {\n const deadline = Date.now() + this.#waitBudgetMs;\n try {\n // Once pi begins closing, pi.wake() throws (SessionFailed after a\n // storage error), which is what ends this loop: a closed pi's wake does\n // not go inactive. Closing kicks `#changed` only so the loop reads it\n // again now rather than at the end of its sleep.\n let wake = pi.wake();\n while (wake.active) {\n const now = Date.now();\n const left = deadline - now;\n if (left <= 0) return true;\n let sleep = this.#onWakeWired ? left : Math.min(left, this.#pollMs);\n // `at` is a sleep not yet due on pi's clock, so this is positive.\n // That holds because pi keeps its default clock, `Date.now`; see\n // `PiHarnessContext`.\n if (wake.at !== undefined) sleep = Math.min(sleep, wake.at - now);\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, sleep);\n this.#changed = () => {\n clearTimeout(timer);\n resolve();\n };\n });\n this.#changed = undefined;\n // A sleep beside the running work came due: make it runnable.\n if (wake.at !== undefined && Date.now() >= wake.at) pi.resume();\n wake = pi.wake();\n }\n return true;\n } catch (error) {\n // A pi that began closing is expected to throw; it is no longer the\n // harness's pi, and Pi reports a failure itself (`session_failed`).\n if (!this.#closing.has(pi)) this.#wakeError(error);\n // Only Lifecycle's alarm breaker can act on a memory-limit reset,\n // including one that failed pi's Session (SessionFailed's cause).\n if (isDurableObjectMemoryLimitReset(error)) throw error;\n return false;\n }\n }\n\n #wakeError(error: unknown): void {\n this.lifecycle.events.emit(\"pi:wake_error\", {\n error: error instanceof Error ? error.message : String(error)\n });\n }\n\n // ── pi ───────────────────────────────────────────────────────────────────\n\n /**\n * pi, opened. Waits for Lifecycle startup first, so pi is only ever\n * opened inside it: startup holds the input gate (`blockConcurrencyWhile`)\n * and awaits the open in `onStart`, so an open begun before startup would\n * be awaited behind a closed gate, with its timers and I/O held back, and\n * never finish.\n *\n * pi stays open until `dispose()`, or until it closes on its own: any\n * storage error fails pi's Session for good. Then the next call, or the\n * wake job's next step, opens pi again once the failed pi has closed, and\n * pi recovers from what it had committed. Closing waits for running task\n * code to return, so code that ignores its abort signal delays the reopen.\n * An open that fails is not kept either, so the next call tries again.\n */\n async #open(): Promise<Opened> {\n await this.lifecycle.ready();\n if (this.#opening === undefined) {\n const opening: Promise<Opened> = this.#doOpen((pi, closed) =>\n this.#piClosing(opening, pi, closed)\n ).catch((error: unknown) => {\n if (this.#opening === opening) this.#opening = undefined;\n throw error;\n });\n this.#opening = opening;\n }\n return this.#opening;\n }\n\n async #doOpen(\n onClose: (pi: Harness, closed: Promise<unknown>) => void\n ): Promise<Opened> {\n // A pi that closed on its own closes its storage last, after its tasks\n // have returned; let it finish before another opens over the same\n // database.\n await this.#lastClose;\n const storage = await openPiSessionStore(this.lifecycle.storage);\n const pi = await this.#options.harness({\n storage,\n context: BG,\n onWake: this.#onWake\n });\n try {\n const closed = pi.closed;\n // Called synchronously when pi begins closing, unlike `closed`, so a\n // closed pi is never handed out. It must not call pi.\n pi.subscribeClose(() => onClose(pi, closed));\n await pi.root(BG, { agent: this.agentDefaults() });\n // Continue whatever the last pi left, in this isolate or the last one:\n // pi reconciles tasks that were running to pending and schedules them\n // again.\n pi.resume();\n // pi calls onWake right after open, from a microtask.\n await new Promise((resolve) => setTimeout(resolve, 0));\n if (!this.#onWakeWired) {\n console.warn(\n \"PiHarness: the harness factory did not pass onWake to Harness.open, \" +\n \"so pi's timers keep this Durable Object in memory while a task \" +\n \"sleeps. Pass it: harness: ({ storage, context, onWake }) => \" +\n \"Harness.open(storage, { ...options, onWake }, context)\"\n );\n }\n // Whatever the last pi left gets a wake, including work whose wake\n // failed out. With `onWake`, pi has already said so; this covers a\n // factory without it. The job id is fixed, so this is idempotent.\n await this.#wakeFor(pi.wake());\n } catch (error) {\n // pi is open and running its tasks: close it, so the next open does\n // not start a second pi over the same database beside it.\n pi.close(BG).catch(() => {});\n throw error;\n }\n return { pi, storage };\n }\n\n /**\n * pi began closing: on its own, as a storage error makes it, or by\n * `dispose()`.\n */\n #piClosing(\n opening: Promise<Opened>,\n pi: Harness,\n closed: Promise<unknown>\n ): void {\n this.#closing.add(pi);\n // End a wait sleeping on this pi now: pi will not call onWake again.\n this.#changed?.();\n // `dispose()` took its pi out of `#opening` already, and an open begun\n // since must stay.\n if (this.#opening !== opening) return;\n // Drop it, so the next call opens pi again once this one has closed.\n this.#opening = undefined;\n this.#lastClose = closed;\n }\n\n /** @internal The per-conversation defaults supported by pi-durable. */\n agentDefaults(): AgentChange {\n const defaults = this.#options.defaults;\n return {\n ...(defaults?.model === undefined\n ? {}\n : { model: modelRef(defaults.model) }),\n ...(defaults?.thinkingLevel === undefined\n ? {}\n : { thinkingLevel: defaults.thinkingLevel })\n };\n }\n\n /**\n * Tasks pi's restart limit parked, each with the sessions whose work it\n * is: its own, and every session that owns that one, such as the session\n * of a tool that started a subagent.\n */\n async #parked(\n inspection: HarnessInspection\n ): Promise<{ id: TaskId; sessions: Set<ConversationId> }[]> {\n const { storage } = await this.#open();\n const parked: { id: TaskId; sessions: Set<ConversationId> }[] = [];\n for (const { record, state } of inspection.tasks) {\n if (state.kind !== \"blocked\" || state.reason !== \"restart_limit\") {\n continue;\n }\n const sessions = new Set<ConversationId>();\n let id: ConversationId | undefined = record.conversationId;\n while (id !== undefined && !sessions.has(id)) {\n sessions.add(id);\n id = (await storage.conversation(id, BG))?.owner?.conversationId;\n }\n parked.push({ id: record.id, sessions });\n }\n return parked;\n }\n\n async #findSubmission(\n id: ConversationId,\n operationId: string,\n context: Context\n ) {\n const { pi, storage } = await this.#open();\n // Read from pi's storage: the Harness only reacquires submissions by id.\n const record = await storage.submissionByRequest(id, operationId, context);\n return record ? pi.submission(record.id, context) : undefined;\n }\n\n async #result(\n session: PiSessionId,\n operationId: string,\n settled: SettledSubmissionRecord,\n context: Context\n ): Promise<PiOperationResult> {\n if (settled.status === \"unanswered\") {\n return {\n operationId,\n session,\n status: \"unanswered\",\n reason: settled.reason\n };\n }\n if (settled.type !== \"input\")\n return { operationId, session, status: \"done\" };\n const conversation = await this.conversation(session);\n const page = await conversation.entries(\n { minEntryId: settled.answer, maxEntryId: settled.answer },\n 1,\n undefined,\n context\n );\n return {\n operationId,\n session,\n status: \"done\",\n text: assistantText(page.items[0])\n };\n }\n}\n\n/** One pi conversation, addressed through the harness. */\nexport class PiSession {\n readonly #harness: PiHarness;\n readonly id: PiSessionId;\n\n constructor(harness: PiHarness, id: PiSessionId) {\n this.#harness = harness;\n this.id = id;\n }\n\n /** Durably submit a prompt. Resolves before the model runs. */\n submit(input: UserInput, options: PiSubmitOptions = {}): Promise<PiReceipt> {\n return this.#harness.enqueue(this.id, input, options);\n }\n\n /** Submit and wait for the answer and the updated transcript. */\n async prompt(\n input: UserInput,\n options: PiSubmitOptions = {}\n ): Promise<PiPromptResponse> {\n const receipt = await this.submit(input, options);\n const result = await this.wait(receipt.operationId);\n return { ...result, messages: await this.messages() };\n }\n\n /** Join the running work after its current tool round. */\n steer(input: UserInput, options: Omit<PiSubmitOptions, \"whenBusy\"> = {}) {\n return this.submit(input, { ...options, whenBusy: \"steer\" });\n }\n\n /** Wait for an operation to settle. Aborting `signal` stops only the wait. */\n wait(operationId: string, signal?: AbortSignal): Promise<PiOperationResult> {\n return this.#harness.settled(this.id, operationId, signal);\n }\n\n /**\n * Withdraw one queued operation (or abort the run it joined), or, with no\n * id, abort the session: pi withdraws queued inputs and aborts the\n * running work.\n */\n async abort(operationId?: string): Promise<boolean> {\n if (operationId !== undefined) {\n return this.#harness.withdraw(this.id, operationId);\n }\n const conversation = await this.#harness.conversation(this.id);\n await conversation.abort(BG);\n return true;\n }\n\n /**\n * Run again the tasks pi's crash-loop guard (`settings.restartLimit`)\n * parked in this session's work, including subagent sessions it owns.\n * False when nothing was parked.\n */\n retry(): Promise<boolean> {\n return this.#harness.retryParked(this.id);\n }\n\n /** Start a new context, optionally from a handoff note. */\n async reset(handoff?: string): Promise<void> {\n await (await this.#harness.conversation(this.id)).reset(handoff, BG);\n }\n\n /**\n * Change this session's model, by its `provider` and `id`; it must be on\n * the `Models` the factory opened pi with (see `PiModel`).\n */\n async setModel(model: PiModel): Promise<void> {\n await (\n await this.#harness.conversation(this.id)\n ).configure({ model: modelRef(model) }, BG);\n }\n\n /** The active transcript, as pi's entries since the newest reset. */\n async messages(): Promise<EntryRecord[]> {\n const view = await (await this.#harness.conversation(this.id)).context(BG);\n return [...view.entries];\n }\n\n /** pi's agent events for this session: a snapshot, then one batch per commit. */\n async events(context: Context = BG): Promise<AgentEventStream> {\n const pi = await this.#harness.pi();\n return watchEvents(pi, conversationId(this.id), context);\n }\n\n async busy(): Promise<boolean> {\n const pi = await this.#harness.pi();\n const live = await pi.snapshot(LiveDoc, conversationId(this.id), BG);\n return live?.run !== undefined;\n }\n}\n\n/** Every pi conversation in this object. */\nexport class PiSessions {\n readonly #harness: PiHarness;\n\n constructor(harness: PiHarness) {\n this.#harness = harness;\n }\n\n get(id: PiSessionId): PiSession {\n return this.#harness.session(id);\n }\n\n /** A new top-level session, configured like the root. */\n async create(): Promise<PiSession> {\n const pi = await this.#harness.pi();\n const conversation = await pi.createConversation(\n {\n ownership: { kind: \"ownerless\" },\n agent: this.#harness.agentDefaults()\n },\n BG\n );\n return this.#harness.session(String(conversation.id));\n }\n\n /** A new session that sees `from`'s history up to its newest entry. */\n async fork(from: PiSessionId): Promise<PiSession> {\n const conversation = await this.#harness.conversation(from);\n const newest = await conversation.entries({}, 1, undefined, BG);\n const at = newest.items[0];\n if (!at) throw new Error(`Session ${from} has no entries to fork from`);\n const fork = await conversation.fork(\n at.id,\n { ownership: { kind: \"ownerless\" } },\n BG\n );\n return this.#harness.session(String(fork.id));\n }\n\n /**\n * Every conversation, including ones subagent tools own. Read from pi's\n * storage directly: the Harness has no conversation listing.\n */\n async list(): Promise<PiSessionInfo[]> {\n const storage = await this.#harness.storage();\n const pi = await this.#harness.pi();\n const sessions: PiSessionInfo[] = [];\n let cursor: Parameters<SqliteStorage[\"scanConversations\"]>[2];\n for (;;) {\n const page = await storage.scanConversations({}, 100, cursor, BG);\n for (const record of page.items) {\n const live = await pi.snapshot(LiveDoc, record.id, BG);\n sessions.push({\n id: String(record.id),\n ...(record.parent\n ? { parent: String(record.parent.conversationId) }\n : {}),\n busy: live?.run !== undefined\n });\n }\n if (page.next === undefined) return sessions;\n cursor = page.next;\n }\n }\n}\n","import { Type } from \"@earendil-works/pi-ai\";\nimport type {\n Extension,\n ToolExecutionResult,\n ToolRegistration\n} from \"@earendil-works/pi-durable\";\nimport type {\n SkillContent,\n SkillDescriptor,\n SkillResourceDescriptor,\n SkillSource\n} from \"../../skills\";\n\n/** Skills resolved from `agents/skills` sources for one process lifetime. */\nexport type ResolvedSkills = {\n /** Changes when any source's fingerprint changes. */\n readonly fingerprint: string;\n /** Model-facing activation tools; empty when there are no skills. */\n readonly tools: readonly ToolRegistration[];\n /** System-prompt catalog, or null when there are no skills. */\n readonly catalog: string | null;\n readonly warnings: readonly string[];\n};\n\ntype ResolvedSkill = {\n readonly descriptor: SkillDescriptor;\n readonly content: SkillContent;\n readonly source: SkillSource;\n};\n\nexport function skillsFingerprint(sources: readonly SkillSource[]): string {\n return sources\n .map((source) => `${source.id}:${source.fingerprint}`)\n .join(\"|\");\n}\n\nfunction textResult(text: string): ToolExecutionResult {\n return { output: [{ type: \"text\", text }] };\n}\n\nfunction attributes(\n pairs: ReadonlyArray<readonly [string, string | undefined]>\n) {\n return pairs\n .filter((pair): pair is readonly [string, string] => pair[1] !== undefined)\n .map(([key, value]) => ` ${key}=\"${value.replace(/\"/g, \"&quot;\")}\"`)\n .join(\"\");\n}\n\nfunction describeResource(resource: SkillResourceDescriptor): string {\n const details = [\n resource.kind,\n resource.encoding ?? \"text\",\n resource.mimeType,\n resource.size === undefined ? undefined : `${resource.size} bytes`\n ].filter((value): value is string => value !== undefined);\n return `- ${resource.path} (${details.join(\", \")})`;\n}\n\nfunction renderSkillContent(skill: ResolvedSkill): string {\n const resources = skill.content.resources ?? [];\n const lines = [\n `<skill_content${attributes([\n [\"name\", skill.descriptor.name],\n [\"version\", skill.descriptor.version]\n ])}>`,\n skill.content.body.trim()\n ];\n if (resources.length > 0) {\n lines.push(\"<skill_resources>\");\n for (const resource of resources) {\n lines.push(\n ` <file${attributes([\n [\"kind\", resource.kind],\n [\"encoding\", resource.encoding ?? \"text\"],\n [\n \"size\",\n resource.size === undefined ? undefined : String(resource.size)\n ]\n ])}>${resource.path}</file>`\n );\n }\n lines.push(\"</skill_resources>\");\n }\n lines.push(\"</skill_content>\", \"\");\n lines.push(\n resources.length === 0\n ? \"No bundled resources.\"\n : [\"Bundled resources:\", ...resources.map(describeResource)].join(\"\\n\")\n );\n return lines.join(\"\\n\");\n}\n\n/**\n * Resolve `agents/skills` sources into a system-prompt catalog and two\n * tools.\n *\n * The first source to list a name wins, as in `SkillRegistry`. pi-durable\n * has no skill concept of its own, so the model activates skills through\n * `activate_skill` and reads bundled files through `read_skill_resource` —\n * the same tools `@cloudflare/think` offers, so skills authored for one\n * framework work in the other.\n */\nexport async function resolveSkillSources(\n sources: readonly SkillSource[]\n): Promise<ResolvedSkills> {\n const fingerprint = skillsFingerprint(sources);\n const warnings: string[] = [];\n const resolved = new Map<string, ResolvedSkill>();\n for (const source of sources) {\n let descriptors: SkillDescriptor[];\n try {\n descriptors = await source.list();\n } catch (error) {\n warnings.push(\n `Skill source \"${source.id}\" failed to list skills: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n continue;\n }\n for (const descriptor of descriptors) {\n if (resolved.has(descriptor.name)) {\n warnings.push(\n `Skill \"${descriptor.name}\" from source \"${source.id}\" is shadowed by an earlier source`\n );\n continue;\n }\n let content: SkillContent | null;\n try {\n content = await source.load(descriptor.name);\n } catch (error) {\n warnings.push(\n `Skill \"${descriptor.name}\" from source \"${source.id}\" failed to load: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n continue;\n }\n if (!content) continue;\n resolved.set(descriptor.name, { descriptor, content, source });\n }\n }\n\n const visible = [...resolved.values()].filter(\n (skill) => skill.descriptor.metadata?.[\"disable-model-invocation\"] !== true\n );\n if (visible.length === 0) {\n return { fingerprint, tools: [], catalog: null, warnings };\n }\n\n const names = visible.map((skill) => skill.descriptor.name);\n const nameSchema = Type.Union(names.map((name) => Type.Literal(name)));\n const byName = new Map(\n visible.map((skill) => [skill.descriptor.name, skill])\n );\n\n const activateParameters = Type.Object({ name: nameSchema });\n const activateSkill: ToolRegistration<typeof activateParameters> = {\n name: \"activate_skill\",\n description:\n \"Activate a skill by name. Use this when the user's task matches one of the available skills; the response contains the skill's full instructions.\",\n parameters: activateParameters,\n replay: \"safe\",\n async execute(input) {\n const skill = byName.get(input.name);\n return textResult(\n skill ? renderSkillContent(skill) : `Skill not found: ${input.name}`\n );\n }\n };\n\n const resourceParameters = Type.Object({\n name: Type.Optional(nameSchema),\n path: Type.String({ minLength: 1 })\n });\n const readResource: ToolRegistration<typeof resourceParameters> = {\n name: \"read_skill_resource\",\n description:\n \"Read a file bundled with a skill, such as a reference document or template. Provide the skill name and the file's path from the skill's resource list.\",\n parameters: resourceParameters,\n replay: \"safe\",\n async execute(input) {\n const target = resolveResourceTarget(byName, input.name, input.path);\n if (!target) {\n return textResult(\n `Skill resource not found: ${input.name ? `${input.name}/` : \"\"}${input.path}`\n );\n }\n const resource = await target.skill.source\n .readResource?.(target.skill.descriptor.name, target.path)\n .catch(() => null);\n if (!resource) {\n return textResult(\n `Skill resource not found: ${target.skill.descriptor.name}/${target.path}`\n );\n }\n return textResult(\n [\n `<skill_resource${attributes([\n [\"name\", target.skill.descriptor.name],\n [\"path\", resource.path],\n [\"kind\", resource.kind],\n [\"encoding\", resource.encoding ?? \"text\"],\n [\"mimeType\", resource.mimeType]\n ])}>`,\n resource.content,\n \"</skill_resource>\"\n ].join(\"\\n\")\n );\n }\n };\n\n const catalog = [\n \"Available skills. When a task matches a skill, use activate_skill with its name before proceeding.\",\n \"\",\n ...visible.map(\n (skill) => `- ${skill.descriptor.name}: ${skill.descriptor.description}`\n )\n ].join(\"\\n\");\n\n return {\n fingerprint,\n tools: [activateSkill, readResource],\n catalog,\n warnings\n };\n}\n\nfunction resolveResourceTarget(\n byName: ReadonlyMap<string, ResolvedSkill>,\n name: string | undefined,\n path: string\n): { readonly skill: ResolvedSkill; readonly path: string } | undefined {\n if (path.split(\"/\").some((segment) => segment === \"..\")) return undefined;\n if (name !== undefined) {\n const skill = byName.get(name);\n return skill && hasResource(skill, path) ? { skill, path } : undefined;\n }\n // A qualified path names the skill in its first segment.\n const [head, ...rest] = path.split(\"/\");\n const skill = head === undefined ? undefined : byName.get(head);\n const relative = rest.join(\"/\");\n return skill && relative && hasResource(skill, relative)\n ? { skill, path: relative }\n : undefined;\n}\n\nfunction hasResource(skill: ResolvedSkill, path: string): boolean {\n return (skill.content.resources ?? []).some(\n (resource) => resource.path === path\n );\n}\n\n/**\n * `agents/skills` sources as a pi extension, named `agents.skills`: the\n * activation tools and a `skills` system prompt section. Install it on\n * pi's registry in the harness factory.\n *\n * ```ts\n * registry.install(await skills(sources));\n * ```\n */\nexport async function skills(\n sources: readonly SkillSource[]\n): Promise<Extension> {\n const resolved = await resolveSkillSources(sources);\n for (const warning of resolved.warnings) {\n console.warn(`pi skills: ${warning}`);\n }\n const catalog = resolved.catalog;\n return {\n name: \"agents.skills\",\n tools: resolved.tools,\n sections: catalog === null ? [] : [{ key: \"skills\", render: () => catalog }]\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["exhaustive"],"sources":["../../../src/harness/pi/session-store.ts","../../../src/harness/pi/harness.ts","../../../src/harness/pi/skills.ts"],"sourcesContent":["import type { SqliteStorage } from \"@earendil-works/pi-durable/storage/sqlite\";\nimport { openDurableObjectSqliteStorage } from \"@earendil-works/pi-durable/storage/sqlite/cloudflare\";\n\n/**\n * pi's session store on a Durable Object's SQLite database.\n *\n * pi owns its sessions: conversations, entries, tasks, submissions, and\n * documents live in pi's own schema, created and migrated by pi's portable\n * `SqliteStorage` through pi's own Durable Object adapter. The store keeps\n * pi's tables under a prefix, so they cannot collide with the SDK's or the\n * host's tables in the same object.\n *\n * It is the Durable Object counterpart of `agents/sessions` for a harness\n * that brings its own session model, and has nothing pi-harness specific in\n * it: any harness built on pi-durable can open its storage with it.\n */\nexport type PiSessionStoreOptions = {\n /**\n * Prefix for every table and index pi creates. Must not start with `_cf_`,\n * which Durable Objects reserve. Default `pi_`.\n */\n readonly prefix?: string;\n};\n\nconst DEFAULT_PREFIX = \"pi_\";\n\n/** Open pi-durable's storage over this object's SQLite database. */\nexport function openPiSessionStore(\n storage: DurableObjectStorage,\n options: PiSessionStoreOptions = {}\n): Promise<SqliteStorage> {\n const prefix = options.prefix ?? DEFAULT_PREFIX;\n // pi validates the prefix as a SQLite identifier; Durable Objects also\n // reserve `_cf_` in any case, which pi does not know about.\n if (prefix.toLowerCase().startsWith(\"_cf_\")) {\n return Promise.reject(\n new Error(\"The pi session store prefix must not start with _cf_\")\n );\n }\n return openDurableObjectSqliteStorage(storage, { prefix });\n}\n","import type { Api, Model, ModelThinkingLevel } from \"@earendil-works/pi-ai\";\nimport {\n LiveDoc,\n ROOT_CONVERSATION_ID,\n watchEvents,\n type AgentEventStream,\n type Conversation,\n type ConversationId,\n type AgentChange,\n type EntryRecord,\n type Harness,\n type HarnessInspection,\n type ModelRef,\n type SettledSubmissionRecord,\n type TaskId,\n type UserInput,\n type Wake\n} from \"@earendil-works/pi-durable\";\nimport type { SqliteStorage } from \"@earendil-works/pi-durable/storage/sqlite\";\nimport {\n LifecycleCapability,\n type CapabilityStartContext,\n type LifecycleJobContext,\n type LifecycleJobOutcome\n} from \"../../lifecycle\";\nimport { isDurableObjectMemoryLimitReset } from \"../../retries\";\nimport {\n BACKGROUND_CONTEXT,\n withAbortSignal,\n type Context\n} from \"@earendil-works/chord/context\";\nimport { openPiSessionStore } from \"./session-store\";\nimport type {\n PiOperationResult,\n PiPendingOperation,\n PiPromptResponse,\n PiReceipt,\n PiSessionId,\n PiSessionInfo,\n PiSessionOptions,\n PiSubmitOptions\n} from \"./types\";\n\nconst BG = BACKGROUND_CONTEXT;\n\n/** The root session's id. */\nexport const ROOT_SESSION: PiSessionId = String(ROOT_CONVERSATION_ID);\n\n/**\n * The wake timings. They suit a real deployment; only tests change them,\n * with `setWakeTimingForTests`, so a suite does not sit on the real\n * heartbeat.\n *\n * Longest one wake waits on pi. It waits inside an alarm invocation, which\n * has a 15 minute wall-time limit, so a longer run is waited on across\n * several alarms.\n */\nconst WAIT_BUDGET_MS = 10 * 60_000;\n\n/**\n * The wake job's heartbeat while it waits, and how often it re-checks work\n * it cannot wait on, such as background tasks. If the object is evicted, the\n * job is still due and its alarm restarts the object.\n */\nconst HEARTBEAT_MS = 30_000;\n\n/**\n * How often a wait re-reads `pi.wake()` when the factory did not pass\n * `onWake`, so nothing tells the harness when it changes.\n */\nconst POLL_MS = 1_000;\n\n/**\n * The longest a wake job whose dispatch keeps failing waits before it tries\n * again. Its delay starts at the heartbeat and doubles up to this.\n */\nconst MAX_WAKE_BACKOFF_MS = 10 * 60_000;\n\n/**\n * Wake dispatches that failed in a row. Stored, so the backoff holds across\n * restarts, and outside the job: a push that saved it in the job's payload\n * could overwrite a submit's due-now push.\n */\nconst WAKE_ERRORS_KEY = \"pi-harness:wake-errors\";\n\nlet setWakeTiming: (harness: PiHarness, timing: WakeTiming) => void;\n\n/**\n * @internal Shorten a harness's wake timings, so a test suite does not sit\n * on the real heartbeat. Not exported from `agents/harness/pi`.\n */\nexport function setWakeTimingForTests(\n harness: PiHarness,\n timing: WakeTiming\n): void {\n setWakeTiming(harness, timing);\n}\n\nconst WAKE_FN = \"wake\";\n\n/**\n * The one wake job. Before Pi 1.4 there was one per session, with ids\n * `pi-wake:<session>`; a left-over one hands over to this one.\n */\nconst WAKE_JOB_ID = \"pi-wake\";\n\n/**\n * What the factory is handed: the things only the harness can build.\n * Everything else `Harness.open` takes (models, registry, settings, env,\n * onReport) the factory builds itself.\n */\nexport type PiHarnessContext = {\n /** pi's storage over this object's SQLite, its migrations already run. */\n readonly storage: SqliteStorage;\n /** Background context, for the open itself. */\n readonly context: Context;\n /**\n * Pass this to `Harness.open` as its `onWake` option. pi calls it when it\n * next needs to run, and the harness sets this object's alarm for then.\n *\n * With it, pi sets no in-memory timer for a sleeping task (a retry\n * backoff, a poll, a `sleepUntil`), so the object can hibernate until the\n * alarm. Without it the harness still works, but pi's timer keeps the\n * object in memory, and billed, while a task sleeps, and the harness logs\n * a warning when it opens pi.\n *\n * The harness reads pi's wake times against `Date.now()`, so do not pass\n * `now` to `Harness.open`.\n */\n readonly onWake: (wake: Wake) => void;\n};\n\n/**\n * Opens pi's `Harness`. The harness adopts what it returns. Pass `onWake`\n * through to `Harness.open`.\n *\n * ```ts\n * harness: async ({ storage, context, onWake }) => {\n * const registry = createRegistry();\n * registry.install(await skills(sources));\n * return Harness.open(storage, { models, registry, onWake }, context);\n * }\n * ```\n */\nexport type PiHarnessFactory = (\n context: PiHarnessContext\n) => Harness | Promise<Harness>;\n\n/**\n * A model, as pi-ai describes one: `createAI`'s `ai(\"@cf/…\")` returns one.\n *\n * Only its `provider` and `id` are used. pi stores that reference with\n * the session and resolves it, at each request, against the `Models` the\n * factory opened pi with. So the model must be one those `Models` list,\n * and options passed to `ai(id, options)` here, such as `fallback`, are not\n * applied.\n */\nexport type PiModel = Pick<Model<Api>, \"provider\" | \"id\">;\n\n/**\n * Applied to a session the first time it is created. Without a model, a\n * session's generation fails as unanswered until `session.setModel` sets one.\n */\nexport type PiSessionDefaults = {\n /**\n * Model for new sessions, by its `provider` and `id`; it must be on the\n * `Models` the factory opens pi with (see `PiModel`). Change one\n * session's with `session.setModel`.\n */\n readonly model?: PiModel;\n readonly thinkingLevel?: ModelThinkingLevel;\n};\n\n/** How long the wake waits on pi, and how often it checks. */\ntype WakeTiming = {\n /** Longest one wake waits inside an alarm. Default 600_000. */\n readonly waitBudgetMs?: number;\n /** Heartbeat while waiting. Default 30_000. */\n readonly heartbeatMs?: number;\n /** How often a wait re-reads `pi.wake()` without `onWake`. Default 1_000. */\n readonly pollMs?: number;\n};\n\n/** `PiHarness`'s options. Only `harness`, which opens pi, is required. */\nexport type PiHarnessOptions = {\n /** Opens pi's `Harness` over the storage this object prepared. */\n readonly harness: PiHarnessFactory;\n /** What a new session starts with. */\n readonly defaults?: PiSessionDefaults;\n};\n\ntype Opened = {\n readonly pi: Harness;\n readonly storage: SqliteStorage;\n};\n\n/** pi-durable's stored reference to a pi-ai model. */\nfunction modelRef(model: PiModel): ModelRef {\n return { provider: model.provider, modelId: model.id };\n}\n\nfunction conversationId(session: PiSessionId): ConversationId {\n const id = Number(session);\n if (!Number.isSafeInteger(id) || id < 1) {\n throw new Error(`Invalid pi session ${JSON.stringify(session)}`);\n }\n return id as ConversationId;\n}\n\n/** The text of an assistant entry, for an operation's result. */\nfunction assistantText(entry: EntryRecord | undefined): string {\n const message = entry?.model?.[0];\n if (message?.role !== \"assistant\") return \"\";\n return message.content\n .map((part) => (part.type === \"text\" ? part.text : \"\"))\n .join(\"\");\n}\n\nfunction signalContext(signal: AbortSignal | undefined): Context {\n return signal ? withAbortSignal(signal, BG) : BG;\n}\n\n/**\n * pi-durable hosted in a Durable Object, behind a small harness interface:\n * `harness.prompt()`, `harness.sessions`, `harness.session(id)`. How a session reaches a\n * client (sockets, SSE, RPC) is the host's glue, built on `session.events()`.\n *\n * pi owns everything about a run: the transcript, the inbox of steers and\n * follow-ups, generation and tool tasks, retries, crash recovery, and the\n * live view. It keeps all of it in its own tables in this object's SQLite\n * database (see `session-store.ts`).\n *\n * What pi cannot do on a Durable Object is wake itself: its scheduler runs\n * in memory, and an evicted object has no memory. The harness is that wake,\n * with one Lifecycle job driven by `pi.wake()`. Input goes to pi once, in\n * `submit()`, after the job is scheduled. While pi has work running, the\n * job waits on it, rescheduling itself as a heartbeat. While pi's tasks\n * sleep, the job is due when the first one wakes; pi tells the harness\n * through the `onWake` the factory passes to `Harness.open`. When pi has\n * nothing to do, the job completes. An eviction mid-run leaves the job due,\n * so its alarm restarts the object, pi reopens and resumes its own tasks,\n * and the job waits again.\n */\nexport class PiHarness extends LifecycleCapability {\n readonly sessions: PiSessions;\n readonly #options: PiHarnessOptions;\n /** The in-memory wait on pi's running work, inside an alarm's work. */\n #waiting: Promise<void> | undefined;\n /** Resolves the current wait's sleep early: `pi.wake()` changed. */\n #changed: (() => void) | undefined;\n /** Submissions between their wake and pi's admission. */\n #admitting = 0;\n /** Whether pi has called `onWake`, so the factory passed it. */\n #onWakeWired = false;\n #waitBudgetMs = WAIT_BUDGET_MS;\n #heartbeatMs = HEARTBEAT_MS;\n #pollMs = POLL_MS;\n #opening: Promise<Opened> | undefined;\n /** Settles once the last pi that closed on its own has closed. */\n #lastClose: Promise<unknown> = Promise.resolve();\n /** Every pi that has begun closing, on its own or by `dispose()`. */\n readonly #closing = new WeakSet<Harness>();\n\n static {\n setWakeTiming = (harness, timing) => harness.#setWakeTiming(timing);\n }\n\n constructor(options: PiHarnessOptions) {\n super(\"pi-harness\");\n this.#options = options;\n this.sessions = new PiSessions(this);\n }\n\n #setWakeTiming(timing: WakeTiming): void {\n for (const [name, value] of Object.entries(timing)) {\n if (!Number.isFinite(value) || value <= 0) {\n throw new Error(`PiHarness timing.${name} must be a positive number`);\n }\n }\n this.#waitBudgetMs = timing.waitBudgetMs ?? this.#waitBudgetMs;\n this.#heartbeatMs = timing.heartbeatMs ?? this.#heartbeatMs;\n this.#pollMs = timing.pollMs ?? this.#pollMs;\n }\n\n // ── Lifecycle ────────────────────────────────────────────────────────────\n\n override async onStart(_context: CapabilityStartContext): Promise<void> {\n await this.#open();\n }\n\n async onJob(\n context: LifecycleJobContext\n ): Promise<LifecycleJobOutcome | void> {\n if (context.job.fn !== WAKE_FN) return;\n let outcome: LifecycleJobOutcome;\n if (context.job.id !== WAKE_JOB_ID) {\n // A per-session wake from before Pi 1.4: hand over to the one wake.\n await this.#wake();\n outcome = undefined;\n } else {\n outcome = await this.#wakeStep();\n }\n // It got through, so a failing wake's backoff starts over.\n const kv = this.lifecycle.storage.kv;\n if (kv.get(WAKE_ERRORS_KEY) !== undefined) kv.delete(WAKE_ERRORS_KEY);\n return outcome;\n }\n\n /**\n * A wake dispatch that failed through Lifecycle's retries, as when pi\n * cannot be opened. Lifecycle would complete the job, and pi's work would\n * never be woken again, so try again later: at the heartbeat, doubling\n * while the failures continue, up to 10 minutes.\n */\n onJobError(\n context: LifecycleJobContext,\n error: unknown\n ): LifecycleJobOutcome | void {\n if (context.job.fn !== WAKE_FN) return;\n console.error(\n `pi wake job \"${context.job.id}\" failed after ${context.attempt} ` +\n \"attempts; retrying with backoff\",\n error\n );\n this.#wakeError(error);\n const kv = this.lifecycle.storage.kv;\n const errors = (kv.get<number>(WAKE_ERRORS_KEY) ?? 0) + 1;\n kv.put(WAKE_ERRORS_KEY, errors);\n const delay = Math.min(\n this.#heartbeatMs * 2 ** (errors - 1),\n MAX_WAKE_BACKOFF_MS\n );\n return { rescheduleAt: Date.now() + delay };\n }\n\n /** Close pi's in-memory resources. Durable state is untouched. */\n async dispose(): Promise<void> {\n const opening = this.#opening;\n this.#opening = undefined;\n const opened = await opening?.catch(() => undefined);\n // Closing calls #piClosing, which also ends a wait sleeping on this pi.\n await opened?.pi.close(BG);\n }\n\n // ── The harness interface ────────────────────────────────────────────────\n\n /** A handle on one session. No I/O until you call it. */\n session(id: PiSessionId = ROOT_SESSION): PiSession {\n return new PiSession(this, id);\n }\n\n /** Submit a prompt and wait for its answer. */\n prompt(\n input: UserInput,\n options: PiSubmitOptions = {}\n ): Promise<PiPromptResponse> {\n return this.session(options.session).prompt(input, options);\n }\n\n /** Durably submit a prompt. Resolves before the model runs. */\n submit(input: UserInput, options: PiSubmitOptions = {}): Promise<PiReceipt> {\n return this.session(options.session).submit(input, options);\n }\n\n /** Stop one operation, or everything running in a session. */\n abort(\n options: PiSessionOptions & { readonly operationId?: string } = {}\n ): Promise<boolean> {\n return this.session(options.session).abort(options.operationId);\n }\n\n /**\n * Run again the tasks pi's crash-loop guard parked in a session's work.\n * False when nothing was parked.\n */\n retry(options: PiSessionOptions = {}): Promise<boolean> {\n return this.session(options.session).retry();\n }\n\n wait(\n operationId: string,\n options: PiSessionOptions & { readonly signal?: AbortSignal } = {}\n ): Promise<PiOperationResult> {\n return this.session(options.session).wait(operationId, options.signal);\n }\n\n /** The session's active transcript, as pi's entries. */\n messages(options: PiSessionOptions = {}): Promise<EntryRecord[]> {\n return this.session(options.session).messages();\n }\n\n /** Submissions pi has not settled yet, oldest first. */\n async pending(options: PiSessionOptions = {}): Promise<PiPendingOperation[]> {\n const { pi } = await this.#open();\n const id =\n options.session === undefined\n ? undefined\n : conversationId(options.session);\n const inspection = await pi.inspect(BG);\n const parked = await this.#parked(inspection);\n return inspection.submissions.flatMap((record): PiPendingOperation[] => {\n if (record.requestId === undefined) return [];\n if (id !== undefined && record.conversationId !== id) return [];\n let status: PiPendingOperation[\"status\"];\n switch (record.status) {\n case \"queued\":\n status = \"queued\";\n break;\n case \"placed\":\n status = parked.some((task) =>\n task.sessions.has(record.conversationId)\n )\n ? \"parked\"\n : \"running\";\n break;\n case \"done\":\n case \"unanswered\":\n // Settled. pi's inspection holds only unsettled submissions.\n return [];\n default: {\n // A status added by a newer pi: decide what it reports.\n const exhaustive: never = record;\n return exhaustive;\n }\n }\n return [\n {\n operationId: record.requestId,\n session: String(record.conversationId),\n status\n }\n ];\n });\n }\n\n /** The opened pi Harness, for anything the interface does not cover. */\n async pi(): Promise<Harness> {\n return (await this.#open()).pi;\n }\n\n // ── Used by PiSession and PiSessions ─────────────────────────────────────\n\n /** @internal */\n async conversation(session: PiSessionId): Promise<Conversation> {\n const { pi } = await this.#open();\n const conversation = await pi.conversation(conversationId(session), BG);\n if (!conversation) throw new Error(`Unknown pi session ${session}`);\n return conversation;\n }\n\n /** @internal */\n async storage(): Promise<SqliteStorage> {\n return (await this.#open()).storage;\n }\n\n /** @internal */\n async enqueue(\n session: PiSessionId,\n input: UserInput,\n options: PiSubmitOptions\n ): Promise<PiReceipt> {\n const operationId = options.operationId ?? crypto.randomUUID();\n const { storage } = await this.#open();\n const conversation = await this.conversation(session);\n const accepted = await this.#admit(async () => {\n // The one admission. pi deduplicates by request id.\n const accepted =\n (await storage.submissionByRequest(\n conversation.id,\n operationId,\n BG\n )) === undefined;\n await conversation.submit(\n {\n type: \"input\",\n content: input,\n whenBusy: options.whenBusy ?? \"followUp\",\n requestId: operationId,\n ...(options.entry ? { entry: options.entry } : {})\n },\n BG\n );\n return accepted;\n });\n return { operationId, session, accepted };\n }\n\n /** @internal Run again the tasks pi's restart limit parked in a session. */\n async retryParked(session: PiSessionId): Promise<boolean> {\n const { pi } = await this.#open();\n const id = conversationId(session);\n const parked = (await this.#parked(await pi.inspect(BG))).filter((task) =>\n task.sessions.has(id)\n );\n if (parked.length === 0) return false;\n await this.#admit(async () => {\n for (const task of parked) await pi.retryTask(task.id, BG);\n });\n return true;\n }\n\n /** @internal Withdraw a queued input, or abort the run it joined. */\n async withdraw(session: PiSessionId, operationId: string): Promise<boolean> {\n const { pi, storage } = await this.#open();\n const id = conversationId(session);\n const record = await storage.submissionByRequest(id, operationId, BG);\n if (!record || record.status === \"done\" || record.status === \"unanswered\") {\n return false;\n }\n const outcome = await pi.abortSubmission(record.id, BG, id);\n switch (outcome) {\n case \"aborted\":\n return true;\n case \"already_placed\":\n await (await pi.conversation(id, BG))?.abort(BG);\n return true;\n case \"settled\":\n case \"not_found\":\n return false;\n default: {\n // An outcome added by a newer pi: decide whether it withdrew.\n const exhaustive: never = outcome;\n return exhaustive;\n }\n }\n }\n\n /** @internal Wait for pi to settle an operation, by its request id. */\n async settled(\n session: PiSessionId,\n operationId: string,\n signal?: AbortSignal\n ): Promise<PiOperationResult> {\n const conversation = await this.conversation(session);\n const context = signalContext(signal);\n const submission = await this.#findSubmission(\n conversation.id,\n operationId,\n context\n );\n if (!submission) {\n return {\n operationId,\n session,\n status: \"unanswered\",\n reason: \"not_found\"\n };\n }\n return this.#result(\n session,\n operationId,\n await submission.wait(context),\n context\n );\n }\n\n // ── The wake ─────────────────────────────────────────────────────────────\n\n /**\n * Hand pi work inside the wake. The wake is scheduled first, so if the\n * object dies after pi has the work, that job restarts it; while `hand`\n * is in flight the step will not complete. The wake steps again after, so\n * it sees the work even if it just completed.\n */\n async #admit<T>(hand: () => Promise<T>): Promise<T> {\n this.#admitting++;\n let result: T;\n try {\n await this.#wake();\n result = await hand();\n } finally {\n this.#admitting--;\n }\n await this.#wake();\n return result;\n }\n\n /** Schedule the wake job now, or at `time`. */\n #wake(time = Date.now()): Promise<unknown> {\n // A push made while the job is dispatching supersedes that dispatch's\n // outcome, so a submit is never lost to a wake that is completing.\n return this.lifecycle.jobs.push({\n id: WAKE_JOB_ID,\n fn: WAKE_FN,\n time,\n singleflight: true,\n recoveryLoop: true\n });\n }\n\n /** Schedule the wake job for what `pi.wake()` says, if pi needs one. */\n async #wakeFor(wake: Wake): Promise<void> {\n if (wake.active) await this.#wake();\n else if (wake.at !== undefined) await this.#wake(wake.at);\n }\n\n /**\n * pi's `onWake`, handed to the factory. pi calls it after open and\n * whenever `pi.wake()` changes. It must not block, so the job push is\n * left running.\n */\n readonly #onWake = (wake: Wake): void => {\n this.#onWakeWired = true;\n this.#changed?.();\n // A running wait re-reads pi.wake() and steps again when it ends.\n if (this.#waiting) return;\n this.#wakeFor(wake).catch((error: unknown) => this.#wakeError(error));\n };\n\n /**\n * One run of the wake job. It never admits or replays anything: it reads\n * `pi.wake()`, which is all of pi's sessions at once. Running work is\n * waited on; a sleep reschedules the job for when it ends; no work\n * completes the job. pi does all the work in between.\n */\n async #wakeStep(): Promise<LifecycleJobOutcome> {\n const heartbeat = { rescheduleAt: Date.now() + this.#heartbeatMs };\n if (this.#waiting) return heartbeat;\n const { pi } = await this.#open();\n // The alarm may be for a sleeping task: make due ones runnable.\n pi.resume();\n const wake = pi.wake();\n if (wake.active) {\n const wait = this.#waitWhileActive(pi).then(\n (ended) => {\n this.#waiting = undefined;\n // Step again now: pi may be sleeping, or have nothing left. After\n // a failed wait, as when pi's Session fails, the heartbeat that is\n // already due steps instead, so a pi that keeps failing is not\n // reopened in a loop.\n if (ended) void this.#wake();\n },\n (error: unknown) => {\n // A memory-limit reset: the alarm's breaker backs the job off.\n this.#waiting = undefined;\n throw error;\n }\n );\n this.#waiting = wait;\n // The wait runs past this dispatch, inside the alarm's work, so the\n // object stays alive for it, and a memory-limit reset it ends with\n // counts against the alarm's breaker. The heartbeat covers an\n // eviction.\n if (!this.lifecycle.trackAlarmWork(wait)) wait.catch(() => {});\n return heartbeat;\n }\n // A submit between its wake and pi's admission: check again later.\n if (this.#admitting > 0) return heartbeat;\n if (wake.at !== undefined) return { rescheduleAt: wake.at };\n // Nothing to do. A task parked by pi's restart limit is not work: it\n // waits for `retry()`.\n return undefined;\n }\n\n /**\n * Wait while pi has work running, up to the wait budget. With `onWake`, a\n * change ends each sleep early, and so does pi closing; without it, the\n * sleep is `pollMs`. A task sleeping beside the running work, such as a\n * retry backoff, also ends the sleep when it is due, and the wait calls\n * `pi.resume()` to run it: with `onWake`, pi arms no timer for it, and\n * the wake job's alarm is not set for it while the job waits. Whether the\n * wait ended, with pi idle or at the budget, rather than failing. Rejects\n * with a memory-limit reset.\n */\n async #waitWhileActive(pi: Harness): Promise<boolean> {\n const deadline = Date.now() + this.#waitBudgetMs;\n try {\n // Once pi begins closing, pi.wake() throws (SessionFailed after a\n // storage error), which is what ends this loop: a closed pi's wake does\n // not go inactive. Closing kicks `#changed` only so the loop reads it\n // again now rather than at the end of its sleep.\n let wake = pi.wake();\n while (wake.active) {\n const now = Date.now();\n const left = deadline - now;\n if (left <= 0) return true;\n let sleep = this.#onWakeWired ? left : Math.min(left, this.#pollMs);\n // `at` is a sleep not yet due on pi's clock, so this is positive.\n // That holds because pi keeps its default clock, `Date.now`; see\n // `PiHarnessContext`.\n if (wake.at !== undefined) sleep = Math.min(sleep, wake.at - now);\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, sleep);\n this.#changed = () => {\n clearTimeout(timer);\n resolve();\n };\n });\n this.#changed = undefined;\n // A sleep beside the running work came due: make it runnable.\n if (wake.at !== undefined && Date.now() >= wake.at) pi.resume();\n wake = pi.wake();\n }\n return true;\n } catch (error) {\n // A pi that began closing is expected to throw; it is no longer the\n // harness's pi, and Pi reports a failure itself (`session_failed`).\n if (!this.#closing.has(pi)) this.#wakeError(error);\n // Only Lifecycle's alarm breaker can act on a memory-limit reset,\n // including one that failed pi's Session (SessionFailed's cause).\n if (isDurableObjectMemoryLimitReset(error)) throw error;\n return false;\n }\n }\n\n #wakeError(error: unknown): void {\n this.lifecycle.events.emit(\"pi:wake_error\", {\n error: error instanceof Error ? error.message : String(error)\n });\n }\n\n // ── pi ───────────────────────────────────────────────────────────────────\n\n /**\n * pi, opened. Waits for Lifecycle startup first, so pi is only ever\n * opened inside it: startup holds the input gate (`blockConcurrencyWhile`)\n * and awaits the open in `onStart`, so an open begun before startup would\n * be awaited behind a closed gate, with its timers and I/O held back, and\n * never finish.\n *\n * pi stays open until `dispose()`, or until it closes on its own: any\n * storage error fails pi's Session for good. Then the next call, or the\n * wake job's next step, opens pi again once the failed pi has closed, and\n * pi recovers from what it had committed. Closing waits for running task\n * code to return, so code that ignores its abort signal delays the reopen.\n * An open that fails is not kept either, so the next call tries again.\n */\n async #open(): Promise<Opened> {\n await this.lifecycle.ready();\n if (this.#opening === undefined) {\n const opening: Promise<Opened> = this.#doOpen((pi, closed) =>\n this.#piClosing(opening, pi, closed)\n ).catch((error: unknown) => {\n if (this.#opening === opening) this.#opening = undefined;\n throw error;\n });\n this.#opening = opening;\n }\n return this.#opening;\n }\n\n async #doOpen(\n onClose: (pi: Harness, closed: Promise<unknown>) => void\n ): Promise<Opened> {\n // A pi that closed on its own closes its storage last, after its tasks\n // have returned; let it finish before another opens over the same\n // database.\n await this.#lastClose;\n const storage = await openPiSessionStore(this.lifecycle.storage);\n const pi = await this.#options.harness({\n storage,\n context: BG,\n onWake: this.#onWake\n });\n try {\n const closed = pi.closed;\n // Called synchronously when pi begins closing, unlike `closed`, so a\n // closed pi is never handed out. It must not call pi.\n pi.subscribeClose(() => onClose(pi, closed));\n await pi.root(BG, { agent: this.agentDefaults() });\n // Continue whatever the last pi left, in this isolate or the last one:\n // pi reconciles tasks that were running to pending and schedules them\n // again.\n pi.resume();\n // pi calls onWake right after open, from a microtask.\n await new Promise((resolve) => setTimeout(resolve, 0));\n if (!this.#onWakeWired) {\n console.warn(\n \"PiHarness: the harness factory did not pass onWake to Harness.open, \" +\n \"so pi's timers keep this Durable Object in memory while a task \" +\n \"sleeps. Pass it: harness: ({ storage, context, onWake }) => \" +\n \"Harness.open(storage, { ...options, onWake }, context)\"\n );\n }\n // Whatever the last pi left gets a wake, including work whose wake\n // failed out. With `onWake`, pi has already said so; this covers a\n // factory without it. The job id is fixed, so this is idempotent.\n await this.#wakeFor(pi.wake());\n } catch (error) {\n // pi is open and running its tasks: close it, so the next open does\n // not start a second pi over the same database beside it.\n pi.close(BG).catch(() => {});\n throw error;\n }\n return { pi, storage };\n }\n\n /**\n * pi began closing: on its own, as a storage error makes it, or by\n * `dispose()`.\n */\n #piClosing(\n opening: Promise<Opened>,\n pi: Harness,\n closed: Promise<unknown>\n ): void {\n this.#closing.add(pi);\n // End a wait sleeping on this pi now: pi will not call onWake again.\n this.#changed?.();\n // `dispose()` took its pi out of `#opening` already, and an open begun\n // since must stay.\n if (this.#opening !== opening) return;\n // Drop it, so the next call opens pi again once this one has closed.\n this.#opening = undefined;\n this.#lastClose = closed;\n }\n\n /** @internal The per-conversation defaults supported by pi-durable. */\n agentDefaults(): AgentChange {\n const defaults = this.#options.defaults;\n return {\n ...(defaults?.model === undefined\n ? {}\n : { model: modelRef(defaults.model) }),\n ...(defaults?.thinkingLevel === undefined\n ? {}\n : { thinkingLevel: defaults.thinkingLevel })\n };\n }\n\n /**\n * Tasks pi's restart limit parked, each with the sessions whose work it\n * is: its own, and every session that owns that one, such as the session\n * of a tool that started a subagent.\n */\n async #parked(\n inspection: HarnessInspection\n ): Promise<{ id: TaskId; sessions: Set<ConversationId> }[]> {\n const { storage } = await this.#open();\n const parked: { id: TaskId; sessions: Set<ConversationId> }[] = [];\n for (const { record, state } of inspection.tasks) {\n if (state.kind !== \"blocked\" || state.reason !== \"restart_limit\") {\n continue;\n }\n const sessions = new Set<ConversationId>();\n let id: ConversationId | undefined = record.conversationId;\n while (id !== undefined && !sessions.has(id)) {\n sessions.add(id);\n id = (await storage.conversation(id, BG))?.owner?.conversationId;\n }\n parked.push({ id: record.id, sessions });\n }\n return parked;\n }\n\n async #findSubmission(\n id: ConversationId,\n operationId: string,\n context: Context\n ) {\n const { pi, storage } = await this.#open();\n // Read from pi's storage: the Harness only reacquires submissions by id.\n const record = await storage.submissionByRequest(id, operationId, context);\n return record ? pi.submission(record.id, context) : undefined;\n }\n\n async #result(\n session: PiSessionId,\n operationId: string,\n settled: SettledSubmissionRecord,\n context: Context\n ): Promise<PiOperationResult> {\n if (settled.status === \"unanswered\") {\n return {\n operationId,\n session,\n status: \"unanswered\",\n reason: settled.reason\n };\n }\n if (settled.type !== \"input\")\n return { operationId, session, status: \"done\" };\n const conversation = await this.conversation(session);\n const page = await conversation.entries(\n { minEntryId: settled.answer, maxEntryId: settled.answer },\n 1,\n undefined,\n context\n );\n return {\n operationId,\n session,\n status: \"done\",\n text: assistantText(page.items[0])\n };\n }\n}\n\n/** One pi conversation, addressed through the harness. */\nexport class PiSession {\n readonly #harness: PiHarness;\n readonly id: PiSessionId;\n\n constructor(harness: PiHarness, id: PiSessionId) {\n this.#harness = harness;\n this.id = id;\n }\n\n /** Durably submit a prompt. Resolves before the model runs. */\n submit(input: UserInput, options: PiSubmitOptions = {}): Promise<PiReceipt> {\n return this.#harness.enqueue(this.id, input, options);\n }\n\n /** Submit and wait for the answer and the updated transcript. */\n async prompt(\n input: UserInput,\n options: PiSubmitOptions = {}\n ): Promise<PiPromptResponse> {\n const receipt = await this.submit(input, options);\n const result = await this.wait(receipt.operationId);\n return { ...result, messages: await this.messages() };\n }\n\n /** Join the running work after its current tool round. */\n steer(input: UserInput, options: Omit<PiSubmitOptions, \"whenBusy\"> = {}) {\n return this.submit(input, { ...options, whenBusy: \"steer\" });\n }\n\n /** Wait for an operation to settle. Aborting `signal` stops only the wait. */\n wait(operationId: string, signal?: AbortSignal): Promise<PiOperationResult> {\n return this.#harness.settled(this.id, operationId, signal);\n }\n\n /**\n * Withdraw one queued operation (or abort the run it joined), or, with no\n * id, abort the session: pi withdraws queued inputs and aborts the\n * running work.\n */\n async abort(operationId?: string): Promise<boolean> {\n if (operationId !== undefined) {\n return this.#harness.withdraw(this.id, operationId);\n }\n const conversation = await this.#harness.conversation(this.id);\n await conversation.abort(BG);\n return true;\n }\n\n /**\n * Run again the tasks pi's crash-loop guard (`settings.restartLimit`)\n * parked in this session's work, including subagent sessions it owns.\n * False when nothing was parked.\n */\n retry(): Promise<boolean> {\n return this.#harness.retryParked(this.id);\n }\n\n /** Start a new context, optionally from a handoff note. */\n async reset(handoff?: string): Promise<void> {\n await (await this.#harness.conversation(this.id)).reset(handoff, BG);\n }\n\n /**\n * Change this session's model, by its `provider` and `id`; it must be on\n * the `Models` the factory opened pi with (see `PiModel`).\n */\n async setModel(model: PiModel): Promise<void> {\n await (\n await this.#harness.conversation(this.id)\n ).configure({ model: modelRef(model) }, BG);\n }\n\n /** The active transcript, as pi's entries since the newest reset. */\n async messages(): Promise<EntryRecord[]> {\n const view = await (await this.#harness.conversation(this.id)).context(BG);\n return [...view.entries];\n }\n\n /** pi's agent events for this session: a snapshot, then one batch per commit. */\n async events(context: Context = BG): Promise<AgentEventStream> {\n const pi = await this.#harness.pi();\n return watchEvents(pi, conversationId(this.id), context);\n }\n\n async busy(): Promise<boolean> {\n const pi = await this.#harness.pi();\n const live = await pi.snapshot(LiveDoc, conversationId(this.id), BG);\n return live?.run !== undefined;\n }\n}\n\n/** Every pi conversation in this object. */\nexport class PiSessions {\n readonly #harness: PiHarness;\n\n constructor(harness: PiHarness) {\n this.#harness = harness;\n }\n\n get(id: PiSessionId): PiSession {\n return this.#harness.session(id);\n }\n\n /** A new top-level session, configured like the root. */\n async create(): Promise<PiSession> {\n const pi = await this.#harness.pi();\n const conversation = await pi.createConversation(\n {\n ownership: { kind: \"ownerless\" },\n agent: this.#harness.agentDefaults()\n },\n BG\n );\n return this.#harness.session(String(conversation.id));\n }\n\n /** A new session that sees `from`'s history up to its newest entry. */\n async fork(from: PiSessionId): Promise<PiSession> {\n const conversation = await this.#harness.conversation(from);\n const newest = await conversation.entries({}, 1, undefined, BG);\n const at = newest.items[0];\n if (!at) throw new Error(`Session ${from} has no entries to fork from`);\n const fork = await conversation.fork(\n at.id,\n { ownership: { kind: \"ownerless\" } },\n BG\n );\n return this.#harness.session(String(fork.id));\n }\n\n /**\n * Every conversation, including ones subagent tools own. Read from pi's\n * storage directly: the Harness has no conversation listing.\n */\n async list(): Promise<PiSessionInfo[]> {\n const storage = await this.#harness.storage();\n const pi = await this.#harness.pi();\n const sessions: PiSessionInfo[] = [];\n let cursor: Parameters<SqliteStorage[\"scanConversations\"]>[2];\n for (;;) {\n const page = await storage.scanConversations({}, 100, cursor, BG);\n for (const record of page.items) {\n const live = await pi.snapshot(LiveDoc, record.id, BG);\n sessions.push({\n id: String(record.id),\n ...(record.parent\n ? { parent: String(record.parent.conversationId) }\n : {}),\n busy: live?.run !== undefined\n });\n }\n if (page.next === undefined) return sessions;\n cursor = page.next;\n }\n }\n}\n","import { Type } from \"@earendil-works/pi-ai\";\nimport type {\n Extension,\n ToolExecutionResult,\n ToolRegistration\n} from \"@earendil-works/pi-durable\";\nimport {\n formatSkillDiagnostic,\n loadSkillCatalog,\n renderSkillResource,\n type SkillCatalog\n} from \"../../skills/catalog\";\nimport type { SkillSource } from \"../../skills/source\";\n\nfunction textResult(text: string): ToolExecutionResult {\n return { output: [{ type: \"text\", text }] };\n}\n\n/** A failed tool call: pi sends it to the model as an error result. */\nfunction errorResult(error: Error): ToolExecutionResult {\n return { output: [{ type: \"text\", text: error.message }], isError: true };\n}\n\n/**\n * Model-facing tools for a catalog: `activate_skill` and\n * `read_skill_resource`. These match the tools `@cloudflare/think` offers, so\n * a skill behaves the same in both frameworks.\n */\nfunction skillTools(catalog: SkillCatalog): ToolRegistration[] {\n const names = catalog.skills.map((entry) => entry.skill.name);\n if (names.length === 0) return [];\n const nameSchema = Type.Union(names.map((name) => Type.Literal(name)));\n\n const activateParameters = Type.Object({ name: nameSchema });\n const activateSkill: ToolRegistration<typeof activateParameters> = {\n name: \"activate_skill\",\n description:\n \"Activate a skill by name. Use this when the user's task matches one of the available skills; the response contains the skill's full instructions.\",\n parameters: activateParameters,\n replay: \"safe\",\n async execute(input) {\n const activated = catalog.activate(input.name);\n return activated.ok\n ? textResult(activated.value)\n : errorResult(activated.error);\n }\n };\n\n const resourceParameters = Type.Object({\n name: Type.Optional(nameSchema),\n path: Type.String({ minLength: 1 })\n });\n const readResource: ToolRegistration<typeof resourceParameters> = {\n name: \"read_skill_resource\",\n description:\n \"Read a file bundled with a skill, such as a reference document or template. Provide the skill name and the file's path from the skill's resource list, or a qualified path like skill-name/references/file.md.\",\n parameters: resourceParameters,\n replay: \"safe\",\n async execute(input) {\n const read = await catalog.readResource(\n input.name === undefined\n ? { path: input.path }\n : { name: input.name, path: input.path }\n );\n return read.ok\n ? textResult(renderSkillResource(read.value))\n : errorResult(read.error);\n }\n };\n\n return [activateSkill, readResource];\n}\n\n/**\n * `agents/skills` sources as a pi extension, named `agents.skills`: the\n * activation tools and a `skills` system prompt section. Install it on\n * pi's registry in the harness factory. Sources are read once, when the\n * extension is built.\n *\n * ```ts\n * import * as agentSkills from \"agents/skills\";\n *\n * registry.install(\n * await skills([agentSkills.workspace(workspace), agentSkills.r2(env.SKILLS)])\n * );\n * ```\n *\n * @param sources - Skill sources in priority order.\n * @returns The pi extension.\n */\nexport async function skills(\n sources: readonly SkillSource[]\n): Promise<Extension> {\n const catalog = await loadSkillCatalog(sources);\n for (const diagnostic of catalog.diagnostics) {\n console.warn(`pi skills: ${formatSkillDiagnostic(diagnostic)}`);\n }\n const prompt = catalog.prompt();\n return {\n name: \"agents.skills\",\n tools: skillTools(catalog),\n sections: prompt === null ? [] : [{ key: \"skills\", render: () => prompt }]\n };\n}\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /// <reference path="../skills-module.d.ts" />
2
1
  import {
3
2
  S as ConnectionContext,
4
3
  T as WSMessage,
@@ -86,7 +85,7 @@ import {
86
85
  x as MCPServer,
87
86
  y as FiberStatus,
88
87
  z as AgentToolEventState
89
- } from "./agent-routing-wS1TimZ_.js";
88
+ } from "./agent-routing-vVMA7m8Y.js";
90
89
  import {
91
90
  a as EmailSendBinding,
92
91
  d as createHeaderBasedEmailResolver,
@@ -97,7 +96,7 @@ import {
97
96
  n as AgentsOAuthProvider,
98
97
  r as DurableObjectOAuthClientProvider,
99
98
  t as AgentMcpOAuthProvider
100
- } from "./do-oauth-client-provider-DfsUcpc3.js";
99
+ } from "./do-oauth-client-provider-DtNqv7oj.js";
101
100
  import { o as TransportType } from "./types-D2naO3rA.js";
102
101
  import { t as MessageType } from "./types-6Zo2zfoO.js";
103
102
  import {
package/dist/index.js CHANGED
@@ -5,9 +5,9 @@ import { t as __DO_NOT_USE_WILL_BREAK__agentContext } from "./current-agent-DhoD
5
5
  import { callable, unstable_callable } from "./callable-decorator.js";
6
6
  import { MessageType } from "./types.js";
7
7
  import { createHeaderBasedEmailResolver } from "./email.js";
8
- import { n as withInvocationScope } from "./cloudflare-Dzvc7V2N.js";
8
+ import { r as withInvocationScope } from "./cloudflare-CUUm_9q9.js";
9
9
  import { SUB_PREFIX, buildAgentPath, buildAgentUrl, getSubAgentByName, parseSubAgentPath, routeSubAgentRequest } from "./sub-routing.js";
10
- import { a as routeAgentEmail, i as getCurrentAgent, n as DEFAULT_AGENT_STATIC_OPTIONS, r as StreamingResponse, t as Agent } from "./src-BGolXG_H.js";
10
+ import { a as routeAgentEmail, i as getCurrentAgent, n as DEFAULT_AGENT_STATIC_OPTIONS, r as StreamingResponse, t as Agent } from "./src-DoGNJ4Ud.js";
11
11
  import { isDurableObjectCodeUpdateReset, isDurableObjectMemoryLimitReset, isDurableObjectStorageReset, isPlatformTransientError } from "./retries.js";
12
12
  import { SqlError } from "./sql-error.js";
13
13
  import { i as normalizeServerId, n as MCP_SERVER_ID_MAX_LENGTH } from "./client-DMWujQJ1.js";