@kortix/sdk 0.12.4 → 0.12.5
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.
- package/README.md +58 -15
- package/dist/browser/session-sync/session-transcript-cache.d.ts +17 -0
- package/dist/browser/session-sync/session-transcript-cache.d.ts.map +1 -1
- package/dist/browser/session-sync/session-transcript-cache.js +14 -2
- package/dist/browser/session-sync/session-transcript-cache.js.map +1 -1
- package/dist/browser/stores/sync-store.d.ts +86 -2
- package/dist/browser/stores/sync-store.d.ts.map +1 -1
- package/dist/browser/stores/sync-store.js +386 -33
- package/dist/browser/stores/sync-store.js.map +1 -1
- package/dist/core/client/kortix.d.ts +57 -54
- package/dist/core/client/kortix.d.ts.map +1 -1
- package/dist/core/client/kortix.js +40 -21
- package/dist/core/client/kortix.js.map +1 -1
- package/dist/core/http/api-client.d.ts +19 -1
- package/dist/core/http/api-client.d.ts.map +1 -1
- package/dist/core/http/api-client.js +39 -6
- package/dist/core/http/api-client.js.map +1 -1
- package/dist/core/http/auth.d.ts.map +1 -1
- package/dist/core/http/auth.js +6 -4
- package/dist/core/http/auth.js.map +1 -1
- package/dist/core/http/config.d.ts +4 -0
- package/dist/core/http/config.d.ts.map +1 -1
- package/dist/core/http/config.js.map +1 -1
- package/dist/core/rest/platform-client/host-boundary.js +2 -2
- package/dist/core/rest/platform-client/host-boundary.js.map +1 -1
- package/dist/core/rest/projects-client/access.d.ts +1 -1
- package/dist/core/rest/projects-client/agent-config.d.ts +1 -1
- package/dist/core/rest/projects-client/agent-config.d.ts.map +1 -1
- package/dist/core/rest/projects-client/audit.js +1 -1
- package/dist/core/rest/projects-client/audit.js.map +1 -1
- package/dist/core/rest/projects-client/billing.d.ts +7 -0
- package/dist/core/rest/projects-client/billing.d.ts.map +1 -1
- package/dist/core/rest/projects-client/billing.js.map +1 -1
- package/dist/core/rest/projects-client/channels.d.ts +7 -6
- package/dist/core/rest/projects-client/channels.d.ts.map +1 -1
- package/dist/core/rest/projects-client/channels.js +12 -2
- package/dist/core/rest/projects-client/channels.js.map +1 -1
- package/dist/core/rest/projects-client/connectors.d.ts +128 -98
- package/dist/core/rest/projects-client/connectors.d.ts.map +1 -1
- package/dist/core/rest/projects-client/connectors.js +199 -119
- package/dist/core/rest/projects-client/connectors.js.map +1 -1
- package/dist/core/rest/projects-client/files.d.ts.map +1 -1
- package/dist/core/rest/projects-client/files.js +7 -1
- package/dist/core/rest/projects-client/files.js.map +1 -1
- package/dist/core/rest/projects-client/policies.js +3 -3
- package/dist/core/rest/projects-client/policies.js.map +1 -1
- package/dist/core/rest/projects-client/projects.d.ts +46 -0
- package/dist/core/rest/projects-client/projects.d.ts.map +1 -1
- package/dist/core/rest/projects-client/projects.js +12 -0
- package/dist/core/rest/projects-client/projects.js.map +1 -1
- package/dist/core/rest/projects-client/secrets.d.ts +55 -3
- package/dist/core/rest/projects-client/secrets.d.ts.map +1 -1
- package/dist/core/rest/projects-client/secrets.js +14 -4
- package/dist/core/rest/projects-client/secrets.js.map +1 -1
- package/dist/core/rest/projects-client/sessions.d.ts +8 -16
- package/dist/core/rest/projects-client/sessions.d.ts.map +1 -1
- package/dist/core/rest/projects-client/sessions.js +1 -1
- package/dist/core/rest/projects-client/sessions.js.map +1 -1
- package/dist/core/session/index.d.ts +1 -0
- package/dist/core/session/index.d.ts.map +1 -1
- package/dist/core/session/index.js +1 -0
- package/dist/core/session/index.js.map +1 -1
- package/dist/core/session/preview-probe.d.ts +76 -0
- package/dist/core/session/preview-probe.d.ts.map +1 -0
- package/dist/core/session/preview-probe.js +97 -0
- package/dist/core/session/preview-probe.js.map +1 -0
- package/dist/core/turns/classify.js +1 -1
- package/dist/core/turns/errors.js +1 -1
- package/dist/core/turns/errors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/kortix.esm.min.js +19 -19
- package/dist/kortix.global.js +19 -19
- package/dist/platform/auth-core.d.ts +2 -1
- package/dist/platform/auth-core.d.ts.map +1 -1
- package/dist/platform/auth-core.js +10 -1
- package/dist/platform/auth-core.js.map +1 -1
- package/dist/react/use-opencode-sessions/messages.d.ts +19 -3
- package/dist/react/use-opencode-sessions/messages.d.ts.map +1 -1
- package/dist/react/use-opencode-sessions/messages.js +28 -55
- package/dist/react/use-opencode-sessions/messages.js.map +1 -1
- package/dist/react/use-project-secrets.d.ts +24 -0
- package/dist/react/use-project-secrets.d.ts.map +1 -1
- package/dist/react/use-session-sync.d.ts +1 -2
- package/dist/react/use-session-sync.d.ts.map +1 -1
- package/dist/react/use-session-sync.js +17 -40
- package/dist/react/use-session-sync.js.map +1 -1
- package/dist/react/use-session.d.ts.map +1 -1
- package/dist/react/use-session.js +18 -16
- package/dist/react/use-session.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -33,6 +33,31 @@ const kortix = createKortix({
|
|
|
33
33
|
await kortix.projects.list();
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
### Call external systems through Connectors
|
|
37
|
+
|
|
38
|
+
Use one six-method data plane for every Connector provider. A user token binds
|
|
39
|
+
the project explicitly. An agent-minted session token already carries its
|
|
40
|
+
project scope, so it can use the top-level fallback.
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
const connectors = projectId
|
|
44
|
+
? kortix.project(projectId).connectors
|
|
45
|
+
: kortix.connectors;
|
|
46
|
+
|
|
47
|
+
await connectors.catalog();
|
|
48
|
+
await connectors.tools();
|
|
49
|
+
await connectors.search('send email');
|
|
50
|
+
await connectors.describe('gmail.send_email');
|
|
51
|
+
await connectors.call('gmail.send_email', { to, subject, body });
|
|
52
|
+
await connectors.uploadAttachment(bytes, {
|
|
53
|
+
filename: 'invoice.pdf',
|
|
54
|
+
contentType: 'application/pdf',
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
A Connector defines callable tools. A Connection stores one authorization for
|
|
59
|
+
that Connector. Credentials remain server-side and never enter the sandbox.
|
|
60
|
+
|
|
36
61
|
## No bundler, no framework
|
|
37
62
|
|
|
38
63
|
The published package ships a browser IIFE bundle alongside its ESM `dist/` —
|
|
@@ -86,7 +111,19 @@ const kortix = createKortix({
|
|
|
86
111
|
// Projects
|
|
87
112
|
const projects = await kortix.projects.list();
|
|
88
113
|
const detail = await kortix.project(pid).detail();
|
|
89
|
-
await kortix.project(pid).secrets.upsert({
|
|
114
|
+
await kortix.project(pid).secrets.upsert({
|
|
115
|
+
name: "LOCAL_TOOL_TOKEN",
|
|
116
|
+
value,
|
|
117
|
+
strategy: "runtime",
|
|
118
|
+
consumer: "sandbox",
|
|
119
|
+
});
|
|
120
|
+
await kortix.project(pid).secrets.upsert({
|
|
121
|
+
identifier: "anthropic-primary",
|
|
122
|
+
name: "ANTHROPIC_API_KEY",
|
|
123
|
+
value: providerKey,
|
|
124
|
+
strategy: "broker",
|
|
125
|
+
consumer: "llm_gateway",
|
|
126
|
+
});
|
|
90
127
|
const visibleSessions = await kortix.project(pid).sessions.list();
|
|
91
128
|
const projectInventory = await kortix
|
|
92
129
|
.project(pid)
|
|
@@ -150,7 +187,8 @@ exhaustive — see `API-MAP.md` for the full per-domain surface:
|
|
|
150
187
|
| `kortix.billing` | entitlement/usage reads: `accountState` · `accountStateMinimal` · `transactions` · `transactionsSummary` · `creditBreakdown` · `usageHistory` · `usageRollup` · `sessionCosts.{list,get}` · `tierConfigurations` — plus a curated mutation surface: `checkout.{createSession,confirmSession}` · `subscription.{createPortalSession,cancel,reactivate,scheduleDowngrade,cancelScheduledChange,prorationPreview}` · `credits.{purchase,autoTopupSettings,configureAutoTopup}` |
|
|
151
188
|
| `kortix.marketplace` | public marketplace catalog browse + sources (not project-scoped): `items` · `item` · `itemFile` · `marketplaces` · `featured` · `sources.{list,add,remove}` — distinct from the install-scoped `project(id).marketplace` |
|
|
152
189
|
| `kortix.validateToken()` | pasted-API-key validation helper — `GET /accounts/me`, never throws, resolves `{valid, identity?, error?}` |
|
|
153
|
-
| `kortix.
|
|
190
|
+
| `kortix.connectors` | Connector data plane for an agent-minted session token: `catalog` · `tools` · `search` · `describe` · `call` · `uploadAttachment` |
|
|
191
|
+
| `kortix.project(id)` | id-bound handle: `.secrets` · `.access` · `.connectors` (data plane + configuration + Connections) · `.policies` · `.triggers` · `.files` · `.git` · `.changeRequests` (incl. `requestChanges`) · `.sessions` · `.tokens` (project-scoped CLI PATs — the `KORTIX_TOKEN` shape) · `.marketplace` / `.registry` (install/update/remove catalog items) · `.setupLinks.{requestSecret,requestConnector}` (agent-minted secret-entry / connector links) · `.validateManifest` · `.gitToken` · `.setDefaultAgent(name)` · `.session(sid)` (+ more namespaces: `.review`, `.approvals`, `.gateway` (incl. `.routing` and `.playground`), `.channels`, `.modelDefaults`, `.sandbox`) |
|
|
154
192
|
| `kortix.session(pid, sid)` | id-bound handle: lifecycle (`get`/`update`/`delete`/`start`/`restart`/`stop`/`setSharing`/`previews`/`commit`/`publicShares`/`ensureReady`) · finalized `cost()` · `send`/`abort`/`rewind`/`restoreRewind`/`setModel`/`setAgent` · `transcript()` · `.files` · runtime URL helpers (`health`/`previewUrl`/`proxyUrl`) · OpenCode REST compatibility escape hatches: `stream()` and `.runtime` |
|
|
155
193
|
| `kortix.runtime()` | the OpenCode v2 compatibility client for the active sandbox; use a session-scoped handle in multi-tenant code |
|
|
156
194
|
|
|
@@ -172,12 +210,12 @@ await kortix.project(projectId).sessions.create({
|
|
|
172
210
|
```
|
|
173
211
|
|
|
174
212
|
Do not put credentials in this map. For a white-label/backend wrapper, create an
|
|
175
|
-
operator-managed connection
|
|
176
|
-
credential endpoint, and pass only the non-secret
|
|
213
|
+
operator-managed connection, store its credential through the dedicated
|
|
214
|
+
credential endpoint, and pass only the non-secret connection id at session create:
|
|
177
215
|
|
|
178
216
|
```ts
|
|
179
217
|
const project = kortix.project(projectId);
|
|
180
|
-
const
|
|
218
|
+
const connection = await project.connectors.connections.reconcile({
|
|
181
219
|
connector_alias: "customer-data",
|
|
182
220
|
owner_type: "external",
|
|
183
221
|
owner_id: wrapperUserId,
|
|
@@ -191,39 +229,39 @@ const auth = await project.connectors.auth.discover({
|
|
|
191
229
|
provider: "postman",
|
|
192
230
|
spec: "https://github.com/HubSpot/HubSpot-public-api-spec-collection",
|
|
193
231
|
});
|
|
194
|
-
await project.connectors.
|
|
232
|
+
await project.connectors.connections.updateCredential(connection.connection_id, {
|
|
195
233
|
value: shortLivedCapability,
|
|
196
234
|
kind: "secret",
|
|
197
235
|
});
|
|
198
236
|
await project.sessions.create({
|
|
199
237
|
runtime_context: { locale: "de" },
|
|
200
238
|
connector_bindings: {
|
|
201
|
-
"customer-data": {
|
|
239
|
+
"customer-data": { connection_id: connection.connection_id },
|
|
202
240
|
},
|
|
203
241
|
});
|
|
204
242
|
```
|
|
205
243
|
|
|
206
244
|
For bring-your-own authorization, each logged-in member creates their own
|
|
207
|
-
|
|
245
|
+
connection without supplying an owner id; Kortix derives ownership from the bearer
|
|
208
246
|
token:
|
|
209
247
|
|
|
210
248
|
```ts
|
|
211
|
-
const
|
|
249
|
+
const connection = await project.connectors.connections.reconcileMember({
|
|
212
250
|
connector_alias: "gmail",
|
|
213
251
|
label: "My Gmail",
|
|
214
252
|
});
|
|
215
|
-
await project.connectors.
|
|
253
|
+
await project.connectors.connections.pipedreamConnect(connection.connection_id);
|
|
216
254
|
// Complete OAuth, then:
|
|
217
|
-
await project.connectors.
|
|
255
|
+
await project.connectors.connections.pipedreamFinalize(connection.connection_id);
|
|
218
256
|
await project.sessions.create({
|
|
219
|
-
connector_bindings: { gmail: {
|
|
257
|
+
connector_bindings: { gmail: { connection_id: connection.connection_id } },
|
|
220
258
|
});
|
|
221
259
|
```
|
|
222
260
|
|
|
223
|
-
Member
|
|
261
|
+
Member connections are owner-only even for project managers, and sessions using
|
|
224
262
|
one must remain private. Project defaults remain shared; external/agent/subject
|
|
225
|
-
|
|
226
|
-
and resolved on every
|
|
263
|
+
connections remain operator-managed. Every connection is project/connector scoped
|
|
264
|
+
and resolved on every Connector request, so revocation takes effect without a
|
|
227
265
|
restart. Credentials are encrypted server-side and are never returned, placed
|
|
228
266
|
in `KORTIX_SESSION_CONTEXT`, or injected into the sandbox environment. Raw env
|
|
229
267
|
and MCP configuration are not session-create inputs.
|
|
@@ -438,6 +476,7 @@ Stable, tree-shakeable surfaces (also reachable via the facade). Not exhaustive
|
|
|
438
476
|
interface KortixPlatformConfig {
|
|
439
477
|
backendUrl: string;
|
|
440
478
|
getToken: () => Promise<string | null>;
|
|
479
|
+
clientSource?: 'api' | 'cli' | 'mobile' | 'web';
|
|
441
480
|
getUserId?: () => Promise<string | null>;
|
|
442
481
|
billingEnabled?: boolean;
|
|
443
482
|
sandboxId?: string | null;
|
|
@@ -448,6 +487,10 @@ interface KortixPlatformConfig {
|
|
|
448
487
|
}
|
|
449
488
|
```
|
|
450
489
|
|
|
490
|
+
Set `clientSource` when a non-web host needs its requests separated in the
|
|
491
|
+
centralized audit log. The SDK sends the validated value as request metadata.
|
|
492
|
+
Actor identity and permissions still come from the bearer token.
|
|
493
|
+
|
|
451
494
|
The SDK is host-agnostic: no Next.js / web coupling in the core. The host injects
|
|
452
495
|
its token getter and toast/notify sinks; the SDK does the rest. Today that's proven
|
|
453
496
|
in React DOM (`apps/web` and the `apps/whitelabel-demo` reference app are the
|
|
@@ -38,10 +38,27 @@ export declare function toHydrateEntries(transcript: CachedTranscript): Array<{
|
|
|
38
38
|
* store holds anything for this session — from SSE, an optimistic send, or a
|
|
39
39
|
* completed reconcile — it outranks whatever is on disk, so hydrating again
|
|
40
40
|
* could only ever move the transcript backwards.
|
|
41
|
+
*
|
|
42
|
+
* With exactly one exception, and it is not hypothetical: a session whose agent
|
|
43
|
+
* is still running when the store evicts it. Eviction deletes the key; the
|
|
44
|
+
* agent's next SSE frame puts it straight back, holding only what streamed
|
|
45
|
+
* after the eviction. The store "has" the session, but what it has is strictly
|
|
46
|
+
* less than the disk copy, so standing down leaves the user with a fragment and
|
|
47
|
+
* a `loadOlder` for their own history. `hydrate` merges rather than replaces —
|
|
48
|
+
* it never drops a message the store has that the incoming set lacks, and for
|
|
49
|
+
* text parts it keeps whichever side has more — so painting the disk copy under
|
|
50
|
+
* a live fragment restores the history without touching the live tail.
|
|
41
51
|
*/
|
|
42
52
|
export declare function shouldHydrateFromCache(input: {
|
|
43
53
|
storeHasSession: boolean;
|
|
44
54
|
cachedMessageCount: number;
|
|
55
|
+
/**
|
|
56
|
+
* The store's entry for this session is a post-eviction fragment. From
|
|
57
|
+
* `useSyncStore.wasTranscriptEvicted`, which also reports false the moment a
|
|
58
|
+
* send goes in flight — repainting under one would retire the message the
|
|
59
|
+
* user just typed.
|
|
60
|
+
*/
|
|
61
|
+
storeSessionWasEvicted?: boolean;
|
|
45
62
|
}): boolean;
|
|
46
63
|
/**
|
|
47
64
|
* Read this session's cached transcript. Resolves to null when there is no
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-transcript-cache.d.ts","sourceRoot":"","sources":["../../../src/browser/session-sync/session-transcript-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAIhE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;CAC/B;AAED,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;CAC/B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,oBAAoB,EAC3B,SAAS,EAAE,MAAM,GAChB,gBAAgB,GAAG,IAAI,CASzB;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,gBAAgB,GAC3B,KAAK,CAAC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC,CAIzC;AAED
|
|
1
|
+
{"version":3,"file":"session-transcript-cache.d.ts","sourceRoot":"","sources":["../../../src/browser/session-sync/session-transcript-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAIhE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;CAC/B;AAED,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;CAC/B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,oBAAoB,EAC3B,SAAS,EAAE,MAAM,GAChB,gBAAgB,GAAG,IAAI,CASzB;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,gBAAgB,GAC3B,KAAK,CAAC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC,CAIzC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,GAAG,OAAO,CAIV;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAIlC;AAED,iFAAiF;AACjF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,oBAAoB,EAC3B,SAAS,EAAE,MAAM,EACjB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
|
@@ -42,11 +42,23 @@ export function toHydrateEntries(transcript) {
|
|
|
42
42
|
* store holds anything for this session — from SSE, an optimistic send, or a
|
|
43
43
|
* completed reconcile — it outranks whatever is on disk, so hydrating again
|
|
44
44
|
* could only ever move the transcript backwards.
|
|
45
|
+
*
|
|
46
|
+
* With exactly one exception, and it is not hypothetical: a session whose agent
|
|
47
|
+
* is still running when the store evicts it. Eviction deletes the key; the
|
|
48
|
+
* agent's next SSE frame puts it straight back, holding only what streamed
|
|
49
|
+
* after the eviction. The store "has" the session, but what it has is strictly
|
|
50
|
+
* less than the disk copy, so standing down leaves the user with a fragment and
|
|
51
|
+
* a `loadOlder` for their own history. `hydrate` merges rather than replaces —
|
|
52
|
+
* it never drops a message the store has that the incoming set lacks, and for
|
|
53
|
+
* text parts it keeps whichever side has more — so painting the disk copy under
|
|
54
|
+
* a live fragment restores the history without touching the live tail.
|
|
45
55
|
*/
|
|
46
56
|
export function shouldHydrateFromCache(input) {
|
|
47
|
-
if (input.
|
|
57
|
+
if (input.cachedMessageCount <= 0)
|
|
48
58
|
return false;
|
|
49
|
-
|
|
59
|
+
if (!input.storeHasSession)
|
|
60
|
+
return true;
|
|
61
|
+
return input.storeSessionWasEvicted === true;
|
|
50
62
|
}
|
|
51
63
|
/**
|
|
52
64
|
* Read this session's cached transcript. Resolves to null when there is no
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-transcript-cache.js","sourceRoot":"","sources":["../../../src/browser/session-sync/session-transcript-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAY/E;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAA2B,EAC3B,SAAiB;IAEjB,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,EAAE,EAAE;YAAE,SAAS;QAC3B,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,gBAAgB,CAC9B,UAA4B;IAE5B,OAAO,CAAC,UAAU,CAAC,QAAQ,IAAI,EAAE,CAAC;SAC/B,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;SAClC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AACxF,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"session-transcript-cache.js","sourceRoot":"","sources":["../../../src/browser/session-sync/session-transcript-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAY/E;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAA2B,EAC3B,SAAiB;IAEjB,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,EAAE,EAAE;YAAE,SAAS;QAC3B,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,gBAAgB,CAC9B,UAA4B;IAE5B,OAAO,CAAC,UAAU,CAAC,QAAQ,IAAI,EAAE,CAAC;SAC/B,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;SAClC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AACxF,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAUtC;IACC,IAAI,KAAK,CAAC,kBAAkB,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,KAAK,CAAC,sBAAsB,KAAK,IAAI,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,SAAiB,EACjB,kBAA2B;IAE3B,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IACvE,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5F,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;AAClE,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,qBAAqB,CACnC,KAA2B,EAC3B,SAAiB,EACjB,kBAA2B;IAE3B,MAAM,UAAU,GAAG,uBAAuB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC7D,IAAI,CAAC,UAAU;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1C,OAAO,gBAAgB,CAAC,SAAS,EAAE,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;AAChG,CAAC"}
|
|
@@ -13,9 +13,40 @@ interface SyncState {
|
|
|
13
13
|
applyEvent: (event: OpenCodeEvent) => void;
|
|
14
14
|
upsertMessage: (sessionID: string, message: Message) => void;
|
|
15
15
|
removeMessage: (sessionID: string, messageID: string) => void;
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* `sessionID` is optional. Omitted, the deltaActiveParts guard below reads
|
|
18
|
+
* `part.sessionID` directly. Pass it explicitly whenever the caller already
|
|
19
|
+
* resolved a more trustworthy session id than the wire part carries — see
|
|
20
|
+
* the `message.part.updated` handler in `applyEvent`, which falls back to
|
|
21
|
+
* scanning every session's message list specifically because
|
|
22
|
+
* `part.sessionID` can be absent on the wire. Without this parameter that
|
|
23
|
+
* resolved id has nowhere to go, and the guard silently no-ops for exactly
|
|
24
|
+
* the malformed events it exists to protect against.
|
|
25
|
+
*
|
|
26
|
+
* Kept optional (not merged into `part`, not required) because `upsertPart`
|
|
27
|
+
* has real callers outside this file (`apps/web` via `useSessionStateStore`)
|
|
28
|
+
* that only ever pass `(messageID, part)` — this stays source-compatible
|
|
29
|
+
* with them.
|
|
30
|
+
*/
|
|
31
|
+
upsertPart: (messageID: string, part: Part, sessionID?: string) => void;
|
|
17
32
|
removePart: (messageID: string, partID: string) => void;
|
|
18
|
-
|
|
33
|
+
/**
|
|
34
|
+
* `sessionID` is a new REQUIRED leading parameter (was `(messageID, partID,
|
|
35
|
+
* field, delta)`) — a breaking arity change for anyone calling this action
|
|
36
|
+
* directly. Deliberate, not silent: the only caller of `applyPartDelta` in
|
|
37
|
+
* this repo is this file's own `applyEvent` (`message.part.delta` case),
|
|
38
|
+
* which already has a reliable `sessionID` on the event itself — no
|
|
39
|
+
* "resolve it from an unreliable field" case like `upsertPart` above.
|
|
40
|
+
* Kept required, not optional-with-fallback, because there is no
|
|
41
|
+
* `part.sessionID`-equivalent to fall back to here that wouldn't be a
|
|
42
|
+
* guess. Verified no other in-repo caller exists (`apps/web`, `apps/mobile`
|
|
43
|
+
* both use their own stores/methods, not this one). This action is exported
|
|
44
|
+
* on `useSyncStore` (`./sync-store`, `./internal/sync-store`), which makes
|
|
45
|
+
* it technically part of the published surface, so an out-of-repo consumer
|
|
46
|
+
* calling it directly would fail to compile — that needs a semver-relevant
|
|
47
|
+
* callout in the next release notes.
|
|
48
|
+
*/
|
|
49
|
+
applyPartDelta: (sessionID: string, messageID: string, partID: string, field: string, delta: string) => void;
|
|
19
50
|
setStatus: (sessionID: string, status: SessionStatus) => void;
|
|
20
51
|
setDiff: (sessionID: string, diffs: FileDiff[]) => void;
|
|
21
52
|
setTodo: (sessionID: string, todos: Todo[]) => void;
|
|
@@ -39,6 +70,59 @@ interface SyncState {
|
|
|
39
70
|
* whose first prompt the server hasn't registered yet. */
|
|
40
71
|
hasOptimisticMessages: (sessionID: string) => boolean;
|
|
41
72
|
clearSession: (sessionID: string) => void;
|
|
73
|
+
/**
|
|
74
|
+
* Take a hold on `sessionID`'s transcript for one mounted consumer, and get
|
|
75
|
+
* back the release for it. The session's data stays resident until every
|
|
76
|
+
* hold is released; see {@link DETACHED_SESSION_LIMIT} for what happens
|
|
77
|
+
* after that.
|
|
78
|
+
*
|
|
79
|
+
* Returning the release rather than exposing a separate `releaseSession`
|
|
80
|
+
* makes the pairing structural — a caller cannot take a hold without
|
|
81
|
+
* receiving the matching release, and a React effect returns it directly:
|
|
82
|
+
*
|
|
83
|
+
* ```ts
|
|
84
|
+
* useEffect(() => useSyncStore.getState().retainSession(id), [id]);
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* Same shape as `retainSessionSyncController` in session-sync-registry.ts.
|
|
88
|
+
* The release is idempotent: calling it twice drops one hold, not two.
|
|
89
|
+
*/
|
|
90
|
+
retainSession: (sessionID: string) => () => void;
|
|
91
|
+
/**
|
|
92
|
+
* True when this session's `messages` entry — if it has one at all — is a
|
|
93
|
+
* post-eviction fragment rather than the transcript.
|
|
94
|
+
*
|
|
95
|
+
* Eviction deletes the key, and `use-session-sync.ts` reads its absence as
|
|
96
|
+
* "the disk copy may repaint". A session whose agent is still running defeats
|
|
97
|
+
* that on its own: its SSE frames put the key back within a second or two,
|
|
98
|
+
* holding only what streamed after the eviction, so the user came back to the
|
|
99
|
+
* fragment and had to `loadOlder` for everything before it.
|
|
100
|
+
*
|
|
101
|
+
* Answering this at the store is what makes the repaint decision correct
|
|
102
|
+
* without dropping any event — dropping events for a session nobody has
|
|
103
|
+
* mounted would blind the spawn-tool preview of a child session, which has no
|
|
104
|
+
* reconcile of its own and is fed by SSE alone.
|
|
105
|
+
*
|
|
106
|
+
* Goes false again the moment anything re-establishes the session:
|
|
107
|
+
* `hydrate` (the repaint, or a reconcile), `clearSession`, `optimisticAdd`.
|
|
108
|
+
*/
|
|
109
|
+
wasTranscriptEvicted: (sessionID: string) => boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Join this session's messages with their parts, memoized on the identity of
|
|
112
|
+
* the arrays it read.
|
|
113
|
+
*
|
|
114
|
+
* Every consumer selects through here — `useSessionSync` and
|
|
115
|
+
* `useOpenCodeMessages` alike. It has to be one shared memo rather than one
|
|
116
|
+
* per hook: `getMessages` rebuilds via `.map()` on every call, so a raw
|
|
117
|
+
* selector returns a new array each time, fails `useSyncExternalStore`'s
|
|
118
|
+
* `Object.is` check and re-renders forever. The memo previously existed
|
|
119
|
+
* TWICE, once in each hook file, and neither copy was dropped when a
|
|
120
|
+
* session's data was — so an evicted transcript stayed reachable through
|
|
121
|
+
* whichever memo still held its rows. Keeping it in the store, next to the
|
|
122
|
+
* eviction that invalidates it, is what makes that impossible rather than
|
|
123
|
+
* merely fixed.
|
|
124
|
+
*/
|
|
125
|
+
buildSessionMessages: (sessionID: string, msgs: Message[] | undefined, parts: Record<string, Part[]>) => MessageWithParts[];
|
|
42
126
|
hydrate: (sessionID: string, msgs: Array<{
|
|
43
127
|
info: Message;
|
|
44
128
|
parts: Part[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-store.d.ts","sourceRoot":"","sources":["../../../src/browser/stores/sync-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,OAAO,EACP,KAAK,IAAI,aAAa,EACtB,IAAI,EAEJ,aAAa,EAEb,IAAI,EACJ,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAKnF,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AAC/B,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAe/C,UAAU,SAAS;IAElB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAG9B,UAAU,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC3C,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7D,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"sync-store.d.ts","sourceRoot":"","sources":["../../../src/browser/stores/sync-store.ts"],"names":[],"mappings":"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"}
|