oysterun 1.6.0-beta.6 → 1.6.0-beta.7
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/dev/client/connectivity/session-navigation-intent.mjs +189 -0
- package/dev/client/connectivity/session-transition-state.mjs +18 -6
- package/dev/client/web/index.html +1684 -246
- package/dev/client/web-chat/dist/assets/{ReactPrism-DcNXef2k.js → ReactPrism-_isaKkj_.js} +1 -1
- package/dev/client/web-chat/dist/assets/ReactPrism-_isaKkj_.js.map +1 -0
- package/dev/client/web-chat/dist/assets/{index-NYnaSGBb.css → index-4Q0ZOX_Q.css} +1 -1
- package/dev/client/web-chat/dist/assets/index-B9fWrEk-.js.map +1 -1
- package/dev/client/web-chat/dist/assets/{index-BcplGVpl.js → index-D6R0BXEn.js} +1 -1
- package/dev/client/web-chat/dist/assets/index-D6R0BXEn.js.map +1 -0
- package/dev/client/web-chat/dist/assets/{index-DnIWxx_Q.js → index-DrJ06Rmy.js} +90 -90
- package/dev/client/web-chat/dist/assets/index-DrJ06Rmy.js.map +1 -0
- package/dev/client/web-chat/dist/assets/{index-Da35WQaN.js → index-UtO0T-54.js} +2 -2
- package/dev/client/web-chat/dist/assets/index-UtO0T-54.js.map +1 -0
- package/dev/client/web-chat/dist/assets/{pdf-DTluiTFV.js → pdf-CJXoe_Ui.js} +3 -3
- package/dev/client/web-chat/dist/assets/pdf-CJXoe_Ui.js.map +1 -0
- package/dev/client/web-chat/dist/assets/{web-Br6xI6YK.js → web-BAHo4kAL.js} +1 -1
- package/dev/client/web-chat/dist/assets/web-BAHo4kAL.js.map +1 -0
- package/dev/client/web-chat/dist/assets/{web-D_ECINqC.js → web-MIfqkxFv.js} +1 -1
- package/dev/client/web-chat/dist/assets/web-MIfqkxFv.js.map +1 -0
- package/dev/client/web-chat/dist/index.html +2 -2
- package/docs/routec/dev/cloud_deplyments.md +5 -0
- package/docs/routec/oysterun_operation_interface_spec.md +6 -0
- package/host-service/adapters/codex-app-server-adapter.mjs +307 -18
- package/host-service/adapters/debug-fixture-provider-adapter.mjs +2 -0
- package/host-service/adapters/debug-large-tool-spillover-provider-adapter.mjs +2 -0
- package/host-service/adapters/debug-p135-codex-replay-provider-adapter.mjs +2 -0
- package/host-service/adapters/debug-routec-structural-replay-provider-adapter.mjs +2 -0
- package/host-service/assets/product-skills/Oysterun/modules/oysterun-sessions/SKILL.md +27 -0
- package/host-service/assets/product-skills/oysterun-sessions/SKILL.md +27 -0
- package/host-service/callback-durable-store.mjs +313 -47
- package/host-service/callback-host-integration.mjs +324 -29
- package/host-service/cli/product-cli.mjs +14 -0
- package/host-service/completed-turn-service.mjs +383 -0
- package/host-service/lifecycle-continuity-runner.mjs +7 -1
- package/host-service/matrix-event-correlator.mjs +56 -21
- package/host-service/matrix-facade.mjs +22 -0
- package/host-service/package.json +2 -1
- package/host-service/provider-resume-contract.mjs +9 -3
- package/host-service/routec-matrix-sqlite-store.mjs +22 -1
- package/host-service/routec-matrix-storage-adapter.mjs +28 -7
- package/host-service/server.mjs +392 -16
- package/host-service/session-collection-service.mjs +303 -0
- package/host-service/session-history.mjs +43 -9
- package/host-service/session-manager.mjs +85 -4
- package/host-service/session-switcher-projection.mjs +3 -0
- package/host-service/session-tags.mjs +176 -0
- package/package.json +1 -1
- package/static/site/install.sh +13 -1
- package/static/site_source/downloads/install.sh +13 -1
- package/dev/client/web-chat/dist/assets/ReactPrism-DcNXef2k.js.map +0 -1
- package/dev/client/web-chat/dist/assets/index-BcplGVpl.js.map +0 -1
- package/dev/client/web-chat/dist/assets/index-Da35WQaN.js.map +0 -1
- package/dev/client/web-chat/dist/assets/index-DnIWxx_Q.js.map +0 -1
- package/dev/client/web-chat/dist/assets/pdf-DTluiTFV.js.map +0 -1
- package/dev/client/web-chat/dist/assets/web-Br6xI6YK.js.map +0 -1
- package/dev/client/web-chat/dist/assets/web-D_ECINqC.js.map +0 -1
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
export const SESSION_CHAT_NAVIGATION_OUTCOMES = Object.freeze({
|
|
2
|
+
NOOP_EQUIVALENT: "noop_equivalent",
|
|
3
|
+
SAME_SESSION_CONTEXT_NAVIGATION: "same_session_context_navigation",
|
|
4
|
+
CROSS_SESSION_TRANSITION: "cross_session_transition",
|
|
5
|
+
DOCUMENT_HANDOFF: "document_handoff",
|
|
6
|
+
INVALID_OR_STALE: "invalid_or_stale",
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const SESSION_APP_PREFIX = "/app/sessions";
|
|
10
|
+
const DEFAULT_PAGE = "chat";
|
|
11
|
+
const SUPPORTED_SESSION_PAGES = new Set([
|
|
12
|
+
"chat",
|
|
13
|
+
"profile",
|
|
14
|
+
"loop",
|
|
15
|
+
"explorer",
|
|
16
|
+
"file-preview",
|
|
17
|
+
]);
|
|
18
|
+
const SEMANTIC_QUERY_KEYS = new Set(["focus_event_id"]);
|
|
19
|
+
|
|
20
|
+
function normalizedText(value) {
|
|
21
|
+
return typeof value === "string" ? value.trim() : "";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function decodePathPart(value) {
|
|
25
|
+
try {
|
|
26
|
+
return normalizedText(decodeURIComponent(value));
|
|
27
|
+
} catch {
|
|
28
|
+
return "";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function normalizeSessionChatNavigationIntent(input = {}) {
|
|
33
|
+
const sessionId = normalizedText(input.sessionId);
|
|
34
|
+
const page = normalizedText(input.page) || DEFAULT_PAGE;
|
|
35
|
+
const source = normalizedText(input.source) || "unknown";
|
|
36
|
+
const historyPolicy = normalizedText(input.historyPolicy) || "push";
|
|
37
|
+
const documentHandoff = input.documentHandoff === true;
|
|
38
|
+
if (documentHandoff) {
|
|
39
|
+
return {
|
|
40
|
+
valid: true,
|
|
41
|
+
documentHandoff: true,
|
|
42
|
+
sessionId,
|
|
43
|
+
page,
|
|
44
|
+
semantic: {},
|
|
45
|
+
explicitSemanticKeys: [],
|
|
46
|
+
source,
|
|
47
|
+
historyPolicy,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (!sessionId || !SUPPORTED_SESSION_PAGES.has(page)) {
|
|
51
|
+
return {
|
|
52
|
+
valid: false,
|
|
53
|
+
documentHandoff: false,
|
|
54
|
+
sessionId,
|
|
55
|
+
page,
|
|
56
|
+
semantic: {},
|
|
57
|
+
explicitSemanticKeys: [],
|
|
58
|
+
source,
|
|
59
|
+
historyPolicy,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const semantic = {};
|
|
64
|
+
const explicitSemanticKeys = [];
|
|
65
|
+
const semanticInput =
|
|
66
|
+
input.semantic && typeof input.semantic === "object" ? input.semantic : {};
|
|
67
|
+
for (const key of SEMANTIC_QUERY_KEYS) {
|
|
68
|
+
const value = normalizedText(semanticInput[key]);
|
|
69
|
+
if (!value) continue;
|
|
70
|
+
semantic[key] = value;
|
|
71
|
+
explicitSemanticKeys.push(key);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
valid: true,
|
|
75
|
+
documentHandoff: false,
|
|
76
|
+
sessionId,
|
|
77
|
+
page,
|
|
78
|
+
semantic,
|
|
79
|
+
explicitSemanticKeys,
|
|
80
|
+
source,
|
|
81
|
+
historyPolicy,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function parseSessionChatNavigationIntent(
|
|
86
|
+
urlValue,
|
|
87
|
+
{ source = "route", historyPolicy = "push", documentHandoff = false } = {}
|
|
88
|
+
) {
|
|
89
|
+
let url;
|
|
90
|
+
try {
|
|
91
|
+
url = new URL(urlValue, "http://oysterun.invalid");
|
|
92
|
+
} catch {
|
|
93
|
+
return normalizeSessionChatNavigationIntent({ source, historyPolicy });
|
|
94
|
+
}
|
|
95
|
+
const parts = url.pathname.split("/").filter(Boolean);
|
|
96
|
+
if (parts.length !== 4 || parts[0] !== "app" || parts[1] !== "sessions") {
|
|
97
|
+
return normalizeSessionChatNavigationIntent({
|
|
98
|
+
source,
|
|
99
|
+
historyPolicy,
|
|
100
|
+
documentHandoff,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const sessionId = decodePathPart(parts[2]);
|
|
104
|
+
const page = normalizedText(parts[3]);
|
|
105
|
+
const semantic = {};
|
|
106
|
+
for (const key of SEMANTIC_QUERY_KEYS) {
|
|
107
|
+
const value = normalizedText(url.searchParams.get(key));
|
|
108
|
+
if (value) semantic[key] = value;
|
|
109
|
+
}
|
|
110
|
+
return normalizeSessionChatNavigationIntent({
|
|
111
|
+
sessionId,
|
|
112
|
+
page,
|
|
113
|
+
semantic,
|
|
114
|
+
source,
|
|
115
|
+
historyPolicy,
|
|
116
|
+
documentHandoff,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function classifySessionChatNavigation({ committed, target } = {}) {
|
|
121
|
+
if (!committed?.valid || !target?.valid) {
|
|
122
|
+
return SESSION_CHAT_NAVIGATION_OUTCOMES.INVALID_OR_STALE;
|
|
123
|
+
}
|
|
124
|
+
if (committed.documentHandoff || target.documentHandoff) {
|
|
125
|
+
return SESSION_CHAT_NAVIGATION_OUTCOMES.DOCUMENT_HANDOFF;
|
|
126
|
+
}
|
|
127
|
+
if (committed.sessionId !== target.sessionId) {
|
|
128
|
+
return SESSION_CHAT_NAVIGATION_OUTCOMES.CROSS_SESSION_TRANSITION;
|
|
129
|
+
}
|
|
130
|
+
if (committed.page !== target.page) {
|
|
131
|
+
return SESSION_CHAT_NAVIGATION_OUTCOMES.SAME_SESSION_CONTEXT_NAVIGATION;
|
|
132
|
+
}
|
|
133
|
+
for (const key of target.explicitSemanticKeys) {
|
|
134
|
+
if (target.semantic[key] !== committed.semantic[key]) {
|
|
135
|
+
return SESSION_CHAT_NAVIGATION_OUTCOMES.SAME_SESSION_CONTEXT_NAVIGATION;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return SESSION_CHAT_NAVIGATION_OUTCOMES.NOOP_EQUIVALENT;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function classifySessionChatNavigationFromUrls({
|
|
142
|
+
committedSessionId,
|
|
143
|
+
currentUrl,
|
|
144
|
+
targetUrl,
|
|
145
|
+
source = "route",
|
|
146
|
+
historyPolicy = "push",
|
|
147
|
+
documentHandoff = false,
|
|
148
|
+
} = {}) {
|
|
149
|
+
const committedFromUrl = parseSessionChatNavigationIntent(currentUrl, {
|
|
150
|
+
source: "committed_binding",
|
|
151
|
+
historyPolicy: "preserve",
|
|
152
|
+
});
|
|
153
|
+
const committed = normalizeSessionChatNavigationIntent({
|
|
154
|
+
...committedFromUrl,
|
|
155
|
+
sessionId: normalizedText(committedSessionId),
|
|
156
|
+
});
|
|
157
|
+
const target = parseSessionChatNavigationIntent(targetUrl, {
|
|
158
|
+
source,
|
|
159
|
+
historyPolicy,
|
|
160
|
+
documentHandoff,
|
|
161
|
+
});
|
|
162
|
+
return classifySessionChatNavigation({ committed, target });
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function buildNormalizedSessionChatPath(
|
|
166
|
+
sessionId,
|
|
167
|
+
{ focusEventId } = {}
|
|
168
|
+
) {
|
|
169
|
+
const intent = normalizeSessionChatNavigationIntent({
|
|
170
|
+
sessionId,
|
|
171
|
+
page: DEFAULT_PAGE,
|
|
172
|
+
semantic: { focus_event_id: focusEventId },
|
|
173
|
+
source: "route_builder",
|
|
174
|
+
historyPolicy: "push",
|
|
175
|
+
});
|
|
176
|
+
if (!intent.valid) {
|
|
177
|
+
throw new Error("Session Chat path requires a valid Session id.");
|
|
178
|
+
}
|
|
179
|
+
const url = new URL(
|
|
180
|
+
`${SESSION_APP_PREFIX}/${encodeURIComponent(intent.sessionId)}/${
|
|
181
|
+
intent.page
|
|
182
|
+
}`,
|
|
183
|
+
"http://oysterun.invalid"
|
|
184
|
+
);
|
|
185
|
+
if (intent.semantic.focus_event_id) {
|
|
186
|
+
url.searchParams.set("focus_event_id", intent.semantic.focus_event_id);
|
|
187
|
+
}
|
|
188
|
+
return `${url.pathname}${url.search}`;
|
|
189
|
+
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildNormalizedSessionChatPath,
|
|
3
|
+
classifySessionChatNavigationFromUrls,
|
|
4
|
+
SESSION_CHAT_NAVIGATION_OUTCOMES,
|
|
5
|
+
} from "./session-navigation-intent.mjs";
|
|
6
|
+
|
|
1
7
|
export const OYSTERUN_SESSION_TRANSITION_SCHEMA =
|
|
2
8
|
"routec.p217_session_transition.v1";
|
|
3
9
|
export const OYSTERUN_SESSION_TRANSITION_VERIFICATION_DELAY_PARAM =
|
|
@@ -89,18 +95,24 @@ export function sessionIdFromCleanChatPath(pathname) {
|
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
export function cleanSessionChatPath(sessionId) {
|
|
92
|
-
|
|
93
|
-
if (!normalized)
|
|
94
|
-
throw new Error("Session transition path requires a Session id.");
|
|
95
|
-
return `/app/sessions/${encodeURIComponent(normalized)}/chat`;
|
|
98
|
+
return buildNormalizedSessionChatPath(sessionId);
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
export function shouldBlockSessionHistoryTransition({
|
|
99
102
|
committedSessionId,
|
|
100
103
|
nextPathname,
|
|
104
|
+
currentPathname = cleanSessionChatPath(committedSessionId),
|
|
105
|
+
currentSearch = "",
|
|
106
|
+
nextSearch = "",
|
|
101
107
|
}) {
|
|
102
|
-
const
|
|
103
|
-
|
|
108
|
+
const outcome = classifySessionChatNavigationFromUrls({
|
|
109
|
+
committedSessionId,
|
|
110
|
+
currentUrl: `${currentPathname}${currentSearch}`,
|
|
111
|
+
targetUrl: `${nextPathname}${nextSearch}`,
|
|
112
|
+
source: "browser_history",
|
|
113
|
+
historyPolicy: "pop",
|
|
114
|
+
});
|
|
115
|
+
return outcome === SESSION_CHAT_NAVIGATION_OUTCOMES.CROSS_SESSION_TRANSITION;
|
|
104
116
|
}
|
|
105
117
|
|
|
106
118
|
export function sessionTransitionVerificationDelayMs({ hostname, search }) {
|