@whittlelabs/sifter 0.43.2 → 0.43.4
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/bin.js +436 -274
- package/bin.js.map +4 -4
- package/package.json +1 -1
package/bin.js
CHANGED
|
@@ -9780,12 +9780,129 @@ var require_canonicalise = __commonJS({
|
|
|
9780
9780
|
}
|
|
9781
9781
|
});
|
|
9782
9782
|
|
|
9783
|
+
// ../../packages/contracts/dist/client.js
|
|
9784
|
+
var require_client = __commonJS({
|
|
9785
|
+
"../../packages/contracts/dist/client.js"(exports2) {
|
|
9786
|
+
"use strict";
|
|
9787
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
9788
|
+
exports2.createContractClient = createContractClient;
|
|
9789
|
+
function createContractClient({ baseUrl, transport }) {
|
|
9790
|
+
const root = baseUrl.replace(/\/+$/, "");
|
|
9791
|
+
async function request(method, template, options = {}) {
|
|
9792
|
+
const headers = { Accept: "application/json" };
|
|
9793
|
+
if (options.body !== void 0)
|
|
9794
|
+
headers["Content-Type"] = "application/json";
|
|
9795
|
+
Object.assign(headers, options.headers);
|
|
9796
|
+
let response;
|
|
9797
|
+
try {
|
|
9798
|
+
response = await transport(`${root}${filledPath(template, options.path)}${queryString(options.query)}`, {
|
|
9799
|
+
method: method.toUpperCase(),
|
|
9800
|
+
headers,
|
|
9801
|
+
body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
9802
|
+
signal: options.signal
|
|
9803
|
+
});
|
|
9804
|
+
} catch (err2) {
|
|
9805
|
+
return failure("NETWORK_ERROR", err2 instanceof Error ? err2.message : "Network request failed", null);
|
|
9806
|
+
}
|
|
9807
|
+
return answered(response);
|
|
9808
|
+
}
|
|
9809
|
+
const call = (method) => (path, options) => request(method, path, options);
|
|
9810
|
+
return {
|
|
9811
|
+
get: call("get"),
|
|
9812
|
+
post: call("post"),
|
|
9813
|
+
put: call("put"),
|
|
9814
|
+
patch: call("patch"),
|
|
9815
|
+
delete: call("delete")
|
|
9816
|
+
};
|
|
9817
|
+
}
|
|
9818
|
+
function filledPath(template, params) {
|
|
9819
|
+
const values = params ?? {};
|
|
9820
|
+
return template.replace(/\{([^}]+)\}/g, (_, name2) => {
|
|
9821
|
+
const value = values[name2];
|
|
9822
|
+
if (value === void 0 || value === null)
|
|
9823
|
+
throw new TypeError(`${template} needs the path parameter ${name2}`);
|
|
9824
|
+
return encodeURIComponent(String(value));
|
|
9825
|
+
});
|
|
9826
|
+
}
|
|
9827
|
+
function queryString(query) {
|
|
9828
|
+
const search = new URLSearchParams();
|
|
9829
|
+
for (const [key, value] of Object.entries(query ?? {})) {
|
|
9830
|
+
if (value === void 0 || value === null)
|
|
9831
|
+
continue;
|
|
9832
|
+
for (const item of Array.isArray(value) ? value : [value])
|
|
9833
|
+
search.append(key, String(item));
|
|
9834
|
+
}
|
|
9835
|
+
const text = search.toString();
|
|
9836
|
+
return text ? `?${text}` : "";
|
|
9837
|
+
}
|
|
9838
|
+
async function answered(response) {
|
|
9839
|
+
const { status } = response;
|
|
9840
|
+
let text;
|
|
9841
|
+
try {
|
|
9842
|
+
text = await response.text();
|
|
9843
|
+
} catch (err2) {
|
|
9844
|
+
return failure("NETWORK_ERROR", err2 instanceof Error ? err2.message : "The response could not be read", status);
|
|
9845
|
+
}
|
|
9846
|
+
let payload;
|
|
9847
|
+
let parsed = true;
|
|
9848
|
+
if (text !== "") {
|
|
9849
|
+
try {
|
|
9850
|
+
payload = JSON.parse(text);
|
|
9851
|
+
} catch {
|
|
9852
|
+
parsed = false;
|
|
9853
|
+
}
|
|
9854
|
+
}
|
|
9855
|
+
if (response.ok) {
|
|
9856
|
+
if (text === "")
|
|
9857
|
+
return { success: true, data: void 0, status };
|
|
9858
|
+
if (!parsed)
|
|
9859
|
+
return failure("SERVER_ERROR", `The ${status} response was not JSON`, status);
|
|
9860
|
+
if (isRecord(payload) && payload.success === true)
|
|
9861
|
+
return { success: true, data: payload.data, status };
|
|
9862
|
+
return { success: true, data: payload, status };
|
|
9863
|
+
}
|
|
9864
|
+
if (isRecord(payload) && payload.success === false && isRecord(payload.error)) {
|
|
9865
|
+
const { code, message } = payload.error;
|
|
9866
|
+
if (typeof code === "string" && typeof message === "string") {
|
|
9867
|
+
return failure(code, message, status, saysMore(payload, payload.error) ? payload : void 0);
|
|
9868
|
+
}
|
|
9869
|
+
}
|
|
9870
|
+
return failure("SERVER_ERROR", `Request failed with status ${status}`, status, text !== "" && parsed ? payload : void 0);
|
|
9871
|
+
}
|
|
9872
|
+
function saysMore(envelope, error) {
|
|
9873
|
+
return Object.keys(envelope).some((key) => key !== "success" && key !== "error") || Object.keys(error).some((key) => key !== "code" && key !== "message");
|
|
9874
|
+
}
|
|
9875
|
+
function failure(code, message, status, body2) {
|
|
9876
|
+
return { success: false, error: { code, message, status, ...body2 !== void 0 ? { body: body2 } : {} } };
|
|
9877
|
+
}
|
|
9878
|
+
function isRecord(value) {
|
|
9879
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9880
|
+
}
|
|
9881
|
+
}
|
|
9882
|
+
});
|
|
9883
|
+
|
|
9884
|
+
// ../../packages/contracts/dist/services/loom.js
|
|
9885
|
+
var require_loom = __commonJS({
|
|
9886
|
+
"../../packages/contracts/dist/services/loom.js"(exports2) {
|
|
9887
|
+
"use strict";
|
|
9888
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
9889
|
+
exports2.service = void 0;
|
|
9890
|
+
exports2.createClient = createClient;
|
|
9891
|
+
var client_1 = require_client();
|
|
9892
|
+
exports2.service = "whittle-loom";
|
|
9893
|
+
function createClient(options) {
|
|
9894
|
+
return (0, client_1.createContractClient)(options);
|
|
9895
|
+
}
|
|
9896
|
+
}
|
|
9897
|
+
});
|
|
9898
|
+
|
|
9783
9899
|
// ../../packages/loom/dist/seed/seed-workflows.js
|
|
9784
9900
|
var require_seed_workflows = __commonJS({
|
|
9785
9901
|
"../../packages/loom/dist/seed/seed-workflows.js"(exports2) {
|
|
9786
9902
|
"use strict";
|
|
9787
9903
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
9788
9904
|
exports2.seedWorkflows = seedWorkflows;
|
|
9905
|
+
var loom_1 = require_loom();
|
|
9789
9906
|
var canonicalise_1 = require_canonicalise();
|
|
9790
9907
|
var errors_1 = require_errors2();
|
|
9791
9908
|
var NULL_LOGGER = {
|
|
@@ -9799,13 +9916,16 @@ var require_seed_workflows = __commonJS({
|
|
|
9799
9916
|
async function seedWorkflows(opts) {
|
|
9800
9917
|
const logger = opts.logger ?? NULL_LOGGER;
|
|
9801
9918
|
const fetchFn = opts.fetchFn ?? fetch;
|
|
9802
|
-
const
|
|
9803
|
-
const
|
|
9804
|
-
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9919
|
+
const credential = "accessToken" in opts.auth ? { Authorization: `Bearer ${opts.auth.accessToken}` } : { "X-API-Key": opts.auth.apiKey };
|
|
9920
|
+
const loom = (0, loom_1.createClient)({
|
|
9921
|
+
baseUrl: opts.loomApiUrl,
|
|
9922
|
+
transport: (url, init2) => {
|
|
9923
|
+
const headers = new Headers(init2.headers);
|
|
9924
|
+
for (const [name2, value] of Object.entries(credential))
|
|
9925
|
+
headers.set(name2, value);
|
|
9926
|
+
return fetchFn(url, { ...init2, headers });
|
|
9927
|
+
}
|
|
9928
|
+
});
|
|
9809
9929
|
const results = [];
|
|
9810
9930
|
for (const workflow of opts.workflows) {
|
|
9811
9931
|
let ownerClass;
|
|
@@ -9841,17 +9961,12 @@ var require_seed_workflows = __commonJS({
|
|
|
9841
9961
|
nodes: body2.nodes.length,
|
|
9842
9962
|
transitions: body2.transitions.length
|
|
9843
9963
|
});
|
|
9844
|
-
const
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
body: JSON.stringify(body2)
|
|
9848
|
-
});
|
|
9849
|
-
const json = await response.json();
|
|
9850
|
-
if (!response.ok || !json.success || !json.data) {
|
|
9851
|
-
const message = json.error?.message ?? `seedWorkflows: ${workflow.name} failed with HTTP ${response.status}`;
|
|
9964
|
+
const result = await loom.post("/api/admin/seed-workflow", { body: body2 });
|
|
9965
|
+
if (!result.success) {
|
|
9966
|
+
const message = result.error.code === "SERVER_ERROR" ? `seedWorkflows: ${workflow.name} failed with HTTP ${result.error.status}` : result.error.message;
|
|
9852
9967
|
throw new errors_1.SeedWorkflowsError(workflow.name, message);
|
|
9853
9968
|
}
|
|
9854
|
-
results.push(
|
|
9969
|
+
results.push(result.data);
|
|
9855
9970
|
}
|
|
9856
9971
|
return { workflows: results };
|
|
9857
9972
|
}
|
|
@@ -58980,23 +59095,41 @@ var require_http_api = __commonJS({
|
|
|
58980
59095
|
}
|
|
58981
59096
|
});
|
|
58982
59097
|
|
|
59098
|
+
// ../../packages/contracts/dist/services/keep.js
|
|
59099
|
+
var require_keep = __commonJS({
|
|
59100
|
+
"../../packages/contracts/dist/services/keep.js"(exports2) {
|
|
59101
|
+
"use strict";
|
|
59102
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
59103
|
+
exports2.service = void 0;
|
|
59104
|
+
exports2.createClient = createClient;
|
|
59105
|
+
var client_1 = require_client();
|
|
59106
|
+
exports2.service = "whittle-keep";
|
|
59107
|
+
function createClient(options) {
|
|
59108
|
+
return (0, client_1.createContractClient)(options);
|
|
59109
|
+
}
|
|
59110
|
+
}
|
|
59111
|
+
});
|
|
59112
|
+
|
|
58983
59113
|
// ../../packages/keep/dist/client.js
|
|
58984
|
-
var
|
|
59114
|
+
var require_client2 = __commonJS({
|
|
58985
59115
|
"../../packages/keep/dist/client.js"(exports2) {
|
|
58986
59116
|
"use strict";
|
|
58987
59117
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
58988
59118
|
exports2.KeepClient = void 0;
|
|
59119
|
+
var keep_1 = require_keep();
|
|
58989
59120
|
var KeepClient = class {
|
|
58990
|
-
|
|
58991
|
-
headers;
|
|
59121
|
+
api;
|
|
58992
59122
|
constructor(config) {
|
|
58993
|
-
|
|
58994
|
-
this.
|
|
58995
|
-
|
|
58996
|
-
|
|
58997
|
-
|
|
58998
|
-
|
|
58999
|
-
|
|
59123
|
+
const token = config.serviceToken ?? config.accessToken;
|
|
59124
|
+
this.api = (0, keep_1.createClient)({
|
|
59125
|
+
baseUrl: config.baseUrl,
|
|
59126
|
+
transport: (url, init2) => {
|
|
59127
|
+
const headers = new Headers(init2.headers);
|
|
59128
|
+
if (token)
|
|
59129
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
59130
|
+
return fetch(url, { ...init2, headers });
|
|
59131
|
+
}
|
|
59132
|
+
});
|
|
59000
59133
|
}
|
|
59001
59134
|
// ── Actor Tokens ────────────────────────────────────────────────
|
|
59002
59135
|
/**
|
|
@@ -59005,7 +59138,7 @@ var require_client = __commonJS({
|
|
|
59005
59138
|
* constructed with a service token holding `keep:actor-tokens:write`.
|
|
59006
59139
|
*/
|
|
59007
59140
|
async mintActorToken(principal) {
|
|
59008
|
-
return this.
|
|
59141
|
+
return answer(await this.api.post("/api/actor-tokens", { body: { principal } }));
|
|
59009
59142
|
}
|
|
59010
59143
|
// ── Identity ────────────────────────────────────────────────────
|
|
59011
59144
|
/**
|
|
@@ -59014,101 +59147,98 @@ var require_client = __commonJS({
|
|
|
59014
59147
|
* POST /api/challenges/:token/response to mint a session.
|
|
59015
59148
|
*/
|
|
59016
59149
|
async createAccount(email, password, name2) {
|
|
59017
|
-
const
|
|
59018
|
-
|
|
59019
|
-
throw new Error("sign-up returned no challenge; the contract expects one");
|
|
59020
|
-
}
|
|
59021
|
-
return body2.challenge;
|
|
59150
|
+
const issued = answer(await this.api.post("/api/accounts", { body: { email, password, name: name2 } }));
|
|
59151
|
+
return issued.challenge;
|
|
59022
59152
|
}
|
|
59023
59153
|
/**
|
|
59024
59154
|
* Sign in. Two legitimate outcomes, neither an error: a session, or a
|
|
59025
59155
|
* challenge (MFA, unverified email). Both arrive on HTTP 200.
|
|
59026
59156
|
*/
|
|
59027
59157
|
async createSession(email, password) {
|
|
59028
|
-
|
|
59029
|
-
if (body2.challenge) {
|
|
59030
|
-
return { kind: "challenge", challenge: body2.challenge };
|
|
59031
|
-
}
|
|
59032
|
-
const data = body2.data;
|
|
59033
|
-
if (!data?.session) {
|
|
59034
|
-
throw new Error("sign-in returned neither a session nor a challenge");
|
|
59035
|
-
}
|
|
59036
|
-
return { kind: "session", user: data.user, session: data.session };
|
|
59158
|
+
return signedIn(answer(await this.api.post("/api/sessions", { body: { email, password } })));
|
|
59037
59159
|
}
|
|
59038
|
-
/**
|
|
59160
|
+
/**
|
|
59161
|
+
* Answer a challenge. Its answer is the session it was standing in for, or
|
|
59162
|
+
* the next challenge (an MFA step after the email was verified).
|
|
59163
|
+
*/
|
|
59039
59164
|
async respondToChallenge(challengeToken, type, response) {
|
|
59040
|
-
return this.
|
|
59165
|
+
return signedIn(answer(await this.api.post("/api/challenges/{token}/response", {
|
|
59166
|
+
path: { token: challengeToken },
|
|
59167
|
+
body: { type, response }
|
|
59168
|
+
})));
|
|
59041
59169
|
}
|
|
59170
|
+
/** End the session the refresh token belongs to. */
|
|
59042
59171
|
async destroySession(refreshToken) {
|
|
59043
|
-
await this.
|
|
59172
|
+
answer(await this.api.delete("/api/sessions", { body: { refreshToken } }));
|
|
59044
59173
|
}
|
|
59045
59174
|
async refreshSession(refreshToken) {
|
|
59046
|
-
return this.
|
|
59175
|
+
return answer(await this.api.post("/api/sessions/renewal", { body: { refreshToken } })).session;
|
|
59047
59176
|
}
|
|
59048
59177
|
async getCurrentUser() {
|
|
59049
|
-
return this.
|
|
59178
|
+
return answer(await this.api.get("/api/accounts/me")).user;
|
|
59050
59179
|
}
|
|
59051
59180
|
async updateProfile(updates) {
|
|
59052
|
-
return this.
|
|
59181
|
+
return answer(await this.api.patch("/api/accounts/me", { body: updates })).user;
|
|
59053
59182
|
}
|
|
59054
59183
|
async confirmEmail(email, code) {
|
|
59055
|
-
await this.
|
|
59184
|
+
answer(await this.api.post("/api/email-confirmations", { body: { email, code } }));
|
|
59056
59185
|
}
|
|
59057
59186
|
async requestVerificationCode(email) {
|
|
59058
|
-
await this.
|
|
59187
|
+
answer(await this.api.post("/api/verification-codes", { body: { email } }));
|
|
59059
59188
|
}
|
|
59060
59189
|
async requestPasswordReset(email) {
|
|
59061
|
-
await this.
|
|
59190
|
+
answer(await this.api.post("/api/password-resets", { body: { email } }));
|
|
59062
59191
|
}
|
|
59063
59192
|
async resetPassword(email, code, newPassword) {
|
|
59064
|
-
await this.
|
|
59193
|
+
answer(await this.api.put("/api/password-resets/{code}", { path: { code }, body: { email, newPassword } }));
|
|
59065
59194
|
}
|
|
59066
59195
|
async changePassword(currentPassword, newPassword) {
|
|
59067
|
-
await this.
|
|
59196
|
+
answer(await this.api.put("/api/passwords", { body: { currentPassword, newPassword } }));
|
|
59068
59197
|
}
|
|
59069
59198
|
// ── Organizations ───────────────────────────────────────────────
|
|
59070
59199
|
async listOrganizations() {
|
|
59071
|
-
|
|
59072
|
-
return organizations;
|
|
59200
|
+
return answer(await this.api.get("/api/orgs")).organizations;
|
|
59073
59201
|
}
|
|
59074
59202
|
async getOrganization(orgId) {
|
|
59075
|
-
return this.
|
|
59203
|
+
return answer(await this.api.get("/api/orgs/{orgId}", { path: { orgId } }));
|
|
59076
59204
|
}
|
|
59077
59205
|
async createOrganization(name2, description) {
|
|
59078
|
-
return this.
|
|
59206
|
+
return answer(await this.api.post("/api/orgs", { body: { name: name2, description } }));
|
|
59079
59207
|
}
|
|
59080
59208
|
async updateOrganization(orgId, updates) {
|
|
59081
|
-
return this.
|
|
59209
|
+
return answer(await this.api.patch("/api/orgs/{orgId}", { path: { orgId }, body: updates }));
|
|
59082
59210
|
}
|
|
59083
59211
|
async deleteOrganization(orgId) {
|
|
59084
|
-
await this.
|
|
59212
|
+
answer(await this.api.delete("/api/orgs/{orgId}", { path: { orgId } }));
|
|
59085
59213
|
}
|
|
59086
59214
|
async listMembers(orgId) {
|
|
59087
|
-
return this.
|
|
59215
|
+
return answer(await this.api.get("/api/orgs/{orgId}/members", { path: { orgId } }));
|
|
59088
59216
|
}
|
|
59089
59217
|
async removeMember(orgId, userId) {
|
|
59090
|
-
await this.
|
|
59218
|
+
answer(await this.api.delete("/api/orgs/{orgId}/members/{userId}", { path: { orgId, userId } }));
|
|
59091
59219
|
}
|
|
59092
59220
|
async listTeams(orgId) {
|
|
59093
|
-
return this.
|
|
59221
|
+
return answer(await this.api.get("/api/orgs/{orgId}/teams", { path: { orgId } }));
|
|
59094
59222
|
}
|
|
59095
59223
|
async createTeam(orgId, name2, description) {
|
|
59096
|
-
return this.
|
|
59224
|
+
return answer(await this.api.post("/api/orgs/{orgId}/teams", { path: { orgId }, body: { name: name2, description } }));
|
|
59097
59225
|
}
|
|
59098
59226
|
async listTeamMembers(orgId, teamId) {
|
|
59099
|
-
return this.
|
|
59227
|
+
return answer(await this.api.get("/api/orgs/{orgId}/teams/{teamId}/members", { path: { orgId, teamId } }));
|
|
59100
59228
|
}
|
|
59101
59229
|
async addTeamMember(orgId, teamId, userId) {
|
|
59102
|
-
return this.
|
|
59230
|
+
return answer(await this.api.post("/api/orgs/{orgId}/teams/{teamId}/members", { path: { orgId, teamId }, body: { userId } }));
|
|
59103
59231
|
}
|
|
59104
|
-
|
|
59105
|
-
|
|
59232
|
+
/** Invite someone to the organization, seated in at least one of its seat pools (ADR-0147). */
|
|
59233
|
+
async createInvitation(orgId, invitation) {
|
|
59234
|
+
return answer(await this.api.post("/api/orgs/{orgId}/invitations", { path: { orgId }, body: invitation }));
|
|
59106
59235
|
}
|
|
59236
|
+
/** The invitation behind a token, with the organization it is to. */
|
|
59107
59237
|
async getInvitation(token) {
|
|
59108
|
-
return this.
|
|
59238
|
+
return answer(await this.api.get("/api/invitations/{token}", { path: { token } }));
|
|
59109
59239
|
}
|
|
59110
59240
|
async acceptInvitation(token) {
|
|
59111
|
-
await this.
|
|
59241
|
+
answer(await this.api.post("/api/invitations/{token}/acceptance", { path: { token } }));
|
|
59112
59242
|
}
|
|
59113
59243
|
// ── Substrate Provisioning ──────────────────────────────────────
|
|
59114
59244
|
/**
|
|
@@ -59119,7 +59249,10 @@ var require_client = __commonJS({
|
|
|
59119
59249
|
* Requires `keep:service-identities:write`.
|
|
59120
59250
|
*/
|
|
59121
59251
|
async findOrCreateServiceIdentity(request) {
|
|
59122
|
-
return this.
|
|
59252
|
+
return answer(await this.api.post("/api/users/{userId}/service-identities", {
|
|
59253
|
+
path: { userId: request.owner.principalId },
|
|
59254
|
+
body: request
|
|
59255
|
+
}));
|
|
59123
59256
|
}
|
|
59124
59257
|
/**
|
|
59125
59258
|
* Bind a role (by name) to a service identity, held at a structural
|
|
@@ -59128,7 +59261,10 @@ var require_client = __commonJS({
|
|
|
59128
59261
|
* Requires `keep:role-bindings:write`.
|
|
59129
59262
|
*/
|
|
59130
59263
|
async bindServiceIdentityRole(serviceIdentityId, request) {
|
|
59131
|
-
return this.
|
|
59264
|
+
return answer(await this.api.post("/api/service-identities/{id}/role-bindings", {
|
|
59265
|
+
path: { id: serviceIdentityId },
|
|
59266
|
+
body: request
|
|
59267
|
+
}));
|
|
59132
59268
|
}
|
|
59133
59269
|
/**
|
|
59134
59270
|
* Mint a pre-authorised device-code (pairing code) bound to an existing
|
|
@@ -59138,11 +59274,9 @@ var require_client = __commonJS({
|
|
|
59138
59274
|
* Requires `keep:service-identities:write`.
|
|
59139
59275
|
*/
|
|
59140
59276
|
async createDeviceCodePreauth(request) {
|
|
59141
|
-
return this.
|
|
59142
|
-
client_id: request.clientId,
|
|
59143
|
-
|
|
59144
|
-
ttlSeconds: request.ttlSeconds
|
|
59145
|
-
});
|
|
59277
|
+
return answer(await this.api.post("/api/oauth/device-code/preauth", {
|
|
59278
|
+
body: { client_id: request.clientId, boundAgentId: request.boundAgentId, ttlSeconds: request.ttlSeconds }
|
|
59279
|
+
}));
|
|
59146
59280
|
}
|
|
59147
59281
|
// ── Hosted Sifter ───────────────────────────────────────────────
|
|
59148
59282
|
/**
|
|
@@ -59155,7 +59289,10 @@ var require_client = __commonJS({
|
|
|
59155
59289
|
* Use the credential for the dispatch and drop it from memory afterwards.
|
|
59156
59290
|
*/
|
|
59157
59291
|
async revealModelCredential(userId, options = {}) {
|
|
59158
|
-
return this.
|
|
59292
|
+
return answer(await this.api.post("/api/users/{userId}/model-credential", {
|
|
59293
|
+
path: { userId },
|
|
59294
|
+
body: options.provider ? { provider: options.provider } : {}
|
|
59295
|
+
}));
|
|
59159
59296
|
}
|
|
59160
59297
|
// ── GitHub OAuth token ──────────────────────────────────────────
|
|
59161
59298
|
/**
|
|
@@ -59166,50 +59303,23 @@ var require_client = __commonJS({
|
|
|
59166
59303
|
* NotFound) when the user has not connected GitHub.
|
|
59167
59304
|
*/
|
|
59168
59305
|
async getUserGithubToken(userId) {
|
|
59169
|
-
return this.
|
|
59170
|
-
}
|
|
59171
|
-
// ── HTTP ────────────────────────────────────────────────────────
|
|
59172
|
-
/**
|
|
59173
|
-
* Reads the response envelope WITHOUT treating `success: false` as a
|
|
59174
|
-
* failure. Sign-in and sign-up use it because a challenge arrives on a 2xx
|
|
59175
|
-
* with success:false and no error object — `request` would raise a
|
|
59176
|
-
* misleading "Request failed with status 200" and give the caller no way to
|
|
59177
|
-
* tell MFA from a bad password (whittlelabs#530). A real error still throws.
|
|
59178
|
-
*/
|
|
59179
|
-
async envelope(method, path, body2) {
|
|
59180
|
-
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
59181
|
-
method,
|
|
59182
|
-
headers: this.headers,
|
|
59183
|
-
body: body2 ? JSON.stringify(body2) : void 0
|
|
59184
|
-
});
|
|
59185
|
-
const json = await response.json();
|
|
59186
|
-
if (!response.ok || !json.success && !json.challenge) {
|
|
59187
|
-
const error = new Error(json.error?.message ?? `Request failed with status ${response.status}`);
|
|
59188
|
-
error.code = json.error?.code;
|
|
59189
|
-
error.statusCode = response.status;
|
|
59190
|
-
throw error;
|
|
59191
|
-
}
|
|
59192
|
-
return json;
|
|
59193
|
-
}
|
|
59194
|
-
async request(method, path, body2) {
|
|
59195
|
-
const url = `${this.baseUrl}${path}`;
|
|
59196
|
-
const response = await fetch(url, {
|
|
59197
|
-
method,
|
|
59198
|
-
headers: this.headers,
|
|
59199
|
-
body: body2 ? JSON.stringify(body2) : void 0
|
|
59200
|
-
});
|
|
59201
|
-
const json = await response.json();
|
|
59202
|
-
if (!response.ok || !json.success) {
|
|
59203
|
-
const errorMessage = json.error?.message ?? `Request failed with status ${response.status}`;
|
|
59204
|
-
const error = new Error(errorMessage);
|
|
59205
|
-
error.code = json.error?.code;
|
|
59206
|
-
error.statusCode = response.status;
|
|
59207
|
-
throw error;
|
|
59208
|
-
}
|
|
59209
|
-
return json.data;
|
|
59306
|
+
return answer(await this.api.get("/api/users/{userId}/github-token", { path: { userId } }));
|
|
59210
59307
|
}
|
|
59211
59308
|
};
|
|
59212
59309
|
exports2.KeepClient = KeepClient;
|
|
59310
|
+
function signedIn(answered) {
|
|
59311
|
+
if ("challenge" in answered)
|
|
59312
|
+
return { kind: "challenge", challenge: answered.challenge };
|
|
59313
|
+
return { kind: "session", user: answered.user, session: answered.session };
|
|
59314
|
+
}
|
|
59315
|
+
function answer(result) {
|
|
59316
|
+
if (result.success)
|
|
59317
|
+
return result.data;
|
|
59318
|
+
const error = new Error(result.error.message);
|
|
59319
|
+
error.code = result.error.code;
|
|
59320
|
+
error.statusCode = result.error.status ?? void 0;
|
|
59321
|
+
throw error;
|
|
59322
|
+
}
|
|
59213
59323
|
}
|
|
59214
59324
|
});
|
|
59215
59325
|
|
|
@@ -59299,6 +59409,7 @@ var require_exchange = __commonJS({
|
|
|
59299
59409
|
exports2.KeepUnavailableError = void 0;
|
|
59300
59410
|
exports2.exchangeCredentials = exchangeCredentials;
|
|
59301
59411
|
exports2.hostOf = hostOf;
|
|
59412
|
+
var keep_1 = require_keep();
|
|
59302
59413
|
var rate_limited_1 = require_rate_limited();
|
|
59303
59414
|
var KeepUnavailableError = class extends Error {
|
|
59304
59415
|
code = "SERVICE_UNAVAILABLE";
|
|
@@ -59315,52 +59426,77 @@ var require_exchange = __commonJS({
|
|
|
59315
59426
|
};
|
|
59316
59427
|
exports2.KeepUnavailableError = KeepUnavailableError;
|
|
59317
59428
|
async function exchangeCredentials(request) {
|
|
59318
|
-
const { manager
|
|
59319
|
-
const host = hostOf(
|
|
59320
|
-
let
|
|
59321
|
-
|
|
59322
|
-
|
|
59323
|
-
|
|
59324
|
-
|
|
59325
|
-
|
|
59326
|
-
|
|
59327
|
-
|
|
59328
|
-
|
|
59329
|
-
|
|
59330
|
-
|
|
59331
|
-
|
|
59429
|
+
const { manager } = request;
|
|
59430
|
+
const host = hostOf(request.keepApiUrl);
|
|
59431
|
+
let raised;
|
|
59432
|
+
const raise = (error) => {
|
|
59433
|
+
raised = { error };
|
|
59434
|
+
throw error;
|
|
59435
|
+
};
|
|
59436
|
+
let refusalMessage;
|
|
59437
|
+
const api = (0, keep_1.createClient)({
|
|
59438
|
+
baseUrl: request.keepApiUrl,
|
|
59439
|
+
transport: async (url, init2) => {
|
|
59440
|
+
let response;
|
|
59441
|
+
try {
|
|
59442
|
+
response = await fetch(url, init2);
|
|
59443
|
+
} catch (err2) {
|
|
59444
|
+
return raise(new KeepUnavailableError(`[${manager}] could not reach Keep at ${host}: ${describeTransportError(err2)}`, {
|
|
59445
|
+
host,
|
|
59446
|
+
statusCode: null,
|
|
59447
|
+
cause: err2
|
|
59448
|
+
}));
|
|
59449
|
+
}
|
|
59450
|
+
try {
|
|
59451
|
+
request.onResponse?.(response);
|
|
59452
|
+
} catch (err2) {
|
|
59453
|
+
return raise(err2);
|
|
59454
|
+
}
|
|
59455
|
+
const text = await response.text().catch(() => "");
|
|
59456
|
+
const json = parsedEnvelope(text);
|
|
59457
|
+
if (response.status >= 500) {
|
|
59458
|
+
const reason = json?.error?.message ?? `${request.exchangeName} failed with status ${response.status}`;
|
|
59459
|
+
return raise(new KeepUnavailableError(`[${manager}] Keep at ${host} is unavailable (${response.status}): ${reason}`, {
|
|
59460
|
+
host,
|
|
59461
|
+
statusCode: response.status
|
|
59462
|
+
}));
|
|
59463
|
+
}
|
|
59464
|
+
if (response.status === 429) {
|
|
59465
|
+
return raise(request.rateLimit.close({
|
|
59466
|
+
manager,
|
|
59467
|
+
host,
|
|
59468
|
+
reason: json?.error?.message ?? "Too Many Requests",
|
|
59469
|
+
retryAfterMs: (0, rate_limited_1.retryAfterMsOf)(json, response.headers)
|
|
59470
|
+
}));
|
|
59471
|
+
}
|
|
59472
|
+
if (json === null) {
|
|
59473
|
+
return raise(new Error(`[${manager}] Keep at ${host} answered ${response.status} with a body that is not JSON`));
|
|
59474
|
+
}
|
|
59475
|
+
refusalMessage = json.error?.message;
|
|
59476
|
+
if (response.ok && json.success === false) {
|
|
59477
|
+
return raise(new Error(`[${manager}] ${refusalMessage ?? `${request.exchangeName} failed with status ${response.status}`}`));
|
|
59478
|
+
}
|
|
59479
|
+
return new Response(text, { status: response.status, statusText: response.statusText, headers: response.headers });
|
|
59480
|
+
}
|
|
59481
|
+
});
|
|
59482
|
+
const result = await request.send(api);
|
|
59483
|
+
if (raised)
|
|
59484
|
+
throw raised.error;
|
|
59485
|
+
if (result.success)
|
|
59486
|
+
return result.data;
|
|
59487
|
+
const msg = refusalMessage ?? `${request.exchangeName} failed with status ${result.error.status}`;
|
|
59488
|
+
if (result.error.status === 401 && request.refused) {
|
|
59489
|
+
throw request.refused(msg);
|
|
59332
59490
|
}
|
|
59333
|
-
|
|
59334
|
-
|
|
59335
|
-
|
|
59491
|
+
throw new Error(`[${manager}] ${msg}`);
|
|
59492
|
+
}
|
|
59493
|
+
function parsedEnvelope(text) {
|
|
59336
59494
|
try {
|
|
59337
|
-
|
|
59495
|
+
const parsed = JSON.parse(text);
|
|
59496
|
+
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
59338
59497
|
} catch {
|
|
59339
|
-
|
|
59340
|
-
}
|
|
59341
|
-
if (response.status >= 500) {
|
|
59342
|
-
const reason = json?.error?.message ?? `${request.exchangeName} failed with status ${response.status}`;
|
|
59343
|
-
throw new KeepUnavailableError(`[${manager}] Keep at ${host} is unavailable (${response.status}): ${reason}`, { host, statusCode: response.status });
|
|
59344
|
-
}
|
|
59345
|
-
if (response.status === 429) {
|
|
59346
|
-
throw request.rateLimit.close({
|
|
59347
|
-
manager,
|
|
59348
|
-
host,
|
|
59349
|
-
reason: json?.error?.message ?? "Too Many Requests",
|
|
59350
|
-
retryAfterMs: (0, rate_limited_1.retryAfterMsOf)(json, response.headers)
|
|
59351
|
-
});
|
|
59352
|
-
}
|
|
59353
|
-
if (json === null) {
|
|
59354
|
-
throw new Error(`[${manager}] Keep at ${host} answered ${response.status} with a body that is not JSON`);
|
|
59355
|
-
}
|
|
59356
|
-
if (!response.ok || !json.success) {
|
|
59357
|
-
const msg = json.error?.message ?? `${request.exchangeName} failed with status ${response.status}`;
|
|
59358
|
-
if (response.status === 401 && request.refused) {
|
|
59359
|
-
throw request.refused(msg);
|
|
59360
|
-
}
|
|
59361
|
-
throw new Error(`[${manager}] ${msg}`);
|
|
59498
|
+
return null;
|
|
59362
59499
|
}
|
|
59363
|
-
return json.data;
|
|
59364
59500
|
}
|
|
59365
59501
|
function hostOf(url) {
|
|
59366
59502
|
try {
|
|
@@ -59604,9 +59740,8 @@ var require_service_token = __commonJS({
|
|
|
59604
59740
|
async exchange() {
|
|
59605
59741
|
const data = await (0, exchange_1.exchangeCredentials)({
|
|
59606
59742
|
manager: "ServiceTokenManager",
|
|
59607
|
-
|
|
59608
|
-
clientId: this.clientId,
|
|
59609
|
-
clientSecret: this.clientSecret,
|
|
59743
|
+
keepApiUrl: this.keepApiUrl,
|
|
59744
|
+
send: (api) => api.post("/api/service-tokens", { body: { clientId: this.clientId, clientSecret: this.clientSecret } }),
|
|
59610
59745
|
rateLimit: this.rateLimit,
|
|
59611
59746
|
onResponse: this.onResponse,
|
|
59612
59747
|
exchangeName: "Token exchange",
|
|
@@ -59677,9 +59812,8 @@ var require_agent_token = __commonJS({
|
|
|
59677
59812
|
async exchange() {
|
|
59678
59813
|
const data = await (0, exchange_1.exchangeCredentials)({
|
|
59679
59814
|
manager: "AgentTokenManager",
|
|
59680
|
-
|
|
59681
|
-
clientId: this.clientId,
|
|
59682
|
-
clientSecret: this.clientSecret,
|
|
59815
|
+
keepApiUrl: this.keepApiUrl,
|
|
59816
|
+
send: (api) => api.post("/api/agent-tokens", { body: { clientId: this.clientId, clientSecret: this.clientSecret } }),
|
|
59683
59817
|
rateLimit: this.rateLimit,
|
|
59684
59818
|
onResponse: this.onResponse,
|
|
59685
59819
|
exchangeName: "Agent token exchange",
|
|
@@ -59700,7 +59834,7 @@ var require_dist4 = __commonJS({
|
|
|
59700
59834
|
"use strict";
|
|
59701
59835
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
59702
59836
|
exports2.waitForKeepToken = exports2.KeepCredentialsRefusedError = exports2.KeepRateLimitedError = exports2.KeepUnavailableError = exports2.AgentCredentialRevokedError = exports2.AgentTokenManager = exports2.ServiceTokenManager = exports2.KeepClient = void 0;
|
|
59703
|
-
var client_1 =
|
|
59837
|
+
var client_1 = require_client2();
|
|
59704
59838
|
Object.defineProperty(exports2, "KeepClient", { enumerable: true, get: function() {
|
|
59705
59839
|
return client_1.KeepClient;
|
|
59706
59840
|
} });
|
|
@@ -68558,13 +68692,28 @@ var require_typed_exit = __commonJS({
|
|
|
68558
68692
|
}
|
|
68559
68693
|
});
|
|
68560
68694
|
|
|
68695
|
+
// ../../packages/contracts/dist/services/jobs.js
|
|
68696
|
+
var require_jobs = __commonJS({
|
|
68697
|
+
"../../packages/contracts/dist/services/jobs.js"(exports2) {
|
|
68698
|
+
"use strict";
|
|
68699
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
68700
|
+
exports2.service = void 0;
|
|
68701
|
+
exports2.createClient = createClient;
|
|
68702
|
+
var client_1 = require_client();
|
|
68703
|
+
exports2.service = "whittle-jobs";
|
|
68704
|
+
function createClient(options) {
|
|
68705
|
+
return (0, client_1.createContractClient)(options);
|
|
68706
|
+
}
|
|
68707
|
+
}
|
|
68708
|
+
});
|
|
68709
|
+
|
|
68561
68710
|
// ../../packages/jobs/dist/response.js
|
|
68562
68711
|
var require_response = __commonJS({
|
|
68563
68712
|
"../../packages/jobs/dist/response.js"(exports2) {
|
|
68564
68713
|
"use strict";
|
|
68565
68714
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
68566
68715
|
exports2.NonJsonResponseError = exports2.ServiceUnavailableError = void 0;
|
|
68567
|
-
exports2.
|
|
68716
|
+
exports2.refuseUnreadable = refuseUnreadable;
|
|
68568
68717
|
var EXCERPT_LIMIT = 120;
|
|
68569
68718
|
var UNAVAILABLE_STATUSES = /* @__PURE__ */ new Set([502, 503, 504]);
|
|
68570
68719
|
var UnreadableResponseError = class extends Error {
|
|
@@ -68618,31 +68767,31 @@ var require_response = __commonJS({
|
|
|
68618
68767
|
return url;
|
|
68619
68768
|
}
|
|
68620
68769
|
}
|
|
68621
|
-
async function
|
|
68770
|
+
async function refuseUnreadable(response, url) {
|
|
68622
68771
|
const contentType = response.headers.get("content-type");
|
|
68623
68772
|
const unavailable = UNAVAILABLE_STATUSES.has(response.status);
|
|
68624
|
-
if (unavailable
|
|
68625
|
-
|
|
68626
|
-
|
|
68627
|
-
|
|
68628
|
-
|
|
68629
|
-
|
|
68630
|
-
|
|
68631
|
-
|
|
68632
|
-
|
|
68633
|
-
|
|
68634
|
-
|
|
68635
|
-
return await response.json();
|
|
68773
|
+
if (!unavailable && isJson(contentType))
|
|
68774
|
+
return;
|
|
68775
|
+
const body2 = await response.text().catch(() => "");
|
|
68776
|
+
const detail = {
|
|
68777
|
+
host: hostOf(url),
|
|
68778
|
+
statusCode: response.status,
|
|
68779
|
+
statusText: response.statusText ?? "",
|
|
68780
|
+
contentType,
|
|
68781
|
+
bodyExcerpt: excerpt(body2)
|
|
68782
|
+
};
|
|
68783
|
+
throw unavailable ? new ServiceUnavailableError(detail) : new NonJsonResponseError(detail);
|
|
68636
68784
|
}
|
|
68637
68785
|
}
|
|
68638
68786
|
});
|
|
68639
68787
|
|
|
68640
68788
|
// ../../packages/jobs/dist/client.js
|
|
68641
|
-
var
|
|
68789
|
+
var require_client3 = __commonJS({
|
|
68642
68790
|
"../../packages/jobs/dist/client.js"(exports2) {
|
|
68643
68791
|
"use strict";
|
|
68644
68792
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
68645
68793
|
exports2.JobsClient = void 0;
|
|
68794
|
+
var jobs_1 = require_jobs();
|
|
68646
68795
|
var response_1 = require_response();
|
|
68647
68796
|
var JobsClient = class {
|
|
68648
68797
|
baseUrl;
|
|
@@ -68682,19 +68831,26 @@ var require_client2 = __commonJS({
|
|
|
68682
68831
|
* revoke-then-repair, clock skew) while the local expiry timer still thinks
|
|
68683
68832
|
* it's valid. Force a re-mint and retry once before surfacing the failure.
|
|
68684
68833
|
* `onResponse` (min-version contract) fires on the response we actually act
|
|
68685
|
-
* on.
|
|
68834
|
+
* on. The contract client hands over its body as a string, so it is safe to resend.
|
|
68686
68835
|
*/
|
|
68687
|
-
async fetchWithAuthRetry(
|
|
68688
|
-
|
|
68836
|
+
async fetchWithAuthRetry(url, init2) {
|
|
68837
|
+
const send = async (forceRefresh) => {
|
|
68838
|
+
const headers = new Headers(init2.headers);
|
|
68839
|
+
for (const [name2, value] of Object.entries(await this.buildHeaders(forceRefresh)))
|
|
68840
|
+
headers.set(name2, value);
|
|
68841
|
+
return fetch(url, { ...init2, headers });
|
|
68842
|
+
};
|
|
68843
|
+
let response = await send(false);
|
|
68689
68844
|
if (response.status === 401 && this.getAccessToken) {
|
|
68690
|
-
|
|
68845
|
+
await response.body?.cancel().catch(() => void 0);
|
|
68846
|
+
response = await send(true);
|
|
68691
68847
|
}
|
|
68692
68848
|
this.onResponse?.(response);
|
|
68693
68849
|
return response;
|
|
68694
68850
|
}
|
|
68695
68851
|
// ── Job Pools ──────────────────────────────────────────────
|
|
68696
68852
|
async createJobPool(options) {
|
|
68697
|
-
return this.
|
|
68853
|
+
return this.call((api) => api.post("/api/job-pools", { body: options }));
|
|
68698
68854
|
}
|
|
68699
68855
|
/**
|
|
68700
68856
|
* Idempotent upsert by owner and name. When the
|
|
@@ -68702,7 +68858,7 @@ var require_client2 = __commonJS({
|
|
|
68702
68858
|
* constraints. The Sift provisioning hook relies on this semantics.
|
|
68703
68859
|
*/
|
|
68704
68860
|
async findOrCreateJobPool(options) {
|
|
68705
|
-
return this.
|
|
68861
|
+
return this.call((api) => api.post("/api/job-pools", { query: { idempotent: "true" }, body: options }));
|
|
68706
68862
|
}
|
|
68707
68863
|
/**
|
|
68708
68864
|
* Every tenant's pools, which needs jobs:job-pools:read at operator context
|
|
@@ -68710,17 +68866,12 @@ var require_client2 = __commonJS({
|
|
|
68710
68866
|
* one exact name; neither confers standing (BE-035).
|
|
68711
68867
|
*/
|
|
68712
68868
|
async listJobPools(filters) {
|
|
68713
|
-
const
|
|
68714
|
-
|
|
68715
|
-
params.set("owner", `${filters.owner.principalClass}:${filters.owner.principalId}`);
|
|
68716
|
-
if (filters?.name)
|
|
68717
|
-
params.set("name", filters.name);
|
|
68718
|
-
const qs = params.toString();
|
|
68719
|
-
const { pools } = await this.request("GET", `/api/job-pools${qs ? `?${qs}` : ""}`);
|
|
68869
|
+
const owner = filters?.owner ? `${filters.owner.principalClass}:${filters.owner.principalId}` : void 0;
|
|
68870
|
+
const { pools } = await this.call((api) => api.get("/api/job-pools", { query: { owner, name: filters?.name } }));
|
|
68720
68871
|
return pools;
|
|
68721
68872
|
}
|
|
68722
68873
|
async getJobPool(poolId) {
|
|
68723
|
-
return this.
|
|
68874
|
+
return this.call((api) => api.get("/api/job-pools/{id}", { path: { id: poolId } }));
|
|
68724
68875
|
}
|
|
68725
68876
|
/**
|
|
68726
68877
|
* Resolve a pool by exact name. Names are unique per OWNER, not globally
|
|
@@ -68756,46 +68907,51 @@ var require_client2 = __commonJS({
|
|
|
68756
68907
|
// A subscriber joins a pool by registering as a member of it. These
|
|
68757
68908
|
// map to the server's `/api/job-pools/:poolId/members` routes.
|
|
68758
68909
|
async listMembers(poolId) {
|
|
68759
|
-
const { members } = await this.
|
|
68910
|
+
const { members } = await this.call((api) => api.get("/api/job-pools/{poolId}/members", { path: { poolId } }));
|
|
68760
68911
|
return members;
|
|
68761
68912
|
}
|
|
68762
68913
|
async registerMember(poolId, options) {
|
|
68763
|
-
return this.
|
|
68914
|
+
return this.call((api) => api.post("/api/job-pools/{poolId}/members", { path: { poolId }, body: options }));
|
|
68764
68915
|
}
|
|
68765
68916
|
async updateMember(poolId, memberId, options) {
|
|
68766
|
-
return this.
|
|
68917
|
+
return this.call((api) => api.put("/api/job-pools/{poolId}/members/{mid}", { path: { poolId, mid: memberId }, body: options }));
|
|
68767
68918
|
}
|
|
68768
68919
|
// ── Jobs (producer) ──────────────────────────────────────────────
|
|
68769
68920
|
/**
|
|
68770
68921
|
* Enqueue a job into a job pool. The `inputs` are opaque to Jobs; a Shuttle
|
|
68771
68922
|
* reads the strategy header inside them to decide how to run it (ADR 0005).
|
|
68923
|
+
* The body names its fields one by one, so nothing a caller spreads into
|
|
68924
|
+
* the options reaches the wire.
|
|
68772
68925
|
*/
|
|
68773
68926
|
async enqueueJob(options) {
|
|
68774
68927
|
const jobPoolId = await this.resolvePoolRef(options.pool);
|
|
68775
|
-
|
|
68776
|
-
|
|
68777
|
-
|
|
68778
|
-
|
|
68779
|
-
|
|
68780
|
-
|
|
68781
|
-
|
|
68782
|
-
|
|
68783
|
-
|
|
68784
|
-
|
|
68785
|
-
|
|
68786
|
-
|
|
68787
|
-
|
|
68788
|
-
|
|
68789
|
-
|
|
68928
|
+
return this.call((api) => api.post("/api/jobs", {
|
|
68929
|
+
body: {
|
|
68930
|
+
jobPoolId,
|
|
68931
|
+
title: options.title,
|
|
68932
|
+
progressChannel: options.progressChannel,
|
|
68933
|
+
instructions: options.instructions,
|
|
68934
|
+
maxAttempts: options.maxAttempts,
|
|
68935
|
+
deadlineDuration: options.deadlineDuration,
|
|
68936
|
+
claimDeadlineDuration: options.claimDeadlineDuration,
|
|
68937
|
+
priority: options.priority,
|
|
68938
|
+
tags: options.tags,
|
|
68939
|
+
clientRef: options.clientRef,
|
|
68940
|
+
clientContext: options.clientContext,
|
|
68941
|
+
inputs: options.inputs
|
|
68942
|
+
}
|
|
68943
|
+
}));
|
|
68790
68944
|
}
|
|
68791
68945
|
async getJob(jobId) {
|
|
68792
|
-
return this.
|
|
68946
|
+
return this.call((api) => api.get("/api/jobs/{id}", { path: { id: jobId } }));
|
|
68793
68947
|
}
|
|
68948
|
+
/** Answers the job without its inputs, as the route does. */
|
|
68794
68949
|
async updateJob(jobId, options) {
|
|
68795
|
-
return this.
|
|
68950
|
+
return this.call((api) => api.patch("/api/jobs/{id}", { path: { id: jobId }, body: options }));
|
|
68796
68951
|
}
|
|
68952
|
+
/** Answers the job without its inputs, as the route does. */
|
|
68797
68953
|
async cancelJob(jobId) {
|
|
68798
|
-
return this.
|
|
68954
|
+
return this.call((api) => api.put("/api/jobs/{id}", { path: { id: jobId } }));
|
|
68799
68955
|
}
|
|
68800
68956
|
/**
|
|
68801
68957
|
* Permanently delete every job filed under `clientRefPrefix` (which must end
|
|
@@ -68803,14 +68959,14 @@ var require_client2 = __commonJS({
|
|
|
68803
68959
|
* the caller needs `jobs:job-purges:write` at '*'. Idempotent.
|
|
68804
68960
|
*/
|
|
68805
68961
|
async purgeJobs(clientRefPrefix) {
|
|
68806
|
-
return this.
|
|
68962
|
+
return this.call((api) => api.post("/api/job-purges", { body: { clientRefPrefix } }));
|
|
68807
68963
|
}
|
|
68808
68964
|
// ── Outputs ──────────────────────────────────────────────────────
|
|
68809
68965
|
async listOutputs(jobId) {
|
|
68810
68966
|
const all = [];
|
|
68811
|
-
const
|
|
68812
|
-
for (let offset = 0; ; offset +=
|
|
68813
|
-
const { outputs, total } = await this.
|
|
68967
|
+
const limit = 100;
|
|
68968
|
+
for (let offset = 0; ; offset += limit) {
|
|
68969
|
+
const { outputs, total } = await this.call((api) => api.get("/api/jobs/{jobId}/output", { path: { jobId }, query: { limit, offset } }));
|
|
68814
68970
|
all.push(...outputs);
|
|
68815
68971
|
if (outputs.length === 0 || all.length >= total)
|
|
68816
68972
|
break;
|
|
@@ -68818,7 +68974,7 @@ var require_client2 = __commonJS({
|
|
|
68818
68974
|
return all;
|
|
68819
68975
|
}
|
|
68820
68976
|
async createOutput(jobId, options) {
|
|
68821
|
-
return this.
|
|
68977
|
+
return this.call((api) => api.post("/api/jobs/{jobId}/output", { path: { jobId }, body: options }));
|
|
68822
68978
|
}
|
|
68823
68979
|
/**
|
|
68824
68980
|
* Post a batch of live progress frames for a running job. Best-effort
|
|
@@ -68827,7 +68983,7 @@ var require_client2 = __commonJS({
|
|
|
68827
68983
|
* let a dropped frame affect the job.
|
|
68828
68984
|
*/
|
|
68829
68985
|
async postProgress(jobId, options) {
|
|
68830
|
-
await this.
|
|
68986
|
+
await this.call((api) => api.post("/api/jobs/{jobId}/progress", { path: { jobId }, body: options }));
|
|
68831
68987
|
}
|
|
68832
68988
|
// ── Attendance (subscriber dispatch lifecycle) ───────────────────
|
|
68833
68989
|
/**
|
|
@@ -68836,7 +68992,10 @@ var require_client2 = __commonJS({
|
|
|
68836
68992
|
* subscriber needs to execute and submit.
|
|
68837
68993
|
*/
|
|
68838
68994
|
async acceptDispatch(jobId, options) {
|
|
68839
|
-
return this.
|
|
68995
|
+
return this.call((api) => api.post("/api/jobs/{jobId}/attendance", {
|
|
68996
|
+
path: { jobId },
|
|
68997
|
+
body: options?.shiftId ? { shiftId: options.shiftId } : void 0
|
|
68998
|
+
}));
|
|
68840
68999
|
}
|
|
68841
69000
|
// ── Shifts (whittlelabs ADR 0129) ────────────────────────────────
|
|
68842
69001
|
/**
|
|
@@ -68844,39 +69003,33 @@ var require_client2 = __commonJS({
|
|
|
68844
69003
|
* answers 404; the subscribe loop then claims without one.
|
|
68845
69004
|
*/
|
|
68846
69005
|
async startShift() {
|
|
68847
|
-
return this.
|
|
69006
|
+
return this.call((api) => api.post("/api/my/shifts"));
|
|
68848
69007
|
}
|
|
68849
69008
|
/** End a shift, releasing every claim still taken on it back to the queue. */
|
|
68850
69009
|
async endShift(shiftId) {
|
|
68851
|
-
await this.
|
|
69010
|
+
await this.call((api) => api.delete("/api/my/shifts/{shiftId}", { path: { shiftId } }));
|
|
68852
69011
|
}
|
|
68853
69012
|
async submit(jobId, options) {
|
|
68854
|
-
return this.
|
|
69013
|
+
return this.call((api) => api.put("/api/jobs/{jobId}/attendance", { path: { jobId }, body: options }));
|
|
68855
69014
|
}
|
|
68856
69015
|
// ── Discovery (rare) ─────────────────────────────────────────────
|
|
68857
69016
|
async listDispatchableJobs(options) {
|
|
68858
|
-
const
|
|
68859
|
-
|
|
68860
|
-
|
|
68861
|
-
|
|
68862
|
-
|
|
68863
|
-
|
|
68864
|
-
|
|
68865
|
-
|
|
68866
|
-
|
|
68867
|
-
|
|
68868
|
-
|
|
68869
|
-
|
|
68870
|
-
params.set("offset", String(options.offset));
|
|
68871
|
-
if (options?.sort)
|
|
68872
|
-
params.set("sort", options.sort);
|
|
68873
|
-
if (options?.shift)
|
|
68874
|
-
params.set("shift", options.shift);
|
|
68875
|
-
const qs = params.toString();
|
|
68876
|
-
const { jobs, total, directives, shift } = await this.request("GET", `/api/my/jobs${qs ? `?${qs}` : ""}`);
|
|
69017
|
+
const { jobs, total, directives, shift } = await this.call((api) => api.get("/api/my/jobs", {
|
|
69018
|
+
query: {
|
|
69019
|
+
pools: options?.pools?.length ? options.pools.join(",") : void 0,
|
|
69020
|
+
tags: options?.tags?.length ? options.tags.join(",") : void 0,
|
|
69021
|
+
maxAttempts: options?.maxAttempts === void 0 ? void 0 : String(options.maxAttempts),
|
|
69022
|
+
minPriority: options?.minPriority === void 0 ? void 0 : String(options.minPriority),
|
|
69023
|
+
limit: options?.limit,
|
|
69024
|
+
offset: options?.offset,
|
|
69025
|
+
sort: options?.sort || void 0,
|
|
69026
|
+
shift: options?.shift || void 0
|
|
69027
|
+
}
|
|
69028
|
+
}));
|
|
68877
69029
|
return {
|
|
68878
69030
|
data: jobs,
|
|
68879
69031
|
pagination: { total, limit: options?.limit ?? 25, offset: options?.offset ?? 0 },
|
|
69032
|
+
// Absent from a Jobs that predates directives or shifts.
|
|
68880
69033
|
directives: directives ?? null,
|
|
68881
69034
|
shift: shift ?? null
|
|
68882
69035
|
};
|
|
@@ -68890,38 +69043,47 @@ var require_client2 = __commonJS({
|
|
|
68890
69043
|
async openHintStream(options = {}) {
|
|
68891
69044
|
const qs = options.shift ? `?shift=${encodeURIComponent(options.shift)}` : "";
|
|
68892
69045
|
const url = `${this.baseUrl}/api/my/jobs/stream${qs}`;
|
|
68893
|
-
|
|
68894
|
-
...
|
|
68895
|
-
|
|
68896
|
-
...options.lastEventId ? { "Last-Event-ID": options.lastEventId } : {}
|
|
69046
|
+
return this.fetchWithAuthRetry(url, {
|
|
69047
|
+
headers: { Accept: "text/event-stream", ...options.lastEventId ? { "Last-Event-ID": options.lastEventId } : {} },
|
|
69048
|
+
signal: options.signal
|
|
68897
69049
|
});
|
|
68898
|
-
let response = await fetch(url, { headers: await headers(false), signal: options.signal });
|
|
68899
|
-
if (response.status === 401 && this.getAccessToken) {
|
|
68900
|
-
await response.body?.cancel().catch(() => void 0);
|
|
68901
|
-
response = await fetch(url, { headers: await headers(true), signal: options.signal });
|
|
68902
|
-
}
|
|
68903
|
-
this.onResponse?.(response);
|
|
68904
|
-
return response;
|
|
68905
69050
|
}
|
|
68906
69051
|
// ── HTTP plumbing ────────────────────────────────────────────────
|
|
68907
69052
|
/**
|
|
68908
|
-
* Every call's one
|
|
68909
|
-
*
|
|
68910
|
-
*
|
|
68911
|
-
*
|
|
69053
|
+
* Every call's one path. The contract client builds the request and reads
|
|
69054
|
+
* the API's envelope; the transport under it authenticates (one retry on a
|
|
69055
|
+
* 401 for a token provider), fires `onResponse`, and refuses a reply that is
|
|
69056
|
+
* not the API's JSON with a named failure (`refuseUnreadable`: an ingress
|
|
69057
|
+
* 502/503/504 while a pod rolls, or any non-JSON body). A failure the
|
|
69058
|
+
* transport raises is rethrown as raised, so `ServiceUnavailableError` and
|
|
69059
|
+
* fetch's own `TypeError` reach the subscribe loop's outage handling rather
|
|
69060
|
+
* than arriving as a NETWORK_ERROR result. The API's own refusal throws an
|
|
69061
|
+
* `Error` carrying `code` and `statusCode`, as it always has.
|
|
68912
69062
|
*/
|
|
68913
|
-
async
|
|
68914
|
-
|
|
68915
|
-
const
|
|
68916
|
-
|
|
68917
|
-
|
|
68918
|
-
|
|
68919
|
-
|
|
68920
|
-
|
|
68921
|
-
|
|
68922
|
-
|
|
68923
|
-
|
|
68924
|
-
|
|
69063
|
+
async call(send) {
|
|
69064
|
+
let raised;
|
|
69065
|
+
const api = (0, jobs_1.createClient)({
|
|
69066
|
+
baseUrl: this.baseUrl,
|
|
69067
|
+
transport: async (url, init2) => {
|
|
69068
|
+
try {
|
|
69069
|
+
const response = await this.fetchWithAuthRetry(url, init2);
|
|
69070
|
+
await (0, response_1.refuseUnreadable)(response, url);
|
|
69071
|
+
return response;
|
|
69072
|
+
} catch (error2) {
|
|
69073
|
+
raised = { error: error2 };
|
|
69074
|
+
throw error2;
|
|
69075
|
+
}
|
|
69076
|
+
}
|
|
69077
|
+
});
|
|
69078
|
+
const result = await send(api);
|
|
69079
|
+
if (raised)
|
|
69080
|
+
throw raised.error;
|
|
69081
|
+
if (result.success)
|
|
69082
|
+
return result.data;
|
|
69083
|
+
const error = new Error(result.error.message);
|
|
69084
|
+
error.code = result.error.code;
|
|
69085
|
+
error.statusCode = result.error.status ?? void 0;
|
|
69086
|
+
throw error;
|
|
68925
69087
|
}
|
|
68926
69088
|
};
|
|
68927
69089
|
exports2.JobsClient = JobsClient;
|
|
@@ -69804,7 +69966,7 @@ var require_dist7 = __commonJS({
|
|
|
69804
69966
|
"use strict";
|
|
69805
69967
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
69806
69968
|
exports2.subscribe = exports2.ServiceUnavailableError = exports2.NonJsonResponseError = exports2.JobsClient = void 0;
|
|
69807
|
-
var client_1 =
|
|
69969
|
+
var client_1 = require_client3();
|
|
69808
69970
|
Object.defineProperty(exports2, "JobsClient", { enumerable: true, get: function() {
|
|
69809
69971
|
return client_1.JobsClient;
|
|
69810
69972
|
} });
|
|
@@ -76245,7 +76407,7 @@ var import_shuttle2 = __toESM(require_dist8());
|
|
|
76245
76407
|
|
|
76246
76408
|
// src/brand.ts
|
|
76247
76409
|
var import_shuttle = __toESM(require_dist8());
|
|
76248
|
-
var buildVersion = true ? "0.43.
|
|
76410
|
+
var buildVersion = true ? "0.43.4" : pkg.version;
|
|
76249
76411
|
var AGENT_EXECUTORS = ["claude-code", "codex", "copilot"];
|
|
76250
76412
|
var sifterBrand = {
|
|
76251
76413
|
product: {
|