@butlerbot/sdk 0.0.37 → 0.0.39
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/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.js +10 -1
- package/dist/modules/jobs.d.ts +29 -1
- package/dist/modules/jobs.js +30 -1
- package/dist/types/jobs/job.d.ts +41 -1
- package/package.json +1 -1
- package/readme.md +10 -2
package/dist/config.d.ts
CHANGED
|
@@ -60,7 +60,7 @@ export declare const CONFIG: {
|
|
|
60
60
|
};
|
|
61
61
|
};
|
|
62
62
|
jobs: {
|
|
63
|
-
/** The collection. One job is `${base}/${jobId}`, its cancel `${base}/${jobId}/cancel`. */
|
|
63
|
+
/** The collection. One job is `${base}/${jobId}`, its cancel `${base}/${jobId}/cancel` and its resume `${base}/${jobId}/resume`. */
|
|
64
64
|
base: string;
|
|
65
65
|
/** The owner's job settings, which live on the user rather than on a job. */
|
|
66
66
|
settings: string;
|
package/dist/config.js
CHANGED
|
@@ -52,7 +52,7 @@ exports.CONFIG = {
|
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
jobs: {
|
|
55
|
-
/** The collection. One job is `${base}/${jobId}`, its cancel `${base}/${jobId}/cancel`. */
|
|
55
|
+
/** The collection. One job is `${base}/${jobId}`, its cancel `${base}/${jobId}/cancel` and its resume `${base}/${jobId}/resume`. */
|
|
56
56
|
base: "/api/jobs",
|
|
57
57
|
/** The owner's job settings, which live on the user rather than on a job. */
|
|
58
58
|
settings: "/api/user/jobs-settings",
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { APIPath } from "./config";
|
|
|
2
2
|
import { Link, LinkOptions } from "./link";
|
|
3
3
|
import { Conversation, ConversationOptions } from "./modules/conversation";
|
|
4
4
|
import { UsagePolicyDataOptions } from "./modules/usage";
|
|
5
|
-
import { type CancelJobOptions, type GetJobJournalOptions, type GetJobOptions, type ListJobsOptions, type UpdateJobOptions, type UpdateJobSettingsOptions } from "./modules/jobs";
|
|
5
|
+
import { type CancelJobOptions, type GetJobJournalOptions, type GetJobOptions, type SetPhaseModelOptions, type ListJobsOptions, type ResumeJobOptions, type UpdateJobOptions, type UpdateJobSettingsOptions } from "./modules/jobs";
|
|
6
6
|
import { type AnswerDeliveryOptions, type ListDeliveriesOptions } from "./modules/outreach";
|
|
7
7
|
type OptionalApiKey<T> = Omit<T, "apiKey"> & {
|
|
8
8
|
/** Optional API key, defaults to API key specified in client */
|
|
@@ -52,8 +52,12 @@ export declare class ButlerBotClient {
|
|
|
52
52
|
getJobJournal(config: OptionalApiKey<GetJobJournalOptions>): Promise<import("./types/type_registry").JobJournalPage>;
|
|
53
53
|
/** Stops a job. Throws a `ButlerBotAPIError` with `isConflict` when it had already finished */
|
|
54
54
|
cancelJob(config: OptionalApiKey<CancelJobOptions>): Promise<import("./types/type_registry").JobCancelResponse>;
|
|
55
|
+
/** Continues a job parked waiting for budget. Throws a `ButlerBotAPIError` with `isConflict` when it is in any other status */
|
|
56
|
+
resumeJob(config: OptionalApiKey<ResumeJobOptions>): Promise<import("./types/type_registry").JobResumeResponse>;
|
|
55
57
|
/** Changes one job's name, and its autonomy: how far it may act, until when, and what it always asks about */
|
|
56
58
|
updateJob(config: OptionalApiKey<UpdateJobOptions>): Promise<import("./types/type_registry").JobUpdateResponse>;
|
|
59
|
+
/** Changes the model one phase of a job's plan runs on; only a phase that has not started */
|
|
60
|
+
setPhaseModel(config: OptionalApiKey<SetPhaseModelOptions>): Promise<import("./types/type_registry").JobPhaseModelResponse>;
|
|
57
61
|
/** Changes this user's job settings: their daily allowance and what new jobs start with */
|
|
58
62
|
updateJobSettings(config?: OptionalApiKey<UpdateJobSettingsOptions>): Promise<import("./types/type_registry").JobSettingsResponse>;
|
|
59
63
|
/** A page of the inbox: what Alfred has told or asked this user outside a chat */
|
|
@@ -70,8 +74,8 @@ export type { ConversationOptions };
|
|
|
70
74
|
export type { APIPath };
|
|
71
75
|
export type { ConversationStream, ConversationTransport, TransportTurnRequest, TransportHandlers, } from "./modules/transport";
|
|
72
76
|
export { ButlerBotAPIError } from "./util/api_error";
|
|
73
|
-
export { listJobs, getJob, cancelJob, updateJob, updateJobSettings } from "./modules/jobs";
|
|
74
|
-
export type { JobsRequestOptions, ListJobsOptions, GetJobOptions, CancelJobOptions, UpdateJobOptions, UpdateJobSettingsOptions, } from "./modules/jobs";
|
|
77
|
+
export { listJobs, getJob, cancelJob, resumeJob, updateJob, updateJobSettings } from "./modules/jobs";
|
|
78
|
+
export type { JobsRequestOptions, ListJobsOptions, GetJobOptions, CancelJobOptions, ResumeJobOptions, UpdateJobOptions, UpdateJobSettingsOptions, } from "./modules/jobs";
|
|
75
79
|
export { listDeliveries, answerDelivery } from "./modules/outreach";
|
|
76
80
|
export type { OutreachRequestOptions, ListDeliveriesOptions, AnswerDeliveryOptions, } from "./modules/outreach";
|
|
77
81
|
export { LinkConversationTransport } from "./modules/transport_link";
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.SSEConversationTransport = exports.LinkConversationTransport = exports.answerDelivery = exports.listDeliveries = exports.updateJobSettings = exports.updateJob = exports.cancelJob = exports.getJob = exports.listJobs = exports.ButlerBotAPIError = exports.Conversation = exports.ButlerBotClient = void 0;
|
|
17
|
+
exports.SSEConversationTransport = exports.LinkConversationTransport = exports.answerDelivery = exports.listDeliveries = exports.updateJobSettings = exports.updateJob = exports.resumeJob = exports.cancelJob = exports.getJob = exports.listJobs = exports.ButlerBotAPIError = exports.Conversation = exports.ButlerBotClient = void 0;
|
|
18
18
|
const config_1 = require("./config");
|
|
19
19
|
const link_1 = require("./link");
|
|
20
20
|
const conversation_1 = require("./modules/conversation");
|
|
@@ -88,10 +88,18 @@ class ButlerBotClient {
|
|
|
88
88
|
cancelJob(config) {
|
|
89
89
|
return (0, jobs_1.cancelJob)(this.forRequest(config));
|
|
90
90
|
}
|
|
91
|
+
/** Continues a job parked waiting for budget. Throws a `ButlerBotAPIError` with `isConflict` when it is in any other status */
|
|
92
|
+
resumeJob(config) {
|
|
93
|
+
return (0, jobs_1.resumeJob)(this.forRequest(config));
|
|
94
|
+
}
|
|
91
95
|
/** Changes one job's name, and its autonomy: how far it may act, until when, and what it always asks about */
|
|
92
96
|
updateJob(config) {
|
|
93
97
|
return (0, jobs_1.updateJob)(this.forRequest(config));
|
|
94
98
|
}
|
|
99
|
+
/** Changes the model one phase of a job's plan runs on; only a phase that has not started */
|
|
100
|
+
setPhaseModel(config) {
|
|
101
|
+
return (0, jobs_1.setPhaseModel)(this.forRequest(config));
|
|
102
|
+
}
|
|
95
103
|
/** Changes this user's job settings: their daily allowance and what new jobs start with */
|
|
96
104
|
updateJobSettings(config = {}) {
|
|
97
105
|
return (0, jobs_1.updateJobSettings)(this.forRequest(config));
|
|
@@ -119,6 +127,7 @@ var jobs_2 = require("./modules/jobs");
|
|
|
119
127
|
Object.defineProperty(exports, "listJobs", { enumerable: true, get: function () { return jobs_2.listJobs; } });
|
|
120
128
|
Object.defineProperty(exports, "getJob", { enumerable: true, get: function () { return jobs_2.getJob; } });
|
|
121
129
|
Object.defineProperty(exports, "cancelJob", { enumerable: true, get: function () { return jobs_2.cancelJob; } });
|
|
130
|
+
Object.defineProperty(exports, "resumeJob", { enumerable: true, get: function () { return jobs_2.resumeJob; } });
|
|
122
131
|
Object.defineProperty(exports, "updateJob", { enumerable: true, get: function () { return jobs_2.updateJob; } });
|
|
123
132
|
Object.defineProperty(exports, "updateJobSettings", { enumerable: true, get: function () { return jobs_2.updateJobSettings; } });
|
|
124
133
|
var outreach_2 = require("./modules/outreach");
|
package/dist/modules/jobs.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { JobAutonomy, JobCancelResponse, JobDetailResponse, JobJournalPage, JobListResponse, JobSettingsResponse, JobSettingsUpdate, JobStatus, JobUpdateResponse } from "../types/jobs";
|
|
1
|
+
import type { JobAutonomy, JobCancelResponse, JobDetailResponse, JobJournalPage, JobListResponse, JobPhaseModelResponse, JobResumeResponse, JobSettingsResponse, JobSettingsUpdate, JobStatus, JobUpdateResponse } from "../types/jobs";
|
|
2
2
|
/** What every jobs call needs: where the server is, and who is asking. */
|
|
3
3
|
export type JobsRequestOptions = {
|
|
4
4
|
serverURL?: string;
|
|
@@ -28,6 +28,9 @@ export type GetJobJournalOptions = JobsRequestOptions & {
|
|
|
28
28
|
export type CancelJobOptions = JobsRequestOptions & {
|
|
29
29
|
jobId: string;
|
|
30
30
|
};
|
|
31
|
+
export type ResumeJobOptions = JobsRequestOptions & {
|
|
32
|
+
jobId: string;
|
|
33
|
+
};
|
|
31
34
|
export type UpdateJobOptions = JobsRequestOptions & {
|
|
32
35
|
jobId: string;
|
|
33
36
|
/** A new short name for the job, a few words at most. */
|
|
@@ -38,6 +41,15 @@ export type UpdateJobOptions = JobsRequestOptions & {
|
|
|
38
41
|
autonomyUntil?: string | number | null;
|
|
39
42
|
/** Things this job asks about however free it otherwise is. */
|
|
40
43
|
alwaysAsk?: string[];
|
|
44
|
+
/** A ceiling on what the job may spend in all, in dollars. Null clears it. */
|
|
45
|
+
capUsd?: number | null;
|
|
46
|
+
};
|
|
47
|
+
export type SetPhaseModelOptions = JobsRequestOptions & {
|
|
48
|
+
jobId: string;
|
|
49
|
+
/** The phase's id as the plan names it. */
|
|
50
|
+
phaseId: string;
|
|
51
|
+
/** One of the detail's `phaseModels`. */
|
|
52
|
+
model: string;
|
|
41
53
|
};
|
|
42
54
|
export type UpdateJobSettingsOptions = JobsRequestOptions & JobSettingsUpdate;
|
|
43
55
|
/** A page of the caller's jobs, newest first, with what their jobs may spend today. */
|
|
@@ -53,7 +65,23 @@ export declare function getJobJournal(options: GetJobJournalOptions): Promise<Jo
|
|
|
53
65
|
* `isConflict` is true and whose `body` still carries the job as it stands.
|
|
54
66
|
*/
|
|
55
67
|
export declare function cancelJob(options: CancelJobOptions): Promise<JobCancelResponse>;
|
|
68
|
+
/**
|
|
69
|
+
* Continues a job that is parked waiting for budget, when there is room for it again.
|
|
70
|
+
*
|
|
71
|
+
* The answer says what happened either way: `resumed` is the job queued again, and otherwise
|
|
72
|
+
* `reason`, `action` and `message` say why it is still parked and what would change that. A
|
|
73
|
+
* job in any other status is a 409: the call throws a `ButlerBotAPIError` whose `isConflict`
|
|
74
|
+
* is true and whose `body` still carries the job as it stands.
|
|
75
|
+
*/
|
|
76
|
+
export declare function resumeJob(options: ResumeJobOptions): Promise<JobResumeResponse>;
|
|
56
77
|
/** Changes one job's name, and its autonomy: how far it may act, until when, and what it always asks about. */
|
|
57
78
|
export declare function updateJob(options: UpdateJobOptions): Promise<JobUpdateResponse>;
|
|
79
|
+
/**
|
|
80
|
+
* Changes the model one phase of a job's plan runs on.
|
|
81
|
+
*
|
|
82
|
+
* Only a phase that has not started or is blocked: a running or done phase's model is what its
|
|
83
|
+
* work ran on. A model the owner's plan cannot run is a 400 whose body names the ones it can.
|
|
84
|
+
*/
|
|
85
|
+
export declare function setPhaseModel(options: SetPhaseModelOptions): Promise<JobPhaseModelResponse>;
|
|
58
86
|
/** Changes the owner's job settings: their daily allowance and the autonomy new jobs start with. */
|
|
59
87
|
export declare function updateJobSettings(options: UpdateJobSettingsOptions): Promise<JobSettingsResponse>;
|
package/dist/modules/jobs.js
CHANGED
|
@@ -4,7 +4,9 @@ exports.listJobs = listJobs;
|
|
|
4
4
|
exports.getJob = getJob;
|
|
5
5
|
exports.getJobJournal = getJobJournal;
|
|
6
6
|
exports.cancelJob = cancelJob;
|
|
7
|
+
exports.resumeJob = resumeJob;
|
|
7
8
|
exports.updateJob = updateJob;
|
|
9
|
+
exports.setPhaseModel = setPhaseModel;
|
|
8
10
|
exports.updateJobSettings = updateJobSettings;
|
|
9
11
|
const config_1 = require("../config");
|
|
10
12
|
const url_formatter_1 = require("../util/url_formatter");
|
|
@@ -50,16 +52,43 @@ async function cancelJob(options) {
|
|
|
50
52
|
const url = (0, url_formatter_1.formatURL)(`${jobsBase(options)}/${encodeURIComponent(options.jobId)}/cancel`, {}, { apiKey: options.apiKey, debug: options.debug });
|
|
51
53
|
return (0, api_request_1.requestAPI)({ url, method: "POST", action: `cancel job ${options.jobId}` });
|
|
52
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Continues a job that is parked waiting for budget, when there is room for it again.
|
|
57
|
+
*
|
|
58
|
+
* The answer says what happened either way: `resumed` is the job queued again, and otherwise
|
|
59
|
+
* `reason`, `action` and `message` say why it is still parked and what would change that. A
|
|
60
|
+
* job in any other status is a 409: the call throws a `ButlerBotAPIError` whose `isConflict`
|
|
61
|
+
* is true and whose `body` still carries the job as it stands.
|
|
62
|
+
*/
|
|
63
|
+
async function resumeJob(options) {
|
|
64
|
+
const url = (0, url_formatter_1.formatURL)(`${jobsBase(options)}/${encodeURIComponent(options.jobId)}/resume`, {}, { apiKey: options.apiKey, debug: options.debug });
|
|
65
|
+
return (0, api_request_1.requestAPI)({ url, method: "POST", action: `resume job ${options.jobId}` });
|
|
66
|
+
}
|
|
53
67
|
/** Changes one job's name, and its autonomy: how far it may act, until when, and what it always asks about. */
|
|
54
68
|
async function updateJob(options) {
|
|
55
69
|
const url = (0, url_formatter_1.formatURL)(`${jobsBase(options)}/${encodeURIComponent(options.jobId)}`, {}, { apiKey: options.apiKey, debug: options.debug });
|
|
56
70
|
return (0, api_request_1.requestAPI)({
|
|
57
71
|
url,
|
|
58
72
|
method: "PATCH",
|
|
59
|
-
body: body({ title: options.title, autonomy: options.autonomy, autonomyUntil: options.autonomyUntil, alwaysAsk: options.alwaysAsk }),
|
|
73
|
+
body: body({ title: options.title, autonomy: options.autonomy, autonomyUntil: options.autonomyUntil, alwaysAsk: options.alwaysAsk, capUsd: options.capUsd }),
|
|
60
74
|
action: `update job ${options.jobId}`,
|
|
61
75
|
});
|
|
62
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Changes the model one phase of a job's plan runs on.
|
|
79
|
+
*
|
|
80
|
+
* Only a phase that has not started or is blocked: a running or done phase's model is what its
|
|
81
|
+
* work ran on. A model the owner's plan cannot run is a 400 whose body names the ones it can.
|
|
82
|
+
*/
|
|
83
|
+
async function setPhaseModel(options) {
|
|
84
|
+
const url = (0, url_formatter_1.formatURL)(`${jobsBase(options)}/${encodeURIComponent(options.jobId)}/plan/${encodeURIComponent(options.phaseId)}`, {}, { apiKey: options.apiKey, debug: options.debug });
|
|
85
|
+
return (0, api_request_1.requestAPI)({
|
|
86
|
+
url,
|
|
87
|
+
method: "PATCH",
|
|
88
|
+
body: { model: options.model },
|
|
89
|
+
action: `set the model of phase ${options.phaseId} of job ${options.jobId}`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
63
92
|
/** Changes the owner's job settings: their daily allowance and the autonomy new jobs start with. */
|
|
64
93
|
async function updateJobSettings(options) {
|
|
65
94
|
const endpoint = (options.serverURL || config_1.CONFIG.server) + (options.path || config_1.CONFIG.paths.jobs.settings);
|
package/dist/types/jobs/job.d.ts
CHANGED
|
@@ -31,6 +31,13 @@ export type JobView = {
|
|
|
31
31
|
reviewRounds: number;
|
|
32
32
|
/** What the job has spent in total, in USD. */
|
|
33
33
|
spentUsd: number;
|
|
34
|
+
/**
|
|
35
|
+
* A ceiling on what this job may spend over its whole life, in dollars, or null for none.
|
|
36
|
+
*
|
|
37
|
+
* Measured against everything the job and its sub-jobs have spent. A job that reaches it
|
|
38
|
+
* with work left parks blocked and asks; raising it starts the job again.
|
|
39
|
+
*/
|
|
40
|
+
capUsd: number | null;
|
|
34
41
|
/** What the job has spent today, in USD. */
|
|
35
42
|
spendTodayUsd: number;
|
|
36
43
|
/** How many questions of this job's are waiting on the user. */
|
|
@@ -73,7 +80,7 @@ export type JobAllowanceRefused = {
|
|
|
73
80
|
export type JobAllowance = JobAllowanceGranted | JobAllowanceRefused;
|
|
74
81
|
/** Whether an allowance is a refusal rather than a grant. */
|
|
75
82
|
export declare function isJobAllowanceRefused(allowance: JobAllowance): allowance is JobAllowanceRefused;
|
|
76
|
-
export type JobPlanPhaseKind = "plan" | "work" | "review";
|
|
83
|
+
export type JobPlanPhaseKind = "plan" | "work" | "map" | "review";
|
|
77
84
|
export type JobPlanPhaseStatus = "pending" | "running" | "blocked" | "done";
|
|
78
85
|
/** One phase of a job's plan, as the plan card spells it out. */
|
|
79
86
|
export type JobPlanPhase = {
|
|
@@ -182,6 +189,13 @@ export type JobDetailResponse = {
|
|
|
182
189
|
journalTotal: number;
|
|
183
190
|
/** Questions of this job's nobody has answered yet. */
|
|
184
191
|
openDeliveries: Delivery[];
|
|
192
|
+
/** The model names a phase of this job may be set to: the aliases first, then the tier's models. */
|
|
193
|
+
phaseModels: string[];
|
|
194
|
+
};
|
|
195
|
+
/** A phase after its model was changed. */
|
|
196
|
+
export type JobPhaseModelResponse = {
|
|
197
|
+
success: true;
|
|
198
|
+
phase: JobPlanPhase;
|
|
185
199
|
};
|
|
186
200
|
/** One page of a job's journal. Page 1 is the newest; within a page the entries are in written order. */
|
|
187
201
|
export type JobJournalPage = {
|
|
@@ -206,3 +220,29 @@ export type JobSettingsResponse = {
|
|
|
206
220
|
success: true;
|
|
207
221
|
jobs: JobSettings;
|
|
208
222
|
};
|
|
223
|
+
/**
|
|
224
|
+
* Why a resume answered as it did.
|
|
225
|
+
*
|
|
226
|
+
* `resumed` is the job queued again; the rest are why it was left where it is — the owner's
|
|
227
|
+
* tier does not allow the job to run, today's allowance is spent, or the server refused for a
|
|
228
|
+
* reason of its own.
|
|
229
|
+
*/
|
|
230
|
+
export type JobResumeReason = "resumed" | "over_tier_limit" | "allowance_spent" | "refused";
|
|
231
|
+
/** What the user can do about a job that was not resumed. */
|
|
232
|
+
export type JobResumeAction = "raise_allowance" | "upgrade_tier" | "wait";
|
|
233
|
+
/**
|
|
234
|
+
* A job after a resume was asked for.
|
|
235
|
+
*
|
|
236
|
+
* `resumed` says whether it is queued again; when it is not, `reason` and `action` say why and
|
|
237
|
+
* what would change it, and `wakeAt` is the earliest the runner would pick it up on its own,
|
|
238
|
+
* in epoch milliseconds. `message` is the same thing in a sentence or two, ready to show.
|
|
239
|
+
*/
|
|
240
|
+
export type JobResumeResponse = {
|
|
241
|
+
success: true;
|
|
242
|
+
resumed: boolean;
|
|
243
|
+
reason: JobResumeReason;
|
|
244
|
+
action?: JobResumeAction;
|
|
245
|
+
wakeAt?: number;
|
|
246
|
+
message: string;
|
|
247
|
+
job: JobView;
|
|
248
|
+
};
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -332,14 +332,22 @@ const { jobs, allowance, spentTodayUsd } = await client.listJobs({ status: "runn
|
|
|
332
332
|
const { job, plan, journal, journalTotal, openDeliveries, autonomyLine } = await client.getJob({ jobId });
|
|
333
333
|
const { entries, hasMore } = await client.getJobJournal({ jobId, page: 2 });
|
|
334
334
|
|
|
335
|
-
await client.updateJob({ jobId, title: "Flat hunt", autonomy: "free", autonomyUntil: Date.now() + 86_400_000 });
|
|
335
|
+
await client.updateJob({ jobId, title: "Flat hunt", autonomy: "free", autonomyUntil: Date.now() + 86_400_000, capUsd: 5 });
|
|
336
|
+
await client.setPhaseModel({ jobId, phaseId: "search", model: "Butler-Auto-Smart" });
|
|
336
337
|
await client.cancelJob({ jobId });
|
|
338
|
+
const { resumed, reason, action, message } = await client.resumeJob({ jobId });
|
|
337
339
|
```
|
|
338
340
|
|
|
339
341
|
`getJob` carries the newest page of the journal and `journalTotal`; `getJobJournal` pages the rest,
|
|
340
342
|
newest page first, with each page in the order its entries were written and `hasMore` saying whether
|
|
341
343
|
an older page exists. Each entry says which shift wrote it (`shiftIndex`, `shiftKind`) and on which
|
|
342
|
-
model. A job's `title` is a few words of its own, set at start or renamed with `updateJob
|
|
344
|
+
model. A job's `title` is a few words of its own, set at start or renamed with `updateJob`, which
|
|
345
|
+
also takes `capUsd`, a ceiling on what the job may spend in all (null clears it). `setPhaseModel`
|
|
346
|
+
changes the model a phase that has not started runs on, to one of the detail's `phaseModels`.
|
|
347
|
+
`resumeJob` continues a job parked as `waiting_budget` when there is room for it again: it answers
|
|
348
|
+
with `resumed`, a `reason` of `resumed`, `over_tier_limit`, `allowance_spent` or `refused`, an
|
|
349
|
+
`action` of `raise_allowance`, `upgrade_tier` or `wait` when there is one, a `wakeAt` when the job
|
|
350
|
+
would carry on by itself, and a `message` written for the user. A job in any other status is a 409.
|
|
343
351
|
|
|
344
352
|
Paging is 1-based, and every listing answers with `page`, `limit` and `total`. A listing also
|
|
345
353
|
carries `allowance` — what this user's jobs may spend today and what is left of it, or
|