@vibesdotdev/code-sessions 0.0.0-stage → 1.0.0-rc.0
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/LICENSE +18 -0
- package/README.md +165 -2
- package/dist/agent/coordinator.agent.descriptor.d.ts +69 -0
- package/dist/agent/coordinator.agent.descriptor.d.ts.map +1 -0
- package/dist/agent/coordinator.agent.descriptor.js +60 -0
- package/dist/agent/coordinator.agent.descriptor.js.map +1 -0
- package/dist/agent/coordinator.prompt.descriptor.d.ts +135 -0
- package/dist/agent/coordinator.prompt.descriptor.d.ts.map +1 -0
- package/dist/agent/coordinator.prompt.descriptor.js +29 -0
- package/dist/agent/coordinator.prompt.descriptor.js.map +1 -0
- package/dist/agent/coordinator.system-prompt.d.ts +3 -0
- package/dist/agent/coordinator.system-prompt.d.ts.map +1 -0
- package/dist/agent/coordinator.system-prompt.js +18 -0
- package/dist/agent/coordinator.system-prompt.js.map +1 -0
- package/dist/agent/developer.agent.descriptor.d.ts +74 -0
- package/dist/agent/developer.agent.descriptor.d.ts.map +1 -0
- package/dist/agent/developer.agent.descriptor.js +138 -0
- package/dist/agent/developer.agent.descriptor.js.map +1 -0
- package/dist/agent/developer.prompt.descriptor.d.ts +137 -0
- package/dist/agent/developer.prompt.descriptor.d.ts.map +1 -0
- package/dist/agent/developer.prompt.descriptor.js +29 -0
- package/dist/agent/developer.prompt.descriptor.js.map +1 -0
- package/dist/agent/reviewer.agent.descriptor.d.ts +69 -0
- package/dist/agent/reviewer.agent.descriptor.d.ts.map +1 -0
- package/dist/agent/reviewer.agent.descriptor.js +60 -0
- package/dist/agent/reviewer.agent.descriptor.js.map +1 -0
- package/dist/agent/reviewer.prompt.descriptor.d.ts +135 -0
- package/dist/agent/reviewer.prompt.descriptor.d.ts.map +1 -0
- package/dist/agent/reviewer.prompt.descriptor.js +29 -0
- package/dist/agent/reviewer.prompt.descriptor.js.map +1 -0
- package/dist/agent/reviewer.system-prompt.d.ts +3 -0
- package/dist/agent/reviewer.system-prompt.d.ts.map +1 -0
- package/dist/agent/reviewer.system-prompt.js +17 -0
- package/dist/agent/reviewer.system-prompt.js.map +1 -0
- package/dist/agent/system-prompt.d.ts +12 -0
- package/dist/agent/system-prompt.d.ts.map +1 -0
- package/dist/agent/system-prompt.js +28 -0
- package/dist/agent/system-prompt.js.map +1 -0
- package/dist/api/code-sessions.api-client.descriptor.d.ts +25 -0
- package/dist/api/code-sessions.api-client.descriptor.d.ts.map +1 -0
- package/dist/api/code-sessions.api-client.descriptor.js +26 -0
- package/dist/api/code-sessions.api-client.descriptor.js.map +1 -0
- package/dist/api/code-sessions.api-client.impl.d.ts +156 -0
- package/dist/api/code-sessions.api-client.impl.d.ts.map +1 -0
- package/dist/api/code-sessions.api-client.impl.js +852 -0
- package/dist/api/code-sessions.api-client.impl.js.map +1 -0
- package/dist/api/code-sessions.api-client.schemas.d.ts +2 -0
- package/dist/api/code-sessions.api-client.schemas.d.ts.map +1 -0
- package/dist/api/code-sessions.api-client.schemas.js +2 -0
- package/dist/api/code-sessions.api-client.schemas.js.map +1 -0
- package/dist/api/code-sessions.api-client.types.d.ts +252 -0
- package/dist/api/code-sessions.api-client.types.d.ts.map +1 -0
- package/dist/api/code-sessions.api-client.types.js +77 -0
- package/dist/api/code-sessions.api-client.types.js.map +1 -0
- package/dist/api/index.d.ts +13 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +20 -0
- package/dist/api/index.js.map +1 -0
- package/dist/capability.d.ts +9 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +9 -0
- package/dist/capability.js.map +1 -0
- package/dist/catalog/index.d.ts +2 -0
- package/dist/catalog/index.d.ts.map +1 -0
- package/dist/catalog/index.js +2 -0
- package/dist/catalog/index.js.map +1 -0
- package/dist/catalog/session-catalog.d.ts +131 -0
- package/dist/catalog/session-catalog.d.ts.map +1 -0
- package/dist/catalog/session-catalog.impl.consumer.worker.d.ts +113 -0
- package/dist/catalog/session-catalog.impl.consumer.worker.d.ts.map +1 -0
- package/dist/catalog/session-catalog.impl.consumer.worker.js +32 -0
- package/dist/catalog/session-catalog.impl.consumer.worker.js.map +1 -0
- package/dist/catalog/session-catalog.js +126 -0
- package/dist/catalog/session-catalog.js.map +1 -0
- package/dist/clock/clock.client.d.ts +18 -0
- package/dist/clock/clock.client.d.ts.map +1 -0
- package/dist/clock/clock.client.js +43 -0
- package/dist/clock/clock.client.js.map +1 -0
- package/dist/code-sessions.consumer.plugin.d.ts +4 -0
- package/dist/code-sessions.consumer.plugin.d.ts.map +1 -0
- package/dist/code-sessions.consumer.plugin.js +16 -0
- package/dist/code-sessions.consumer.plugin.js.map +1 -0
- package/dist/code-sessions.plugin.d.ts +15 -0
- package/dist/code-sessions.plugin.d.ts.map +1 -0
- package/dist/code-sessions.plugin.js +65 -0
- package/dist/code-sessions.plugin.js.map +1 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +9 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/preparation.d.ts +2 -0
- package/dist/config/preparation.d.ts.map +1 -0
- package/dist/config/preparation.js +2 -0
- package/dist/config/preparation.js.map +1 -0
- package/dist/docs/code-sessions.docs.descriptor.d.ts +4 -0
- package/dist/docs/code-sessions.docs.descriptor.d.ts.map +1 -0
- package/dist/docs/code-sessions.docs.descriptor.js +241 -0
- package/dist/docs/code-sessions.docs.descriptor.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/pull-request-plan.d.ts +68 -0
- package/dist/pull-request-plan.d.ts.map +1 -0
- package/dist/pull-request-plan.js +94 -0
- package/dist/pull-request-plan.js.map +1 -0
- package/dist/schemas/preparation.d.ts +51 -0
- package/dist/schemas/preparation.d.ts.map +1 -0
- package/dist/schemas/preparation.js +20 -0
- package/dist/schemas/preparation.js.map +1 -0
- package/dist/schemas/requests.d.ts +411 -0
- package/dist/schemas/requests.d.ts.map +1 -0
- package/dist/schemas/requests.js +87 -0
- package/dist/schemas/requests.js.map +1 -0
- package/dist/schemas/responses.d.ts +275 -0
- package/dist/schemas/responses.d.ts.map +1 -0
- package/dist/schemas/responses.js +90 -0
- package/dist/schemas/responses.js.map +1 -0
- package/dist/svelte/actions.d.ts +70 -0
- package/dist/svelte/actions.d.ts.map +1 -0
- package/dist/svelte/actions.js +280 -0
- package/dist/svelte/clock.svelte.d.ts +6 -0
- package/dist/svelte/clock.svelte.d.ts.map +1 -0
- package/dist/svelte/clock.svelte.js +33 -0
- package/dist/svelte/components/CreateSessionDialog.svelte +470 -0
- package/dist/svelte/components/CreateSessionDialog.svelte.d.ts +57 -0
- package/dist/svelte/components/CreateSessionDialog.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SessionCard.svelte +216 -0
- package/dist/svelte/components/SessionCard.svelte.d.ts +27 -0
- package/dist/svelte/components/SessionCard.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SessionList.svelte +86 -0
- package/dist/svelte/components/SessionList.svelte.d.ts +23 -0
- package/dist/svelte/components/SessionList.svelte.d.ts.map +1 -0
- package/dist/svelte/components/SessionSeed.svelte +60 -0
- package/dist/svelte/components/SessionSeed.svelte.d.ts +9 -0
- package/dist/svelte/components/SessionSeed.svelte.d.ts.map +1 -0
- package/dist/svelte/components/TranscriptView.svelte +360 -0
- package/dist/svelte/components/TranscriptView.svelte.d.ts +26 -0
- package/dist/svelte/components/TranscriptView.svelte.d.ts.map +1 -0
- package/dist/svelte/create-session-form.d.ts +84 -0
- package/dist/svelte/create-session-form.d.ts.map +1 -0
- package/dist/svelte/create-session-form.js +107 -0
- package/dist/svelte/index.d.ts +20 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +18 -0
- package/dist/svelte/live-session.d.ts +156 -0
- package/dist/svelte/live-session.d.ts.map +1 -0
- package/dist/svelte/live-session.js +152 -0
- package/dist/svelte/loaders.d.ts +74 -0
- package/dist/svelte/loaders.d.ts.map +1 -0
- package/dist/svelte/loaders.js +124 -0
- package/dist/svelte/outcome.d.ts +46 -0
- package/dist/svelte/outcome.d.ts.map +1 -0
- package/dist/svelte/outcome.js +49 -0
- package/dist/svelte/relative-time.d.ts +32 -0
- package/dist/svelte/relative-time.d.ts.map +1 -0
- package/dist/svelte/relative-time.js +51 -0
- package/dist/svelte/session-list-item.d.ts +23 -0
- package/dist/svelte/session-list-item.d.ts.map +1 -0
- package/dist/svelte/session-list-item.js +1 -0
- package/dist/svelte/styles.css +8 -0
- package/dist/svelte/transcript-input.d.ts +45 -0
- package/dist/svelte/transcript-input.d.ts.map +1 -0
- package/dist/svelte/transcript-input.js +188 -0
- package/dist/tui/code-sessions-tui.plugin.d.ts +10 -0
- package/dist/tui/code-sessions-tui.plugin.d.ts.map +1 -0
- package/dist/tui/code-sessions-tui.plugin.js +29 -0
- package/dist/tui/code-sessions-tui.plugin.js.map +1 -0
- package/dist/tui/code-sessions.tui-app.descriptor.d.ts +7 -0
- package/dist/tui/code-sessions.tui-app.descriptor.d.ts.map +1 -0
- package/dist/tui/code-sessions.tui-app.descriptor.js +30 -0
- package/dist/tui/code-sessions.tui-app.descriptor.js.map +1 -0
- package/dist/tui/code-sessions.tui-app.impl.consumer.d.ts +14 -0
- package/dist/tui/code-sessions.tui-app.impl.consumer.d.ts.map +1 -0
- package/dist/tui/code-sessions.tui-app.impl.consumer.js +453 -0
- package/dist/tui/code-sessions.tui-app.impl.consumer.js.map +1 -0
- package/dist/tui/code-sessions.tui-client.d.ts +22 -0
- package/dist/tui/code-sessions.tui-client.d.ts.map +1 -0
- package/dist/tui/code-sessions.tui-client.js +95 -0
- package/dist/tui/code-sessions.tui-client.js.map +1 -0
- package/dist/tui/code-sessions.tui-open.descriptor.d.ts +7 -0
- package/dist/tui/code-sessions.tui-open.descriptor.d.ts.map +1 -0
- package/dist/tui/code-sessions.tui-open.descriptor.js +16 -0
- package/dist/tui/code-sessions.tui-open.descriptor.js.map +1 -0
- package/dist/tui/code-sessions.tui-open.impl.consumer.d.ts +7 -0
- package/dist/tui/code-sessions.tui-open.impl.consumer.d.ts.map +1 -0
- package/dist/tui/code-sessions.tui-open.impl.consumer.js +11 -0
- package/dist/tui/code-sessions.tui-open.impl.consumer.js.map +1 -0
- package/dist/tui/code-sessions.tui-state.descriptor.d.ts +16 -0
- package/dist/tui/code-sessions.tui-state.descriptor.d.ts.map +1 -0
- package/dist/tui/code-sessions.tui-state.descriptor.js +50 -0
- package/dist/tui/code-sessions.tui-state.descriptor.js.map +1 -0
- package/dist/tui/code-sessions.tui-state.impl.consumer.d.ts +30 -0
- package/dist/tui/code-sessions.tui-state.impl.consumer.d.ts.map +1 -0
- package/dist/tui/code-sessions.tui-state.impl.consumer.js +533 -0
- package/dist/tui/code-sessions.tui-state.impl.consumer.js.map +1 -0
- package/dist/tui/code-sessions.tui-state.key.d.ts +322 -0
- package/dist/tui/code-sessions.tui-state.key.d.ts.map +1 -0
- package/dist/tui/code-sessions.tui-state.key.js +104 -0
- package/dist/tui/code-sessions.tui-state.key.js.map +1 -0
- package/dist/tui/index.d.ts +9 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +8 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/workspace/index.d.ts +2 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +2 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace/workspace-binding.d.ts +74 -0
- package/dist/workspace/workspace-binding.d.ts.map +1 -0
- package/dist/workspace/workspace-binding.impl.consumer.worker.d.ts +17 -0
- package/dist/workspace/workspace-binding.impl.consumer.worker.d.ts.map +1 -0
- package/dist/workspace/workspace-binding.impl.consumer.worker.js +134 -0
- package/dist/workspace/workspace-binding.impl.consumer.worker.js.map +1 -0
- package/dist/workspace/workspace-binding.js +72 -0
- package/dist/workspace/workspace-binding.js.map +1 -0
- package/package.json +238 -4
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Liveness rules for a watched code session.
|
|
3
|
+
*
|
|
4
|
+
* A session view is a WATCH surface: the user opens it to see work happen, so
|
|
5
|
+
* state has to arrive without them reaching for reload. These are the pure
|
|
6
|
+
* decisions behind that — kept out of the component so they can be tested
|
|
7
|
+
* without a DOM, and out of the app so every surface watching a session
|
|
8
|
+
* (HQ today, others later) answers "should I still be watching?" the same way.
|
|
9
|
+
*
|
|
10
|
+
* The refresh mechanism itself is deliberately NOT here: surfaces re-run their
|
|
11
|
+
* own canonical loader (SvelteKit `invalidate`), so watching reuses the one
|
|
12
|
+
* data path a session already resolves through instead of a second client-side
|
|
13
|
+
* fetch that could drift from it.
|
|
14
|
+
*/
|
|
15
|
+
import { type PullRequestPlan, type PullRequestPlanSession } from '@vibesdotdev/code-sessions/pull-request-plan';
|
|
16
|
+
/**
|
|
17
|
+
* Statuses from which a session will never change again on its own.
|
|
18
|
+
*
|
|
19
|
+
* Polling past one of these is pure cost: nothing upstream can move the record,
|
|
20
|
+
* so the surface would ask forever and learn nothing.
|
|
21
|
+
*
|
|
22
|
+
* These are the TERMINAL members of `PlatformCodeSessionStatus`
|
|
23
|
+
* (`initializing | active | error | ended` —
|
|
24
|
+
* `platform/src/api/platform.api-client.types.ts:88`, and the same
|
|
25
|
+
* enum the create route validates against). The first version of this file
|
|
26
|
+
* invented `stopped/failed/expired/deleted`, which the platform cannot emit —
|
|
27
|
+
* so the settled set never matched anything, `shouldWatchSession` was a
|
|
28
|
+
* constant `true`, and every session-detail tab polled forever, finished or
|
|
29
|
+
* not. Caught by independent review, not by the tests: they asserted the
|
|
30
|
+
* invented words against themselves.
|
|
31
|
+
*
|
|
32
|
+
* If a new terminal status is added to the platform enum, it belongs here — and
|
|
33
|
+
* the test below that walks the real enum will fail until it is.
|
|
34
|
+
*/
|
|
35
|
+
export declare const SETTLED_SESSION_STATUSES: readonly ["ended", "error"];
|
|
36
|
+
/** Every status the platform can emit — mirrored so the tests can walk it. */
|
|
37
|
+
export declare const PLATFORM_SESSION_STATUSES: readonly ["initializing", "active", "error", "ended"];
|
|
38
|
+
export type SettledSessionStatus = (typeof SETTLED_SESSION_STATUSES)[number];
|
|
39
|
+
/** True when the session has reached a state it cannot leave. */
|
|
40
|
+
export declare function isSessionSettled(status: string | null | undefined): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether a watching surface should keep refreshing.
|
|
43
|
+
*
|
|
44
|
+
* An unknown/absent status keeps polling ON PURPOSE: a session that has not
|
|
45
|
+
* reported yet is exactly the case the user is waiting on, and treating
|
|
46
|
+
* "unknown" as settled would leave a starting-up session frozen on screen —
|
|
47
|
+
* the failure this whole predicate exists to remove.
|
|
48
|
+
*/
|
|
49
|
+
export declare function shouldWatchSession(status: string | null | undefined): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Poll interval for a watched session, in milliseconds.
|
|
52
|
+
*
|
|
53
|
+
* Short enough that "it is starting up now" resolves while the user is still
|
|
54
|
+
* looking, long enough that a forgotten open tab is not a load generator. The
|
|
55
|
+
* caller is expected to poll only while the document is visible.
|
|
56
|
+
*/
|
|
57
|
+
export declare const SESSION_WATCH_INTERVAL_MS = 5000;
|
|
58
|
+
/** SvelteKit invalidation key a session-detail surface depends on. */
|
|
59
|
+
export declare const SESSION_DETAIL_DEPENDENCY = "code-session:detail";
|
|
60
|
+
/**
|
|
61
|
+
* Fully-specified PR offer a surface can render after publish.
|
|
62
|
+
*
|
|
63
|
+
* `plan` is the single planner output (`pullRequestPlanForSession` /
|
|
64
|
+
* `pullRequestPlanAfterPublish`). Title/description/head/repo always come from
|
|
65
|
+
* that plan — never reinvented here. `url` is a link into Forge's `pulls/new`
|
|
66
|
+
* with head (+ optional base) and plan title/body as query prefills; actual PR
|
|
67
|
+
* *creation* via `forge-pr-create-from-branch` is a follow-up that consumes the
|
|
68
|
+
* same plan fields.
|
|
69
|
+
*/
|
|
70
|
+
export type SessionPullRequestPresentation = {
|
|
71
|
+
ready: false;
|
|
72
|
+
reason: string;
|
|
73
|
+
} | {
|
|
74
|
+
ready: true;
|
|
75
|
+
plan: Extract<PullRequestPlan, {
|
|
76
|
+
ready: true;
|
|
77
|
+
}>;
|
|
78
|
+
/** Repo ref for forge-pr-create-from-branch / Forge URL. */
|
|
79
|
+
repo: string;
|
|
80
|
+
/** Head branch (session work). */
|
|
81
|
+
head: string;
|
|
82
|
+
/** Optional merge target; omit so Forge uses the repo default. */
|
|
83
|
+
base?: string;
|
|
84
|
+
title: string;
|
|
85
|
+
/** PR body — plan description (session/branch/work-item lines). */
|
|
86
|
+
body: string;
|
|
87
|
+
/**
|
|
88
|
+
* Link into Forge pulls/new carrying head (+ base) and title/body
|
|
89
|
+
* prefills. `null` when the repository is not `owner/name` or the
|
|
90
|
+
* forge origin is missing — plan fields still render.
|
|
91
|
+
*/
|
|
92
|
+
url: string | null;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Where a published branch becomes a pull request link.
|
|
96
|
+
*
|
|
97
|
+
* Deliberately a LINK into Forge rather than a second PR-creation path. Forge's
|
|
98
|
+
* `pulls/new` resolves the merge base and head SHA; plan title/body ride as
|
|
99
|
+
* query prefills so the form opens with session truth, not only base/head.
|
|
100
|
+
*
|
|
101
|
+
* Prefer {@link sessionPullRequestPresentation} at call sites that have a
|
|
102
|
+
* session — it routes through the single planner first. This helper remains
|
|
103
|
+
* for pure URL construction from already-planned fields.
|
|
104
|
+
*
|
|
105
|
+
* Returns `null` rather than a half-built URL when the repository ref or branch
|
|
106
|
+
* is missing. A dead "Open pull request" button is worse than no button: it
|
|
107
|
+
* claims a next step exists when nothing can happen.
|
|
108
|
+
*/
|
|
109
|
+
export declare function forgePullRequestUrl(input: {
|
|
110
|
+
/** Forge origin, e.g. `https://git.vibes.dev`. */
|
|
111
|
+
forgeOrigin: string | null | undefined;
|
|
112
|
+
/** `owner/name` as proven by the platform, not as typed by anyone. */
|
|
113
|
+
repository: string | null | undefined;
|
|
114
|
+
branch: string | null | undefined;
|
|
115
|
+
/** Target branch; Forge falls back to the repo default when omitted. */
|
|
116
|
+
base?: string | null;
|
|
117
|
+
/** Prefill for the new-PR form title (from the plan when known). */
|
|
118
|
+
title?: string | null;
|
|
119
|
+
/** Prefill for the new-PR form body (from the plan when known). */
|
|
120
|
+
body?: string | null;
|
|
121
|
+
}): string | null;
|
|
122
|
+
/**
|
|
123
|
+
* Single entry for "after publish, what PR do we show?".
|
|
124
|
+
*
|
|
125
|
+
* Routes through {@link pullRequestPlanAfterPublish} so HQ, CLI, and any future
|
|
126
|
+
* automation share one answer for readiness, title, body, head, and repo.
|
|
127
|
+
* Never pass `session.checkoutRef` as the merge *base* — that field is the
|
|
128
|
+
* session's work branch (head), and using it as base made base===head.
|
|
129
|
+
*/
|
|
130
|
+
export declare function sessionPullRequestPresentation(input: {
|
|
131
|
+
session: PullRequestPlanSession;
|
|
132
|
+
forgeOrigin: string | null | undefined;
|
|
133
|
+
/** Platform-proven publish result; preferred over create-time session fields. */
|
|
134
|
+
published?: {
|
|
135
|
+
repository?: string | null;
|
|
136
|
+
branch?: string | null;
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Merge target when the surface knows one. Omit so Forge uses the repo
|
|
140
|
+
* default — do not pass the session checkout ref here.
|
|
141
|
+
*/
|
|
142
|
+
base?: string | null;
|
|
143
|
+
}): SessionPullRequestPresentation;
|
|
144
|
+
/**
|
|
145
|
+
* Render the exact authority result returned by publish.
|
|
146
|
+
*
|
|
147
|
+
* Consumers must not feed the response back through the planner: doing so
|
|
148
|
+
* silently turns an absent published branch into the session's stale
|
|
149
|
+
* create-time checkout ref. This helper is deliberately presentation-only.
|
|
150
|
+
*/
|
|
151
|
+
export declare function pullRequestPresentationFromPlan(input: {
|
|
152
|
+
plan: PullRequestPlan;
|
|
153
|
+
forgeOrigin: string | null | undefined;
|
|
154
|
+
base?: string | null;
|
|
155
|
+
}): SessionPullRequestPresentation;
|
|
156
|
+
//# sourceMappingURL=live-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live-session.d.ts","sourceRoot":"","sources":["../../src/svelte/live-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAEN,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,MAAM,8CAA8C,CAAC;AAEtD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,wBAAwB,6BAA8B,CAAC;AAEpE,8EAA8E;AAC9E,eAAO,MAAM,yBAAyB,uDAAwD,CAAC;AAE/F,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7E,iEAAiE;AACjE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAG3E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE7E;AAED;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAE/C,sEAAsE;AACtE,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAE/D;;;;;;;;;GASG;AACH,MAAM,MAAM,8BAA8B,GACvC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChC;IACA,KAAK,EAAE,IAAI,CAAC;IACZ,IAAI,EAAE,OAAO,CAAC,eAAe,EAAE;QAAE,KAAK,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;IAChD,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAClB,CAAC;AAEL;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IAC1C,kDAAkD;IAClD,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,sEAAsE;IACtE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACtC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,GAAG,MAAM,GAAG,IAAI,CAmBhB;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACrD,OAAO,EAAE,sBAAsB,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,iFAAiF;IACjF,SAAS,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACnE;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,GAAG,8BAA8B,CAOjC;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE;IACtD,IAAI,EAAE,eAAe,CAAC;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,GAAG,8BAA8B,CAyBjC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Liveness rules for a watched code session.
|
|
3
|
+
*
|
|
4
|
+
* A session view is a WATCH surface: the user opens it to see work happen, so
|
|
5
|
+
* state has to arrive without them reaching for reload. These are the pure
|
|
6
|
+
* decisions behind that — kept out of the component so they can be tested
|
|
7
|
+
* without a DOM, and out of the app so every surface watching a session
|
|
8
|
+
* (HQ today, others later) answers "should I still be watching?" the same way.
|
|
9
|
+
*
|
|
10
|
+
* The refresh mechanism itself is deliberately NOT here: surfaces re-run their
|
|
11
|
+
* own canonical loader (SvelteKit `invalidate`), so watching reuses the one
|
|
12
|
+
* data path a session already resolves through instead of a second client-side
|
|
13
|
+
* fetch that could drift from it.
|
|
14
|
+
*/
|
|
15
|
+
import { pullRequestPlanAfterPublish } from '@vibesdotdev/code-sessions/pull-request-plan';
|
|
16
|
+
/**
|
|
17
|
+
* Statuses from which a session will never change again on its own.
|
|
18
|
+
*
|
|
19
|
+
* Polling past one of these is pure cost: nothing upstream can move the record,
|
|
20
|
+
* so the surface would ask forever and learn nothing.
|
|
21
|
+
*
|
|
22
|
+
* These are the TERMINAL members of `PlatformCodeSessionStatus`
|
|
23
|
+
* (`initializing | active | error | ended` —
|
|
24
|
+
* `platform/src/api/platform.api-client.types.ts:88`, and the same
|
|
25
|
+
* enum the create route validates against). The first version of this file
|
|
26
|
+
* invented `stopped/failed/expired/deleted`, which the platform cannot emit —
|
|
27
|
+
* so the settled set never matched anything, `shouldWatchSession` was a
|
|
28
|
+
* constant `true`, and every session-detail tab polled forever, finished or
|
|
29
|
+
* not. Caught by independent review, not by the tests: they asserted the
|
|
30
|
+
* invented words against themselves.
|
|
31
|
+
*
|
|
32
|
+
* If a new terminal status is added to the platform enum, it belongs here — and
|
|
33
|
+
* the test below that walks the real enum will fail until it is.
|
|
34
|
+
*/
|
|
35
|
+
export const SETTLED_SESSION_STATUSES = ['ended', 'error'];
|
|
36
|
+
/** Every status the platform can emit — mirrored so the tests can walk it. */
|
|
37
|
+
export const PLATFORM_SESSION_STATUSES = ['initializing', 'active', 'error', 'ended'];
|
|
38
|
+
/** True when the session has reached a state it cannot leave. */
|
|
39
|
+
export function isSessionSettled(status) {
|
|
40
|
+
if (!status)
|
|
41
|
+
return false;
|
|
42
|
+
return SETTLED_SESSION_STATUSES.some((settled) => settled === status);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Whether a watching surface should keep refreshing.
|
|
46
|
+
*
|
|
47
|
+
* An unknown/absent status keeps polling ON PURPOSE: a session that has not
|
|
48
|
+
* reported yet is exactly the case the user is waiting on, and treating
|
|
49
|
+
* "unknown" as settled would leave a starting-up session frozen on screen —
|
|
50
|
+
* the failure this whole predicate exists to remove.
|
|
51
|
+
*/
|
|
52
|
+
export function shouldWatchSession(status) {
|
|
53
|
+
return !isSessionSettled(status);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Poll interval for a watched session, in milliseconds.
|
|
57
|
+
*
|
|
58
|
+
* Short enough that "it is starting up now" resolves while the user is still
|
|
59
|
+
* looking, long enough that a forgotten open tab is not a load generator. The
|
|
60
|
+
* caller is expected to poll only while the document is visible.
|
|
61
|
+
*/
|
|
62
|
+
export const SESSION_WATCH_INTERVAL_MS = 5_000;
|
|
63
|
+
/** SvelteKit invalidation key a session-detail surface depends on. */
|
|
64
|
+
export const SESSION_DETAIL_DEPENDENCY = 'code-session:detail';
|
|
65
|
+
/**
|
|
66
|
+
* Where a published branch becomes a pull request link.
|
|
67
|
+
*
|
|
68
|
+
* Deliberately a LINK into Forge rather than a second PR-creation path. Forge's
|
|
69
|
+
* `pulls/new` resolves the merge base and head SHA; plan title/body ride as
|
|
70
|
+
* query prefills so the form opens with session truth, not only base/head.
|
|
71
|
+
*
|
|
72
|
+
* Prefer {@link sessionPullRequestPresentation} at call sites that have a
|
|
73
|
+
* session — it routes through the single planner first. This helper remains
|
|
74
|
+
* for pure URL construction from already-planned fields.
|
|
75
|
+
*
|
|
76
|
+
* Returns `null` rather than a half-built URL when the repository ref or branch
|
|
77
|
+
* is missing. A dead "Open pull request" button is worse than no button: it
|
|
78
|
+
* claims a next step exists when nothing can happen.
|
|
79
|
+
*/
|
|
80
|
+
export function forgePullRequestUrl(input) {
|
|
81
|
+
const origin = input.forgeOrigin?.trim().replace(/\/+$/, '');
|
|
82
|
+
const repository = input.repository?.trim();
|
|
83
|
+
const branch = input.branch?.trim();
|
|
84
|
+
if (!origin || !repository || !branch)
|
|
85
|
+
return null;
|
|
86
|
+
const [owner, ...rest] = repository.split('/');
|
|
87
|
+
const name = rest.join('/');
|
|
88
|
+
if (!owner || !name)
|
|
89
|
+
return null;
|
|
90
|
+
const url = new URL(`${origin}/${encodeURIComponent(owner)}/${encodeURIComponent(name)}/pulls/new`);
|
|
91
|
+
url.searchParams.set('head', branch);
|
|
92
|
+
const base = input.base?.trim();
|
|
93
|
+
if (base)
|
|
94
|
+
url.searchParams.set('base', base);
|
|
95
|
+
const title = input.title?.trim();
|
|
96
|
+
if (title)
|
|
97
|
+
url.searchParams.set('title', title);
|
|
98
|
+
const body = input.body?.trim();
|
|
99
|
+
if (body)
|
|
100
|
+
url.searchParams.set('body', body);
|
|
101
|
+
return url.toString();
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Single entry for "after publish, what PR do we show?".
|
|
105
|
+
*
|
|
106
|
+
* Routes through {@link pullRequestPlanAfterPublish} so HQ, CLI, and any future
|
|
107
|
+
* automation share one answer for readiness, title, body, head, and repo.
|
|
108
|
+
* Never pass `session.checkoutRef` as the merge *base* — that field is the
|
|
109
|
+
* session's work branch (head), and using it as base made base===head.
|
|
110
|
+
*/
|
|
111
|
+
export function sessionPullRequestPresentation(input) {
|
|
112
|
+
const plan = pullRequestPlanAfterPublish(input.session, input.published ?? {});
|
|
113
|
+
return pullRequestPresentationFromPlan({
|
|
114
|
+
plan,
|
|
115
|
+
forgeOrigin: input.forgeOrigin,
|
|
116
|
+
base: input.base
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Render the exact authority result returned by publish.
|
|
121
|
+
*
|
|
122
|
+
* Consumers must not feed the response back through the planner: doing so
|
|
123
|
+
* silently turns an absent published branch into the session's stale
|
|
124
|
+
* create-time checkout ref. This helper is deliberately presentation-only.
|
|
125
|
+
*/
|
|
126
|
+
export function pullRequestPresentationFromPlan(input) {
|
|
127
|
+
const { plan } = input;
|
|
128
|
+
if (!plan.ready) {
|
|
129
|
+
return { ready: false, reason: plan.reason };
|
|
130
|
+
}
|
|
131
|
+
const base = input.base?.trim() || undefined;
|
|
132
|
+
const url = forgePullRequestUrl({
|
|
133
|
+
forgeOrigin: input.forgeOrigin,
|
|
134
|
+
repository: plan.repo,
|
|
135
|
+
branch: plan.sourceRef,
|
|
136
|
+
base,
|
|
137
|
+
title: plan.title,
|
|
138
|
+
body: plan.description
|
|
139
|
+
});
|
|
140
|
+
const presentation = {
|
|
141
|
+
ready: true,
|
|
142
|
+
plan,
|
|
143
|
+
repo: plan.repo,
|
|
144
|
+
head: plan.sourceRef,
|
|
145
|
+
title: plan.title,
|
|
146
|
+
body: plan.description,
|
|
147
|
+
url
|
|
148
|
+
};
|
|
149
|
+
if (base)
|
|
150
|
+
presentation.base = base;
|
|
151
|
+
return presentation;
|
|
152
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvelteKit `load` helpers for `@vibesdotdev/code-sessions/svelte`.
|
|
3
|
+
*
|
|
4
|
+
* Exported under the `./loaders` subpath so server routes can assemble
|
|
5
|
+
* code-session data without importing the Svelte component barrel.
|
|
6
|
+
*
|
|
7
|
+
* Code-session persistence is owned by platform-web. This loader resolves the
|
|
8
|
+
* canonical `CodeSessionsClient` (`runtime/client` id `code-sessions`) and
|
|
9
|
+
* forks it with request-scoped Bearer/fetch overrides for SSR.
|
|
10
|
+
*/
|
|
11
|
+
import type { ServerLoadEvent } from '@sveltejs/kit';
|
|
12
|
+
import { type VibesRuntime } from '@vibesdotdev/kernel';
|
|
13
|
+
import type { CodeSessionCreateInput, CodeSessionListOptions, CodeSessionsClientOptions, RunCommandRequest, RunCommandResponse, SessionWithCapability } from '@vibesdotdev/code-sessions/api';
|
|
14
|
+
/** SvelteKit event; `locals.runtime` is the request's handed runtime (D1). */
|
|
15
|
+
export type CodeSessionsLoaderEvent = Pick<ServerLoadEvent, 'request' | 'fetch'> & {
|
|
16
|
+
locals: {
|
|
17
|
+
runtime: VibesRuntime;
|
|
18
|
+
sessionToken?: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export interface CodeSessionsLoaderClient {
|
|
22
|
+
ensureLoaded(): Promise<void>;
|
|
23
|
+
forRequest(overrides: Partial<CodeSessionsClientOptions>): CodeSessionsLoaderClient;
|
|
24
|
+
list(options?: CodeSessionListOptions): Promise<SessionWithCapability[]>;
|
|
25
|
+
get(sessionId: string): Promise<SessionWithCapability | null>;
|
|
26
|
+
create(input: CodeSessionCreateInput): Promise<SessionWithCapability>;
|
|
27
|
+
run(input: RunCommandRequest): Promise<RunCommandResponse>;
|
|
28
|
+
delete(sessionId: string): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export interface CodeSessionsRequestClientOptions {
|
|
31
|
+
/** Test hook or already-resolved runtime client. Defaults to `getVibesClient('code-sessions', event.locals.runtime)`. */
|
|
32
|
+
client?: CodeSessionsLoaderClient;
|
|
33
|
+
/** Platform origin for SSR/cross-app calls, e.g. `PUBLIC_VIBES_PLATFORM_ORIGIN`. */
|
|
34
|
+
platformOrigin?: string;
|
|
35
|
+
/** Extra headers to send to platform-web. Bearer from `locals.sessionToken` is merged when absent. */
|
|
36
|
+
headers?: HeadersInit;
|
|
37
|
+
}
|
|
38
|
+
export interface LoadCodeSessionsLayoutOptions extends CodeSessionsRequestClientOptions {
|
|
39
|
+
listOptions?: CodeSessionListOptions;
|
|
40
|
+
/** Re-throw errors instead of degrading to an empty list. */
|
|
41
|
+
throwOnError?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface CodeSessionsLayoutData {
|
|
44
|
+
sessions: SessionWithCapability[];
|
|
45
|
+
sessionsError: string | null;
|
|
46
|
+
}
|
|
47
|
+
export interface LoadCodeSessionDetailOptions extends CodeSessionsRequestClientOptions {
|
|
48
|
+
sessionId: string;
|
|
49
|
+
/** Re-throw errors instead of degrading to a null session. */
|
|
50
|
+
throwOnError?: boolean;
|
|
51
|
+
}
|
|
52
|
+
export interface CodeSessionDetailData {
|
|
53
|
+
session: SessionWithCapability | null;
|
|
54
|
+
sessionError: string | null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Resolve a request-scoped code-sessions client for SvelteKit server loaders
|
|
58
|
+
* and actions. The base runtime client remains a singleton; `forRequest(...)`
|
|
59
|
+
* carries the incoming Bearer/fetch/origin for this SSR request only.
|
|
60
|
+
*/
|
|
61
|
+
export declare function resolveCodeSessionsRequestClient(event: CodeSessionsLoaderEvent, options?: CodeSessionsRequestClientOptions): Promise<CodeSessionsLoaderClient>;
|
|
62
|
+
/**
|
|
63
|
+
* Compose the code-sessions list payload for a SvelteKit `+page.server.ts` or
|
|
64
|
+
* `+layout.server.ts`. Consuming apps may spread the returned fields into their
|
|
65
|
+
* own route data and keep app-specific actions/copy local.
|
|
66
|
+
*/
|
|
67
|
+
export declare function loadCodeSessionsLayoutData(event: CodeSessionsLoaderEvent, options?: LoadCodeSessionsLayoutOptions): Promise<CodeSessionsLayoutData>;
|
|
68
|
+
/**
|
|
69
|
+
* Compose the single-session payload for detail pages. A missing or unauthorized
|
|
70
|
+
* session is represented as `session: null`; callers decide whether to redirect,
|
|
71
|
+
* render a not-found state, or preserve app-specific recovery UI.
|
|
72
|
+
*/
|
|
73
|
+
export declare function loadCodeSessionDetailData(event: CodeSessionsLoaderEvent, options: LoadCodeSessionDetailOptions): Promise<CodeSessionDetailData>;
|
|
74
|
+
//# sourceMappingURL=loaders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loaders.d.ts","sourceRoot":"","sources":["../../src/svelte/loaders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGzE,OAAO,KAAK,EACX,sBAAsB,EACtB,sBAAsB,EAEtB,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,MAAM,gCAAgC,CAAC;AAExC,8EAA8E;AAC9E,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG;IAClF,MAAM,EAAE;QAAE,OAAO,EAAE,YAAY,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACxC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,wBAAwB,CAAC;IACpF,IAAI,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IACzE,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IAC9D,MAAM,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACtE,GAAG,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC3D,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,gCAAgC;IAChD,yHAAyH;IACzH,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAClC,oFAAoF;IACpF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sGAAsG;IACtG,OAAO,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,6BAA8B,SAAQ,gCAAgC;IACtF,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,4BAA6B,SAAQ,gCAAgC;IACrF,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACtC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA8DD;;;;GAIG;AACH,wBAAsB,gCAAgC,CACrD,KAAK,EAAE,uBAAuB,EAC9B,OAAO,GAAE,gCAAqC,GAC5C,OAAO,CAAC,wBAAwB,CAAC,CAsBnC;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC/C,KAAK,EAAE,uBAAuB,EAC9B,OAAO,GAAE,6BAAkC,GACzC,OAAO,CAAC,sBAAsB,CAAC,CAOjC;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC9C,KAAK,EAAE,uBAAuB,EAC9B,OAAO,EAAE,4BAA4B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAWhC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvelteKit `load` helpers for `@vibesdotdev/code-sessions/svelte`.
|
|
3
|
+
*
|
|
4
|
+
* Exported under the `./loaders` subpath so server routes can assemble
|
|
5
|
+
* code-session data without importing the Svelte component barrel.
|
|
6
|
+
*
|
|
7
|
+
* Code-session persistence is owned by platform-web. This loader resolves the
|
|
8
|
+
* canonical `CodeSessionsClient` (`runtime/client` id `code-sessions`) and
|
|
9
|
+
* forks it with request-scoped Bearer/fetch overrides for SSR.
|
|
10
|
+
*/
|
|
11
|
+
import { getLogger } from '@vibesdotdev/logging';
|
|
12
|
+
import { CapabilityError } from '@vibesdotdev/kernel';
|
|
13
|
+
import { getVibesClient } from '@vibesdotdev/kernel/client';
|
|
14
|
+
import { attempt } from "./outcome.js";
|
|
15
|
+
/** One plain record of the caller's headers, names as given (a `Headers` instance reads lower-cased). */
|
|
16
|
+
function headersInitToRecord(headers) {
|
|
17
|
+
if (headers instanceof Headers)
|
|
18
|
+
return Object.fromEntries(headers);
|
|
19
|
+
if (Array.isArray(headers))
|
|
20
|
+
return Object.fromEntries(headers.map(([name, value]) => [name, value]));
|
|
21
|
+
return Object.fromEntries(Object.entries(headers ?? {}));
|
|
22
|
+
}
|
|
23
|
+
function hasHeader(record, name) {
|
|
24
|
+
const lower = name.toLowerCase();
|
|
25
|
+
return Object.keys(record).some((key) => key.toLowerCase() === lower);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Copy a person may see for a failed load. Route data is serialized to the
|
|
29
|
+
* browser, so the thrown error's own text (a credential resolution, a platform
|
|
30
|
+
* body, a transport message) never goes there: the failure is read as its typed
|
|
31
|
+
* `CapabilityError` code and the full cause goes to the request runtime's log.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* A failed load: rethrown for a strict route, otherwise reported once through
|
|
35
|
+
* the request runtime's logger and turned into safe copy for the route data.
|
|
36
|
+
*/
|
|
37
|
+
function reportLoadFailure(event, options, loaded, message) {
|
|
38
|
+
if (options.throwOnError)
|
|
39
|
+
throw loaded.failure;
|
|
40
|
+
const error = CapabilityError.from(loaded.failure);
|
|
41
|
+
const logger = getLogger('code-sessions:svelte-loaders', event.locals.runtime);
|
|
42
|
+
logger.warn(message, { error });
|
|
43
|
+
return loadFailureCopy(error);
|
|
44
|
+
}
|
|
45
|
+
function loadFailureCopy(err) {
|
|
46
|
+
switch (err.code) {
|
|
47
|
+
case 'AUTH_REQUIRED':
|
|
48
|
+
return 'Sign in to see your code sessions.';
|
|
49
|
+
case 'PERMISSION_DENIED':
|
|
50
|
+
return "You don't have access to these code sessions.";
|
|
51
|
+
case 'NOT_FOUND':
|
|
52
|
+
return "That code session wasn't found.";
|
|
53
|
+
case 'UNAVAILABLE':
|
|
54
|
+
case 'TIMEOUT':
|
|
55
|
+
case 'RATE_LIMITED':
|
|
56
|
+
return 'Code sessions are unavailable right now. Try again in a moment.';
|
|
57
|
+
default:
|
|
58
|
+
return 'Code sessions could not be loaded.';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function getBaseClient(event, client) {
|
|
62
|
+
if (client)
|
|
63
|
+
return client;
|
|
64
|
+
return getVibesClient('code-sessions', event.locals.runtime);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Resolve a request-scoped code-sessions client for SvelteKit server loaders
|
|
68
|
+
* and actions. The base runtime client remains a singleton; `forRequest(...)`
|
|
69
|
+
* carries the incoming Bearer/fetch/origin for this SSR request only.
|
|
70
|
+
*/
|
|
71
|
+
export async function resolveCodeSessionsRequestClient(event, options = {}) {
|
|
72
|
+
const base = await getBaseClient(event, options.client);
|
|
73
|
+
await base.ensureLoaded();
|
|
74
|
+
const headers = headersInitToRecord(options.headers);
|
|
75
|
+
const token = event.locals.sessionToken;
|
|
76
|
+
const hasExplicitAuthorization = hasHeader(headers, 'authorization');
|
|
77
|
+
if (token && !hasExplicitAuthorization) {
|
|
78
|
+
headers.Authorization = `Bearer ${token}`;
|
|
79
|
+
}
|
|
80
|
+
const overrides = { fetch: event.fetch };
|
|
81
|
+
if (options.platformOrigin)
|
|
82
|
+
overrides.origin = options.platformOrigin;
|
|
83
|
+
if (token && !hasExplicitAuthorization)
|
|
84
|
+
overrides.token = token;
|
|
85
|
+
if (Object.keys(headers).length > 0)
|
|
86
|
+
overrides.headers = headers;
|
|
87
|
+
const requestClient = base.forRequest(overrides);
|
|
88
|
+
if (requestClient !== base) {
|
|
89
|
+
await requestClient.ensureLoaded();
|
|
90
|
+
}
|
|
91
|
+
return requestClient;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Compose the code-sessions list payload for a SvelteKit `+page.server.ts` or
|
|
95
|
+
* `+layout.server.ts`. Consuming apps may spread the returned fields into their
|
|
96
|
+
* own route data and keep app-specific actions/copy local.
|
|
97
|
+
*/
|
|
98
|
+
export async function loadCodeSessionsLayoutData(event, options = {}) {
|
|
99
|
+
const loaded = await attempt(async () => {
|
|
100
|
+
const client = await resolveCodeSessionsRequestClient(event, options);
|
|
101
|
+
return client.list(options.listOptions);
|
|
102
|
+
});
|
|
103
|
+
if (loaded.ok)
|
|
104
|
+
return { sessions: loaded.value, sessionsError: null };
|
|
105
|
+
return { sessions: [], sessionsError: reportLoadFailure(event, options, loaded, 'code-session list load failed') };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Compose the single-session payload for detail pages. A missing or unauthorized
|
|
109
|
+
* session is represented as `session: null`; callers decide whether to redirect,
|
|
110
|
+
* render a not-found state, or preserve app-specific recovery UI.
|
|
111
|
+
*/
|
|
112
|
+
export async function loadCodeSessionDetailData(event, options) {
|
|
113
|
+
const sessionId = options.sessionId.trim();
|
|
114
|
+
if (!sessionId) {
|
|
115
|
+
return { session: null, sessionError: 'sessionId is required' };
|
|
116
|
+
}
|
|
117
|
+
const loaded = await attempt(async () => {
|
|
118
|
+
const client = await resolveCodeSessionsRequestClient(event, options);
|
|
119
|
+
return client.get(sessionId);
|
|
120
|
+
});
|
|
121
|
+
if (loaded.ok)
|
|
122
|
+
return { session: loaded.value, sessionError: null };
|
|
123
|
+
return { session: null, sessionError: reportLoadFailure(event, options, loaded, 'code-session detail load failed') };
|
|
124
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The package's two failure-carrying primitives: {@link readUntrusted}, the one
|
|
3
|
+
* guard untrusted values are read through, and {@link attempt}, the outcome
|
|
4
|
+
* helper that captures a failure once as a value for the caller to handle.
|
|
5
|
+
*
|
|
6
|
+
* It lives beside the Svelte helpers because `svelte-package` compiles only
|
|
7
|
+
* `src/svelte`; the core modules import it from here so there is one copy.
|
|
8
|
+
*
|
|
9
|
+
* The one guard this package reads untrusted values through.
|
|
10
|
+
*
|
|
11
|
+
* `safeParse` reports a bad shape as a result, but a value whose own getter
|
|
12
|
+
* throws, or a Proxy that traps or is revoked, throws out of the parse itself.
|
|
13
|
+
* {@link readUntrusted} settles all three into one result: the parsed copy, the
|
|
14
|
+
* shape refusal, or the read that threw (carried as `cause`). Callers use the
|
|
15
|
+
* parsed copy and never read the original again.
|
|
16
|
+
*
|
|
17
|
+
* Package-internal: not part of any export map.
|
|
18
|
+
*/
|
|
19
|
+
import { type CaughtFailure } from '@vibesdotdev/kernel';
|
|
20
|
+
import type * as z from 'zod/v4';
|
|
21
|
+
export type UntrustedRead<Output> = {
|
|
22
|
+
readonly outcome: 'parsed';
|
|
23
|
+
readonly data: Output;
|
|
24
|
+
} | {
|
|
25
|
+
readonly outcome: 'invalid';
|
|
26
|
+
readonly error: z.ZodError;
|
|
27
|
+
} | {
|
|
28
|
+
readonly outcome: 'threw';
|
|
29
|
+
readonly cause: CaughtFailure;
|
|
30
|
+
};
|
|
31
|
+
/** Anything a caller, a host or the network can hand over: what the guard reads exactly once. */
|
|
32
|
+
export type UntrustedValue = {} | null | undefined;
|
|
33
|
+
export declare function readUntrusted<Schema extends z.ZodType>(schema: Schema, value: UntrustedValue): UntrustedRead<z.output<Schema>>;
|
|
34
|
+
/** A step's outcome: its value, or its failure captured once as a value. */
|
|
35
|
+
export type Attempt<T> = {
|
|
36
|
+
readonly ok: true;
|
|
37
|
+
readonly value: T;
|
|
38
|
+
} | {
|
|
39
|
+
readonly ok: false;
|
|
40
|
+
readonly failure: CaughtFailure;
|
|
41
|
+
};
|
|
42
|
+
/** Run `work` and capture its value or its failure; the caller handles the failure (report, degrade or rethrow). */
|
|
43
|
+
export declare function attempt<T>(work: () => T | PromiseLike<T>): Promise<Attempt<T>>;
|
|
44
|
+
/** Run synchronous `work` and capture its value or its failure. */
|
|
45
|
+
export declare function attemptSync<T>(work: () => T): Attempt<T>;
|
|
46
|
+
//# sourceMappingURL=outcome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outcome.d.ts","sourceRoot":"","sources":["../../src/svelte/outcome.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,KAAK,KAAK,CAAC,MAAM,QAAQ,CAAC;AAEjC,MAAM,MAAM,aAAa,CAAC,MAAM,IAC7B;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;CAAE,CAAC;AAEhE,iGAAiG;AACjG,MAAM,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AAEnD,wBAAgB,aAAa,CAAC,MAAM,SAAS,CAAC,CAAC,OAAO,EACrD,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,cAAc,GACnB,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAUjC;AAED,4EAA4E;AAC5E,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;CAAE,CAAC;AAE5H,oHAAoH;AACpH,wBAAsB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAMpF;AAED,mEAAmE;AACnE,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAMxD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The package's two failure-carrying primitives: {@link readUntrusted}, the one
|
|
3
|
+
* guard untrusted values are read through, and {@link attempt}, the outcome
|
|
4
|
+
* helper that captures a failure once as a value for the caller to handle.
|
|
5
|
+
*
|
|
6
|
+
* It lives beside the Svelte helpers because `svelte-package` compiles only
|
|
7
|
+
* `src/svelte`; the core modules import it from here so there is one copy.
|
|
8
|
+
*
|
|
9
|
+
* The one guard this package reads untrusted values through.
|
|
10
|
+
*
|
|
11
|
+
* `safeParse` reports a bad shape as a result, but a value whose own getter
|
|
12
|
+
* throws, or a Proxy that traps or is revoked, throws out of the parse itself.
|
|
13
|
+
* {@link readUntrusted} settles all three into one result: the parsed copy, the
|
|
14
|
+
* shape refusal, or the read that threw (carried as `cause`). Callers use the
|
|
15
|
+
* parsed copy and never read the original again.
|
|
16
|
+
*
|
|
17
|
+
* Package-internal: not part of any export map.
|
|
18
|
+
*/
|
|
19
|
+
import { CaughtFailureSchema } from '@vibesdotdev/kernel';
|
|
20
|
+
export function readUntrusted(schema, value) {
|
|
21
|
+
let result;
|
|
22
|
+
try {
|
|
23
|
+
result = schema.safeParse(value);
|
|
24
|
+
}
|
|
25
|
+
catch (thrown) {
|
|
26
|
+
return { outcome: 'threw', cause: CaughtFailureSchema.parse(thrown) };
|
|
27
|
+
}
|
|
28
|
+
return result.success
|
|
29
|
+
? { outcome: 'parsed', data: result.data }
|
|
30
|
+
: { outcome: 'invalid', error: result.error };
|
|
31
|
+
}
|
|
32
|
+
/** Run `work` and capture its value or its failure; the caller handles the failure (report, degrade or rethrow). */
|
|
33
|
+
export async function attempt(work) {
|
|
34
|
+
try {
|
|
35
|
+
return { ok: true, value: await work() };
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
return { ok: false, failure: CaughtFailureSchema.parse(error) };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Run synchronous `work` and capture its value or its failure. */
|
|
42
|
+
export function attemptSync(work) {
|
|
43
|
+
try {
|
|
44
|
+
return { ok: true, value: work() };
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return { ok: false, failure: CaughtFailureSchema.parse(error) };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact relative-age formatting for code-session surfaces.
|
|
3
|
+
*
|
|
4
|
+
* Pure on purpose: `nowMs` is a parameter, never `Date.now()` read inside. The
|
|
5
|
+
* previous inline `formatAge` read the clock during render, so the label froze
|
|
6
|
+
* at first paint — a list tab left open reported "just now" for hours. Taking
|
|
7
|
+
* the clock as an argument makes the function testable AND lets the caller
|
|
8
|
+
* drive it from a ticking source (`sharedNow()`).
|
|
9
|
+
*
|
|
10
|
+
* `@vibesdotdev/kit`'s `formatRelativeTime` is deliberately NOT reused here: it
|
|
11
|
+
* renders the verbose form ("2 minutes ago") where these dense session rows
|
|
12
|
+
* need the compact form ("2m"), and it reads the clock internally, so it
|
|
13
|
+
* carries the same freeze.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Compact age label, e.g. `just now`, `12m ago`, `3h ago`, `5d ago`.
|
|
17
|
+
*
|
|
18
|
+
* An unparseable or future timestamp degrades to `just now` rather than
|
|
19
|
+
* rendering `NaNm ago` — a wrong-but-plausible label beats visible breakage in
|
|
20
|
+
* a metadata line, and the adjacent `<time datetime>` still carries the truth.
|
|
21
|
+
*/
|
|
22
|
+
export declare function formatRelativeAge(iso: string, nowMs?: number): string;
|
|
23
|
+
/**
|
|
24
|
+
* Absolute, locale-formatted timestamp for the `title` attribute that sits
|
|
25
|
+
* beside every relative label. The relative form is the scannable one; this is
|
|
26
|
+
* the one a user checks when the relative form is not precise enough.
|
|
27
|
+
*
|
|
28
|
+
* Returns `null` for an unparseable timestamp so callers can omit the attribute
|
|
29
|
+
* entirely instead of rendering the string "Invalid Date" as a tooltip.
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatAbsoluteTime(iso: string): string | null;
|
|
32
|
+
//# sourceMappingURL=relative-time.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relative-time.d.ts","sourceRoot":"","sources":["../../src/svelte/relative-time.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,MAAmB,GAAG,MAAM,CASjF;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI7D"}
|