@sixb/core 0.1.10 → 0.1.11

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 (129) hide show
  1. package/dist/actions/index.js +5 -5
  2. package/dist/agents/index.js +10 -10
  3. package/dist/blob-storage/types.d.ts +4 -1
  4. package/dist/blob-storage/types.d.ts.map +1 -1
  5. package/dist/bootstrap/index.js +14 -14
  6. package/dist/{chunk-nmbxcaqx.js → chunk-01kj2pbh.js} +1 -1
  7. package/dist/{chunk-rtk71jzp.js → chunk-1yefycb1.js} +1 -1
  8. package/dist/chunk-2c4j899j.js.map +1 -1
  9. package/dist/{chunk-t1f4f1ve.js → chunk-3ckk0xfj.js} +2 -2
  10. package/dist/{chunk-r7fj830t.js → chunk-4zhmdsx6.js} +48 -15
  11. package/dist/{chunk-r7fj830t.js.map → chunk-4zhmdsx6.js.map} +6 -6
  12. package/dist/{chunk-g7knyczr.js → chunk-a0e6x5hd.js} +1 -1
  13. package/dist/{chunk-5c7ga8zz.js → chunk-cfvakeax.js} +1 -1
  14. package/dist/chunk-d62kjtbg.js.map +1 -1
  15. package/dist/{chunk-28ja2cjs.js → chunk-d63nnr5b.js} +2 -2
  16. package/dist/{chunk-agbbygvh.js → chunk-fh8kgex1.js} +4 -4
  17. package/dist/{chunk-b0ec55a1.js → chunk-g91qxjj0.js} +1 -1
  18. package/dist/{chunk-5p1v802y.js → chunk-gq8vhakp.js} +12 -8
  19. package/dist/{chunk-5p1v802y.js.map → chunk-gq8vhakp.js.map} +4 -4
  20. package/dist/{chunk-p6a4npdx.js → chunk-gqm76kse.js} +21 -20
  21. package/dist/{chunk-p6a4npdx.js.map → chunk-gqm76kse.js.map} +4 -4
  22. package/dist/{chunk-e0d1rzef.js → chunk-jsy70480.js} +16 -3
  23. package/dist/chunk-jsy70480.js.map +15 -0
  24. package/dist/{chunk-p5vcsw9c.js → chunk-sepyxgpc.js} +2 -2
  25. package/dist/{chunk-nt99sxd6.js → chunk-wf88w4kp.js} +16 -22
  26. package/dist/chunk-wf88w4kp.js.map +14 -0
  27. package/dist/{chunk-bn138h9w.js → chunk-x9m9x2eq.js} +1 -1
  28. package/dist/{chunk-qyeptdyv.js → chunk-z0271qkp.js} +3 -1
  29. package/dist/{chunk-qyeptdyv.js.map → chunk-z0271qkp.js.map} +3 -3
  30. package/dist/{chunk-976rxdpx.js → chunk-z0s4axeh.js} +4 -4
  31. package/dist/connectors/connections/command-context.d.ts +2 -0
  32. package/dist/connectors/connections/command-context.d.ts.map +1 -1
  33. package/dist/connectors/connections/contracts.d.ts +1 -1
  34. package/dist/connectors/connections/contracts.d.ts.map +1 -1
  35. package/dist/connectors/connections/execution.d.ts +1 -0
  36. package/dist/connectors/connections/execution.d.ts.map +1 -1
  37. package/dist/connectors/connections/runs.d.ts +1 -0
  38. package/dist/connectors/connections/runs.d.ts.map +1 -1
  39. package/dist/connectors/connections/service.d.ts +2 -0
  40. package/dist/connectors/connections/service.d.ts.map +1 -1
  41. package/dist/events/index.js +1 -1
  42. package/dist/events/outbox-dispatcher.d.ts +2 -2
  43. package/dist/events/outbox-dispatcher.d.ts.map +1 -1
  44. package/dist/execution/agent.js +10 -10
  45. package/dist/execution/primitive.js +10 -10
  46. package/dist/execution/request.js +10 -10
  47. package/dist/index.js +17 -17
  48. package/dist/lake-storage/in-memory.d.ts.map +1 -1
  49. package/dist/lake-storage/index.js +1 -1
  50. package/dist/lake-storage/types.d.ts +2 -0
  51. package/dist/lake-storage/types.d.ts.map +1 -1
  52. package/dist/maintenance/ontology-maintenance.d.ts.map +1 -1
  53. package/dist/maintenance/types.d.ts +1 -1
  54. package/dist/maintenance/types.d.ts.map +1 -1
  55. package/dist/materializer/index.js +2 -2
  56. package/dist/models/definitions.d.ts +7 -0
  57. package/dist/models/definitions.d.ts.map +1 -1
  58. package/dist/models/execution/index.js +3 -3
  59. package/dist/models/index.js +1 -1
  60. package/dist/objects/index.js +5 -5
  61. package/dist/objects/query/index.js +3 -3
  62. package/dist/pipelines/index.js +4 -4
  63. package/dist/projections/internal.js +2 -2
  64. package/dist/shares/internal.js +2 -2
  65. package/dist/storage/agents/provider.js +1 -1
  66. package/dist/storage/connector-connections/in-memory.d.ts +1 -0
  67. package/dist/storage/connector-connections/in-memory.d.ts.map +1 -1
  68. package/dist/storage/connector-connections/provider/connections.d.ts.map +1 -1
  69. package/dist/storage/connector-connections/provider/runs.d.ts +1 -0
  70. package/dist/storage/connector-connections/provider/runs.d.ts.map +1 -1
  71. package/dist/storage/connector-connections/provider/shared.d.ts +1 -0
  72. package/dist/storage/connector-connections/provider/shared.d.ts.map +1 -1
  73. package/dist/storage/connector-connections/provider.d.ts +1 -0
  74. package/dist/storage/connector-connections/provider.d.ts.map +1 -1
  75. package/dist/storage/connector-connections/provider.js +10 -16
  76. package/dist/storage/connector-connections/provider.js.map +6 -6
  77. package/dist/storage/connector-connections/types.d.ts +3 -1
  78. package/dist/storage/connector-connections/types.d.ts.map +1 -1
  79. package/dist/storage/index.js +2 -2
  80. package/dist/storage/ontology/in-memory/shared-state.d.ts.map +1 -1
  81. package/dist/storage/ontology/outbox.d.ts +1 -0
  82. package/dist/storage/ontology/outbox.d.ts.map +1 -1
  83. package/dist/syncs/index.js +4 -4
  84. package/dist/testing/index.js +58 -30
  85. package/dist/testing/index.js.map +5 -5
  86. package/dist/testing/lake-storage-contract.d.ts.map +1 -1
  87. package/dist/testing/ontology-storage-contract.d.ts.map +1 -1
  88. package/dist/webhooks/internal.js +2 -2
  89. package/dist/workflows/index.js +11 -11
  90. package/package.json +1 -1
  91. package/src/agents/model-loop.ts +7 -0
  92. package/src/blob-storage/types.ts +4 -1
  93. package/src/connectors/connections/command-context.ts +21 -4
  94. package/src/connectors/connections/contracts.ts +4 -1
  95. package/src/connectors/connections/execution.ts +3 -0
  96. package/src/connectors/connections/runs.ts +38 -1
  97. package/src/connectors/connections/service.ts +6 -0
  98. package/src/events/outbox-dispatcher.ts +20 -26
  99. package/src/lake-storage/in-memory.ts +2 -0
  100. package/src/lake-storage/types.ts +2 -0
  101. package/src/maintenance/ontology-maintenance.ts +6 -2
  102. package/src/maintenance/types.ts +1 -1
  103. package/src/materializer/README.md +1 -1
  104. package/src/models/definitions.ts +19 -0
  105. package/src/models/pricing.ts +6 -2
  106. package/src/storage/connector-connections/in-memory.ts +16 -18
  107. package/src/storage/connector-connections/provider/connections.ts +1 -15
  108. package/src/storage/connector-connections/provider/runs.ts +6 -0
  109. package/src/storage/connector-connections/provider/shared.ts +2 -3
  110. package/src/storage/connector-connections/provider.ts +6 -0
  111. package/src/storage/connector-connections/types.ts +5 -1
  112. package/src/storage/ontology/in-memory/shared-state.ts +10 -3
  113. package/src/storage/ontology/outbox.ts +1 -0
  114. package/src/testing/connector-connection-storage-contract.ts +11 -11
  115. package/src/testing/lake-storage-contract.ts +29 -0
  116. package/src/testing/ontology-storage-contract.ts +8 -3
  117. package/dist/chunk-e0d1rzef.js.map +0 -15
  118. package/dist/chunk-nt99sxd6.js.map +0 -14
  119. /package/dist/{chunk-nmbxcaqx.js.map → chunk-01kj2pbh.js.map} +0 -0
  120. /package/dist/{chunk-rtk71jzp.js.map → chunk-1yefycb1.js.map} +0 -0
  121. /package/dist/{chunk-t1f4f1ve.js.map → chunk-3ckk0xfj.js.map} +0 -0
  122. /package/dist/{chunk-g7knyczr.js.map → chunk-a0e6x5hd.js.map} +0 -0
  123. /package/dist/{chunk-5c7ga8zz.js.map → chunk-cfvakeax.js.map} +0 -0
  124. /package/dist/{chunk-28ja2cjs.js.map → chunk-d63nnr5b.js.map} +0 -0
  125. /package/dist/{chunk-agbbygvh.js.map → chunk-fh8kgex1.js.map} +0 -0
  126. /package/dist/{chunk-b0ec55a1.js.map → chunk-g91qxjj0.js.map} +0 -0
  127. /package/dist/{chunk-p5vcsw9c.js.map → chunk-sepyxgpc.js.map} +0 -0
  128. /package/dist/{chunk-bn138h9w.js.map → chunk-x9m9x2eq.js.map} +0 -0
  129. /package/dist/{chunk-976rxdpx.js.map → chunk-z0s4axeh.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"lake-storage-contract.d.ts","sourceRoot":"","sources":["../../src/testing/lake-storage-contract.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEpE,MAAM,MAAM,oCAAoC,GAAG,QAAQ,GAAG,oBAAoB,CAAA;AAElF,MAAM,WAAW,+BAA+B,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW;IACzF,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,EAAE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC1D,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,oCAAoC,CAAA;IAC/D;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACnC;AA2CD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,SAAS,WAAW,EACtE,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,+BAA+B,CAAC,QAAQ,CAAC,GACjD,IAAI,CA6uBN"}
1
+ {"version":3,"file":"lake-storage-contract.d.ts","sourceRoot":"","sources":["../../src/testing/lake-storage-contract.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEpE,MAAM,MAAM,oCAAoC,GAAG,QAAQ,GAAG,oBAAoB,CAAA;AAElF,MAAM,WAAW,+BAA+B,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW;IACzF,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,EAAE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC1D,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,oCAAoC,CAAA;IAC/D;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACnC;AA2CD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,SAAS,WAAW,EACtE,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,+BAA+B,CAAC,QAAQ,CAAC,GACjD,IAAI,CA0wBN"}
@@ -1 +1 @@
1
- {"version":3,"file":"ontology-storage-contract.d.ts","sourceRoot":"","sources":["../../src/testing/ontology-storage-contract.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACtE,OAAO,EAML,KAAK,uBAAuB,EAC7B,MAAM,6BAA6B,CAAA;AAGpC,MAAM,WAAW,8BAA+B,SAAQ,uBAAuB;IAC7E,QAAQ,CAAC,cAAc,EAAE,oBAAoB,CAAA;CAC9C;AAED,MAAM,WAAW,mCAAmC,CAClD,QAAQ,SAAS,8BAA8B,GAAG,8BAA8B;IAEhF,4FAA4F;IAC5F,QAAQ,CAAC,aAAa,EAAE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC1D,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5D,kFAAkF;IAClF,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/D;AAkDD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,QAAQ,SAAS,8BAA8B,EAC7F,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mCAAmC,CAAC,QAAQ,CAAC,GACrD,IAAI,CA6sBN"}
1
+ {"version":3,"file":"ontology-storage-contract.d.ts","sourceRoot":"","sources":["../../src/testing/ontology-storage-contract.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACtE,OAAO,EAML,KAAK,uBAAuB,EAC7B,MAAM,6BAA6B,CAAA;AAGpC,MAAM,WAAW,8BAA+B,SAAQ,uBAAuB;IAC7E,QAAQ,CAAC,cAAc,EAAE,oBAAoB,CAAA;CAC9C;AAED,MAAM,WAAW,mCAAmC,CAClD,QAAQ,SAAS,8BAA8B,GAAG,8BAA8B;IAEhF,4FAA4F;IAC5F,QAAQ,CAAC,aAAa,EAAE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC1D,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5D,kFAAkF;IAClF,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/D;AAkDD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,QAAQ,SAAS,8BAA8B,EAC7F,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mCAAmC,CAAC,QAAQ,CAAC,GACrD,IAAI,CAktBN"}
@@ -12,7 +12,7 @@ import"../chunk-vsj3mdfj.js";
12
12
  import"../chunk-g00bfdq6.js";
13
13
  import"../chunk-q5gz3g2j.js";
14
14
  import"../chunk-pqajwytd.js";
15
- import"../chunk-e0d1rzef.js";
15
+ import"../chunk-jsy70480.js";
16
16
  import"../chunk-gfdh9kqa.js";
17
17
  import"../chunk-39tqv9hz.js";
18
18
  import"../chunk-7bs40fe1.js";
@@ -27,7 +27,7 @@ import {
27
27
  import"../chunk-ap0g1g74.js";
28
28
  import {
29
29
  canRetryWebhookRun2
30
- } from "../chunk-p6a4npdx.js";
30
+ } from "../chunk-gqm76kse.js";
31
31
  import"../chunk-c5rkjrgp.js";
32
32
  import"../chunk-gqh45d2n.js";
33
33
  import"../chunk-z30bv4ga.js";
@@ -8,7 +8,7 @@ import {
8
8
  defineWorkflow2,
9
9
  createWorkflowNodeFailure2,
10
10
  unwrapWorkflowNodeFailure2
11
- } from "../chunk-t1f4f1ve.js";
11
+ } from "../chunk-3ckk0xfj.js";
12
12
  import"../chunk-e1c18xjx.js";
13
13
  import"../chunk-fb3feg1e.js";
14
14
  import"../chunk-dfm066qg.js";
@@ -44,26 +44,26 @@ import {
44
44
  snapshotWorkflowActionInput2,
45
45
  WorkflowRunDispatcher2,
46
46
  requestWorkflowRun2
47
- } from "../chunk-5p1v802y.js";
48
- import"../chunk-5c7ga8zz.js";
47
+ } from "../chunk-gq8vhakp.js";
48
+ import"../chunk-cfvakeax.js";
49
49
  import"../chunk-v2vcg0w6.js";
50
50
  import"../chunk-awbhdqyc.js";
51
- import"../chunk-976rxdpx.js";
51
+ import"../chunk-z0s4axeh.js";
52
52
  import"../chunk-85cd7e8c.js";
53
- import"../chunk-b0ec55a1.js";
54
- import"../chunk-28ja2cjs.js";
53
+ import"../chunk-g91qxjj0.js";
54
+ import"../chunk-d63nnr5b.js";
55
55
  import"../chunk-g6cke204.js";
56
56
  import"../chunk-0y39rgsb.js";
57
57
  import"../chunk-5a4a52tq.js";
58
58
  import"../chunk-mrp7k0pw.js";
59
59
  import"../chunk-9qsh3p5y.js";
60
60
  import"../chunk-860dwwy0.js";
61
- import"../chunk-p5vcsw9c.js";
62
- import"../chunk-nmbxcaqx.js";
63
- import"../chunk-g7knyczr.js";
61
+ import"../chunk-sepyxgpc.js";
62
+ import"../chunk-01kj2pbh.js";
63
+ import"../chunk-a0e6x5hd.js";
64
64
  import"../chunk-ftv470j8.js";
65
65
  import"../chunk-17kfctj6.js";
66
- import"../chunk-p6a4npdx.js";
66
+ import"../chunk-gqm76kse.js";
67
67
  import"../chunk-qf954wje.js";
68
68
  import"../chunk-pr2h4bv4.js";
69
69
  import"../chunk-8vj0rjgs.js";
@@ -81,7 +81,7 @@ import"../chunk-s3csryxe.js";
81
81
  import"../chunk-jgwb25gc.js";
82
82
  import"../chunk-93csa55g.js";
83
83
  import"../chunk-b19g04jk.js";
84
- import"../chunk-e0d1rzef.js";
84
+ import"../chunk-jsy70480.js";
85
85
  import"../chunk-pqajwytd.js";
86
86
  import"../chunk-ap0g1g74.js";
87
87
  import"../chunk-653vwrzr.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sixb/core",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "The ontology-first runtime for Sixb — objects, links, telemetry, actions, and provider contracts",
5
5
  "keywords": [
6
6
  "sixb",
@@ -255,6 +255,13 @@ export async function runModelLoop(
255
255
  }
256
256
 
257
257
  const localCalls = response.toolCalls.filter((call) => call.part.providerExecuted !== true)
258
+ // Closed tool arguments are not proof of a successful response. In particular,
259
+ // providers can close valid JSON before reporting truncation or content filtering.
260
+ if (localCalls.length > 0 && !["stop", "tool-calls", "pause"].includes(response.finishReason)) {
261
+ throw new ModelStreamError(
262
+ `[SixbModels] Cannot execute local tools after '${response.finishReason}'.`
263
+ )
264
+ }
258
265
  if (
259
266
  input.rejectLocalToolCalls &&
260
267
  (localCalls.length > 0 || response.finishReason === "tool-calls")
@@ -87,6 +87,8 @@ export interface DirectPutBlobUploadSession {
87
87
 
88
88
  export interface MultipartBlobUploadSession {
89
89
  readonly strategy: "multipart"
90
+ /** Required upload-response receipt. Omission defaults to "etag" for compatibility. */
91
+ readonly partReceipt?: "etag" | "none"
90
92
  readonly uploadId: string
91
93
  readonly partSizeBytes: number
92
94
  readonly expiresAt: Date
@@ -114,7 +116,8 @@ export interface SignedBlobUploadPart {
114
116
 
115
117
  export interface BlobUploadPart {
116
118
  readonly partNumber: number
117
- readonly etag: string
119
+ /** Required when the multipart session's partReceipt is "etag" or omitted. */
120
+ readonly etag?: string
118
121
  }
119
122
 
120
123
  export interface CompleteBlobUploadInput {
@@ -50,10 +50,7 @@ export function assertConnectorConnectionRunInitiator(
50
50
  current: ConnectorConnectionCommandActor,
51
51
  connectorId: string
52
52
  ): asserts execution is ExecutionRecord {
53
- const initiating = execution
54
- ? connectorConnectionActorFromExecution(execution, execution.projectId)
55
- : null
56
- if (!initiating || !sameConnectorConnectionCommandActor(initiating, current)) {
53
+ if (!isConnectorConnectionRunInitiator(execution, current)) {
57
54
  throw new AuthorizationError(
58
55
  `connection-run:connector:${connectorId}`,
59
56
  "[Sixb] This connector connection run can only be accessed by its initiating actor."
@@ -61,6 +58,26 @@ export function assertConnectorConnectionRunInitiator(
61
58
  }
62
59
  }
63
60
 
61
+ /** User-owned runs survive session renewal; access-token runs remain bound to their credential. */
62
+ export function isConnectorConnectionRunInitiator(
63
+ execution: ExecutionRecord | null,
64
+ current: ConnectorConnectionCommandActor
65
+ ): boolean {
66
+ const initiating = execution
67
+ ? connectorConnectionActorFromExecution(execution, execution.projectId)
68
+ : null
69
+ if (!initiating) return false
70
+ if (
71
+ initiating.principal.type === "user" &&
72
+ current.principal.type === "user" &&
73
+ initiating.credential.type === "session" &&
74
+ current.credential.type === "session"
75
+ ) {
76
+ return initiating.principal.id === current.principal.id
77
+ }
78
+ return sameConnectorConnectionCommandActor(initiating, current)
79
+ }
80
+
64
81
  function connectorConnectionActorFromExecution(
65
82
  execution: CreateExecutionInput | ExecutionRecord,
66
83
  projectId: string
@@ -118,7 +118,6 @@ export type ConnectorConnectionRunView =
118
118
  readonly status: "waiting"
119
119
  readonly waitingFor: "account_selection"
120
120
  readonly accounts: readonly ConnectorAccountCandidate[]
121
- readonly expiresAt: Date
122
121
  })
123
122
  | (ConnectorConnectionRunViewBase & {
124
123
  readonly status: "succeeded"
@@ -162,6 +161,10 @@ export interface ConnectorConnectionProcess {
162
161
  connectorId: string,
163
162
  input: AddConnectorConnectionInput
164
163
  ): Promise<ConnectorConnectionRunView>
164
+ listPendingConnectionRuns(
165
+ context: ConnectorConnectionCommandContext,
166
+ connectorId: string
167
+ ): Promise<readonly ConnectorConnectionRunView[]>
165
168
  getConnectionRun(
166
169
  context: ConnectorConnectionCommandContext,
167
170
  connectorId: string,
@@ -31,6 +31,7 @@ export interface ConnectorConnectionsRuntime {
31
31
  connectorId: string,
32
32
  input: AddConnectorConnectionInput
33
33
  ): Promise<ConnectorConnectionRunView>
34
+ listPendingConnectionRuns(connectorId: string): Promise<readonly ConnectorConnectionRunView[]>
34
35
  getConnectionRun(connectorId: string, runId: string): Promise<ConnectorConnectionRunView | null>
35
36
  selectConnectionRunAccount(
36
37
  connectorId: string,
@@ -77,6 +78,8 @@ export function createConnectorConnectionsRuntime(
77
78
  process.startConnectionRun(contextFor(connectorId), connectorId, input),
78
79
  addConnection: (connectorId, input) =>
79
80
  process.addConnection(contextFor(connectorId), connectorId, input),
81
+ listPendingConnectionRuns: (connectorId) =>
82
+ process.listPendingConnectionRuns(contextFor(connectorId), connectorId),
80
83
  getConnectionRun: (connectorId, runId) =>
81
84
  process.getConnectionRun(contextFor(connectorId), connectorId, runId),
82
85
  selectConnectionRunAccount: (connectorId, input) =>
@@ -16,6 +16,7 @@ import {
16
16
  } from "./authorizations"
17
17
  import {
18
18
  assertConnectorConnectionRunInitiator,
19
+ isConnectorConnectionRunInitiator,
19
20
  requireConnectorConnectionCommandActor,
20
21
  } from "./command-context"
21
22
  import type {
@@ -238,6 +239,42 @@ export class ConnectorConnectionRunService {
238
239
  }
239
240
  }
240
241
 
242
+ async listPending(
243
+ command: ConnectorConnectionCommandContext,
244
+ connectorId: string
245
+ ): Promise<readonly ConnectorConnectionRunView[]> {
246
+ const actor = requireConnectorConnectionCommandActor(command.execution, this.projectId)
247
+ const candidates = await withConnectorStorageBoundary(
248
+ "Pending connector connection runs could not be read.",
249
+ () =>
250
+ this.connectionStorage.listPendingConnectionRuns({ projectId: this.projectId, connectorId })
251
+ )
252
+ const runs: ConnectorConnectionRunView[] = []
253
+ for (const candidate of candidates) {
254
+ const initiating = await withConnectorStorageBoundary(
255
+ "Connector connection run initiating execution could not be read.",
256
+ () =>
257
+ this.storage.executions.getById({
258
+ projectId: this.projectId,
259
+ id: candidate.initiatedByExecutionId,
260
+ })
261
+ )
262
+ if (!isConnectorConnectionRunInitiator(initiating, actor)) continue
263
+ // Re-read through the normal expiry/cleanup path before exposing accounts.
264
+ const run = await this.get(command, connectorId, candidate.id)
265
+ if (
266
+ run &&
267
+ (run.status === "running" ||
268
+ (run.status === "waiting" && run.waitingFor === "account_selection"))
269
+ )
270
+ runs.push(run)
271
+ }
272
+ return runs.sort(
273
+ (left, right) =>
274
+ right.createdAt.getTime() - left.createdAt.getTime() || left.id.localeCompare(right.id)
275
+ )
276
+ }
277
+
241
278
  async get(
242
279
  command: ConnectorConnectionCommandContext,
243
280
  connectorId: string,
@@ -581,7 +618,6 @@ export class ConnectorConnectionRunService {
581
618
  status: "waiting",
582
619
  waitingFor: "account_selection",
583
620
  accounts: authorization.accounts,
584
- expiresAt: run.expiresAt,
585
621
  }
586
622
  }
587
623
  if (run.status === "succeeded") {
@@ -645,6 +681,7 @@ export class ConnectorConnectionRunService {
645
681
  : CLEANUP_RETRY_DELAY_MS
646
682
  ): void {
647
683
  this.cancelRunMaintenance(run.id)
684
+ if (run.status === "waiting" && run.waitingFor === "account_selection") return
648
685
  const timer = setTimeout(
649
686
  () => void this.maintainRun(run.connectorId, run.id),
650
687
  Math.min(delayMs, MAX_TIMER_DELAY_MS)
@@ -66,6 +66,7 @@ export interface ConnectorConnectionServiceOptions {
66
66
  readonly storage?: Storage
67
67
  readonly credentialProtector?: ConnectorCredentialProtector
68
68
  readonly authorizationAttemptTtlMs?: number
69
+ /** @deprecated Selection no longer expires; retained for legacy storage metadata only. */
69
70
  readonly accountSelectionTtlMs?: number
70
71
  readonly credentialMutationLeaseMs?: number
71
72
  readonly providerOperationTimeoutMs?: number
@@ -322,6 +323,11 @@ export class ConnectorConnectionService implements ConnectorConnectionProcess {
322
323
  })
323
324
  }
324
325
 
326
+ listPendingConnectionRuns(command: ConnectorConnectionCommandContext, connectorId: string) {
327
+ this.requireOAuthDefinition(connectorId)
328
+ return this.runs.listPending(command, connectorId)
329
+ }
330
+
325
331
  getConnectionRun(
326
332
  command: ConnectorConnectionCommandContext,
327
333
  connectorId: string,
@@ -46,6 +46,7 @@ export interface OntologyOutboxDispatcherOptions {
46
46
  readonly maxIsolationAttempts?: number
47
47
  /** Maximum claimed batches handled by one drain pass. */
48
48
  readonly maxClaimsPerDrain?: number
49
+ /** Broker grace period. Shutdown still waits for outstanding storage operations afterward. */
49
50
  readonly shutdownTimeoutMs?: number
50
51
  readonly now?: () => Date
51
52
  readonly random?: () => number
@@ -100,10 +101,10 @@ export class OntologyOutboxDispatcher {
100
101
  private readonly createLeaseId: () => string
101
102
  private readonly onDeliveryFailure?: OntologyOutboxDispatcherOptions["onDeliveryFailure"]
102
103
  private readonly onError: (error: unknown) => void
103
- private readonly inFlight = new Set<ClaimedBatch>()
104
104
  private draining: Promise<void> | null = null
105
105
  private pendingDrain: Promise<void> | null = null
106
106
  private stopping: Promise<void> | null = null
107
+ private closing = false
107
108
  private stopRequested = false
108
109
  private readonly forcedStop = new AbortController()
109
110
 
@@ -166,7 +167,7 @@ export class OntologyOutboxDispatcher {
166
167
  * mutation.
167
168
  */
168
169
  drain(): Promise<void> {
169
- if (this.stopRequested) return Promise.resolve()
170
+ if (this.closing || this.stopRequested) return Promise.resolve()
170
171
  if (!this.draining) return this.startDrainPass()
171
172
 
172
173
  this.pendingDrain ??= settled(this.draining).then(() => {
@@ -178,7 +179,7 @@ export class OntologyOutboxDispatcher {
178
179
 
179
180
  /** Starts a tracked, best-effort drain without extending mutation latency. */
180
181
  notify(): void {
181
- if (this.stopRequested) return
182
+ if (this.closing || this.stopRequested) return
182
183
  void this.drain().catch((error) => this.reportError(error))
183
184
  }
184
185
 
@@ -193,19 +194,16 @@ export class OntologyOutboxDispatcher {
193
194
  // Include one final bounded pass so commits whose notifications were coalesced immediately
194
195
  // before shutdown are not left pending merely because the process is stopping.
195
196
  const gracefulDrain = this.drain().catch((error) => this.reportError(error))
196
- if (await settlesWithin(gracefulDrain, this.shutdownTimeoutMs)) {
197
- this.stopRequested = true
198
- return
199
- }
200
-
197
+ this.closing = true
198
+ const finished = await settlesWithin(gracefulDrain, this.shutdownTimeoutMs)
201
199
  this.stopRequested = true
202
- this.forcedStop.abort()
203
- await settlesWithin(
204
- this.rescheduleUnsettledForShutdown(),
205
- Math.min(this.shutdownTimeoutMs, 1_000)
206
- )
207
- this.draining = null
208
- this.pendingDrain = null
200
+ if (!finished) this.forcedStop.abort()
201
+ // Storage operations cannot be cancelled by this contract. A late claim must release its
202
+ // lease, and an acknowledgement already started must finish before callers close storage.
203
+ // publishClaim owns settlement, including forced stop; never race a second cleanup against it.
204
+ await gracefulDrain
205
+ if (this.draining) await settled(this.draining)
206
+ if (this.pendingDrain) await settled(this.pendingDrain)
209
207
  }
210
208
 
211
209
  private startDrainPass(): Promise<void> {
@@ -224,11 +222,14 @@ export class OntologyOutboxDispatcher {
224
222
  if (rows.length === 0) return
225
223
  const publishedCount = await this.publishClaim(rows)
226
224
  if (this.stopRequested || publishedCount === 0 || rows.length < this.batchSize) return
225
+ // In-memory/SQLite can resolve without I/O. Yield between full batches so catch-up cannot
226
+ // monopolize the event loop, while keeping small post-commit deliveries immediate.
227
+ await new Promise<void>((resolve) => setImmediate(resolve))
227
228
  }
228
229
 
229
230
  // A healthy full slice means more due rows may remain. Reuse the existing coalescing path so
230
231
  // catch-up continues without recursion, an idle polling loop, or an unbounded individual pass.
231
- if (!this.stopRequested) this.notify()
232
+ if (!this.closing && !this.stopRequested) this.notify()
232
233
  }
233
234
 
234
235
  private claimBatch(): Promise<readonly ClaimedOntologyOutboxRow[]> {
@@ -247,7 +248,6 @@ export class OntologyOutboxDispatcher {
247
248
  private async publishClaim(rows: readonly ClaimedOntologyOutboxRow[]): Promise<number> {
248
249
  const claim = new ClaimedBatch(rows)
249
250
  const failures = new DeliveryFailureAccumulator()
250
- this.inFlight.add(claim)
251
251
  const pending: PublicationGroup[] = [{ rows }]
252
252
  let publishAttempts = 0
253
253
  let publishedCount = 0
@@ -288,7 +288,6 @@ export class OntologyOutboxDispatcher {
288
288
  if (this.stopRequested) {
289
289
  await this.rescheduleClaimedForShutdown(claim.close())
290
290
  }
291
- this.inFlight.delete(claim)
292
291
  for (const failure of failures.list()) {
293
292
  this.reportDeliveryFailure(failure.error, failure.context)
294
293
  }
@@ -378,15 +377,10 @@ export class OntologyOutboxDispatcher {
378
377
  }
379
378
  }
380
379
 
381
- private async rescheduleUnsettledForShutdown(): Promise<void> {
382
- for (const claim of [...this.inFlight]) {
383
- await this.rescheduleClaimedForShutdown(claim.close())
384
- this.inFlight.delete(claim)
385
- }
386
- }
387
-
388
380
  private withOutbox<T>(run: (outbox: OntologyOutboxStorage) => Promise<T> | T): Promise<T> {
389
- return this.storage.transaction((tx) => run(tx.ontology.outbox))
381
+ // Every outbox method owns its atomic provider operation. A framework-wide transaction
382
+ // adds no guarantee here and copies the entire InMemoryStorage state for every batch.
383
+ return Promise.resolve(run(this.storage.ontology.outbox))
390
384
  }
391
385
 
392
386
  private reportDeliveryFailure(error: unknown, failure: OntologyOutboxDeliveryFailure): void {
@@ -367,6 +367,7 @@ export class InMemoryLakeStorage implements LakeStorage {
367
367
  }
368
368
 
369
369
  async *readRows(input: ReadDatasetRowsInput): AsyncIterable<DatasetRow> {
370
+ input.signal?.throwIfAborted()
370
371
  const definition = this.datasets.get(input.datasetId)
371
372
  if (!definition) {
372
373
  throw new LakeStorageError(`[LakeStorage] Unknown dataset '${input.datasetId}'`)
@@ -390,6 +391,7 @@ export class InMemoryLakeStorage implements LakeStorage {
390
391
  ?.slice(offset, limit === undefined ? undefined : offset + limit)
391
392
 
392
393
  for (const row of rows ?? []) {
394
+ input.signal?.throwIfAborted()
393
395
  yield selectColumns(row, input.columns)
394
396
  }
395
397
  }
@@ -71,6 +71,8 @@ export interface ReadDatasetRowsInput {
71
71
  readonly columns?: readonly string[]
72
72
  readonly limit?: number
73
73
  readonly offset?: number
74
+ /** Cancel an active read or a read waiting for provider capacity. */
75
+ readonly signal?: AbortSignal
74
76
  }
75
77
 
76
78
  export interface ReadDatasetChangesInput {
@@ -93,6 +93,7 @@ export class OntologyMaintenance {
93
93
 
94
94
  /** Runs one coalesced pass. Exposed for deterministic hosting and tests. */
95
95
  runNow(): Promise<void> {
96
+ if (this.stopping) return this.stopping
96
97
  this.pass ??= this.runPass().finally(() => {
97
98
  this.pass = null
98
99
  })
@@ -244,12 +245,15 @@ export class OntologyMaintenance {
244
245
  this.timer = null
245
246
  }
246
247
  const activePass = this.pass ?? Promise.resolve()
247
- const stopping = settlesWithin(activePass, this.shutdownTimeoutMs).then((settled) => {
248
+ const stopping = settlesWithin(activePass, this.shutdownTimeoutMs).then(async (settled) => {
248
249
  if (!settled) {
249
250
  this.reportError(
250
- new Error(`[Sixb] Ontology maintenance did not stop within ${this.shutdownTimeoutMs}ms.`)
251
+ new Error(
252
+ `[Sixb] Ontology maintenance is still stopping after ${this.shutdownTimeoutMs}ms; waiting for active storage operations.`
253
+ )
251
254
  )
252
255
  }
256
+ await activePass
253
257
  })
254
258
  this.stopping = stopping.finally(() => {
255
259
  this.stopping = null
@@ -7,7 +7,7 @@ export interface OntologyMaintenanceOptions {
7
7
  readonly terminalSourceRetentionMs?: number
8
8
  /** Maximum deletions attempted per cleanup domain and pass. Defaults to 1,000. */
9
9
  readonly cleanupLimit?: number
10
- /** Maximum time to wait for an active pass during shutdown. Defaults to 30 seconds. */
10
+ /** Warn after this shutdown grace period, then wait for active operations. Defaults to 30 seconds. */
11
11
  readonly shutdownTimeoutMs?: number
12
12
  }
13
13
 
@@ -17,7 +17,7 @@ runtime telemetry -> telemetry.append (origin: telemetry/runtime)
17
17
 
18
18
  Committed facts are published from the transactional outbox after the commit resolves.
19
19
  `OntologyOutboxDispatcher` owns that protocol: ingresses call `notify()` for prompt, non-blocking
20
- in-process delivery, and a process may call `start()` to host the durable poll loop. Publication is
20
+ in-process delivery; `OntologyMaintenance` hosts recovery catch-up. Publication is
21
21
  best effort — delivery may lag, but a committed fact is never lost.
22
22
 
23
23
  ## Common commit pipeline
@@ -14,6 +14,10 @@ export interface ModelDefinition {
14
14
  readonly modelId: string
15
15
  readonly name?: string
16
16
  readonly description?: string
17
+ /** Model author for display; does not change the provider/model routing identity. */
18
+ readonly publisher?: { readonly id: string; readonly name: string }
19
+ /** Hosting service label, when the model is offered through an intermediary. */
20
+ readonly via?: string
17
21
  readonly family?: string
18
22
  readonly tags?: readonly string[]
19
23
  readonly releaseDate?: string
@@ -38,6 +42,17 @@ export function defineLanguageModel(definition: LanguageModelDefinition): Langua
38
42
  assertModelId(definition.modelId, "modelId")
39
43
  assertOptionalString(definition.name, "name")
40
44
  assertOptionalString(definition.description, "description")
45
+ assertOptionalString(definition.via, "via")
46
+ if (definition.via !== undefined && !definition.via.trim())
47
+ throw new TypeError("[Sixb] Model via must not be empty.")
48
+ const publisher = definition.publisher
49
+ if (publisher !== undefined) {
50
+ assertRecord(publisher, "publisher")
51
+ for (const [field, value] of Object.entries({ id: publisher.id, name: publisher.name })) {
52
+ if (typeof value !== "string" || !value.trim() || value !== value.trim())
53
+ throw new TypeError(`[Sixb] Model publisher.${field} must be a nonempty trimmed string.`)
54
+ }
55
+ }
41
56
  assertOptionalString(definition.family, "family")
42
57
  assertOptionalString(definition.releaseDate, "releaseDate")
43
58
  assertOptionalString(definition.knowledgeCutoff, "knowledgeCutoff")
@@ -52,6 +67,10 @@ export function defineLanguageModel(definition: LanguageModelDefinition): Langua
52
67
  modelId: definition.modelId,
53
68
  ...(definition.name === undefined ? {} : { name: definition.name }),
54
69
  ...(definition.description === undefined ? {} : { description: definition.description }),
70
+ ...(publisher === undefined
71
+ ? {}
72
+ : { publisher: Object.freeze({ id: publisher.id, name: publisher.name }) }),
73
+ ...(definition.via === undefined ? {} : { via: definition.via }),
55
74
  ...(definition.family === undefined ? {} : { family: definition.family }),
56
75
  ...(tags === undefined ? {} : { tags }),
57
76
  ...(definition.releaseDate === undefined ? {} : { releaseDate: definition.releaseDate }),
@@ -335,8 +335,12 @@ function partitionInputUsage(usage: ModelUsage, rateCard: LanguageModelRateCard)
335
335
  ...(rateCard.cacheReadInput === undefined ? {} : { cacheRead }),
336
336
  ...(hasSpecificWrites
337
337
  ? {
338
- cacheWrite5m: usage.cacheWrite5mInputTokens ?? 0,
339
- cacheWrite1h: usage.cacheWrite1hInputTokens ?? 0,
338
+ ...(rateCard.cacheWriteInput5m !== undefined || rateCard.cacheWriteInput !== undefined
339
+ ? { cacheWrite5m: usage.cacheWrite5mInputTokens ?? 0 }
340
+ : {}),
341
+ ...(rateCard.cacheWriteInput1h !== undefined || rateCard.cacheWriteInput !== undefined
342
+ ? { cacheWrite1h: usage.cacheWrite1hInputTokens ?? 0 }
343
+ : {}),
340
344
  }
341
345
  : rateCard.cacheWriteInput === undefined
342
346
  ? {}
@@ -413,6 +413,20 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
413
413
  return structuredClone(finished)
414
414
  }
415
415
 
416
+ async listPendingConnectionRuns(
417
+ input: Parameters<ConnectorConnectionStorage["listPendingConnectionRuns"]>[0]
418
+ ): Promise<readonly ConnectorConnectionRunRecord[]> {
419
+ return [...this.connectionRuns.values()]
420
+ .filter(
421
+ (run) =>
422
+ run.projectId === input.projectId &&
423
+ run.connectorId === input.connectorId &&
424
+ (run.status === "running" ||
425
+ (run.status === "waiting" && run.waitingFor === "account_selection"))
426
+ )
427
+ .map((run) => structuredClone(run))
428
+ }
429
+
416
430
  async getConnectionRun(
417
431
  input: GetConnectorConnectionRunInput
418
432
  ): Promise<ConnectorConnectionRunRecord | null> {
@@ -855,7 +869,7 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
855
869
  input: PutConnectorConnectionInput,
856
870
  now: Date
857
871
  ): PutConnectorConnectionResult {
858
- let authorization = this.authorizations.get(input.authorizationId)
872
+ const authorization = this.authorizations.get(input.authorizationId)
859
873
  if (
860
874
  !sameAuthorizationScope(authorization, input) ||
861
875
  !isSelectable(authorization.status) ||
@@ -863,20 +877,6 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
863
877
  ) {
864
878
  throw authorizationConflict()
865
879
  }
866
- if (
867
- authorization.status === "pending_selection" &&
868
- authorization.selectionExpiresAt!.getTime() <= now.getTime()
869
- ) {
870
- authorization = {
871
- ...authorization,
872
- status: "revocation_pending",
873
- selectionExpiresAt: undefined,
874
- revision: authorization.revision + 1,
875
- updatedAt: now,
876
- }
877
- this.authorizations.set(authorization.id, authorization)
878
- throw authorizationConflict()
879
- }
880
880
  const account = authorization.accounts.find((candidate) => candidate.id === input.account.id)
881
881
  if (!account) {
882
882
  throw new ConnectorConnectionStorageError(
@@ -1078,6 +1078,7 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
1078
1078
  const run = this.connectionRuns.get(runId)
1079
1079
  if (!run || (run.status !== "waiting" && run.status !== "running")) return run
1080
1080
 
1081
+ if (run.status === "waiting" && run.waitingFor === "account_selection") return run
1081
1082
  const now = this.now()
1082
1083
  if (run.expiresAt.getTime() > now.getTime()) return run
1083
1084
 
@@ -1086,9 +1087,6 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
1086
1087
  if (attempt) this.attempts.delete(attempt.id)
1087
1088
  }
1088
1089
  if (run.status === "waiting") {
1089
- if (run.kind === "connect" && run.waitingFor === "account_selection") {
1090
- this.markPendingAuthorizationForCleanup(run.connectorId, run.authorizationId, now)
1091
- }
1092
1090
  const expired = expireConnectionRun(run, now)
1093
1091
  this.connectionRuns.set(run.id, expired)
1094
1092
  return expired
@@ -165,7 +165,7 @@ export class DurableConnectorConnections extends ConnectorConnectionOperations {
165
165
  input: PutConnectorConnectionInput,
166
166
  now: Date
167
167
  ): Promise<PutConnectorConnectionResult | CommittedConnectorConnectionError> {
168
- let authorization = await persistence.getAuthorization(input.authorizationId)
168
+ const authorization = await persistence.getAuthorization(input.authorizationId)
169
169
  if (
170
170
  !authorization ||
171
171
  !isSelectable(authorization.status) ||
@@ -173,20 +173,6 @@ export class DurableConnectorConnections extends ConnectorConnectionOperations {
173
173
  ) {
174
174
  throw authorizationConflict()
175
175
  }
176
- if (
177
- authorization.status === "pending_selection" &&
178
- authorization.selectionExpiresAt!.getTime() <= now.getTime()
179
- ) {
180
- authorization = {
181
- ...authorization,
182
- status: "revocation_pending",
183
- selectionExpiresAt: undefined,
184
- revision: authorization.revision + 1,
185
- updatedAt: now,
186
- }
187
- await persistence.updateAuthorization(authorization)
188
- return { error: authorizationConflict() }
189
- }
190
176
  const account = authorization.accounts.find((candidate) => candidate.id === input.account.id)
191
177
  if (!account) {
192
178
  throw new ConnectorConnectionStorageError(
@@ -360,6 +360,12 @@ export class DurableConnectorConnectionRuns extends ConnectorConnectionOperation
360
360
  })
361
361
  }
362
362
 
363
+ listPendingConnectionRuns(
364
+ input: Parameters<ConnectorConnectionStorage["listPendingConnectionRuns"]>[0]
365
+ ) {
366
+ return this.read(input, (persistence) => persistence.listPendingConnectionRuns())
367
+ }
368
+
363
369
  getConnectionRun(
364
370
  input: GetConnectorConnectionRunInput
365
371
  ): Promise<ConnectorConnectionRunRecord | null> {