@fungi.computer/oyster 0.3.2 → 0.4.1

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 (86) hide show
  1. package/dist/agent-computer-source.d.ts +42 -0
  2. package/dist/agent-computer-source.js +88 -0
  3. package/dist/agent-computers.d.ts +104 -0
  4. package/dist/agent-computers.js +227 -0
  5. package/dist/agents.d.ts +10 -0
  6. package/dist/agents.js +33 -0
  7. package/dist/app-builds.d.ts +1 -1
  8. package/dist/app-builds.js +16 -6
  9. package/dist/boot-capability.d.ts +2 -1
  10. package/dist/boot-capability.js +7 -5
  11. package/dist/browser/boot.d.ts +2 -2
  12. package/dist/browser/boot.js +10 -3
  13. package/dist/browser/browser.d.ts +1 -1
  14. package/dist/browser/browser.js +2 -1
  15. package/dist/browser/cdp-client.d.ts +2 -0
  16. package/dist/browser/errors.d.ts +2 -2
  17. package/dist/browser/errors.js +2 -2
  18. package/dist/browser/index.d.ts +3 -2
  19. package/dist/browser/index.js +3 -2
  20. package/dist/browser/page.js +11 -4
  21. package/dist/browser/sessions.d.ts +7 -4
  22. package/dist/browser/sessions.js +159 -0
  23. package/dist/browser/url-policy.d.ts +4 -2
  24. package/dist/browser/url-policy.js +4 -2
  25. package/dist/build/build-jobs.d.ts +3 -3
  26. package/dist/build/build-jobs.js +10 -5
  27. package/dist/build/candidate-cli.js +5 -3
  28. package/dist/build/candidate-cli.mjs +223 -5
  29. package/dist/build/candidate-diagnostic.d.ts +2 -0
  30. package/dist/build/candidate-diagnostic.js +16 -0
  31. package/dist/computer-control-port.d.ts +26 -0
  32. package/dist/computer-control-port.js +1 -0
  33. package/dist/host.d.ts +3 -0
  34. package/dist/machine-link/delivery.d.ts +1 -1
  35. package/dist/machine-link/delivery.js +2 -3
  36. package/dist/machine-link/host.d.ts +37 -6
  37. package/dist/machine-link/host.js +209 -14
  38. package/dist/machine-link/link.d.ts +13 -1
  39. package/dist/machine-link/link.js +20 -7
  40. package/dist/mcp.d.ts +144 -10
  41. package/dist/mcp.js +130 -13
  42. package/dist/page/computer-handles.d.ts +3 -3
  43. package/dist/page-script.js +1 -1
  44. package/dist/standalone/agent-computers.d.ts +29 -0
  45. package/dist/standalone/agent-computers.js +101 -0
  46. package/dist/standalone/agent-mail.d.ts +41 -18
  47. package/dist/standalone/agent-model-choice.d.ts +29 -0
  48. package/dist/standalone/agent-model-choice.js +72 -0
  49. package/dist/standalone/agents.d.ts +44 -4
  50. package/dist/standalone/agents.js +502 -46
  51. package/dist/standalone/app-set.d.ts +8 -1
  52. package/dist/standalone/app-set.js +46 -31
  53. package/dist/standalone/computer-control.d.ts +4 -0
  54. package/dist/standalone/computer-control.js +62 -0
  55. package/dist/standalone/computer-fleet.d.ts +1 -0
  56. package/dist/standalone/computer-fleet.js +1 -1
  57. package/dist/standalone/computer.d.ts +21 -2
  58. package/dist/standalone/computer.js +12 -0
  59. package/dist/standalone/install-apps-bin.d.ts +2 -0
  60. package/dist/standalone/install-apps-bin.js +3 -0
  61. package/dist/standalone/install-apps-cli.d.ts +3 -1
  62. package/dist/standalone/install-apps-cli.js +27 -17
  63. package/dist/standalone/machine-link.d.ts +10 -0
  64. package/dist/standalone/machine-link.js +6 -0
  65. package/dist/standalone/registry.d.ts +10 -1
  66. package/dist/standalone/registry.js +9 -0
  67. package/dist/standalone/worker.js +12 -0
  68. package/dist/standalone/workflow-binding.d.ts +2 -2
  69. package/dist/standalone/workflow-host.d.ts +11 -11
  70. package/dist/standalone/workflows.d.ts +22 -22
  71. package/dist/storage-frame.d.ts +3 -3
  72. package/dist/workers-git.d.ts +2 -0
  73. package/dist/workers-git.js +2 -0
  74. package/dist/workers.d.ts +8 -8
  75. package/dist/workers.js +9 -1
  76. package/docs/api/agents.md +66 -0
  77. package/docs/api/apps.md +104 -104
  78. package/docs/api/build-contract.md +35 -35
  79. package/docs/api/build.md +12 -12
  80. package/docs/api/host.md +61 -61
  81. package/docs/api/mcp.md +127 -13
  82. package/docs/api/root-data.md +1 -1
  83. package/docs/api/tenancy.md +1 -1
  84. package/docs/api/workers-git.md +3 -2
  85. package/docs/api/workers.md +81 -83
  86. package/package.json +26 -18
@@ -14544,6 +14544,21 @@ function makeIsGreaterThanOrEqualTo(options) {
14544
14544
  });
14545
14545
  };
14546
14546
  }
14547
+ function makeIsLessThanOrEqualTo(options) {
14548
+ const lte = isLessThanOrEqualTo(options.order);
14549
+ const formatter = options.formatter ?? format;
14550
+ return (maximum, annotations) => {
14551
+ return makeFilter2((input) => lte(input, maximum), {
14552
+ expected: `a value less than or equal to ${formatter(maximum)}`,
14553
+ arbitraryConstraint: {
14554
+ order: options.order,
14555
+ maximum
14556
+ },
14557
+ ...options.annotate?.(maximum),
14558
+ ...annotations
14559
+ });
14560
+ };
14561
+ }
14547
14562
  function makeIsBetween(deriveOptions) {
14548
14563
  const greaterThanOrEqualTo = isGreaterThanOrEqualTo(deriveOptions.order);
14549
14564
  const greaterThan = isGreaterThan(deriveOptions.order);
@@ -14611,6 +14626,23 @@ var isGreaterThanOrEqualTo2 = /* @__PURE__ */ makeIsGreaterThanOrEqualTo({
14611
14626
  })
14612
14627
  })
14613
14628
  });
14629
+ var isLessThanOrEqualTo2 = /* @__PURE__ */ makeIsLessThanOrEqualTo({
14630
+ order: Number2,
14631
+ annotate: (maximum) => ({
14632
+ representation: {
14633
+ id: "effect/schema/isLessThanOrEqualTo",
14634
+ payload: {
14635
+ maximum: encodeNumberPayload(maximum)
14636
+ }
14637
+ },
14638
+ toJsonSchema: () => ({
14639
+ maximum
14640
+ }),
14641
+ toCode: () => ({
14642
+ runtime: `Schema.isLessThanOrEqualTo(${format(maximum)})`
14643
+ })
14644
+ })
14645
+ });
14614
14646
  var isBetween = /* @__PURE__ */ makeIsBetween({
14615
14647
  order: Number2,
14616
14648
  annotate: (options) => {
@@ -16806,14 +16838,14 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
16806
16838
  return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
16807
16839
  };
16808
16840
  doc.write(`const input = payload.value;`);
16809
- const ids = /* @__PURE__ */ Object.create(null);
16841
+ const ids2 = /* @__PURE__ */ Object.create(null);
16810
16842
  let counter = 0;
16811
16843
  for (const key of normalized.keys) {
16812
- ids[key] = `key_${counter++}`;
16844
+ ids2[key] = `key_${counter++}`;
16813
16845
  }
16814
16846
  doc.write(`const newResult = {};`);
16815
16847
  for (const key of normalized.keys) {
16816
- const id = ids[key];
16848
+ const id = ids2[key];
16817
16849
  const k = esc(key);
16818
16850
  const schema2 = shape[key];
16819
16851
  const isOptionalIn = schema2?._zod?.optin === "optional";
@@ -21625,6 +21657,189 @@ var publicRouteConfigurationSchema = Struct({
21625
21657
  // src/build/candidate-cli.ts
21626
21658
  import { readFile as readFile6 } from "node:fs/promises";
21627
21659
 
21660
+ // ../carrier/dist/internal/post-contract.js
21661
+ var CursorResultSchema = Struct({
21662
+ status: Literals(["accepted", "duplicate"]),
21663
+ cursor: Int.check(isGreaterThanOrEqualTo2(0))
21664
+ });
21665
+ var PostDeliveryResultSchema = Union2([
21666
+ Literals(["accepted", "duplicate", "refused"]),
21667
+ CursorResultSchema,
21668
+ Struct({
21669
+ status: Literals(["accepted", "duplicate", "refused"]),
21670
+ receipt: Json2
21671
+ })
21672
+ ]);
21673
+ var PostError = class extends TaggedError2("PostError") {
21674
+ constructor(message, reason) {
21675
+ super(reason === void 0 ? { message } : { message, reason });
21676
+ }
21677
+ };
21678
+
21679
+ // ../carrier/dist/post.js
21680
+ var Key = String4.check(isMinLength(1), isMaxLength(256));
21681
+ var JobPayload = Struct({ postKey: Key });
21682
+ var PageLimit = Int.check(isGreaterThanOrEqualTo2(1), isLessThanOrEqualTo2(64));
21683
+ var maxRouteDeadlineMs = 7 * 24 * 60 * 60 * 1e3;
21684
+ var ids = defineIdFamily({
21685
+ family: "post",
21686
+ version: 1,
21687
+ kinds: { work: { prefix: "post_work" } }
21688
+ });
21689
+ var PostEnvelopeSchema = Struct({
21690
+ key: Key,
21691
+ kind: Key,
21692
+ address: Unknown2,
21693
+ event: Unknown2
21694
+ });
21695
+ var PostRowSchema = fromJsonString2(Union2([
21696
+ Struct({
21697
+ state: Literal2("pending"),
21698
+ envelope: PostEnvelopeSchema,
21699
+ attempts: Int.check(isGreaterThanOrEqualTo2(0)),
21700
+ nextAttemptAt: Number5.check(isGreaterThanOrEqualTo2(0)),
21701
+ deadlineAt: optional2(Number5.check(isGreaterThanOrEqualTo2(0))),
21702
+ jobId: optional2(Key),
21703
+ delivery: optional2(PostEnvelopeSchema),
21704
+ nextKey: optional2(Key)
21705
+ }),
21706
+ Struct({
21707
+ state: Literal2("delivered"),
21708
+ receipt: optional2(Json2),
21709
+ nextKey: optional2(Key)
21710
+ }),
21711
+ Struct({
21712
+ state: Literal2("dead"),
21713
+ envelope: PostEnvelopeSchema,
21714
+ attempts: Int.check(isGreaterThanOrEqualTo2(0)),
21715
+ reason: Literals(["refused", "exhausted", "expired"]),
21716
+ deadlineAt: optional2(Number5.check(isGreaterThanOrEqualTo2(0))),
21717
+ receipt: optional2(Json2),
21718
+ delivery: optional2(PostEnvelopeSchema),
21719
+ nextKey: optional2(Key)
21720
+ })
21721
+ ]));
21722
+ var StoredRow = Struct({ key: String4, value: String4 });
21723
+ var DueRow = Struct({
21724
+ due: NullOr(Number5.check(isGreaterThanOrEqualTo2(0)))
21725
+ });
21726
+
21727
+ // ../bird-dog/dist/effect.js
21728
+ var Identifier = String4.check(isMinLength(1), isMaxLength(256));
21729
+ var BIRD_DOG_MAIL_CONTENT_MAX_BYTES = 256 * 1024;
21730
+ var MailContent = String4.check(makeFilter2((content) => new TextEncoder().encode(content).byteLength <= BIRD_DOG_MAIL_CONTENT_MAX_BYTES, {
21731
+ message: `Mail content must be at most ${String(BIRD_DOG_MAIL_CONTENT_MAX_BYTES)} UTF-8 bytes`
21732
+ }));
21733
+ var BirdDogAgentReferenceSchema = Struct({
21734
+ kind: Literal2("agent"),
21735
+ agentId: Identifier,
21736
+ sessionId: Identifier
21737
+ });
21738
+ var BirdDogAgentRecipientReferenceSchema = Struct({
21739
+ kind: Literal2("agent"),
21740
+ agentId: Identifier,
21741
+ sessionId: optionalKey2(Identifier)
21742
+ });
21743
+ var BIRD_DOG_DIAGNOSTIC_MAX_LENGTH = 200;
21744
+ var SettledBirdDogReplySchema = Struct({
21745
+ commandId: Identifier,
21746
+ outcome: Literals([
21747
+ "completed",
21748
+ "failed",
21749
+ "interrupted",
21750
+ "cancelled",
21751
+ "outcome_unknown"
21752
+ ]),
21753
+ diagnostic: optionalKey2(String4.check(isMinLength(1), isMaxLength(BIRD_DOG_DIAGNOSTIC_MAX_LENGTH)))
21754
+ });
21755
+ var BirdDogUndeliverableReasonSchema = Literals([
21756
+ "recipient_offline",
21757
+ "recipient_left"
21758
+ ]);
21759
+ var UndeliverableBirdDogReplySchema = Struct({
21760
+ outcome: Literal2("undeliverable"),
21761
+ reason: BirdDogUndeliverableReasonSchema
21762
+ });
21763
+ var AcceptedBirdDogReplySchema = Struct({
21764
+ outcome: Literal2("accepted"),
21765
+ commandId: Identifier
21766
+ });
21767
+ var BirdDogReplySchema = Union2([
21768
+ SettledBirdDogReplySchema,
21769
+ UndeliverableBirdDogReplySchema,
21770
+ AcceptedBirdDogReplySchema
21771
+ ]);
21772
+ var REDACTED = "[redacted]";
21773
+ var schemeCredential = /\b(bearer|basic)\s+[^\s"',;]+/giu;
21774
+ var namedCredential = /\b((?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|secret|password|authorization)["']?\s*[:=]\s*["']?)(?!(?:bearer|basic)\s)[^\s"',;&]+/giu;
21775
+ var opaqueToken = /[A-Za-z0-9][\w-]{23,}/gu;
21776
+ function redactCredentials(text) {
21777
+ return text.replace(schemeCredential, `$1 ${REDACTED}`).replace(namedCredential, `$1${REDACTED}`).replace(opaqueToken, (token) => /\d/u.test(token) && /[A-Za-z]/u.test(token) ? REDACTED : token);
21778
+ }
21779
+ function boundedDiagnostic(text) {
21780
+ const line = redactCredentials(text.replace(/[\p{Cc}\p{Zl}\p{Zp}\s]+/gu, " ").trim()).slice(0, BIRD_DOG_DIAGNOSTIC_MAX_LENGTH).trimEnd();
21781
+ return line.length === 0 ? void 0 : line;
21782
+ }
21783
+ var BirdDogMailFields = {
21784
+ key: Identifier,
21785
+ to: BirdDogAgentRecipientReferenceSchema,
21786
+ replyTo: ArraySchema(BirdDogAgentReferenceSchema),
21787
+ content: MailContent,
21788
+ createdAt: Number5.check(isGreaterThanOrEqualTo2(0)),
21789
+ /** The sender's opaque host metadata; BirdDog never reads it. */
21790
+ meta: optionalKey2(Json2)
21791
+ };
21792
+ var BirdDogMailSchema = Union2([
21793
+ Struct({
21794
+ ...BirdDogMailFields,
21795
+ from: BirdDogAgentReferenceSchema,
21796
+ /** Settlement or acceptance facts, present only on a reply. */
21797
+ reply: optionalKey2(BirdDogReplySchema)
21798
+ }),
21799
+ Struct({
21800
+ ...BirdDogMailFields,
21801
+ from: BirdDogAgentRecipientReferenceSchema,
21802
+ /** An unstarted recipient can only author an undeliverable reply. */
21803
+ reply: UndeliverableBirdDogReplySchema
21804
+ })
21805
+ ]);
21806
+ var BirdDogAgentWorkSchema = Struct({
21807
+ jobId: Identifier,
21808
+ sessionId: Identifier,
21809
+ commandFactId: Identifier,
21810
+ recovery: optional2(Struct({
21811
+ maxRecoveries: Int.check(isGreaterThanOrEqualTo2(0))
21812
+ }))
21813
+ });
21814
+ var BirdDogAgentJobPayloadSchema = Struct({
21815
+ work: Struct({
21816
+ sessionId: Identifier,
21817
+ commandFactId: Identifier
21818
+ }),
21819
+ mail: optional2(BirdDogMailSchema)
21820
+ });
21821
+ var BirdDogAgentJobInputSchema = Struct({
21822
+ work: BirdDogAgentWorkSchema,
21823
+ mail: optional2(BirdDogMailSchema)
21824
+ });
21825
+
21826
+ // src/build/candidate-diagnostic.ts
21827
+ function candidateFailureDiagnostic(cause) {
21828
+ const messages = [];
21829
+ let current = cause;
21830
+ for (let depth = 0; depth < 3; depth += 1) {
21831
+ if (!(current instanceof Error)) {
21832
+ if (depth === 0) messages.push("Non-error thrown");
21833
+ break;
21834
+ }
21835
+ messages.push(
21836
+ `${depth === 0 ? "" : "Caused by: "}${current.message || current.name}`
21837
+ );
21838
+ current = current.cause;
21839
+ }
21840
+ return boundedDiagnostic(messages.join("; ")) ?? "Build failed";
21841
+ }
21842
+
21628
21843
  // ../puffball/dist/assets.js
21629
21844
  var positiveInteger = Number5.pipe(check(isInt()), check(isGreaterThan2(0)), check(makeFilter2(Number.isSafeInteger)));
21630
21845
  var assetBuildPolicySchema = Struct({
@@ -36087,10 +36302,14 @@ async function buildTeamCandidate(input) {
36087
36302
  var uploadConcurrency = 4;
36088
36303
  var uploadAttempts = 3;
36089
36304
  function reportFailure2(cause) {
36305
+ const diagnostic = candidateFailureDiagnostic(cause);
36306
+ process.stderr.write(`Team App source/build failed: ${diagnostic}
36307
+ `);
36090
36308
  process.stderr.write(
36091
36309
  `${JSON.stringify({
36092
36310
  source: "oyster-candidate-builder",
36093
- failureKind: cause instanceof Error ? "Error" : "NonErrorThrown"
36311
+ failureKind: cause instanceof Error ? "Error" : "NonErrorThrown",
36312
+ diagnostic
36094
36313
  })}
36095
36314
  `
36096
36315
  );
@@ -36199,7 +36418,6 @@ try {
36199
36418
  );
36200
36419
  } catch (cause) {
36201
36420
  reportFailure2(cause);
36202
- process.stderr.write("Team App source/build failed\n");
36203
36421
  process.exitCode = 1;
36204
36422
  }
36205
36423
  /*! Bundled license information:
@@ -0,0 +1,2 @@
1
+ /** The builder's error and at most two causes, safe for a build record. */
2
+ export declare function candidateFailureDiagnostic(cause: unknown): string;
@@ -0,0 +1,16 @@
1
+ import { boundedDiagnostic } from "@fungi.computer/bird-dog/effect";
2
+ /** The builder's error and at most two causes, safe for a build record. */
3
+ export function candidateFailureDiagnostic(cause) {
4
+ const messages = [];
5
+ let current = cause;
6
+ for (let depth = 0; depth < 3; depth += 1) {
7
+ if (!(current instanceof Error)) {
8
+ if (depth === 0)
9
+ messages.push("Non-error thrown");
10
+ break;
11
+ }
12
+ messages.push(`${depth === 0 ? "" : "Caused by: "}${current.message || current.name}`);
13
+ current = current.cause;
14
+ }
15
+ return boundedDiagnostic(messages.join("; ")) ?? "Build failed";
16
+ }
@@ -0,0 +1,26 @@
1
+ import type { z } from "zod";
2
+ import type { computerCreateRequestSchema, computerPageSchema } from "@fungi.computer/computer/fleet/inventory-wire";
3
+ import type { computerStateSchema } from "@fungi.computer/computer/fleet/wire";
4
+ import type { teamComputerDirectorySchema } from "@fungi.computer/nacre/workbench";
5
+ import type { InvocationContext } from "@fungi.computer/mycelium";
6
+ /** Host policy stays outside this family: Hub admits funded slots, standalone
7
+ * admits its current owner. Both call their durable fleet through this port.
8
+ * Keep the host contract independent of the Worker-only fleet lifecycle. */
9
+ export type ComputerControlPort = Readonly<{
10
+ /** List a bounded page from the host-admitted inventory. */
11
+ list(page: z.output<typeof computerPageSchema>, context: InvocationContext): Promise<z.output<typeof teamComputerDirectorySchema>>;
12
+ /** Read liveness without waking the Computer. */
13
+ state(computerId: string, context: InvocationContext): Promise<z.output<typeof computerStateSchema>>;
14
+ /** Start one inventoried hosted Computer through the host's admission. */
15
+ start(computerId: string, context: InvocationContext): Promise<z.output<typeof computerStateSchema>>;
16
+ /** Create or replay a durable receipt tied to this request identity. */
17
+ create(input: z.output<typeof computerCreateRequestSchema>, context: InvocationContext): Promise<{
18
+ kind: "created";
19
+ computer: {
20
+ computerId: string;
21
+ name: string;
22
+ };
23
+ } | {
24
+ kind: "uncertain" | "denied" | "conflict" | "invalid";
25
+ }>;
26
+ }>;
@@ -0,0 +1 @@
1
+ export {};
package/dist/host.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { OysterApprovalCall } from "./approval-home.js";
2
2
  import type { PendingApproval, ApprovalApplyResult } from "@fungi.computer/approvals";
3
3
  import type { WorkflowControl } from "./workflows.js";
4
+ import type { ComputerControlPort } from "./computer-control-port.js";
4
5
  import { type InstallationOperations } from "./installation-operations.js";
5
6
  export type { InstallationOperations };
6
7
  import type { KnapsackComputer } from "@fungi.computer/knapsack";
@@ -192,6 +193,8 @@ export type OysterHost = Readonly<{
192
193
  * @inlineType WorkflowControl
193
194
  */
194
195
  workflows?: (principal: OysterPrincipal) => Promise<WorkflowControl | null>;
196
+ /** Owner-admitted durable Computer inventory, absent on hosts without a fleet. */
197
+ computerControl?: (principal: OysterPrincipal) => ComputerControlPort | null;
195
198
  auth: OysterAuth;
196
199
  /** Host-held sealing key for member writes; never exposed to the guest.
197
200
  * Absence refuses eligible named member writes, even when the App has no sync continuation.
@@ -13,6 +13,6 @@ export declare function createHomeAwareAgentMailNamespace(options: {
13
13
  home: (agentId: string) => Promise<MachineAgentHome | null>;
14
14
  hosted: PostRoute<never, never>["namespace"];
15
15
  machine: (deviceId: string, envelope: PostEnvelope) => Promise<PostDeliveryResult>;
16
- /** Host's Agent grammar: throws unless the receipt is a well-formed Accepted. */
16
+ /** Host's Agent grammar: validates Accepted or Held without conflating them. */
17
17
  accepted: (receipt: Schema.Json) => void;
18
18
  }): PostRoute<never, never>["namespace"];
@@ -28,8 +28,7 @@ export function createHomeAwareAgentMailNamespace(options) {
28
28
  address.scopeId !== options.sender.teamId ||
29
29
  address.agentId !== agentId ||
30
30
  mail.to.agentId !== agentId ||
31
- mail.from.agentId !== options.sender.agentId ||
32
- new TextEncoder().encode(JSON.stringify(mail)).byteLength > 256 * 1024)
31
+ mail.from.agentId !== options.sender.agentId)
33
32
  return "refused";
34
33
  const projected = await options.home(agentId);
35
34
  if (projected === null)
@@ -45,7 +44,7 @@ export function createHomeAwareAgentMailNamespace(options) {
45
44
  if (result === "accepted" ||
46
45
  result === "duplicate" ||
47
46
  !("receipt" in result))
48
- throw new Error("Agent mail acknowledgment lacks an Accepted receipt");
47
+ throw new Error("Agent mail acknowledgment lacks a valid acceptance or Held receipt");
49
48
  if (result.status !== "refused")
50
49
  options.accepted(result.receipt);
51
50
  return result;
@@ -1,5 +1,6 @@
1
- import type { PostEnvelope, PostDeliveryResult } from "@fungi.computer/carrier/post";
2
- import type { WatchdogSqliteOwner } from "@fungi.computer/watchdog";
1
+ import { type SeamReplayStore } from "@fungi.computer/seam";
2
+ import { type PostEnvelope, type PostDeliveryResult } from "@fungi.computer/carrier/post";
3
+ import { type WatchdogSqliteOwner } from "@fungi.computer/watchdog";
3
4
  export type MachineLinkDevice = Readonly<{
4
5
  deviceId: string;
5
6
  memberId: string;
@@ -8,16 +9,21 @@ export type MachineLinkDevice = Readonly<{
8
9
  }>;
9
10
  /**
10
11
  * Native device socket I/O. Pins/member authority and mail admission are supplied
11
- * by their existing owners. Native attachments survive hibernation; pending
12
- * Post I/O does not claim durable custody and is retried by Carrier.
12
+ * by their existing owners. Native attachments survive hibernation; Carrier
13
+ * owns durable custody and per-Agent ordering across socket lifetimes.
13
14
  */
14
15
  export declare class MachineLinkHost {
15
16
  #private;
16
17
  private readonly context;
18
+ private readonly owner;
17
19
  private readonly options;
18
20
  private readonly channels;
19
- private readonly replay;
20
- private readonly routes;
21
+ private replayRuntime;
22
+ private readonly router;
23
+ private readonly custodyRoutes;
24
+ private deviceId;
25
+ private custodyRuntime;
26
+ private readonly receipts;
21
27
  constructor(context: Pick<DurableObjectState, "getWebSockets" | "acceptWebSocket" | "setWebSocketAutoResponse" | "waitUntil">, owner: WatchdogSqliteOwner, options: Readonly<{
22
28
  teamId: string;
23
29
  directory: () => Promise<readonly {
@@ -25,14 +31,39 @@ export declare class MachineLinkHost {
25
31
  name: string;
26
32
  }[]>;
27
33
  authorize: (deviceId: string) => Promise<MachineLinkDevice>;
34
+ replay: () => Promise<SeamReplayStore>;
28
35
  receive: (device: MachineLinkDevice, envelope: PostEnvelope) => Promise<PostDeliveryResult>;
36
+ /** Arm the Durable Object alarm for Carrier/Watchdog progress. */
37
+ scheduleWake: (at: number) => Promise<void>;
29
38
  /** The host's failure log for refused dials and closed links. */
30
39
  report: (operation: string, cause: unknown) => void;
31
40
  }>);
32
41
  fetch(request: Request): Promise<Response>;
42
+ private replayStore;
43
+ /** Start the fresh socket and then hand durable rows to its live channel. */
44
+ connected(socket: WebSocket, deviceId: string): Promise<void>;
33
45
  private publishDirectory;
34
46
  private channel;
35
47
  deliver(deviceId: string, envelope: PostEnvelope): Promise<PostDeliveryResult>;
48
+ private deliverLiveOperation;
49
+ private deliverCustodyMail;
50
+ /** Run due Carrier work; expired rows remain visible as Carrier dead letters. */
51
+ alarm(): Promise<void>;
52
+ /** Expose terminal custody rows so S9 can stage its own disposition reply. */
53
+ deadLetters(afterKey?: string): Promise<Readonly<{
54
+ letters: readonly Readonly<{
55
+ key: string;
56
+ reason: "refused" | "exhausted" | "expired";
57
+ envelope: PostEnvelope;
58
+ attempts: number;
59
+ }>[];
60
+ nextCursor: string | undefined;
61
+ }>>;
62
+ private deliverToSocket;
63
+ private custody;
64
+ private createCustody;
65
+ private releaseCustody;
66
+ private drainCustody;
36
67
  message(socket: WebSocket, message: string | ArrayBuffer): Promise<void>;
37
68
  close(socket: WebSocket): void;
38
69
  private authorizeSocket;