@kortix/sdk 0.13.4 → 0.13.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/dist/browser/cache/idb-sync-cache.d.ts +19 -1
- package/dist/browser/cache/idb-sync-cache.d.ts.map +1 -1
- package/dist/browser/cache/idb-sync-cache.js +39 -4
- package/dist/browser/cache/idb-sync-cache.js.map +1 -1
- package/dist/browser/session-sync/session-sync-registry.d.ts +20 -0
- package/dist/browser/session-sync/session-sync-registry.d.ts.map +1 -1
- package/dist/browser/session-sync/session-sync-registry.js +69 -6
- package/dist/browser/session-sync/session-sync-registry.js.map +1 -1
- package/dist/browser/session-sync/visibility.d.ts +19 -0
- package/dist/browser/session-sync/visibility.d.ts.map +1 -0
- package/dist/browser/session-sync/visibility.js +16 -0
- package/dist/browser/session-sync/visibility.js.map +1 -0
- package/dist/browser/stores/sandbox-connection-store.js +1 -1
- package/dist/browser/stores/sandbox-connection-store.js.map +1 -1
- package/dist/browser/stores/sync-store.d.ts +27 -1
- package/dist/browser/stores/sync-store.d.ts.map +1 -1
- package/dist/browser/stores/sync-store.js +198 -41
- package/dist/browser/stores/sync-store.js.map +1 -1
- package/dist/core/client/kortix.d.ts +0 -11
- package/dist/core/client/kortix.d.ts.map +1 -1
- package/dist/core/client/kortix.js +14 -8
- package/dist/core/client/kortix.js.map +1 -1
- package/dist/core/rest/projects-client/channels.d.ts +0 -3
- package/dist/core/rest/projects-client/channels.d.ts.map +1 -1
- package/dist/core/rest/projects-client/channels.js +0 -6
- package/dist/core/rest/projects-client/channels.js.map +1 -1
- package/dist/core/rest/projects-client/index.d.ts +0 -2
- package/dist/core/rest/projects-client/index.d.ts.map +1 -1
- package/dist/core/rest/projects-client/index.js +0 -2
- package/dist/core/rest/projects-client/index.js.map +1 -1
- package/dist/core/rest/projects-client/projects.d.ts +1 -1
- package/dist/core/rest/projects-client/projects.d.ts.map +1 -1
- package/dist/core/rest/projects-client/projects.js +5 -3
- package/dist/core/rest/projects-client/projects.js.map +1 -1
- package/dist/core/rest/projects-client/sessions.d.ts +8 -33
- package/dist/core/rest/projects-client/sessions.d.ts.map +1 -1
- package/dist/core/rest/projects-client/sessions.js +1 -18
- package/dist/core/rest/projects-client/sessions.js.map +1 -1
- package/dist/core/runtime/attachment-part.d.ts +26 -0
- package/dist/core/runtime/attachment-part.d.ts.map +1 -0
- package/dist/core/runtime/attachment-part.js +41 -0
- package/dist/core/runtime/attachment-part.js.map +1 -0
- package/dist/core/runtime/client.d.ts +4 -2
- package/dist/core/runtime/client.d.ts.map +1 -1
- package/dist/core/runtime/client.js +3 -2
- package/dist/core/runtime/client.js.map +1 -1
- package/dist/core/runtime/opencode-v2-event-aliases.d.ts +184 -0
- package/dist/core/runtime/opencode-v2-event-aliases.d.ts.map +1 -0
- package/dist/core/runtime/opencode-v2-event-aliases.js +2 -0
- package/dist/core/runtime/opencode-v2-event-aliases.js.map +1 -0
- package/dist/core/runtime/pty.d.ts +11 -1
- package/dist/core/runtime/pty.d.ts.map +1 -1
- package/dist/core/runtime/pty.js +19 -6
- package/dist/core/runtime/pty.js.map +1 -1
- package/dist/core/session/connection.d.ts +64 -0
- package/dist/core/session/connection.d.ts.map +1 -0
- package/dist/core/session/connection.js +36 -0
- package/dist/core/session/connection.js.map +1 -0
- 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-auth.d.ts +25 -0
- package/dist/core/session/preview-auth.d.ts.map +1 -1
- package/dist/core/session/preview-auth.js +31 -1
- package/dist/core/session/preview-auth.js.map +1 -1
- package/dist/core/session/preview-config.d.ts +26 -0
- package/dist/core/session/preview-config.d.ts.map +1 -0
- package/dist/core/session/preview-config.js +95 -0
- package/dist/core/session/preview-config.js.map +1 -0
- package/dist/core/session/preview-options.d.ts +25 -0
- package/dist/core/session/preview-options.d.ts.map +1 -0
- package/dist/core/session/preview-options.js +45 -0
- package/dist/core/session/preview-options.js.map +1 -0
- package/dist/core/session/preview.d.ts +8 -3
- package/dist/core/session/preview.d.ts.map +1 -1
- package/dist/core/session/preview.js +11 -4
- package/dist/core/session/preview.js.map +1 -1
- package/dist/core/session/rewind.d.ts +67 -24
- package/dist/core/session/rewind.d.ts.map +1 -1
- package/dist/core/session/rewind.js +74 -26
- package/dist/core/session/rewind.js.map +1 -1
- package/dist/core/session/server-store/active.d.ts +10 -12
- package/dist/core/session/server-store/active.d.ts.map +1 -1
- package/dist/core/session/server-store/active.js +11 -9
- package/dist/core/session/server-store/active.js.map +1 -1
- package/dist/core/session/server-store/url-helpers.d.ts +11 -2
- package/dist/core/session/server-store/url-helpers.d.ts.map +1 -1
- package/dist/core/session/server-store/url-helpers.js +11 -2
- package/dist/core/session/server-store/url-helpers.js.map +1 -1
- package/dist/core/session/url.d.ts +25 -2
- package/dist/core/session/url.d.ts.map +1 -1
- package/dist/core/session/url.js +87 -11
- package/dist/core/session/url.js.map +1 -1
- package/dist/core/session/working.d.ts +44 -0
- package/dist/core/session/working.d.ts.map +1 -1
- package/dist/core/session/working.js +146 -4
- package/dist/core/session/working.js.map +1 -1
- package/dist/core/session-sync/durable-log.d.ts +96 -0
- package/dist/core/session-sync/durable-log.d.ts.map +1 -0
- package/dist/core/session-sync/durable-log.js +94 -0
- package/dist/core/session-sync/durable-log.js.map +1 -0
- package/dist/core/session-sync/fragment.d.ts +27 -0
- package/dist/core/session-sync/fragment.d.ts.map +1 -0
- package/dist/core/session-sync/fragment.js +24 -0
- package/dist/core/session-sync/fragment.js.map +1 -0
- package/dist/core/session-sync/session-sync-controller.d.ts +83 -9
- package/dist/core/session-sync/session-sync-controller.d.ts.map +1 -1
- package/dist/core/session-sync/session-sync-controller.js +183 -17
- package/dist/core/session-sync/session-sync-controller.js.map +1 -1
- package/dist/core/turns/grouping.d.ts.map +1 -1
- package/dist/core/turns/grouping.js +60 -23
- package/dist/core/turns/grouping.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/kortix.esm.min.js +24 -24
- package/dist/kortix.global.js +24 -24
- package/dist/platform/auth-core.d.ts +13 -1
- package/dist/platform/auth-core.d.ts.map +1 -1
- package/dist/platform/auth-core.js +13 -1
- package/dist/platform/auth-core.js.map +1 -1
- package/dist/react/opencode.d.ts +1 -0
- package/dist/react/opencode.d.ts.map +1 -1
- package/dist/react/opencode.js +3 -0
- package/dist/react/opencode.js.map +1 -1
- package/dist/react/use-admin-accounts.d.ts +35 -0
- package/dist/react/use-admin-accounts.d.ts.map +1 -1
- package/dist/react/use-admin-accounts.js +18 -0
- package/dist/react/use-admin-accounts.js.map +1 -1
- package/dist/react/use-opencode-events/handle-event.d.ts.map +1 -1
- package/dist/react/use-opencode-events/handle-event.js +26 -0
- package/dist/react/use-opencode-events/handle-event.js.map +1 -1
- package/dist/react/use-opencode-events/index.d.ts.map +1 -1
- package/dist/react/use-opencode-events/index.js +59 -6
- package/dist/react/use-opencode-events/index.js.map +1 -1
- package/dist/react/use-opencode-events/rehydrate-targets.d.ts +18 -0
- package/dist/react/use-opencode-events/rehydrate-targets.d.ts.map +1 -0
- package/dist/react/use-opencode-events/rehydrate-targets.js +20 -0
- package/dist/react/use-opencode-events/rehydrate-targets.js.map +1 -0
- package/dist/react/use-opencode-events/stream-revival.d.ts +37 -0
- package/dist/react/use-opencode-events/stream-revival.d.ts.map +1 -0
- package/dist/react/use-opencode-events/stream-revival.js +53 -0
- package/dist/react/use-opencode-events/stream-revival.js.map +1 -0
- package/dist/react/use-opencode-pty.d.ts +7 -1
- package/dist/react/use-opencode-pty.d.ts.map +1 -1
- package/dist/react/use-opencode-pty.js +6 -2
- package/dist/react/use-opencode-pty.js.map +1 -1
- package/dist/react/use-opencode-sessions/agents.d.ts.map +1 -1
- package/dist/react/use-opencode-sessions/agents.js +13 -2
- package/dist/react/use-opencode-sessions/agents.js.map +1 -1
- package/dist/react/use-opencode-sessions/commands.d.ts +12 -0
- package/dist/react/use-opencode-sessions/commands.d.ts.map +1 -1
- package/dist/react/use-opencode-sessions/commands.js +15 -3
- package/dist/react/use-opencode-sessions/commands.js.map +1 -1
- package/dist/react/use-opencode-sessions/index.d.ts +1 -0
- package/dist/react/use-opencode-sessions/index.d.ts.map +1 -1
- package/dist/react/use-opencode-sessions/index.js +1 -0
- package/dist/react/use-opencode-sessions/index.js.map +1 -1
- package/dist/react/use-opencode-sessions/keys.d.ts +8 -0
- package/dist/react/use-opencode-sessions/keys.d.ts.map +1 -1
- package/dist/react/use-opencode-sessions/keys.js +8 -0
- package/dist/react/use-opencode-sessions/keys.js.map +1 -1
- package/dist/react/use-opencode-sessions/providers.d.ts.map +1 -1
- package/dist/react/use-opencode-sessions/providers.js +12 -2
- package/dist/react/use-opencode-sessions/providers.js.map +1 -1
- package/dist/react/use-opencode-sessions/shared.d.ts +23 -0
- package/dist/react/use-opencode-sessions/shared.d.ts.map +1 -1
- package/dist/react/use-opencode-sessions/shared.js +31 -0
- package/dist/react/use-opencode-sessions/shared.js.map +1 -1
- package/dist/react/use-opencode-sessions/vcs.d.ts +28 -0
- package/dist/react/use-opencode-sessions/vcs.d.ts.map +1 -0
- package/dist/react/use-opencode-sessions/vcs.js +42 -0
- package/dist/react/use-opencode-sessions/vcs.js.map +1 -0
- package/dist/react/use-session-prompts.d.ts +37 -2
- package/dist/react/use-session-prompts.d.ts.map +1 -1
- package/dist/react/use-session-prompts.js +62 -15
- package/dist/react/use-session-prompts.js.map +1 -1
- package/dist/react/use-session-send.d.ts +17 -0
- package/dist/react/use-session-send.d.ts.map +1 -1
- package/dist/react/use-session-send.js +40 -4
- package/dist/react/use-session-send.js.map +1 -1
- package/dist/react/use-session-sync.d.ts +13 -1
- package/dist/react/use-session-sync.d.ts.map +1 -1
- package/dist/react/use-session-sync.js +81 -55
- package/dist/react/use-session-sync.js.map +1 -1
- package/dist/react/use-session-working.d.ts +17 -0
- package/dist/react/use-session-working.d.ts.map +1 -1
- package/dist/react/use-session-working.js +33 -3
- package/dist/react/use-session-working.js.map +1 -1
- package/package.json +3 -3
- package/dist/browser/session-sync/session-transcript-cache.d.ts +0 -79
- package/dist/browser/session-sync/session-transcript-cache.d.ts.map +0 -1
- package/dist/browser/session-sync/session-transcript-cache.js +0 -91
- package/dist/browser/session-sync/session-transcript-cache.js.map +0 -1
- package/dist/core/rest/projects-client/public-voice-join.d.ts +0 -59
- package/dist/core/rest/projects-client/public-voice-join.d.ts.map +0 -1
- package/dist/core/rest/projects-client/public-voice-join.js +0 -64
- package/dist/core/rest/projects-client/public-voice-join.js.map +0 -1
- package/dist/core/rest/projects-client/transcription.d.ts +0 -5
- package/dist/core/rest/projects-client/transcription.d.ts.map +0 -1
- package/dist/core/rest/projects-client/transcription.js +0 -14
- package/dist/core/rest/projects-client/transcription.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/core/session/connection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,MAAM,iBAAiB;AAC3B,+EAA+E;AAC7E,SAAS;AACX,mFAAmF;GACjF,QAAQ;AACV,uEAAuE;GACrE,YAAY;AACd,4EAA4E;GAC1E,MAAM;AACR,4EAA4E;GAC1E,aAAa,CAAC;AAElB;gFACgF;AAChF,MAAM,MAAM,gBAAgB;AAC1B;;;qBAGqB;AACnB,QAAQ,GACR,WAAW,GACX,cAAc,GACd,SAAS,GACT,SAAS,GACT,UAAU,GACV,QAAQ,GACR,WAAW,GACX,IAAI,CAAC;AAET,MAAM,WAAW,uBAAuB;IACtC,uEAAuE;IACvE,OAAO,EAAE,gBAAgB,CAAC;IAC1B,mDAAmD;IACnD,YAAY,EAAE,OAAO,CAAC;IACtB,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;0BAEsB;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,uBAAuB,GAAG,iBAAiB,CAwB1F;AAED;+DAC+D;AAC/D,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAE1E"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function projectSessionConnection(input) {
|
|
2
|
+
// Content outranks every probe, including one that has given up: a runtime
|
|
3
|
+
// that is emitting parts is reachable by definition, whatever a health check
|
|
4
|
+
// on a different path concluded.
|
|
5
|
+
if (input.activityFresh)
|
|
6
|
+
return 'live';
|
|
7
|
+
if (input.runtimeReady)
|
|
8
|
+
return 'live';
|
|
9
|
+
if (input.unreachable || input.stalled)
|
|
10
|
+
return 'unreachable';
|
|
11
|
+
// Positive evidence, and the ONLY thing that earns the word "waking".
|
|
12
|
+
if (input.sandbox === 'stopped' || input.sandbox === 'archived')
|
|
13
|
+
return 'waking';
|
|
14
|
+
if (input.sandbox === 'provisioning' ||
|
|
15
|
+
input.sandbox === 'queued' ||
|
|
16
|
+
input.sandbox === 'branching') {
|
|
17
|
+
return 'waking';
|
|
18
|
+
}
|
|
19
|
+
// A finished session has no runtime to reach and nothing to wake. Nothing is
|
|
20
|
+
// wrong with it, so nothing is announced.
|
|
21
|
+
if (input.sandbox === 'completed')
|
|
22
|
+
return 'unknown';
|
|
23
|
+
if (input.sandbox === 'failed')
|
|
24
|
+
return 'unreachable';
|
|
25
|
+
// The box is up; we simply have not reached it yet. Not an alarm.
|
|
26
|
+
if (input.sandbox === 'running')
|
|
27
|
+
return 'connecting';
|
|
28
|
+
// The row has not loaded. We know nothing, and we say nothing.
|
|
29
|
+
return 'unknown';
|
|
30
|
+
}
|
|
31
|
+
/** Whether a surface may draw an alarm (a notice, a warning colour) from this
|
|
32
|
+
* state. `unknown` and `connecting` are waits, not faults. */
|
|
33
|
+
export function connectionIsFaulted(connection) {
|
|
34
|
+
return connection === 'unreachable';
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../src/core/session/connection.ts"],"names":[],"mappings":"AAsEA,MAAM,UAAU,wBAAwB,CAAC,KAA8B;IACrE,2EAA2E;IAC3E,6EAA6E;IAC7E,iCAAiC;IACjC,IAAI,KAAK,CAAC,aAAa;QAAE,OAAO,MAAM,CAAC;IACvC,IAAI,KAAK,CAAC,YAAY;QAAE,OAAO,MAAM,CAAC;IACtC,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,OAAO;QAAE,OAAO,aAAa,CAAC;IAC7D,sEAAsE;IACtE,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,KAAK,UAAU;QAAE,OAAO,QAAQ,CAAC;IACjF,IACE,KAAK,CAAC,OAAO,KAAK,cAAc;QAChC,KAAK,CAAC,OAAO,KAAK,QAAQ;QAC1B,KAAK,CAAC,OAAO,KAAK,WAAW,EAC7B,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,6EAA6E;IAC7E,0CAA0C;IAC1C,IAAI,KAAK,CAAC,OAAO,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IACpD,IAAI,KAAK,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,aAAa,CAAC;IACrD,kEAAkE;IAClE,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,YAAY,CAAC;IACrD,+DAA+D;IAC/D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;+DAC+D;AAC/D,MAAM,UAAU,mBAAmB,CAAC,UAA6B;IAC/D,OAAO,UAAU,KAAK,aAAa,CAAC;AACtC,CAAC"}
|
|
@@ -19,6 +19,7 @@ export * from './preview.js';
|
|
|
19
19
|
export * from './preview-auth.js';
|
|
20
20
|
export * from './preview-probe.js';
|
|
21
21
|
export * from './presentation.js';
|
|
22
|
+
export * from './connection.js';
|
|
22
23
|
export * from './working.js';
|
|
23
24
|
export * from './compaction.js';
|
|
24
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
|
|
@@ -19,6 +19,7 @@ export * from './preview.js';
|
|
|
19
19
|
export * from './preview-auth.js';
|
|
20
20
|
export * from './preview-probe.js';
|
|
21
21
|
export * from './presentation.js';
|
|
22
|
+
export * from './connection.js';
|
|
22
23
|
export * from './working.js';
|
|
23
24
|
export * from './compaction.js';
|
|
24
25
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
|
|
@@ -29,4 +29,29 @@
|
|
|
29
29
|
export declare function ensurePreviewSessionCookie(previewUrl: string, options?: {
|
|
30
30
|
serverUrl?: string;
|
|
31
31
|
}): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* The URL a caller should actually open for `previewUrl`, having given it a
|
|
34
|
+
* credential the destination will accept.
|
|
35
|
+
*
|
|
36
|
+
* The two preview forms take credentials in different ways, and using the wrong
|
|
37
|
+
* one fails silently — which is exactly what happened before this existed:
|
|
38
|
+
* `ensurePreviewSessionCookie` returns false for an ORIGIN URL (there is no
|
|
39
|
+
* `/v1/p/` path to derive an auth endpoint from), so "open in a new tab" opened
|
|
40
|
+
* the origin with no cookie and no token, and the person landed on the sign-in
|
|
41
|
+
* gate instead of their file.
|
|
42
|
+
*
|
|
43
|
+
* - Preview ORIGIN (`{env}-p{port}-{sandbox}.{domain}`, or the localhost
|
|
44
|
+
* form): the API's `__preview_session` cookie is host-scoped and can never
|
|
45
|
+
* reach it, so the credential rides in the URL as a one-shot `?token`. The
|
|
46
|
+
* proxy exchanges it for a host cookie and strips it from the address bar.
|
|
47
|
+
* - Path proxy (`/v1/p/{sandbox}/{port}/…`): same origin as the API, so the
|
|
48
|
+
* cookie works; mint it and return the URL untouched.
|
|
49
|
+
*
|
|
50
|
+
* Never throws. With no token, or for a URL that is not a preview at all, the
|
|
51
|
+
* input is returned unchanged — the destination then answers for itself, which
|
|
52
|
+
* is more honest than fabricating a URL that cannot work.
|
|
53
|
+
*/
|
|
54
|
+
export declare function authorizePreviewUrl(previewUrl: string, options?: {
|
|
55
|
+
serverUrl?: string;
|
|
56
|
+
}): Promise<string>;
|
|
32
57
|
//# sourceMappingURL=preview-auth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview-auth.d.ts","sourceRoot":"","sources":["../../../src/core/session/preview-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,OAAO,CAAC,OAAO,CAAC,CAoBlB"}
|
|
1
|
+
{"version":3,"file":"preview-auth.d.ts","sourceRoot":"","sources":["../../../src/core/session/preview-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,OAAO,CAAC,OAAO,CAAC,CAoBlB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,OAAO,CAAC,MAAM,CAAC,CAOjB"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* reloaded, bookmarked, or sent to anyone.
|
|
19
19
|
*/
|
|
20
20
|
import { getAuthToken } from '../http/auth.js';
|
|
21
|
-
import { buildPreviewAuthEndpoint } from './preview.js';
|
|
21
|
+
import { appendPreviewToken, buildPreviewAuthEndpoint, isSubdomainPreviewUrl } from './preview.js';
|
|
22
22
|
/**
|
|
23
23
|
* Mint the `__preview_session` cookie for `previewUrl`'s proxy origin.
|
|
24
24
|
*
|
|
@@ -50,4 +50,34 @@ export async function ensurePreviewSessionCookie(previewUrl, options = {}) {
|
|
|
50
50
|
return false;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* The URL a caller should actually open for `previewUrl`, having given it a
|
|
55
|
+
* credential the destination will accept.
|
|
56
|
+
*
|
|
57
|
+
* The two preview forms take credentials in different ways, and using the wrong
|
|
58
|
+
* one fails silently — which is exactly what happened before this existed:
|
|
59
|
+
* `ensurePreviewSessionCookie` returns false for an ORIGIN URL (there is no
|
|
60
|
+
* `/v1/p/` path to derive an auth endpoint from), so "open in a new tab" opened
|
|
61
|
+
* the origin with no cookie and no token, and the person landed on the sign-in
|
|
62
|
+
* gate instead of their file.
|
|
63
|
+
*
|
|
64
|
+
* - Preview ORIGIN (`{env}-p{port}-{sandbox}.{domain}`, or the localhost
|
|
65
|
+
* form): the API's `__preview_session` cookie is host-scoped and can never
|
|
66
|
+
* reach it, so the credential rides in the URL as a one-shot `?token`. The
|
|
67
|
+
* proxy exchanges it for a host cookie and strips it from the address bar.
|
|
68
|
+
* - Path proxy (`/v1/p/{sandbox}/{port}/…`): same origin as the API, so the
|
|
69
|
+
* cookie works; mint it and return the URL untouched.
|
|
70
|
+
*
|
|
71
|
+
* Never throws. With no token, or for a URL that is not a preview at all, the
|
|
72
|
+
* input is returned unchanged — the destination then answers for itself, which
|
|
73
|
+
* is more honest than fabricating a URL that cannot work.
|
|
74
|
+
*/
|
|
75
|
+
export async function authorizePreviewUrl(previewUrl, options = {}) {
|
|
76
|
+
if (isSubdomainPreviewUrl(previewUrl)) {
|
|
77
|
+
const token = await getAuthToken();
|
|
78
|
+
return token ? appendPreviewToken(previewUrl, token) : previewUrl;
|
|
79
|
+
}
|
|
80
|
+
await ensurePreviewSessionCookie(previewUrl, options);
|
|
81
|
+
return previewUrl;
|
|
82
|
+
}
|
|
53
83
|
//# sourceMappingURL=preview-auth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview-auth.js","sourceRoot":"","sources":["../../../src/core/session/preview-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"preview-auth.js","sourceRoot":"","sources":["../../../src/core/session/preview-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAEhG;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,UAAkB,EAClB,UAAkC,EAAE;IAEpC,MAAM,YAAY,GAAG,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7E,IAAI,CAAC,YAAY;QAAE,OAAO,KAAK,CAAC;IAEhC,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAEzB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,YAAY,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,WAAW,EAAE,SAAS;YACtB,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,EAAE,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,UAAkB,EAClB,UAAkC,EAAE;IAEpC,IAAI,qBAAqB,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACpE,CAAC;IACD,MAAM,0BAA0B,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACtD,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The cached template for a backend, or null when this deployment serves none —
|
|
3
|
+
* and also null before the first `load` resolves. Both mean "use the path form",
|
|
4
|
+
* which is why they need no distinction at the call site.
|
|
5
|
+
*/
|
|
6
|
+
export declare function cachedPreviewUrlTemplate(backendUrl: string): string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Whether this backend has ANSWERED yet — as opposed to "answered null", which
|
|
9
|
+
* is a real answer meaning "this deployment serves no preview domain".
|
|
10
|
+
*
|
|
11
|
+
* The two look identical through `cachedPreviewUrlTemplate`, and conflating them
|
|
12
|
+
* is how a session gets stuck: during a rolling deploy the first `ensureReady()`
|
|
13
|
+
* can hit a task that predates `/v1/p/config`, and without this the handle would
|
|
14
|
+
* keep building path-proxy URLs for the rest of its life even though every later
|
|
15
|
+
* request would have been answered by a new task.
|
|
16
|
+
*/
|
|
17
|
+
export declare function hasPreviewConfig(backendUrl: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Fetch and cache the template. Concurrent callers share one request; a failed
|
|
20
|
+
* fetch caches nothing, so a deployment that was briefly unreachable is asked
|
|
21
|
+
* again rather than being remembered as having no preview domain.
|
|
22
|
+
*/
|
|
23
|
+
export declare function loadPreviewUrlTemplate(backendUrl: string): Promise<string | null>;
|
|
24
|
+
/** Drop everything remembered — for tests and for a host re-pointing its API. */
|
|
25
|
+
export declare function resetPreviewConfigCache(): void;
|
|
26
|
+
//# sourceMappingURL=preview-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-config.d.ts","sourceRoot":"","sources":["../../../src/core/session/preview-config.ts"],"names":[],"mappings":"AAiCA;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE1E;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgCvF;AAED,iFAAiF;AACjF,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How this deployment addresses previews, fetched once from `GET /v1/p/config`.
|
|
3
|
+
*
|
|
4
|
+
* The preview hostname shape (`{env}-p{port}-{sandbox}.{domain}`) is a property
|
|
5
|
+
* of the deployment, not of the client: it depends on the wildcard domain the
|
|
6
|
+
* operator serves and on which environment the API is. Re-deriving it here from
|
|
7
|
+
* `backendUrl` would mean two implementations of one rule, which is how they
|
|
8
|
+
* drift. So the API states it as a template and this caches the answer.
|
|
9
|
+
*
|
|
10
|
+
* `previewUrl()` is synchronous — a React render calls it — so the fetch cannot
|
|
11
|
+
* happen there. `ensureReady()` warms this first, and until it resolves callers
|
|
12
|
+
* get the path form, which still works for everything that is not a browser.
|
|
13
|
+
*/
|
|
14
|
+
import { backendApi } from '../http/api-client.js';
|
|
15
|
+
const templates = new Map();
|
|
16
|
+
const inFlight = new Map();
|
|
17
|
+
/**
|
|
18
|
+
* Cache key: the backend URL without trailing slashes, stripped LINEARLY. The
|
|
19
|
+
* regex form (`/\/+$/`) backtracks quadratically on adversarial input (CodeQL
|
|
20
|
+
* js/polynomial-redos), and this runs on a host-supplied string.
|
|
21
|
+
*/
|
|
22
|
+
function key(backendUrl) {
|
|
23
|
+
let end = backendUrl.length;
|
|
24
|
+
while (end > 0 && backendUrl.charCodeAt(end - 1) === 47 /* '/' */)
|
|
25
|
+
end--;
|
|
26
|
+
return backendUrl.slice(0, end);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The cached template for a backend, or null when this deployment serves none —
|
|
30
|
+
* and also null before the first `load` resolves. Both mean "use the path form",
|
|
31
|
+
* which is why they need no distinction at the call site.
|
|
32
|
+
*/
|
|
33
|
+
export function cachedPreviewUrlTemplate(backendUrl) {
|
|
34
|
+
return templates.get(key(backendUrl)) ?? null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Whether this backend has ANSWERED yet — as opposed to "answered null", which
|
|
38
|
+
* is a real answer meaning "this deployment serves no preview domain".
|
|
39
|
+
*
|
|
40
|
+
* The two look identical through `cachedPreviewUrlTemplate`, and conflating them
|
|
41
|
+
* is how a session gets stuck: during a rolling deploy the first `ensureReady()`
|
|
42
|
+
* can hit a task that predates `/v1/p/config`, and without this the handle would
|
|
43
|
+
* keep building path-proxy URLs for the rest of its life even though every later
|
|
44
|
+
* request would have been answered by a new task.
|
|
45
|
+
*/
|
|
46
|
+
export function hasPreviewConfig(backendUrl) {
|
|
47
|
+
return templates.has(key(backendUrl));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Fetch and cache the template. Concurrent callers share one request; a failed
|
|
51
|
+
* fetch caches nothing, so a deployment that was briefly unreachable is asked
|
|
52
|
+
* again rather than being remembered as having no preview domain.
|
|
53
|
+
*/
|
|
54
|
+
export async function loadPreviewUrlTemplate(backendUrl) {
|
|
55
|
+
const cacheKey = key(backendUrl);
|
|
56
|
+
const cached = templates.get(cacheKey);
|
|
57
|
+
if (cached !== undefined)
|
|
58
|
+
return cached;
|
|
59
|
+
const pending = inFlight.get(cacheKey);
|
|
60
|
+
if (pending)
|
|
61
|
+
return pending;
|
|
62
|
+
const request = (async () => {
|
|
63
|
+
try {
|
|
64
|
+
const response = await backendApi.get('/p/config', {
|
|
65
|
+
showErrors: false,
|
|
66
|
+
// A deployment without a preview domain, and an API too old to know the
|
|
67
|
+
// route, are both ordinary answers — not incidents to report.
|
|
68
|
+
errorContext: { operation: 'load preview config', silent: true },
|
|
69
|
+
});
|
|
70
|
+
if (!response.success)
|
|
71
|
+
return null;
|
|
72
|
+
const template = typeof response.data?.preview_url_template === 'string'
|
|
73
|
+
? response.data.preview_url_template
|
|
74
|
+
: null;
|
|
75
|
+
templates.set(cacheKey, template);
|
|
76
|
+
return template;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// An older API has no such route, and a network blip is not an answer.
|
|
80
|
+
// Leave the cache empty so the next ensureReady() asks again.
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
inFlight.delete(cacheKey);
|
|
85
|
+
}
|
|
86
|
+
})();
|
|
87
|
+
inFlight.set(cacheKey, request);
|
|
88
|
+
return request;
|
|
89
|
+
}
|
|
90
|
+
/** Drop everything remembered — for tests and for a host re-pointing its API. */
|
|
91
|
+
export function resetPreviewConfigCache() {
|
|
92
|
+
templates.clear();
|
|
93
|
+
inFlight.clear();
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=preview-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-config.js","sourceRoot":"","sources":["../../../src/core/session/preview-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAMhD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;AACnD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkC,CAAC;AAE3D;;;;GAIG;AACH,SAAS,GAAG,CAAC,UAAkB;IAC7B,IAAI,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC;IAC5B,OAAO,GAAG,GAAG,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,SAAS;QAAE,GAAG,EAAE,CAAC;IACzE,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,UAAkB;IACzD,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,IAAI,CAAC;AAChD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,UAAkB;IAC7D,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE;QAC1B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,GAAG,CAAwB,WAAW,EAAE;gBACxE,UAAU,EAAE,KAAK;gBACjB,wEAAwE;gBACxE,8DAA8D;gBAC9D,YAAY,EAAE,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,EAAE,IAAI,EAAE;aACjE,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,OAAO;gBAAE,OAAO,IAAI,CAAC;YACnC,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,EAAE,oBAAoB,KAAK,QAAQ;gBACtE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,oBAAoB;gBACpC,CAAC,CAAC,IAAI,CAAC;YACT,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAClC,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;YACvE,8DAA8D;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,uBAAuB;IACrC,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SubdomainUrlOptions } from './url.js';
|
|
2
|
+
/**
|
|
3
|
+
* A fully-resolved options bag. Every field required — including
|
|
4
|
+
* `previewUrlTemplate`, whose `null` means "this deployment serves no preview
|
|
5
|
+
* domain" and is a real answer, not an omission.
|
|
6
|
+
*/
|
|
7
|
+
export interface ResolvedPreviewOptions extends SubdomainUrlOptions {
|
|
8
|
+
previewUrlTemplate: string | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve preview options for a sandbox against a backend.
|
|
12
|
+
*
|
|
13
|
+
* Reads the deployment's answer from the `GET /v1/p/config` cache, and asks
|
|
14
|
+
* again in the background when this backend has never answered — a rolling
|
|
15
|
+
* deploy can serve one request from a task that predates the route, and without
|
|
16
|
+
* the retry that single miss would pin the caller to the path proxy for its
|
|
17
|
+
* whole life. A backend that answered "no preview domain" HAS answered and is
|
|
18
|
+
* not re-asked.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolvePreviewOptions(input: {
|
|
21
|
+
sandboxId: string;
|
|
22
|
+
apiBaseUrl: string;
|
|
23
|
+
backendPort: number;
|
|
24
|
+
}): ResolvedPreviewOptions;
|
|
25
|
+
//# sourceMappingURL=preview-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-options.d.ts","sourceRoot":"","sources":["../../../src/core/session/preview-options.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAEjD;;;;GAIG;AACH,MAAM,WAAW,sBAAuB,SAAQ,mBAAmB;IACjE,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,sBAAsB,CASzB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE way to build the options a preview URL is derived from.
|
|
3
|
+
*
|
|
4
|
+
* `rewriteLocalhostUrl` and its siblings in `url.ts` are pure: they answer
|
|
5
|
+
* "which URL" from an options bag and never touch the network. That purity is
|
|
6
|
+
* worth keeping — it is why they are exhaustively testable — but it puts the
|
|
7
|
+
* burden of assembling a COMPLETE bag on whoever calls them, and an incomplete
|
|
8
|
+
* bag does not fail. It falls back to the path proxy, silently, forever.
|
|
9
|
+
*
|
|
10
|
+
* That is not hypothetical. There are two call paths — a session handle
|
|
11
|
+
* (`kortix.session(...).previewUrl()`) and the ambient runtime
|
|
12
|
+
* (`deriveSubdomainOpts`, which the web app's preview iframe, `useSandboxProxy`
|
|
13
|
+
* and `buildStaticFilePreviewUrl` all use) — and each assembled the bag itself.
|
|
14
|
+
* When `previewUrlTemplate` was added, only the first was updated, so every
|
|
15
|
+
* preview in the session panel kept rendering `/v1/p/{sandbox}/{port}` however
|
|
16
|
+
* loudly the deployment advertised an origin. Nothing failed; the wrong thing
|
|
17
|
+
* merely kept working.
|
|
18
|
+
*
|
|
19
|
+
* So: one producer, and a return type whose fields are all REQUIRED. A future
|
|
20
|
+
* call path that forgets a field does not compile, which is the only kind of
|
|
21
|
+
* guarantee worth having for a failure mode this quiet.
|
|
22
|
+
*/
|
|
23
|
+
import { cachedPreviewUrlTemplate, hasPreviewConfig, loadPreviewUrlTemplate } from './preview-config.js';
|
|
24
|
+
/**
|
|
25
|
+
* Resolve preview options for a sandbox against a backend.
|
|
26
|
+
*
|
|
27
|
+
* Reads the deployment's answer from the `GET /v1/p/config` cache, and asks
|
|
28
|
+
* again in the background when this backend has never answered — a rolling
|
|
29
|
+
* deploy can serve one request from a task that predates the route, and without
|
|
30
|
+
* the retry that single miss would pin the caller to the path proxy for its
|
|
31
|
+
* whole life. A backend that answered "no preview domain" HAS answered and is
|
|
32
|
+
* not re-asked.
|
|
33
|
+
*/
|
|
34
|
+
export function resolvePreviewOptions(input) {
|
|
35
|
+
const { apiBaseUrl } = input;
|
|
36
|
+
if (!hasPreviewConfig(apiBaseUrl))
|
|
37
|
+
void loadPreviewUrlTemplate(apiBaseUrl).catch(() => { });
|
|
38
|
+
return {
|
|
39
|
+
sandboxId: input.sandboxId,
|
|
40
|
+
backendPort: input.backendPort,
|
|
41
|
+
apiBaseUrl,
|
|
42
|
+
previewUrlTemplate: cachedPreviewUrlTemplate(apiBaseUrl),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=preview-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-options.js","sourceRoot":"","sources":["../../../src/core/session/preview-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAYtG;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAIrC;IACC,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAC7B,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC;QAAE,KAAK,sBAAsB,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC3F,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,UAAU;QACV,kBAAkB,EAAE,wBAAwB,CAAC,UAAU,CAAC;KACzD,CAAC;AACJ,CAAC"}
|
|
@@ -14,9 +14,14 @@
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function buildPreviewAuthEndpoint(previewUrl: string, serverUrl?: string): string | null;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* Preview ORIGIN form: `p{port}-{sandbox}.{host}` locally, or the deployed
|
|
18
|
+
* `{env}-p{port}-{sandbox}.{domain}`.
|
|
19
|
+
*
|
|
20
|
+
* These can't use the host-only `/v1/p/` session cookie — it never reaches
|
|
21
|
+
* another hostname — so they authenticate the FIRST request with a one-shot
|
|
22
|
+
* `?token`, which the proxy exchanges for a cookie on the preview origin and
|
|
23
|
+
* then strips. Every later request (sub-resources, `fetch`, WebSockets) rides
|
|
24
|
+
* that cookie, which is the only credential an app's own code can carry.
|
|
20
25
|
*/
|
|
21
26
|
export declare function isSubdomainPreviewUrl(candidateUrl: string): boolean;
|
|
22
27
|
/** Append a one-shot `?token` to a (subdomain) preview URL. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../src/core/session/preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA6CH;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAMf;AAED
|
|
1
|
+
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../src/core/session/preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA6CH;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAMf;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAUnE;AAED,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ5E"}
|
|
@@ -59,13 +59,20 @@ export function buildPreviewAuthEndpoint(previewUrl, serverUrl) {
|
|
|
59
59
|
derivePreviewAuthEndpoint(previewUrl));
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
62
|
+
* Preview ORIGIN form: `p{port}-{sandbox}.{host}` locally, or the deployed
|
|
63
|
+
* `{env}-p{port}-{sandbox}.{domain}`.
|
|
64
|
+
*
|
|
65
|
+
* These can't use the host-only `/v1/p/` session cookie — it never reaches
|
|
66
|
+
* another hostname — so they authenticate the FIRST request with a one-shot
|
|
67
|
+
* `?token`, which the proxy exchanges for a cookie on the preview origin and
|
|
68
|
+
* then strips. Every later request (sub-resources, `fetch`, WebSockets) rides
|
|
69
|
+
* that cookie, which is the only credential an app's own code can carry.
|
|
65
70
|
*/
|
|
66
71
|
export function isSubdomainPreviewUrl(candidateUrl) {
|
|
67
72
|
try {
|
|
68
|
-
|
|
73
|
+
const { hostname } = new URL(candidateUrl);
|
|
74
|
+
return (/^p\d+-[^.]+\./.test(hostname)
|
|
75
|
+
|| /^(?:dev|staging|prod|preview)-p\d+-[a-z0-9-]+\./i.test(hostname));
|
|
69
76
|
}
|
|
70
77
|
catch {
|
|
71
78
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/core/session/preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,SAAS,yBAAyB,CAAC,YAAoB;IACrD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;QAElC,IAAI,uBAAuB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/C,OAAO,GAAG,GAAG,CAAC,MAAM,YAAY,CAAC;QACnC,CAAC;QAED,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACjD,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;YACxB,OAAO,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC;QACtE,CAAC;QAED,OAAO,GAAG,GAAG,CAAC,MAAM,YAAY,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,YAAoB,EAAE,SAAkB;IACjE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM,aAAa,GACjB,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC;YACzC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,aAAa;YAAE,OAAO,KAAK,CAAC;QAEjC,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;QACzC,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC;gBACH,cAAc,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;QACD,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,cAAc,CAAC,IAAI,KAAK,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,UAAkB,EAClB,SAAkB;IAElB,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,OAAO,CACL,CAAC,SAAS,CAAC,CAAC,CAAC,yBAAyB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACzD,yBAAyB,CAAC,UAAU,CAAC,CACtC,CAAC;AACJ,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/core/session/preview.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,16 +9,27 @@
|
|
|
9
9
|
* 1. Which locally-known messages does a staged rewind hide?
|
|
10
10
|
* 2. When is a message id inside the range a committed rewind must delete?
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
12
|
+
* The window is a SET of message ids, captured at stage time. It used to be a
|
|
13
|
+
* lexical id RANGE — `id >= messageId && id <= watermark` — which assumed ids
|
|
14
|
+
* ascend with time. OpenCode 1.18.15 retired that invariant outright (turn
|
|
15
|
+
* exit now reads `lastAssistant.parentID === lastUser.id`, and
|
|
16
|
+
* `MessageV2.latest()` orders by `time.created` with the id only as a
|
|
17
|
+
* tie-break), and the range failed in both directions:
|
|
18
|
+
*
|
|
19
|
+
* - **under-delete** — a reverted assistant message whose id happens to sort
|
|
20
|
+
* BELOW the boundary falls outside the interval, survives the commit,
|
|
21
|
+
* is orphaned, and reappears at the top of the chat;
|
|
22
|
+
* - **over-delete** — `ascendingId` stubs sit ~2.8e13 above every real id, so
|
|
23
|
+
* a single in-flight optimistic message pushed the watermark to
|
|
24
|
+
* effectively infinity and the interval swallowed the user's replacement
|
|
25
|
+
* prompt and its answer.
|
|
26
|
+
*
|
|
27
|
+
* Membership has neither failure. `hiddenIds` is the exact list of messages
|
|
28
|
+
* that were part of the abandoned trajectory at the moment the rewind was
|
|
29
|
+
* staged: nothing minted afterwards can enter it, and nothing inside it can
|
|
30
|
+
* escape on an id comparison. `watermark` is retained as a published field —
|
|
31
|
+
* it names the newest message known at stage time — and still answers
|
|
32
|
+
* {@link isWithinRewindWindow} for a legacy state that carries no `hiddenIds`.
|
|
22
33
|
*/
|
|
23
34
|
export interface SessionRewindState {
|
|
24
35
|
/** The message the rewind pointer sits at — hidden along with everything
|
|
@@ -26,10 +37,25 @@ export interface SessionRewindState {
|
|
|
26
37
|
messageId: string;
|
|
27
38
|
/**
|
|
28
39
|
* The newest message id known locally at the moment this rewind was staged
|
|
29
|
-
* (or first observed)
|
|
30
|
-
*
|
|
40
|
+
* (or first observed) — see {@link newestMessageId}.
|
|
41
|
+
*
|
|
42
|
+
* No longer the upper bound of anything: {@link hiddenIds} is the window.
|
|
43
|
+
* Retained because it is a published field, and because it is the only
|
|
44
|
+
* bound available to a legacy state that carries no `hiddenIds`.
|
|
31
45
|
*/
|
|
32
46
|
watermark: string;
|
|
47
|
+
/**
|
|
48
|
+
* The exact messages this rewind abandons — the boundary message and
|
|
49
|
+
* everything that followed it in the transcript, captured ONCE at stage
|
|
50
|
+
* time and never recomputed. Membership in this list is the whole of the
|
|
51
|
+
* hide/delete test; see the module comment for the two failures the lexical
|
|
52
|
+
* range it replaced produced.
|
|
53
|
+
*
|
|
54
|
+
* Optional only for backward compatibility: a `SessionRewindState` built by
|
|
55
|
+
* an older consumer (or restored from one) has none, and falls back to the
|
|
56
|
+
* legacy range. Everything in this SDK populates it.
|
|
57
|
+
*/
|
|
58
|
+
hiddenIds?: readonly string[];
|
|
33
59
|
/**
|
|
34
60
|
* False once the replacement prompt has been sent (or a
|
|
35
61
|
* `session.next.revert.committed` wire event says the server has). The
|
|
@@ -40,32 +66,49 @@ export interface SessionRewindState {
|
|
|
40
66
|
*/
|
|
41
67
|
staged: boolean;
|
|
42
68
|
}
|
|
43
|
-
/** Whether `id`
|
|
44
|
-
*
|
|
45
|
-
*
|
|
69
|
+
/** Whether `id` is one of the messages this rewind abandons.
|
|
70
|
+
*
|
|
71
|
+
* Membership in the set captured at stage time — never a comparison between
|
|
72
|
+
* two id strings, which say nothing about which message came first. The
|
|
73
|
+
* legacy `[messageId, watermark]` range answers only for a state that
|
|
74
|
+
* carries no captured set. */
|
|
46
75
|
export declare function isWithinRewindWindow(id: string, rewind: SessionRewindState): boolean;
|
|
47
76
|
/**
|
|
48
|
-
* The newest
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
77
|
+
* The newest message in `messages`, by `time.created` with the id as the only
|
|
78
|
+
* tie-break — the same order the server's own `MessageV2.latest()` uses.
|
|
79
|
+
* `null` for an empty list.
|
|
80
|
+
*
|
|
81
|
+
* Deliberately a max-scan, not "the last element": most callers pass an
|
|
82
|
+
* ordered list, but an optimistic entry appended out of order must never win
|
|
83
|
+
* by position alone. A message with no `time` cannot be dated, so it competes
|
|
84
|
+
* on its id only.
|
|
52
85
|
*/
|
|
53
86
|
export declare function newestMessageId<T extends {
|
|
54
87
|
info: {
|
|
55
88
|
id: string;
|
|
89
|
+
time?: {
|
|
90
|
+
created?: number;
|
|
91
|
+
};
|
|
56
92
|
};
|
|
57
93
|
}>(messages: T[]): string | null;
|
|
58
94
|
/**
|
|
59
95
|
* Build the state for a freshly staged (or freshly discovered) rewind.
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
96
|
+
*
|
|
97
|
+
* The window is captured HERE and never recomputed: `hiddenIds` is the
|
|
98
|
+
* boundary message plus every message that follows it in `messages`, taken in
|
|
99
|
+
* the order the caller holds them — which is the server's own
|
|
100
|
+
* `time.created` page order, not an id order. Falls back to `messageId`
|
|
101
|
+
* itself when the boundary is not in the list (a cross-tab or reload
|
|
102
|
+
* discovery with no synced messages for this session), which hides only the
|
|
103
|
+
* boundary message — the narrowest correct answer with no other information
|
|
104
|
+
* available.
|
|
65
105
|
*/
|
|
66
106
|
export declare function stageSessionRewind<T extends {
|
|
67
107
|
info: {
|
|
68
108
|
id: string;
|
|
109
|
+
time?: {
|
|
110
|
+
created?: number;
|
|
111
|
+
};
|
|
69
112
|
};
|
|
70
113
|
}>(messages: T[], messageId: string): SessionRewindState;
|
|
71
114
|
/** Hide the target message and every message up to the staged watermark.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rewind.d.ts","sourceRoot":"","sources":["../../../src/core/session/rewind.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rewind.d.ts","sourceRoot":"","sources":["../../../src/core/session/rewind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,MAAM,WAAW,kBAAkB;IACjC;6BACyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;;;;;;OAOG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;+BAK+B;AAC/B,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAGpF;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,CAAC,SAAS;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;CAAE,EAC/D,QAAQ,EAAE,CAAC,EAAE,GAAG,MAAM,GAAG,IAAI,CA4B9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,SAAS;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAA;CAAE,EAC/D,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,kBAAkB,CAUtD;AAED;;4EAE4E;AAC5E,wBAAgB,oBAAoB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,EACrE,QAAQ,EAAE,CAAC,EAAE,EACb,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAChC,CAAC,EAAE,CAIL;AAED;;;4EAG4E;AAC5E,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAChC,kBAAkB,GAAG,IAAI,CAE3B"}
|