@neta-art/cohub 5.1.1 → 5.3.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/dist/chunks/http.d.ts +52 -2
- package/dist/chunks/http.js +243 -13
- package/dist/chunks/transport.js +16 -3
- package/dist/chunks/websocket.d.ts +94 -4
- package/dist/chunks/websocket.js +1 -1
- package/dist/http.d.ts +2 -2
- package/dist/index.d.ts +100 -3
- package/dist/index.js +400 -40
- package/dist/protocol/dist/index.js +1 -0
- package/dist/protocol/dist/provenance.js +1 -0
- package/dist/protocol/dist/work-view-stats.js +2 -0
- package/docs/work-runtime-guide.md +32 -0
- package/package.json +1 -1
package/dist/chunks/http.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as CreateSpacePromptInput, $
|
|
1
|
+
import { $ as CreateSpacePromptInput, $n as SpaceFsTreeResponse, Ai as WorkContentKind, Ar as SpaceUsageResponse, At as Permission, Ba as ContentBlock, Bi as UiCommandError, Br as ChannelHealth, Bt as ReferenceAggregateGroupBy, Ca as MessageRecord, Ci as BoardAwarenessUpdate, Cn as SpaceCommerceBenefit, Ct as LabelResourceType, Da as SessionTurnRecord, Dn as SpaceCommerceOrder, Dt as ModelCatalogEntry, Er as SpaceTurnAuthorFilter, Et as MeResponse, Fn as SpaceCreateResponse, Fr as UserRulesResponse, Ft as PublicUserPageResponse, Gt as ReferenceQueryableType, Hi as UiCommandStatus, Hn as SpaceFsCreateUploadResponse, Ht as ReferenceDirection, Ia as SpaceCompletionResult, In as SpaceDefaultResponse, J as ClaimReferralResponse, Jn as SpaceFsMoveInput, Jt as ReferralDashboard, K as CheckpointDiffSummary, La as SpaceCompletionStreamEvent, Ln as SpaceEnvInput, Mn as SpaceConfigInput, Mr as TaskRunDetailResponse, Nn as SpaceConfigResponse, Nr as TaskRunRecord, Nt as PromptTemplateCatalogResponse, Oa as SpaceTurnsResponse, On as SpaceCommerceProduct, Ot as PatchResourceLabelsInput, Pa as CreateSpaceCompletionInput, Pn as SpaceConfigUpdateResponse, Pr as UserProfile, Pt as PublicReferral, Qi as BoardCapabilities, Qn as SpaceFsReadFilesResponse, R as Channel, Ra as Usage, Ri as UiCommand, Rn as SpaceFsCompleteUploadInput, Rr as UserSessionsResponse, Sa as SpacePublicEndpoints, Sn as SpaceCheckpointDetailResponse, Tr as SpaceSessionsResponse, Ut as ReferenceKind, V as CheckpointDiffFileResponse, Vi as UiCommandRecord, Vn as SpaceFsCreateUploadInput, Vt as ReferenceAggregateResponse, Wa as RequestSource, Wt as ReferenceQueryResponse, X as CreateInvitationResponse, Y as CreateInvitationInput, Yn as SpaceFsPreparingFile, Z as CreateSpaceInput, Zi as BoardBootstrap, _a as BoardTransaction, _r as SpacePresenceSnapshot, a as WebsocketClientOptions, an as SessionRecord, at as CursorPageInfo, br as SpaceRecord, ci as BoardTransactionAppliedEvent$1, cn as SessionTurnSignedUrlsResponse, d as BatchUserProfilesResponse, di as RealtimePatchOperation, dn as SessionTurnsPaginatedResponse, dt as GlobalSearchType, ea as BoardCreateInput, et as CreateSpacePromptResponse, fr as SpaceMember, ft as InvitationDetail, gn as SpaceAccessPolicy, gr as SpacePendingDiffSummary, hr as SpacePendingDiffFileResponse, ia as BoardInspectInput, ii as GenerationModelDeclaration, in as SessionMessagesResponse, it as CronJobUpdatePatch, kn as SpaceCommerceProductBenefitBinding, kt as PatchResourceLabelsResponse, l as AcceptInvitationResponse, ln as SessionTurnStreamSnapshotResponse, lr as SpaceInvitationListResponse, lt as GlobalSearchResponse, mr as SpaceModListItem, nn as SessionMessageResponse, oi as BoardAwarenessUpdatedEvent$1, on as SessionTurnIndexResponse, or as SpaceFsUploadResponse, pa as BoardPlaybackSnapshot, pn as SkillCatalogResponse, q as CheckpointRecord, qn as SpaceFsFileResponse, r as WebsocketClient, ri as GenerationContentBlock, rn as SessionMessagesPaginatedResponse, rt as CronJobRecord, s as WebsocketEventPayload, si as BoardPlaybackChangedEvent$1, sn as SessionTurnResponse, sr as SpaceFsWriteFileInput, tt as CreateSpaceSessionInput, ua as BoardPlaybackCommand, un as SessionTurnWindowResponse, va as BoardValidationResult, vi as SessionTurnPatchEvent, vt as LabelAssignmentRecord, wa as SessionForkRecord, wi as WorkArtifactDescriptor, wn as SpaceCommerceBuyerProfile, xr as SpaceRole, xt as LabelListItem, yr as SpacePublicProfile, yt as LabelItemsResponse, za as BillingPayload, zn as SpaceFsCompleteUploadResponse, zr as ChannelConfig } from "./websocket.js";
|
|
2
2
|
import { n as CohubEnvironment } from "./environment.js";
|
|
3
3
|
import { a as VoiceInputCreateOptions } from "./voice-input.js";
|
|
4
4
|
//#region ../protocol/dist/model/status.d.ts
|
|
@@ -1616,6 +1616,37 @@ declare class TasksApi {
|
|
|
1616
1616
|
}>;
|
|
1617
1617
|
}
|
|
1618
1618
|
//#endregion
|
|
1619
|
+
//#region src/apis/ui-commands.d.ts
|
|
1620
|
+
type CreateUiCommandInput = {
|
|
1621
|
+
command: UiCommand;
|
|
1622
|
+
commandId?: string;
|
|
1623
|
+
targetClientId?: string;
|
|
1624
|
+
};
|
|
1625
|
+
type WaitForUiCommandOptions = {
|
|
1626
|
+
timeoutMs?: number;
|
|
1627
|
+
pollIntervalMs?: number;
|
|
1628
|
+
signal?: AbortSignal;
|
|
1629
|
+
};
|
|
1630
|
+
declare class UiCommandsApi {
|
|
1631
|
+
private readonly transport;
|
|
1632
|
+
constructor(transport: HttpTransport);
|
|
1633
|
+
create(input: CreateUiCommandInput): Promise<{
|
|
1634
|
+
command: UiCommandRecord;
|
|
1635
|
+
}>;
|
|
1636
|
+
get(commandId: string): Promise<{
|
|
1637
|
+
command: UiCommandRecord;
|
|
1638
|
+
}>;
|
|
1639
|
+
reportResult(commandId: string, input: {
|
|
1640
|
+
status: UiCommandStatus;
|
|
1641
|
+
result?: unknown;
|
|
1642
|
+
error?: UiCommandError | null;
|
|
1643
|
+
}): Promise<{
|
|
1644
|
+
command: UiCommandRecord;
|
|
1645
|
+
}>;
|
|
1646
|
+
run(input: CreateUiCommandInput, options?: WaitForUiCommandOptions): Promise<UiCommandRecord>;
|
|
1647
|
+
wait(commandId: string, options?: WaitForUiCommandOptions): Promise<UiCommandRecord>;
|
|
1648
|
+
}
|
|
1649
|
+
//#endregion
|
|
1619
1650
|
//#region src/apis/user.d.ts
|
|
1620
1651
|
declare class UserApi {
|
|
1621
1652
|
private readonly transport;
|
|
@@ -1831,6 +1862,23 @@ type WorkDetailResponse = {
|
|
|
1831
1862
|
};
|
|
1832
1863
|
type WorkGetResponse = WorkDetailResponse;
|
|
1833
1864
|
type WorkResolveResponse = WorkDetailResponse;
|
|
1865
|
+
type WorkViewSource = "web" | "cli" | "api";
|
|
1866
|
+
type WorkViewStatsResponse = {
|
|
1867
|
+
summary: {
|
|
1868
|
+
totalViews: number;
|
|
1869
|
+
views24h: number;
|
|
1870
|
+
views7d: number;
|
|
1871
|
+
views30d: number;
|
|
1872
|
+
};
|
|
1873
|
+
daily: Array<{
|
|
1874
|
+
date: string;
|
|
1875
|
+
views: number;
|
|
1876
|
+
}>;
|
|
1877
|
+
sources: Array<{
|
|
1878
|
+
source: WorkViewSource;
|
|
1879
|
+
views: number;
|
|
1880
|
+
}>;
|
|
1881
|
+
};
|
|
1834
1882
|
type WorkSessionResponse = {
|
|
1835
1883
|
token: string;
|
|
1836
1884
|
expiresIn: number;
|
|
@@ -1869,6 +1917,7 @@ declare class WorksApi {
|
|
|
1869
1917
|
delete(id: string): Promise<{
|
|
1870
1918
|
ok: true;
|
|
1871
1919
|
}>;
|
|
1920
|
+
getStats(workId: string): Promise<WorkViewStatsResponse>;
|
|
1872
1921
|
listVersions(workId: string): Promise<{
|
|
1873
1922
|
versions: WorkVersionRecord[];
|
|
1874
1923
|
}>;
|
|
@@ -1973,10 +2022,11 @@ declare class CohubHttpClient {
|
|
|
1973
2022
|
readonly referrals: ReferralsApi;
|
|
1974
2023
|
readonly works: WorksApi;
|
|
1975
2024
|
readonly workCommerce: WorkCommerceApi;
|
|
2025
|
+
readonly ui: UiCommandsApi;
|
|
1976
2026
|
private readonly transport;
|
|
1977
2027
|
constructor(options?: CohubClientOptions);
|
|
1978
2028
|
space(spaceId: string): SpaceClient;
|
|
1979
2029
|
}
|
|
1980
2030
|
declare const createHttpClient: (options?: CohubClientOptions) => CohubHttpClient;
|
|
1981
2031
|
//#endregion
|
|
1982
|
-
export {
|
|
2032
|
+
export { SpaceEventName as $, RawHttpResponse as $t, WorkViewSource as A, ReferenceResourceSelector as At, TasksApi as B, UploadChatAttachmentInput as Bt, WorkRecord as C, ModelStatusEntry as Cn, SessionPatchApplyInput as Ct, WorkTargetType as D, SessionPatchStatus as Dt, WorkStatus as E, SessionPatchState as Et, UsersApi as F, PublicAssetMimeType as Ft, BoardSubscriptionHandlers as G, ModelsApi as Gt, BoardClient as H, UploadPublicAssetInput as Ht, UserApi as I, PublicAssetPurpose as It, BoardTransactionInput as J, ChannelsApi as Jt, BoardTransactionAppliedEvent as K, GenerationsApi as Kt, CreateUiCommandInput as L, PublicAssetUploadProgress as Lt, WorkVisibility as M, SearchApi as Mt, WorksApi as N, CreatePublicAssetUploadInput as Nt, WorkUpdateInput as O, createSessionPatchReducer as Ot, ReferralsApi as P, CreatePublicAssetUploadResponse as Pt, SpaceClient as Q, HttpTransport as Qt, UiCommandsApi as R, PublicAssetUploadProtocol as Rt, WorkPublicSpaceRecord as S, PublicGenerationDeclaration as Sn, parseAssistantMessageCommit as St, WorkSessionResponse as T, SessionPatchReducer as Tt, BoardEventName as U, SkillsApi as Ut, BoardAwarenessUpdatedEvent as V, UploadChatImageAttachmentInput as Vt, BoardPlaybackChangedEvent as W, PromptsApi as Wt, SessionSubscriptionHandlers as X, Fetch as Xt, SessionEventName as Y, CohubClientOptions as Yt, SpaceChannelBindingRecord as Z, HttpError as Zt, WorkExtractedPageMeta as _, CreateGenerationTaskRequest as _n, GenerationStreamSubscribeOptions as _t, WorkCommerceCreditConsumeResponse as a, WorkIdResolver as an, PublicInviteApi as at, WorkPresentationMeta as b, GenerationUsageBilling as bn, SessionGenerationStreamClient as bt, WorkCommerceEntitlementsResponse as c, WorkRuntimeCheckoutStatus as cn, AssistantMessageCommit as ct, WorkCommercePurchaseResponse as d, WorkRuntimeRequestOptions as dn, GenerationStreamEvent as dt, joinApiUrl as en, SpaceTurnListOptions as et, WorkAuthorizeResponse as f, WorkRuntimeTransport as fn, GenerationStreamFinalizedEvent as ft, WorkDetailResponse as g, SpaceStartupResponse as gn, GenerationStreamStateEvent as gt, WorkCreateInput as h, resolveWorkTransport as hn, GenerationStreamOutOfSyncEvent as ht, WorkCommerceCheckoutStatus as i, PopupBrokerTransport as in, BuildSpacePathInput as it, WorkViewStatsResponse as j, ReferencesApi as jt, WorkVersionRecord as k, SessionAccessApi as kt, WorkCommerceOrder as l, WorkRuntimeContext as ln, GenerationStreamCommitEvent as lt, WorkContentDownload as m, createWorkRuntime as mn, GenerationStreamLifecycleEvent as mt, createHttpClient as n, sanitizeAccessToken as nn, WebSocketConnectionState as nt, WorkCommerceCreditConsumeStatus as o, WorkRuntimeApi as on, buildSpaceInvitePath as ot, WorkContent as p, createSlugWorkIdResolver as pn, GenerationStreamIntermediateMessage as pt, BoardTransactionError as q, CronJobsApi as qt, WorkCommerceApi as r, ParentBridgeTransport as rn, BuildSpaceInvitePathInput as rt, WorkCommerceEntitlement as s, WorkRuntimeCheckoutState as sn, buildSpacePath as st, CohubHttpClient as t, matchesUnauthorizedErrorToken as tn, SpacesApi as tt, WorkCommerceProductResolveResponse as u, WorkRuntimeModeConfig as un, GenerationStreamErrorEvent as ut, WorkGetResponse as v, CreateGenerationTaskResponse as vn, GenerationStreamSubscriptionHandlers as vt, WorkResolveResponse as w, ModelStatusResponse as wn, SessionPatchApplyResult as wt, WorkPublicOwnerRecord as x, ListGenerationModelsResponse as xn, createSessionGenerationStreamClient as xt, WorkMeta as y, GenerationTaskResult as yn, GenerationStreamTurnUpdatedEvent as yt, WaitForUiCommandOptions as z, PublicAssetsApi as zt };
|
package/dist/chunks/http.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { E as getRealtimeSpaceRoom, T as getRealtimeBoardRoom, n as HttpTransport, t as HttpError } from "./transport.js";
|
|
2
2
|
import { a as resolveApiBaseUrl } from "./environment.js";
|
|
3
3
|
//#region src/apis/channels.ts
|
|
4
4
|
var ChannelsApi = class {
|
|
@@ -82,7 +82,7 @@ var CronJobsApi = class {
|
|
|
82
82
|
//#region src/apis/generations.ts
|
|
83
83
|
const DEFAULT_INTERVAL_MS = 1500;
|
|
84
84
|
const DEFAULT_TIMEOUT_MS = 1800 * 1e3;
|
|
85
|
-
function sleep(ms, signal) {
|
|
85
|
+
function sleep$1(ms, signal) {
|
|
86
86
|
if (signal?.aborted) return Promise.reject(signal.reason ?? /* @__PURE__ */ new Error("Generation wait aborted"));
|
|
87
87
|
return new Promise((resolve, reject) => {
|
|
88
88
|
const cleanup = () => signal?.removeEventListener("abort", onAbort);
|
|
@@ -147,7 +147,7 @@ var GenerationsApi = class {
|
|
|
147
147
|
}
|
|
148
148
|
const remainingMs = timeoutMs - (Date.now() - startedAt);
|
|
149
149
|
if (remainingMs <= 0) throw new Error(`Generation task timed out after ${timeoutMs}ms`);
|
|
150
|
-
await sleep(Math.min(intervalMs, remainingMs), options.signal);
|
|
150
|
+
await sleep$1(Math.min(intervalMs, remainingMs), options.signal);
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
async createAndWait(request, options) {
|
|
@@ -847,8 +847,8 @@ const createSessionPatchReducer = () => new SessionPatchReducer();
|
|
|
847
847
|
//#region src/session-generation-stream.ts
|
|
848
848
|
const SNAPSHOT_RECOVERY_TIMEOUT_MS = 2500;
|
|
849
849
|
const SNAPSHOT_RECOVERY_MAX_BUFFERED_EVENTS = 256;
|
|
850
|
-
const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
851
|
-
const isContentBlockArray = (value) => Array.isArray(value) && value.every((item) => isRecord(item) && typeof item.type === "string");
|
|
850
|
+
const isRecord$1 = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
851
|
+
const isContentBlockArray = (value) => Array.isArray(value) && value.every((item) => isRecord$1(item) && typeof item.type === "string");
|
|
852
852
|
const getMessageKind = (message) => {
|
|
853
853
|
const kind = message.meta?.messageKind;
|
|
854
854
|
return typeof kind === "string" ? kind : null;
|
|
@@ -888,7 +888,7 @@ function parseAssistantMessageCommit(message) {
|
|
|
888
888
|
}
|
|
889
889
|
function messageRecordToIntermediate(message) {
|
|
890
890
|
if (!isContentBlockArray(message.content) || message.content.length === 0) return null;
|
|
891
|
-
const meta = isRecord(message.meta) ? message.meta : {};
|
|
891
|
+
const meta = isRecord$1(message.meta) ? message.meta : {};
|
|
892
892
|
return {
|
|
893
893
|
id: message.id,
|
|
894
894
|
sessionId: message.sessionId,
|
|
@@ -1006,9 +1006,9 @@ function mergeMessagesSharingToolUseId(messages) {
|
|
|
1006
1006
|
return merged;
|
|
1007
1007
|
}
|
|
1008
1008
|
function getCompactionPlacement(message) {
|
|
1009
|
-
const meta = isRecord(message.meta) ? message.meta : null;
|
|
1010
|
-
const compaction = isRecord(meta?.compaction) ? meta.compaction : null;
|
|
1011
|
-
const placement = isRecord(compaction?.placement) ? compaction.placement : null;
|
|
1009
|
+
const meta = isRecord$1(message.meta) ? message.meta : null;
|
|
1010
|
+
const compaction = isRecord$1(meta?.compaction) ? meta.compaction : null;
|
|
1011
|
+
const placement = isRecord$1(compaction?.placement) ? compaction.placement : null;
|
|
1012
1012
|
return meta?.messageKind === "compacted" ? {
|
|
1013
1013
|
beforeMessageId: typeof placement?.beforeMessageId === "string" ? placement.beforeMessageId : null,
|
|
1014
1014
|
sequence: typeof message.sequence === "number" ? message.sequence : null
|
|
@@ -1282,7 +1282,7 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
|
|
|
1282
1282
|
}
|
|
1283
1283
|
handlePersisted(event, handlers) {
|
|
1284
1284
|
const message = event.payload.message;
|
|
1285
|
-
if (!isRecord(message)) return;
|
|
1285
|
+
if (!isRecord$1(message)) return;
|
|
1286
1286
|
const commit = parseAssistantMessageCommit(message);
|
|
1287
1287
|
if (commit.kind === "intermediate") {
|
|
1288
1288
|
const intermediate = messageRecordToIntermediate(commit.message);
|
|
@@ -1317,7 +1317,7 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
|
|
|
1317
1317
|
}
|
|
1318
1318
|
handleFinalized(event, handlers) {
|
|
1319
1319
|
const turn = event.payload.turn;
|
|
1320
|
-
if (!isRecord(turn)) return;
|
|
1320
|
+
if (!isRecord$1(turn)) return;
|
|
1321
1321
|
const typedTurn = turn;
|
|
1322
1322
|
if (typedTurn.status === "interrupted") this.reducer.interrupt({
|
|
1323
1323
|
spaceId: this.spaceId,
|
|
@@ -1349,7 +1349,7 @@ var SessionGenerationStreamClient = class SessionGenerationStreamClient {
|
|
|
1349
1349
|
return;
|
|
1350
1350
|
case "session.turn.updated": {
|
|
1351
1351
|
const turn = event.payload.turn;
|
|
1352
|
-
if (!isRecord(turn)) return;
|
|
1352
|
+
if (!isRecord$1(turn)) return;
|
|
1353
1353
|
this.emit(handlers, {
|
|
1354
1354
|
type: "turn_updated",
|
|
1355
1355
|
turn,
|
|
@@ -2863,6 +2863,231 @@ var TasksApi = class {
|
|
|
2863
2863
|
}
|
|
2864
2864
|
};
|
|
2865
2865
|
//#endregion
|
|
2866
|
+
//#region ../protocol/dist/ui-command.js
|
|
2867
|
+
/**
|
|
2868
|
+
* Lets an agent drive the Cohub frontend that originated the work. Routing comes
|
|
2869
|
+
* from request provenance, never a caller-supplied target, so a command only
|
|
2870
|
+
* reaches the actor's own instances.
|
|
2871
|
+
*/
|
|
2872
|
+
const UI_COMMAND_VERSION = 1;
|
|
2873
|
+
/** Persisted and broadcast, so every field is capped; MAX_BYTES bounds the whole. */
|
|
2874
|
+
const UI_COMMAND_PAYLOAD_MAX_BYTES = 32 * 1024;
|
|
2875
|
+
const UI_COMMAND_MAX_BYTES = 40 * 1024;
|
|
2876
|
+
const UI_COMMAND_LAUNCH_MAX_LENGTH = 2048;
|
|
2877
|
+
const UI_COMMAND_DEFAULT_TIMEOUT_MS = 600 * 1e3;
|
|
2878
|
+
const UI_COMMAND_MAX_TIMEOUT_MS = 720 * 60 * 1e3;
|
|
2879
|
+
const UI_COMMAND_SETTLEMENT_GRACE_SECONDS = 600;
|
|
2880
|
+
/** Keeps pending commands reportable for the full wait window plus settlement grace. */
|
|
2881
|
+
const UI_COMMAND_PENDING_TTL_SECONDS = 43800;
|
|
2882
|
+
const UI_COMMAND_TERMINAL_TTL_SECONDS = 1800;
|
|
2883
|
+
const UI_COMMAND_TERMINAL_STATUSES = [
|
|
2884
|
+
"applied",
|
|
2885
|
+
"no_active_client",
|
|
2886
|
+
"ui_host_unavailable",
|
|
2887
|
+
"rejected",
|
|
2888
|
+
"unsupported",
|
|
2889
|
+
"timeout"
|
|
2890
|
+
];
|
|
2891
|
+
const isTerminalUiCommandStatus = (status) => UI_COMMAND_TERMINAL_STATUSES.includes(status);
|
|
2892
|
+
const METHOD_RE = /^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/;
|
|
2893
|
+
const isUiSurfaceMethod = (value) => typeof value === "string" && METHOD_RE.test(value);
|
|
2894
|
+
const WORK_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
2895
|
+
const UI_COMMAND_ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
2896
|
+
const parseUiCommandId = (value) => {
|
|
2897
|
+
if (typeof value !== "string") return null;
|
|
2898
|
+
const trimmed = value.trim();
|
|
2899
|
+
return UI_COMMAND_ID_RE.test(trimmed) ? trimmed : null;
|
|
2900
|
+
};
|
|
2901
|
+
const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
2902
|
+
const asTrimmed = (value) => {
|
|
2903
|
+
if (typeof value !== "string") return null;
|
|
2904
|
+
const trimmed = value.trim();
|
|
2905
|
+
return trimmed ? trimmed : null;
|
|
2906
|
+
};
|
|
2907
|
+
const parseLaunch = (value) => {
|
|
2908
|
+
if (!isRecord(value)) return void 0;
|
|
2909
|
+
const search = asTrimmed(value.search);
|
|
2910
|
+
const hash = asTrimmed(value.hash);
|
|
2911
|
+
if (!search && !hash) return void 0;
|
|
2912
|
+
return {
|
|
2913
|
+
...search ? { search: search.startsWith("?") ? search : `?${search}` } : {},
|
|
2914
|
+
...hash ? { hash: hash.startsWith("#") ? hash : `#${hash}` } : {}
|
|
2915
|
+
};
|
|
2916
|
+
};
|
|
2917
|
+
const measureUiCommandPayload = (value) => {
|
|
2918
|
+
if (value === void 0) return 0;
|
|
2919
|
+
try {
|
|
2920
|
+
return new TextEncoder().encode(JSON.stringify(value) ?? "").length;
|
|
2921
|
+
} catch {
|
|
2922
|
+
return null;
|
|
2923
|
+
}
|
|
2924
|
+
};
|
|
2925
|
+
const parseUiCommand = (input) => {
|
|
2926
|
+
if (!isRecord(input)) return {
|
|
2927
|
+
command: null,
|
|
2928
|
+
error: "command must be an object"
|
|
2929
|
+
};
|
|
2930
|
+
if (input.type !== "preview.show") return {
|
|
2931
|
+
command: null,
|
|
2932
|
+
error: "command.type must be one of: preview.show"
|
|
2933
|
+
};
|
|
2934
|
+
const preview = input.preview;
|
|
2935
|
+
if (!isRecord(preview)) return {
|
|
2936
|
+
command: null,
|
|
2937
|
+
error: "command.preview is required"
|
|
2938
|
+
};
|
|
2939
|
+
if (preview.kind !== "work") return {
|
|
2940
|
+
command: null,
|
|
2941
|
+
error: "command.preview.kind must be one of: work"
|
|
2942
|
+
};
|
|
2943
|
+
const workId = asTrimmed(preview.workId);
|
|
2944
|
+
if (!workId) return {
|
|
2945
|
+
command: null,
|
|
2946
|
+
error: "command.preview.workId is required"
|
|
2947
|
+
};
|
|
2948
|
+
if (!WORK_ID_RE.test(workId)) return {
|
|
2949
|
+
command: null,
|
|
2950
|
+
error: "command.preview.workId must be a Work id"
|
|
2951
|
+
};
|
|
2952
|
+
const label = asTrimmed(preview.label);
|
|
2953
|
+
if (label && label.length > 200) return {
|
|
2954
|
+
command: null,
|
|
2955
|
+
error: `command.preview.label exceeds 200 characters`
|
|
2956
|
+
};
|
|
2957
|
+
const launch = parseLaunch(preview.launch);
|
|
2958
|
+
if (launch) {
|
|
2959
|
+
for (const [field, value] of [["search", launch.search], ["hash", launch.hash]]) if (value && value.length > 2048) return {
|
|
2960
|
+
command: null,
|
|
2961
|
+
error: `command.preview.launch.${field} exceeds ${UI_COMMAND_LAUNCH_MAX_LENGTH} characters`
|
|
2962
|
+
};
|
|
2963
|
+
}
|
|
2964
|
+
let request;
|
|
2965
|
+
if (input.request !== void 0 && input.request !== null) {
|
|
2966
|
+
if (!isRecord(input.request)) return {
|
|
2967
|
+
command: null,
|
|
2968
|
+
error: "command.request must be an object"
|
|
2969
|
+
};
|
|
2970
|
+
const method = asTrimmed(input.request.method);
|
|
2971
|
+
if (!method) return {
|
|
2972
|
+
command: null,
|
|
2973
|
+
error: "command.request.method is required"
|
|
2974
|
+
};
|
|
2975
|
+
if (!isUiSurfaceMethod(method)) return {
|
|
2976
|
+
command: null,
|
|
2977
|
+
error: "command.request.method has an unsupported format"
|
|
2978
|
+
};
|
|
2979
|
+
const size = measureUiCommandPayload(input.request.input);
|
|
2980
|
+
if (size === null) return {
|
|
2981
|
+
command: null,
|
|
2982
|
+
error: "command.request.input must be JSON-serializable"
|
|
2983
|
+
};
|
|
2984
|
+
if (size > 32768) return {
|
|
2985
|
+
command: null,
|
|
2986
|
+
error: `command.request.input exceeds ${UI_COMMAND_PAYLOAD_MAX_BYTES} bytes`
|
|
2987
|
+
};
|
|
2988
|
+
request = {
|
|
2989
|
+
method,
|
|
2990
|
+
...input.request.input === void 0 ? {} : { input: input.request.input }
|
|
2991
|
+
};
|
|
2992
|
+
}
|
|
2993
|
+
const command = {
|
|
2994
|
+
type: "preview.show",
|
|
2995
|
+
preview: {
|
|
2996
|
+
kind: "work",
|
|
2997
|
+
workId,
|
|
2998
|
+
...label ? { label } : {},
|
|
2999
|
+
...launch ? { launch } : {}
|
|
3000
|
+
},
|
|
3001
|
+
...request ? { request } : {}
|
|
3002
|
+
};
|
|
3003
|
+
const totalSize = measureUiCommandPayload(command);
|
|
3004
|
+
if (totalSize === null) return {
|
|
3005
|
+
command: null,
|
|
3006
|
+
error: "command must be JSON-serializable"
|
|
3007
|
+
};
|
|
3008
|
+
if (totalSize > 40960) return {
|
|
3009
|
+
command: null,
|
|
3010
|
+
error: `command exceeds ${UI_COMMAND_MAX_BYTES} bytes`
|
|
3011
|
+
};
|
|
3012
|
+
return {
|
|
3013
|
+
command,
|
|
3014
|
+
error: null
|
|
3015
|
+
};
|
|
3016
|
+
};
|
|
3017
|
+
//#endregion
|
|
3018
|
+
//#region src/apis/ui-commands.ts
|
|
3019
|
+
const DEFAULT_POLL_INTERVAL_MS = 300;
|
|
3020
|
+
const resolveTimeoutMs = (timeoutMs) => {
|
|
3021
|
+
const value = timeoutMs ?? 6e5;
|
|
3022
|
+
if (!Number.isFinite(value) || value <= 0 || value > 432e5) throw new RangeError(`timeoutMs must be between 1 and ${UI_COMMAND_MAX_TIMEOUT_MS} milliseconds`);
|
|
3023
|
+
return value;
|
|
3024
|
+
};
|
|
3025
|
+
const sleep = (ms, signal) => new Promise((resolve, reject) => {
|
|
3026
|
+
if (signal?.aborted) {
|
|
3027
|
+
reject(/* @__PURE__ */ new Error("aborted"));
|
|
3028
|
+
return;
|
|
3029
|
+
}
|
|
3030
|
+
const timer = setTimeout(() => {
|
|
3031
|
+
signal?.removeEventListener("abort", onAbort);
|
|
3032
|
+
resolve();
|
|
3033
|
+
}, ms);
|
|
3034
|
+
const onAbort = () => {
|
|
3035
|
+
clearTimeout(timer);
|
|
3036
|
+
reject(/* @__PURE__ */ new Error("aborted"));
|
|
3037
|
+
};
|
|
3038
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
3039
|
+
});
|
|
3040
|
+
var UiCommandsApi = class {
|
|
3041
|
+
transport;
|
|
3042
|
+
constructor(transport) {
|
|
3043
|
+
this.transport = transport;
|
|
3044
|
+
}
|
|
3045
|
+
create(input) {
|
|
3046
|
+
return this.transport.request("/api/ui/commands", {
|
|
3047
|
+
method: "POST",
|
|
3048
|
+
headers: { "Content-Type": "application/json" },
|
|
3049
|
+
body: JSON.stringify(input)
|
|
3050
|
+
});
|
|
3051
|
+
}
|
|
3052
|
+
get(commandId) {
|
|
3053
|
+
return this.transport.request(`/api/ui/commands/${encodeURIComponent(commandId)}`);
|
|
3054
|
+
}
|
|
3055
|
+
reportResult(commandId, input) {
|
|
3056
|
+
return this.transport.request(`/api/ui/commands/${encodeURIComponent(commandId)}/result`, {
|
|
3057
|
+
method: "POST",
|
|
3058
|
+
headers: { "Content-Type": "application/json" },
|
|
3059
|
+
body: JSON.stringify(input)
|
|
3060
|
+
});
|
|
3061
|
+
}
|
|
3062
|
+
async run(input, options = {}) {
|
|
3063
|
+
const { command } = await this.create(input);
|
|
3064
|
+
if (isTerminalUiCommandStatus(command.status)) return command;
|
|
3065
|
+
return this.wait(command.commandId, options);
|
|
3066
|
+
}
|
|
3067
|
+
async wait(commandId, options = {}) {
|
|
3068
|
+
const timeoutMs = resolveTimeoutMs(options.timeoutMs);
|
|
3069
|
+
const pollIntervalMs = Math.max(50, options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
|
|
3070
|
+
const deadline = Date.now() + timeoutMs;
|
|
3071
|
+
let latest = (await this.get(commandId)).command;
|
|
3072
|
+
while (!isTerminalUiCommandStatus(latest.status)) {
|
|
3073
|
+
const remaining = deadline - Date.now();
|
|
3074
|
+
if (remaining <= 0) break;
|
|
3075
|
+
await sleep(Math.min(pollIntervalMs, remaining), options.signal);
|
|
3076
|
+
latest = (await this.get(commandId)).command;
|
|
3077
|
+
}
|
|
3078
|
+
if (isTerminalUiCommandStatus(latest.status)) return latest;
|
|
3079
|
+
return {
|
|
3080
|
+
...latest,
|
|
3081
|
+
status: "timeout",
|
|
3082
|
+
error: {
|
|
3083
|
+
code: "timeout",
|
|
3084
|
+
message: "No Cohub frontend reported a result before the timeout."
|
|
3085
|
+
},
|
|
3086
|
+
settledAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3087
|
+
};
|
|
3088
|
+
}
|
|
3089
|
+
};
|
|
3090
|
+
//#endregion
|
|
2866
3091
|
//#region src/apis/user.ts
|
|
2867
3092
|
var UserApi = class {
|
|
2868
3093
|
transport;
|
|
@@ -3024,6 +3249,9 @@ var WorksApi = class {
|
|
|
3024
3249
|
delete(id) {
|
|
3025
3250
|
return this.transport.request(`/api/works/${id}`, { method: "DELETE" });
|
|
3026
3251
|
}
|
|
3252
|
+
getStats(workId) {
|
|
3253
|
+
return this.transport.request(`/api/works/${workId}/stats`);
|
|
3254
|
+
}
|
|
3027
3255
|
listVersions(workId) {
|
|
3028
3256
|
return this.transport.request(`/api/works/${workId}/versions`);
|
|
3029
3257
|
}
|
|
@@ -3101,6 +3329,7 @@ var CohubHttpClient = class {
|
|
|
3101
3329
|
referrals;
|
|
3102
3330
|
works;
|
|
3103
3331
|
workCommerce;
|
|
3332
|
+
ui;
|
|
3104
3333
|
transport;
|
|
3105
3334
|
constructor(options = {}) {
|
|
3106
3335
|
const apiBaseUrl = resolveApiBaseUrl(options);
|
|
@@ -3123,6 +3352,7 @@ var CohubHttpClient = class {
|
|
|
3123
3352
|
this.referrals = new ReferralsApi(this.transport);
|
|
3124
3353
|
this.works = new WorksApi(this.transport);
|
|
3125
3354
|
this.workCommerce = new WorkCommerceApi(this.transport);
|
|
3355
|
+
this.ui = new UiCommandsApi(this.transport);
|
|
3126
3356
|
}
|
|
3127
3357
|
space(spaceId) {
|
|
3128
3358
|
return new SpaceClient(spaceId, this.transport, null);
|
|
@@ -3130,4 +3360,4 @@ var CohubHttpClient = class {
|
|
|
3130
3360
|
};
|
|
3131
3361
|
const createHttpClient = (options) => new CohubHttpClient(options);
|
|
3132
3362
|
//#endregion
|
|
3133
|
-
export {
|
|
3363
|
+
export { parseAssistantMessageCommit as A, ModelsApi as B, SpaceClient as C, buildSpacePath as D, buildSpaceInvitePath as E, ReferencesApi as F, CronJobsApi as H, SearchApi as I, PublicAssetsApi as L, createSessionPatchReducer as M, ensureRealtimeConnected as N, SessionGenerationStreamClient as O, SessionAccessApi as P, SkillsApi as R, BoardTransactionError as S, PublicInviteApi as T, ChannelsApi as U, GenerationsApi as V, isUiSurfaceMethod as _, ReferralsApi as a, TasksApi as b, UiCommandsApi as c, UI_COMMAND_PAYLOAD_MAX_BYTES as d, UI_COMMAND_PENDING_TTL_SECONDS as f, isTerminalUiCommandStatus as g, UI_COMMAND_VERSION as h, WorksApi as i, SessionPatchReducer as j, createSessionGenerationStreamClient as k, UI_COMMAND_DEFAULT_TIMEOUT_MS as l, UI_COMMAND_TERMINAL_TTL_SECONDS as m, createHttpClient as n, UsersApi as o, UI_COMMAND_SETTLEMENT_GRACE_SECONDS as p, WorkCommerceApi as r, UserApi as s, CohubHttpClient as t, UI_COMMAND_MAX_TIMEOUT_MS as u, parseUiCommand as v, SpacesApi as w, BoardClient as x, parseUiCommandId as y, PromptsApi as z };
|
package/dist/chunks/transport.js
CHANGED
|
@@ -49,11 +49,15 @@ const COHUB_SOURCE_HEADER = {
|
|
|
49
49
|
session: "X-Cohub-Source-Session",
|
|
50
50
|
turn: "X-Cohub-Source-Turn",
|
|
51
51
|
toolCall: "X-Cohub-Source-Tool-Call",
|
|
52
|
+
client: "X-Cohub-Source-Client",
|
|
52
53
|
via: "X-Cohub-Source-Via"
|
|
53
54
|
};
|
|
54
55
|
const UUID_RE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
55
56
|
const isRequestSourceUuid = (value) => typeof value === "string" && UUID_RE.test(value);
|
|
56
57
|
const REQUEST_SOURCE_VIA_MAX_LENGTH = 64;
|
|
58
|
+
/** Opaque, url-safe client instance id. */
|
|
59
|
+
const CLIENT_ID_RE = /^[A-Za-z0-9_-]{8,64}$/;
|
|
60
|
+
const isRequestSourceClientId = (value) => typeof value === "string" && CLIENT_ID_RE.test(value);
|
|
57
61
|
/** Remove C0 controls and DEL without a control-char regex (biome-friendly). */
|
|
58
62
|
const stripControlChars = (value) => {
|
|
59
63
|
let out = "";
|
|
@@ -77,13 +81,17 @@ const asVia = (value) => {
|
|
|
77
81
|
if (!cleaned) return void 0;
|
|
78
82
|
return cleaned.slice(0, 64);
|
|
79
83
|
};
|
|
84
|
+
const asClientId = (value) => {
|
|
85
|
+
const cleaned = asNonEmpty(value);
|
|
86
|
+
return cleaned && isRequestSourceClientId(cleaned) ? cleaned : void 0;
|
|
87
|
+
};
|
|
80
88
|
const isRequestSourceEmpty = (source) => {
|
|
81
89
|
if (!source) return true;
|
|
82
|
-
return !source.spaceId && !source.sessionId && !source.turnId && !source.toolCallId && !source.via;
|
|
90
|
+
return !source.spaceId && !source.sessionId && !source.turnId && !source.toolCallId && !source.clientId && !source.via;
|
|
83
91
|
};
|
|
84
92
|
const hasRequestSourceIdentity = (source) => {
|
|
85
93
|
if (!source) return false;
|
|
86
|
-
return Boolean(source.spaceId || source.sessionId || source.turnId || source.toolCallId);
|
|
94
|
+
return Boolean(source.spaceId || source.sessionId || source.turnId || source.toolCallId || source.clientId);
|
|
87
95
|
};
|
|
88
96
|
/** Drop invalid UUIDs; via-only is valid. */
|
|
89
97
|
const normalizeRequestSource = (input) => {
|
|
@@ -93,12 +101,14 @@ const normalizeRequestSource = (input) => {
|
|
|
93
101
|
const sessionId = asUuid(record.sessionId);
|
|
94
102
|
const turnId = asUuid(record.turnId);
|
|
95
103
|
const toolCallId = asUuid(record.toolCallId);
|
|
104
|
+
const clientId = asClientId(record.clientId);
|
|
96
105
|
const via = asVia(record.via);
|
|
97
106
|
const source = {
|
|
98
107
|
...spaceId ? { spaceId } : {},
|
|
99
108
|
...sessionId ? { sessionId } : {},
|
|
100
109
|
...turnId ? { turnId } : {},
|
|
101
110
|
...toolCallId ? { toolCallId } : {},
|
|
111
|
+
...clientId ? { clientId } : {},
|
|
102
112
|
...via ? { via } : {}
|
|
103
113
|
};
|
|
104
114
|
return isRequestSourceEmpty(source) ? null : source;
|
|
@@ -108,6 +118,7 @@ const parseRequestSourceFromHeaders = (getHeader) => normalizeRequestSource({
|
|
|
108
118
|
sessionId: getHeader(COHUB_SOURCE_HEADER.session),
|
|
109
119
|
turnId: getHeader(COHUB_SOURCE_HEADER.turn),
|
|
110
120
|
toolCallId: getHeader(COHUB_SOURCE_HEADER.toolCall),
|
|
121
|
+
clientId: getHeader(COHUB_SOURCE_HEADER.client),
|
|
111
122
|
via: getHeader(COHUB_SOURCE_HEADER.via)
|
|
112
123
|
});
|
|
113
124
|
const requestSourceToHeaders = (source) => {
|
|
@@ -118,6 +129,7 @@ const requestSourceToHeaders = (source) => {
|
|
|
118
129
|
if (normalized.sessionId) headers[COHUB_SOURCE_HEADER.session] = normalized.sessionId;
|
|
119
130
|
if (normalized.turnId) headers[COHUB_SOURCE_HEADER.turn] = normalized.turnId;
|
|
120
131
|
if (normalized.toolCallId) headers[COHUB_SOURCE_HEADER.toolCall] = normalized.toolCallId;
|
|
132
|
+
if (normalized.clientId) headers[COHUB_SOURCE_HEADER.client] = normalized.clientId;
|
|
121
133
|
if (normalized.via) headers[COHUB_SOURCE_HEADER.via] = normalized.via;
|
|
122
134
|
return headers;
|
|
123
135
|
};
|
|
@@ -127,6 +139,7 @@ const readRequestSourceFromEnv = (env = {}, defaults) => normalizeRequestSource(
|
|
|
127
139
|
sessionId: env.COHUB_SESSION_ID,
|
|
128
140
|
turnId: env.COHUB_TURN_ID,
|
|
129
141
|
toolCallId: env.COHUB_TOOL_CALL_ID,
|
|
142
|
+
clientId: env.COHUB_SOURCE_CLIENT_ID,
|
|
130
143
|
via: env.COHUB_SOURCE_VIA ?? defaults?.via
|
|
131
144
|
});
|
|
132
145
|
const resolveRequestSourceChannel = (source, fallback = "public_api") => {
|
|
@@ -390,4 +403,4 @@ var HttpTransport = class {
|
|
|
390
403
|
}
|
|
391
404
|
};
|
|
392
405
|
//#endregion
|
|
393
|
-
export {
|
|
406
|
+
export { WS_REALTIME_ROOM_CAPABILITY as C, getSessionTurnPatchStreamKey as D, getRealtimeSpaceRoom as E, normalizeRealtimeRooms as O, WS_COMPACT_STREAM_CAPABILITY as S, getRealtimeBoardRoom as T, requestSourceToHeaders as _, sanitizeAccessToken as a, REALTIME_ROOM_MAX_PAYLOAD_BYTES as b, REQUEST_SOURCE_VIA_MAX_LENGTH as c, isRequestSourceEmpty as d, isRequestSourceUuid as f, readRequestSourceFromEnv as g, parseRequestSourceFromHeaders as h, matchesUnauthorizedErrorToken as i, hasRequestSourceIdentity as l, normalizeRequestSource as m, HttpTransport as n, COHUB_SOURCE_HEADER as o, mergeRequestSourceIntoMeta as p, joinApiUrl as r, COHUB_SOURCE_HEADER_NAMES as s, HttpError as t, isRequestSourceClientId as u, resolveRequestSourceChannel as v, WS_ROOM_SUBSCRIPTION_CAPABILITY as w, WS_BOARD_AWARENESS_CAPABILITY as x, REALTIME_ROOM_EVENT_NAME_PATTERN as y };
|