@junejuly-lockstep/sdk 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,12 +1,15 @@
1
1
  # @junejuly-lockstep/sdk
2
2
 
3
- A typed `fetch` client for the Lockstep platform API. Two clients:
3
+ A typed `fetch` client for the Lockstep platform API, used by `@junejuly-lockstep/cli`. Three
4
+ clients:
4
5
 
5
- - `createIngestClient` authenticates with a project API key (`lsk_...`, sent as a bearer token) and
6
- covers the routes the reconciler uses: presigned uploads, baselines, `POST /api/ingest/runs` and
7
- `POST /api/ingest/models`.
8
- - `createSessionClient` rides the SPA's session cookie and covers the read and judgment API
9
- (projects, journeys, board, cards, annotations, ops).
6
+ - `createCheckClient` authenticates with a project API key (`lsk_...`, sent as a bearer token) and
7
+ covers what `lockstep check` needs: presigned screenshot uploads, `POST /api/ingest/checks` and
8
+ the intent manifest.
9
+ - `createDeviceClient` runs the CLI device authorization (`lockstep init`): request a code, then
10
+ poll until a signed-in member approves it and the project API key comes back.
11
+ - `createAgentClient` (project API key) gives coding agents ticket context: the project, tickets,
12
+ a ticket's context and screens, and linking a pull request, comments and agent runs to a ticket.
10
13
 
11
14
  Every response is validated with the `@junejuly-lockstep/model` schemas before it is returned; failures
12
15
  surface as `LockstepApiError` (HTTP status and body) or `LockstepNetworkError` (retries exhausted).
@@ -21,16 +24,16 @@ pnpm add @junejuly-lockstep/sdk @junejuly-lockstep/model
21
24
  ## Usage
22
25
 
23
26
  ```ts
24
- import { createIngestClient, LockstepApiError } from '@junejuly-lockstep/sdk';
27
+ import { createAgentClient, LockstepApiError } from '@junejuly-lockstep/sdk';
25
28
 
26
- const ingest = createIngestClient({
29
+ const agent = createAgentClient({
27
30
  baseUrl: 'https://api.lockstep.example',
28
31
  apiKey: process.env.LOCKSTEP_API_KEY!,
29
32
  });
30
33
 
31
34
  try {
32
- const baselines = await ingest.getBaselines('FERN');
33
- console.log(`${baselines.entries.length} approved baselines`);
35
+ const tickets = await agent.listTickets(['todo', 'in_progress']);
36
+ console.log(`${tickets.length} open tickets`);
34
37
  } catch (err) {
35
38
  if (err instanceof LockstepApiError) console.error(err.status, err.message);
36
39
  else throw err;
@@ -38,7 +41,7 @@ try {
38
41
  ```
39
42
 
40
43
  `@junejuly-lockstep/sdk/testing` exports `fakeFetch`, a recording `fetch` double for unit tests of code that
41
- uses either client.
44
+ uses any client.
42
45
 
43
46
  Published from the [Lockstep monorepo](https://github.com/JuneJulyHealth/lockstep)
44
- (`packages/sdk`). Versioned in lockstep with `@junejuly-lockstep/model` and `@junejuly-lockstep/reconciler`.
47
+ (`packages/sdk`). Versioned in lockstep with `@junejuly-lockstep/model` and `@junejuly-lockstep/cli`.
package/dist/index.d.ts CHANGED
@@ -1,8 +1,6 @@
1
1
  export { LockstepApiError, LockstepNetworkError } from './errors.js';
2
- export { createIngestClient, INGEST_ROUTES } from './ingest.js';
3
- export type { IngestClient, IngestClientOptions } from './ingest.js';
4
- export { createSessionClient, SESSION_ROUTES } from './session.js';
5
- export type { ConditionalOptions, JudgmentAction, RunArtifactsResponse, SessionClient, SessionClientOptions, } from './session.js';
2
+ export { AGENT_ROUTES, CHECK_ROUTES, DEVICE_ROUTES, createAgentClient, createCheckClient, createDeviceClient, } from './v2.js';
3
+ export type { AgentClient, ApiKeyClientOptions, CheckClient, DeviceClient, DeviceClientOptions, } from './v2.js';
6
4
  export { joinUrl, DEFAULT_RETRY } from './http.js';
7
5
  export type { Conditional, FetchLike, RetryPolicy } from './http.js';
8
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnE,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,mBAAmB,GACpB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  export { LockstepApiError, LockstepNetworkError } from './errors.js';
2
- export { createIngestClient, INGEST_ROUTES } from './ingest.js';
3
- export { createSessionClient, SESSION_ROUTES } from './session.js';
2
+ export { AGENT_ROUTES, CHECK_ROUTES, DEVICE_ROUTES, createAgentClient, createCheckClient, createDeviceClient, } from './v2.js';
4
3
  export { joinUrl, DEFAULT_RETRY } from './http.js';
5
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAQjB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC"}
package/dist/v2.d.ts ADDED
@@ -0,0 +1,65 @@
1
+ import { z } from 'zod';
2
+ import { AgentStartedRequest, CheckPayload, DeviceCodeRequest, DeviceCodeResponse, DeviceTokenResponse, IngestCheckResponse, IngestProjectDto, IntentManifest, LinkPrRequest, PresignCheckRequest, PresignCheckResponse, ScreenContextDto, TicketContextDto, TicketDto, type TicketStatus } from '@junejuly-lockstep/model/v2';
3
+ import { type FetchLike, type RetryPolicy } from './http.js';
4
+ /**
5
+ * Lockstep v2 clients (docs/REDESIGN.md). Every route the CLI calls is listed here so the API can
6
+ * be reconciled against one table.
7
+ */
8
+ export declare const CHECK_ROUTES: {
9
+ readonly presign: "/api/ingest/checks/presign";
10
+ readonly checks: "/api/ingest/checks";
11
+ readonly intentManifest: "/api/ingest/intent-manifest";
12
+ };
13
+ export declare const DEVICE_ROUTES: {
14
+ readonly start: "/api/cli/device";
15
+ readonly token: "/api/cli/device/token";
16
+ };
17
+ export declare const AGENT_ROUTES: {
18
+ readonly project: "/api/ingest/project";
19
+ readonly tickets: "/api/ingest/tickets";
20
+ readonly ticketContext: (ref: string) => string;
21
+ readonly ticketPrs: (ref: string) => string;
22
+ readonly ticketComments: (ref: string) => string;
23
+ readonly ticketAgentStarted: (ref: string) => string;
24
+ readonly screen: "/api/ingest/screens";
25
+ };
26
+ export interface ApiKeyClientOptions {
27
+ /** Platform API origin, e.g. https://api-staging.lockstep.junejuly.dev */
28
+ baseUrl: string;
29
+ /** Project API key, `lsk_...`. Sent as `Authorization: Bearer`. */
30
+ apiKey: string;
31
+ fetch?: FetchLike;
32
+ retry?: Partial<RetryPolicy>;
33
+ }
34
+ export interface CheckClient {
35
+ /** POST /api/ingest/checks/presign: presigned PUTs, at most 50 files per call; the first call reserves the check id. */
36
+ presign(req: PresignCheckRequest): Promise<PresignCheckResponse>;
37
+ /** POST /api/ingest/checks: the reality map and visual scores of one check. */
38
+ postCheck(payload: CheckPayload): Promise<IngestCheckResponse>;
39
+ /** GET /api/ingest/intent-manifest?project=KEY: intent screenshots with presigned GETs; null on 404. */
40
+ getIntentManifest(projectKey: string): Promise<IntentManifest | null>;
41
+ }
42
+ export declare function createCheckClient(options: ApiKeyClientOptions): CheckClient;
43
+ export interface DeviceClientOptions {
44
+ baseUrl: string;
45
+ fetch?: FetchLike;
46
+ retry?: Partial<RetryPolicy>;
47
+ }
48
+ export interface DeviceClient {
49
+ /** POST /api/cli/device: no auth; returns the user code and verification URL. */
50
+ start(req: z.input<typeof DeviceCodeRequest>): Promise<DeviceCodeResponse>;
51
+ /** POST /api/cli/device/token: one poll. A non-2xx body that is a token status is returned too. */
52
+ poll(deviceCode: string): Promise<DeviceTokenResponse>;
53
+ }
54
+ export declare function createDeviceClient(options: DeviceClientOptions): DeviceClient;
55
+ export interface AgentClient {
56
+ getProject(): Promise<IngestProjectDto>;
57
+ listTickets(status?: TicketStatus[]): Promise<TicketDto[]>;
58
+ getTicketContext(ref: string): Promise<TicketContextDto>;
59
+ getScreen(screenKey: string, env?: string): Promise<ScreenContextDto>;
60
+ linkPr(ref: string, req: z.input<typeof LinkPrRequest>): Promise<unknown>;
61
+ addComment(ref: string, text: string): Promise<unknown>;
62
+ agentStarted(ref: string, req?: z.input<typeof AgentStartedRequest>): Promise<unknown>;
63
+ }
64
+ export declare function createAgentClient(options: ApiKeyClientOptions): AgentClient;
65
+ //# sourceMappingURL=v2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../src/v2.ts"],"names":[],"mappings":"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"}
package/dist/v2.js ADDED
@@ -0,0 +1,184 @@
1
+ import { z } from 'zod';
2
+ import { AddTicketCommentRequest, AgentStartedRequest, CheckPayload, DeviceCodeRequest, DeviceCodeResponse, DeviceTokenRequest, DeviceTokenResponse, IngestCheckResponse, IngestProjectDto, IntentManifest, LinkPrRequest, PresignCheckRequest, PresignCheckResponse, ScreenContextDto, TicketContextDto, TicketDto, TicketListDto, } from '@junejuly-lockstep/model/v2';
3
+ import { LockstepApiError } from './errors.js';
4
+ import { createHttp } from './http.js';
5
+ /**
6
+ * Lockstep v2 clients (docs/REDESIGN.md). Every route the CLI calls is listed here so the API can
7
+ * be reconciled against one table.
8
+ */
9
+ export const CHECK_ROUTES = {
10
+ presign: '/api/ingest/checks/presign',
11
+ checks: '/api/ingest/checks',
12
+ intentManifest: '/api/ingest/intent-manifest',
13
+ };
14
+ export const DEVICE_ROUTES = {
15
+ start: '/api/cli/device',
16
+ token: '/api/cli/device/token',
17
+ };
18
+ const enc = (ref) => encodeURIComponent(ref);
19
+ export const AGENT_ROUTES = {
20
+ project: '/api/ingest/project',
21
+ tickets: '/api/ingest/tickets',
22
+ ticketContext: (ref) => `/api/ingest/tickets/${enc(ref)}/context`,
23
+ ticketPrs: (ref) => `/api/ingest/tickets/${enc(ref)}/prs`,
24
+ ticketComments: (ref) => `/api/ingest/tickets/${enc(ref)}/comments`,
25
+ ticketAgentStarted: (ref) => `/api/ingest/tickets/${enc(ref)}/agent-started`,
26
+ screen: '/api/ingest/screens',
27
+ };
28
+ function apiKeyHttp(options, who) {
29
+ if (!options.apiKey)
30
+ throw new Error(`${who}: apiKey is required`);
31
+ if (!options.apiKey.startsWith('lsk_'))
32
+ throw new Error(`${who}: apiKey must be a project key starting with lsk_`);
33
+ return createHttp({
34
+ baseUrl: options.baseUrl,
35
+ fetch: options.fetch,
36
+ retry: options.retry,
37
+ headers: { authorization: `Bearer ${options.apiKey}` },
38
+ });
39
+ }
40
+ export function createCheckClient(options) {
41
+ const http = apiKeyHttp(options, 'createCheckClient');
42
+ return {
43
+ async presign(req) {
44
+ return http.request({
45
+ method: 'POST',
46
+ path: CHECK_ROUTES.presign,
47
+ body: PresignCheckRequest.parse(req),
48
+ schema: PresignCheckResponse,
49
+ // Presign is idempotent for a given check id; retry transient failures.
50
+ idempotent: req.checkId !== undefined,
51
+ });
52
+ },
53
+ async postCheck(payload) {
54
+ return http.request({
55
+ method: 'POST',
56
+ path: CHECK_ROUTES.checks,
57
+ body: CheckPayload.parse(payload),
58
+ schema: IngestCheckResponse,
59
+ });
60
+ },
61
+ async getIntentManifest(projectKey) {
62
+ try {
63
+ return await http.request({
64
+ method: 'GET',
65
+ path: CHECK_ROUTES.intentManifest,
66
+ query: { project: projectKey },
67
+ schema: IntentManifest,
68
+ });
69
+ }
70
+ catch (err) {
71
+ if (err instanceof LockstepApiError && err.status === 404)
72
+ return null;
73
+ throw err;
74
+ }
75
+ },
76
+ };
77
+ }
78
+ export function createDeviceClient(options) {
79
+ const http = createHttp({ baseUrl: options.baseUrl, fetch: options.fetch, retry: options.retry });
80
+ return {
81
+ async start(req) {
82
+ return http.request({
83
+ method: 'POST',
84
+ path: DEVICE_ROUTES.start,
85
+ body: DeviceCodeRequest.parse(req),
86
+ schema: DeviceCodeResponse,
87
+ });
88
+ },
89
+ async poll(deviceCode) {
90
+ const body = DeviceTokenRequest.parse({ deviceCode });
91
+ const { response, url } = await http.raw({
92
+ method: 'POST',
93
+ path: DEVICE_ROUTES.token,
94
+ body,
95
+ schema: DeviceTokenResponse,
96
+ idempotent: true,
97
+ });
98
+ const text = await response.text();
99
+ let json = null;
100
+ try {
101
+ json = text ? JSON.parse(text) : null;
102
+ }
103
+ catch {
104
+ json = text;
105
+ }
106
+ const parsed = DeviceTokenResponse.safeParse(json);
107
+ if (parsed.success)
108
+ return parsed.data;
109
+ throw new LockstepApiError({
110
+ status: response.status,
111
+ body: json,
112
+ method: 'POST',
113
+ url,
114
+ message: response.ok
115
+ ? `POST ${url} returned a body that is not a device token status`
116
+ : undefined,
117
+ });
118
+ },
119
+ };
120
+ }
121
+ /* ------------------------------------------------------------------ agents (mcp, work orders) */
122
+ /** The list endpoint may answer `{ tickets }` or a bare array; both parse to `{ tickets }`. */
123
+ const TicketListResponse = z.union([
124
+ TicketListDto,
125
+ z.array(TicketDto).transform((tickets) => ({ tickets })),
126
+ ]);
127
+ export function createAgentClient(options) {
128
+ const http = apiKeyHttp(options, 'createAgentClient');
129
+ const anyBody = z.unknown();
130
+ return {
131
+ async getProject() {
132
+ return http.request({ method: 'GET', path: AGENT_ROUTES.project, schema: IngestProjectDto });
133
+ },
134
+ async listTickets(status) {
135
+ const res = await http.request({
136
+ method: 'GET',
137
+ path: AGENT_ROUTES.tickets,
138
+ query: { status: status && status.length > 0 ? status.join(',') : undefined },
139
+ schema: TicketListResponse,
140
+ });
141
+ return res.tickets;
142
+ },
143
+ async getTicketContext(ref) {
144
+ return http.request({
145
+ method: 'GET',
146
+ path: AGENT_ROUTES.ticketContext(ref),
147
+ schema: TicketContextDto,
148
+ });
149
+ },
150
+ async getScreen(screenKey, env) {
151
+ return http.request({
152
+ method: 'GET',
153
+ path: AGENT_ROUTES.screen,
154
+ query: { key: screenKey, env },
155
+ schema: ScreenContextDto,
156
+ });
157
+ },
158
+ async linkPr(ref, req) {
159
+ return http.request({
160
+ method: 'POST',
161
+ path: AGENT_ROUTES.ticketPrs(ref),
162
+ body: LinkPrRequest.parse(req),
163
+ schema: anyBody,
164
+ });
165
+ },
166
+ async addComment(ref, text) {
167
+ return http.request({
168
+ method: 'POST',
169
+ path: AGENT_ROUTES.ticketComments(ref),
170
+ body: AddTicketCommentRequest.parse({ text }),
171
+ schema: anyBody,
172
+ });
173
+ },
174
+ async agentStarted(ref, req = {}) {
175
+ return http.request({
176
+ method: 'POST',
177
+ path: AGENT_ROUTES.ticketAgentStarted(ref),
178
+ body: AgentStartedRequest.parse(req),
179
+ schema: anyBody,
180
+ });
181
+ },
182
+ };
183
+ }
184
+ //# sourceMappingURL=v2.js.map
package/dist/v2.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2.js","sourceRoot":"","sources":["../src/v2.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@junejuly-lockstep/sdk",
3
- "version": "0.1.1",
4
- "description": "Typed fetch client for the Lockstep platform: ingest API (runs, presign, baselines, model sync) and the session read API.",
3
+ "version": "0.2.1",
4
+ "description": "Typed fetch client for the Lockstep platform: check ingest, CLI device authorization and agent (ticket) clients.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -45,14 +45,14 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "zod": "^3.24.1",
48
- "@junejuly-lockstep/model": "0.1.1"
48
+ "@junejuly-lockstep/model": "0.2.1"
49
49
  },
50
50
  "devDependencies": {
51
51
  "typescript": "^5.7.2",
52
52
  "vitest": "^2.1.8"
53
53
  },
54
54
  "scripts": {
55
- "build": "tsc -p tsconfig.json",
55
+ "build": "node -e \"for (const p of ['dist','tsconfig.tsbuildinfo']) require('node:fs').rmSync(p,{recursive:true,force:true})\" && tsc -p tsconfig.json",
56
56
  "typecheck": "tsc -p tsconfig.typecheck.json --noEmit",
57
57
  "lint": "eslint src",
58
58
  "test": "vitest run"
package/dist/ingest.d.ts DELETED
@@ -1,32 +0,0 @@
1
- import { BaselineManifest, IngestRunResponse, ModelSyncPayload, ModelSyncResponse, PresignRequest, PresignResponse, RunPayload } from '@junejuly-lockstep/model';
2
- import { type FetchLike, type RetryPolicy } from './http.js';
3
- export interface IngestClientOptions {
4
- /** Platform API origin, e.g. https://api.lockstep.example */
5
- baseUrl: string;
6
- /** Project API key, `lsk_...`. Sent as `Authorization: Bearer`. */
7
- apiKey: string;
8
- fetch?: FetchLike;
9
- retry?: Partial<RetryPolicy>;
10
- }
11
- /** Routes the reconciler uses. Kept in one place so the API can be reconciled against them. */
12
- export declare const INGEST_ROUTES: {
13
- readonly presign: "/api/ingest/presign";
14
- readonly runs: "/api/ingest/runs";
15
- readonly baselines: "/api/ingest/baselines";
16
- readonly models: "/api/ingest/models";
17
- };
18
- export interface IngestClient {
19
- /** POST /api/ingest/presign: batch presigned PUT URLs (max 50 files per call). */
20
- presign(req: PresignRequest): Promise<PresignResponse>;
21
- /** GET /api/ingest/baselines?project=KEY: current approved baselines with presigned GET URLs. */
22
- getBaselines(projectKey: string): Promise<BaselineManifest>;
23
- /** POST /api/ingest/runs: the complete run payload. */
24
- postRun(payload: RunPayload): Promise<IngestRunResponse>;
25
- /**
26
- * POST /api/ingest/models: parsed journey models and scenarios at a commit (M3 model sync, run
27
- * by `lockstep sync-models` in client CI on push; the platform never evaluates journey files).
28
- */
29
- syncModels(payload: ModelSyncPayload): Promise<ModelSyncResponse>;
30
- }
31
- export declare function createIngestClient(options: IngestClientOptions): IngestClient;
32
- //# sourceMappingURL=ingest.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../src/ingest.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,UAAU,EACX,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAc,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAEzE,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC9B;AAED,+FAA+F;AAC/F,eAAO,MAAM,aAAa;;;;;CAKhB,CAAC;AAEX,MAAM,WAAW,YAAY;IAC3B,kFAAkF;IAClF,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACvD,iGAAiG;IACjG,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5D,uDAAuD;IACvD,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACzD;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACnE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAiD7E"}
package/dist/ingest.js DELETED
@@ -1,60 +0,0 @@
1
- import { BaselineManifest, IngestRunResponse, ModelSyncPayload, ModelSyncResponse, PresignRequest, PresignResponse, RunPayload, } from '@junejuly-lockstep/model';
2
- import { createHttp } from './http.js';
3
- /** Routes the reconciler uses. Kept in one place so the API can be reconciled against them. */
4
- export const INGEST_ROUTES = {
5
- presign: '/api/ingest/presign',
6
- runs: '/api/ingest/runs',
7
- baselines: '/api/ingest/baselines',
8
- models: '/api/ingest/models',
9
- };
10
- export function createIngestClient(options) {
11
- if (!options.apiKey)
12
- throw new Error('createIngestClient: apiKey is required');
13
- if (!options.apiKey.startsWith('lsk_')) {
14
- throw new Error('createIngestClient: apiKey must be a project key starting with lsk_');
15
- }
16
- const http = createHttp({
17
- baseUrl: options.baseUrl,
18
- fetch: options.fetch,
19
- retry: options.retry,
20
- headers: { authorization: `Bearer ${options.apiKey}` },
21
- });
22
- return {
23
- async presign(req) {
24
- const body = PresignRequest.parse(req);
25
- return http.request({
26
- method: 'POST',
27
- path: INGEST_ROUTES.presign,
28
- body,
29
- schema: PresignResponse,
30
- });
31
- },
32
- async getBaselines(projectKey) {
33
- return http.request({
34
- method: 'GET',
35
- path: INGEST_ROUTES.baselines,
36
- query: { project: projectKey },
37
- schema: BaselineManifest,
38
- });
39
- },
40
- async postRun(payload) {
41
- const body = RunPayload.parse(payload);
42
- return http.request({
43
- method: 'POST',
44
- path: INGEST_ROUTES.runs,
45
- body,
46
- schema: IngestRunResponse,
47
- });
48
- },
49
- async syncModels(payload) {
50
- const body = ModelSyncPayload.parse(payload);
51
- return http.request({
52
- method: 'POST',
53
- path: INGEST_ROUTES.models,
54
- body,
55
- schema: ModelSyncResponse,
56
- });
57
- },
58
- };
59
- }
60
- //# sourceMappingURL=ingest.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ingest.js","sourceRoot":"","sources":["../src/ingest.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,UAAU,GACX,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,UAAU,EAAoC,MAAM,WAAW,CAAC;AAWzE,+FAA+F;AAC/F,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE,qBAAqB;IAC9B,IAAI,EAAE,kBAAkB;IACxB,SAAS,EAAE,uBAAuB;IAClC,MAAM,EAAE,oBAAoB;CACpB,CAAC;AAgBX,MAAM,UAAU,kBAAkB,CAAC,OAA4B;IAC7D,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC/E,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,CAAC,MAAM,EAAE,EAAE;KACvD,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,GAAG;YACf,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACvC,OAAO,IAAI,CAAC,OAAO,CAAC;gBAClB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,aAAa,CAAC,OAAO;gBAC3B,IAAI;gBACJ,MAAM,EAAE,eAAe;aACxB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,YAAY,CAAC,UAAU;YAC3B,OAAO,IAAI,CAAC,OAAO,CAAC;gBAClB,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,aAAa,CAAC,SAAS;gBAC7B,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE;gBAC9B,MAAM,EAAE,gBAAgB;aACzB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACvC,OAAO,IAAI,CAAC,OAAO,CAAC;gBAClB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,aAAa,CAAC,IAAI;gBACxB,IAAI;gBACJ,MAAM,EAAE,iBAAiB;aAC1B,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,OAAO;YACtB,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7C,OAAO,IAAI,CAAC,OAAO,CAAC;gBAClB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,aAAa,CAAC,MAAM;gBAC1B,IAAI;gBACJ,MAAM,EAAE,iBAAiB;aAC1B,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}