tines 0.0.178 → 0.0.180
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/index.js +420 -133
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1006,8 +1006,8 @@ var DualOptions = class {
|
|
|
1006
1006
|
valueFromOption(value, option) {
|
|
1007
1007
|
const optionKey = option.attributeName();
|
|
1008
1008
|
if (!this.dualOptions.has(optionKey)) return true;
|
|
1009
|
-
const
|
|
1010
|
-
const negativeValue =
|
|
1009
|
+
const preset2 = this.negativeOptions.get(optionKey).presetArg;
|
|
1010
|
+
const negativeValue = preset2 !== void 0 ? preset2 : false;
|
|
1011
1011
|
return option.negate === (negativeValue === value);
|
|
1012
1012
|
}
|
|
1013
1013
|
};
|
|
@@ -3130,9 +3130,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3130
3130
|
helpWidth: context.helpWidth,
|
|
3131
3131
|
outputHasColors: context.hasColors
|
|
3132
3132
|
});
|
|
3133
|
-
const
|
|
3134
|
-
if (context.hasColors) return
|
|
3135
|
-
return this._outputConfiguration.stripColor(
|
|
3133
|
+
const text4 = helper.formatHelp(this, helper);
|
|
3134
|
+
if (context.hasColors) return text4;
|
|
3135
|
+
return this._outputConfiguration.stripColor(text4);
|
|
3136
3136
|
}
|
|
3137
3137
|
/**
|
|
3138
3138
|
* @typedef HelpContext
|
|
@@ -3292,7 +3292,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3292
3292
|
* @param {(string | Function)} text - string to add, or a function returning a string
|
|
3293
3293
|
* @return {Command} `this` command for chaining
|
|
3294
3294
|
*/
|
|
3295
|
-
addHelpText(position,
|
|
3295
|
+
addHelpText(position, text4) {
|
|
3296
3296
|
const allowedValues = ["beforeAll", "before", "after", "afterAll"];
|
|
3297
3297
|
if (!allowedValues.includes(position)) {
|
|
3298
3298
|
throw new Error(`Unexpected value for position to addHelpText.
|
|
@@ -3301,10 +3301,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3301
3301
|
const helpEvent = `${position}Help`;
|
|
3302
3302
|
this.on(helpEvent, (context) => {
|
|
3303
3303
|
let helpStr;
|
|
3304
|
-
if (typeof
|
|
3305
|
-
helpStr =
|
|
3304
|
+
if (typeof text4 === "function") {
|
|
3305
|
+
helpStr = text4({ error: context.error, command: context.command });
|
|
3306
3306
|
} else {
|
|
3307
|
-
helpStr =
|
|
3307
|
+
helpStr = text4;
|
|
3308
3308
|
}
|
|
3309
3309
|
if (helpStr) {
|
|
3310
3310
|
context.write(`${helpStr}
|
|
@@ -3534,7 +3534,7 @@ function runCostLabel(run) {
|
|
|
3534
3534
|
const tokens = (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0) + (usage.cache_read_tokens ?? 0) + (usage.cache_write_tokens ?? 0);
|
|
3535
3535
|
return tokens > 0 ? `${tokens.toLocaleString()} tok` : null;
|
|
3536
3536
|
}
|
|
3537
|
-
function utilizationLabel(quota, activeRuns, stateName = (
|
|
3537
|
+
function utilizationLabel(quota, activeRuns, stateName = (id2) => id2) {
|
|
3538
3538
|
if (quota.type === "global_cap") {
|
|
3539
3539
|
return `${activeRuns.length}/${quota.limit} global slot${quota.limit === 1 ? "" : "s"} in use`;
|
|
3540
3540
|
}
|
|
@@ -3978,17 +3978,17 @@ function createApiClient(options) {
|
|
|
3978
3978
|
listProjects: (params = {}) => get(`/api/v1/projects${query(params)}`),
|
|
3979
3979
|
createProject: (body) => request("POST", "/api/v1/projects", body),
|
|
3980
3980
|
listStarters: () => get("/api/v1/projects/starters"),
|
|
3981
|
-
getProject: (
|
|
3982
|
-
updateProject: (
|
|
3983
|
-
deleteProject: (
|
|
3984
|
-
archiveProject: (
|
|
3985
|
-
unarchiveProject: (
|
|
3981
|
+
getProject: (id2) => get(`/api/v1/projects/${id2}`),
|
|
3982
|
+
updateProject: (id2, body) => request("PATCH", `/api/v1/projects/${id2}`, body),
|
|
3983
|
+
deleteProject: (id2, body) => request("DELETE", `/api/v1/projects/${id2}`, body),
|
|
3984
|
+
archiveProject: (id2) => request("POST", `/api/v1/projects/${id2}/archive`),
|
|
3985
|
+
unarchiveProject: (id2) => request("POST", `/api/v1/projects/${id2}/unarchive`),
|
|
3986
3986
|
// Workflows
|
|
3987
3987
|
listWorkflows: (page = {}) => get(`/api/v1/workflows${query(page)}`),
|
|
3988
3988
|
createWorkflow: (body) => request("POST", "/api/v1/workflows", body),
|
|
3989
|
-
getWorkflow: (
|
|
3990
|
-
updateWorkflow: (
|
|
3991
|
-
deleteWorkflow: (
|
|
3989
|
+
getWorkflow: (id2) => get(`/api/v1/workflows/${id2}`),
|
|
3990
|
+
updateWorkflow: (id2, body) => request("PATCH", `/api/v1/workflows/${id2}`, body),
|
|
3991
|
+
deleteWorkflow: (id2, body) => request("DELETE", `/api/v1/workflows/${id2}`, body),
|
|
3992
3992
|
// Issues
|
|
3993
3993
|
listIssues: (filters = {}) => get(`/api/v1/issues${query(filters)}`),
|
|
3994
3994
|
listLabels: () => get("/api/v1/labels"),
|
|
@@ -4003,14 +4003,14 @@ function createApiClient(options) {
|
|
|
4003
4003
|
removeIssueLabel: (issueId, labelRef) => request("DELETE", `/api/v1/issues/${issueId}/labels/${encodeURIComponent(labelRef)}`),
|
|
4004
4004
|
listProjectIssues: (projectId, filters = {}) => get(`/api/v1/projects/${projectId}/issues${query(filters)}`),
|
|
4005
4005
|
createIssue: (projectId, body) => request("POST", `/api/v1/projects/${projectId}/issues`, body),
|
|
4006
|
-
getIssue: (
|
|
4006
|
+
getIssue: (id2) => get(`/api/v1/issues/${id2}`),
|
|
4007
4007
|
getIssueByNumber: (projectId, number) => get(`/api/v1/projects/${projectId}/issues/${number}`),
|
|
4008
|
-
updateIssue: (
|
|
4009
|
-
transitionIssue: (
|
|
4008
|
+
updateIssue: (id2, body) => request("PATCH", `/api/v1/issues/${id2}`, body),
|
|
4009
|
+
transitionIssue: (id2, body) => request("POST", `/api/v1/issues/${id2}/transition`, body),
|
|
4010
4010
|
/** Un-park: clears needs_attention, resets the attempt count. */
|
|
4011
|
-
resumeIssue: (
|
|
4011
|
+
resumeIssue: (id2) => request("POST", `/api/v1/issues/${id2}/resume`),
|
|
4012
4012
|
/** The dispatch explainer: "why isn't this running?". */
|
|
4013
|
-
getIssueDispatch: (
|
|
4013
|
+
getIssueDispatch: (id2) => get(`/api/v1/issues/${id2}/dispatch`),
|
|
4014
4014
|
// Issue links (dependencies & duplicates)
|
|
4015
4015
|
addIssueLink: (issueId, body) => request("POST", `/api/v1/issues/${issueId}/links`, body),
|
|
4016
4016
|
removeIssueLink: (issueId, linkId) => request("DELETE", `/api/v1/issues/${issueId}/links/${linkId}`),
|
|
@@ -4022,19 +4022,19 @@ function createApiClient(options) {
|
|
|
4022
4022
|
// Scheduled tasks
|
|
4023
4023
|
listSchedules: (filters = {}) => get(`/api/v1/schedules${query(filters)}`),
|
|
4024
4024
|
listProjectSchedules: (projectId, page = {}) => get(`/api/v1/projects/${projectId}/schedules${query(page)}`),
|
|
4025
|
-
getSchedule: (
|
|
4026
|
-
updateSchedule: (
|
|
4027
|
-
deleteSchedule: (
|
|
4025
|
+
getSchedule: (id2) => get(`/api/v1/schedules/${id2}`),
|
|
4026
|
+
updateSchedule: (id2, body) => request("PATCH", `/api/v1/schedules/${id2}`, body),
|
|
4027
|
+
deleteSchedule: (id2) => request("DELETE", `/api/v1/schedules/${id2}`),
|
|
4028
4028
|
/** Run now: creates an instance immediately (gate-respecting; 422 when blocked). */
|
|
4029
|
-
runSchedule: (
|
|
4029
|
+
runSchedule: (id2) => request("POST", `/api/v1/schedules/${id2}/run`),
|
|
4030
4030
|
// Context items
|
|
4031
4031
|
listContext: (filters = {}) => get(`/api/v1/context${query(filters)}`),
|
|
4032
4032
|
createContextItem: (body) => request("POST", "/api/v1/context", body),
|
|
4033
|
-
getContextItem: (
|
|
4034
|
-
updateContextItem: (
|
|
4035
|
-
deleteContextItem: (
|
|
4033
|
+
getContextItem: (id2) => get(`/api/v1/context/${id2}`),
|
|
4034
|
+
updateContextItem: (id2, body) => request("PATCH", `/api/v1/context/${id2}`, body),
|
|
4035
|
+
deleteContextItem: (id2) => request("DELETE", `/api/v1/context/${id2}`),
|
|
4036
4036
|
/** Atomic append to a prompt item's body (blank-line separated). */
|
|
4037
|
-
appendContextItem: (
|
|
4037
|
+
appendContextItem: (id2, body) => request("POST", `/api/v1/context/${id2}/append`, body),
|
|
4038
4038
|
/** Effective context for an issue: the assembled bundle. */
|
|
4039
4039
|
getIssueContext: (issueId) => get(`/api/v1/issues/${issueId}/context`),
|
|
4040
4040
|
/**
|
|
@@ -4114,44 +4114,44 @@ function createApiClient(options) {
|
|
|
4114
4114
|
// Runners
|
|
4115
4115
|
listRunners: () => get("/api/v1/runners"),
|
|
4116
4116
|
createRunner: (body) => request("POST", "/api/v1/runners", body),
|
|
4117
|
-
getRunner: (
|
|
4118
|
-
updateRunner: (
|
|
4117
|
+
getRunner: (id2) => get(`/api/v1/runners/${id2}`),
|
|
4118
|
+
updateRunner: (id2, body) => request("PATCH", `/api/v1/runners/${id2}`, body),
|
|
4119
4119
|
/** Reject-by-default: 422 names referencing rules/pins unless `force`. */
|
|
4120
|
-
deleteRunner: (
|
|
4120
|
+
deleteRunner: (id2, body) => request("DELETE", `/api/v1/runners/${id2}`, body),
|
|
4121
4121
|
/** Create/reconnect a local runner; the response's token is shown once. */
|
|
4122
4122
|
registerRunner: (body) => request("POST", "/api/v1/runners/register", body),
|
|
4123
4123
|
/** Invalidate the runner token and mint a fresh one (shown once). */
|
|
4124
|
-
rotateRunnerToken: (
|
|
4124
|
+
rotateRunnerToken: (id2) => request("POST", `/api/v1/runners/${id2}/rotate-token`),
|
|
4125
4125
|
// Local runner protocol (runner-token auth: construct the client with
|
|
4126
4126
|
// the runner token as `apiKey`)
|
|
4127
|
-
pollRunner: (
|
|
4127
|
+
pollRunner: (id2, body) => request("POST", `/api/v1/runners/${id2}/poll`, body),
|
|
4128
4128
|
appendRunLog: (runId, body) => request("POST", `/api/v1/runs/${runId}/logs`, body),
|
|
4129
4129
|
finishRun: (runId, body) => request("POST", `/api/v1/runs/${runId}/finish`, body),
|
|
4130
4130
|
// Agent runs
|
|
4131
4131
|
listRuns: (filters = {}) => get(`/api/v1/runs${query(filters)}`),
|
|
4132
|
-
getRun: (
|
|
4132
|
+
getRun: (id2) => get(`/api/v1/runs/${id2}`),
|
|
4133
4133
|
/**
|
|
4134
4134
|
* The run's complete log (not the 256 KB tail `getRun` returns) as a
|
|
4135
4135
|
* streamed Response, so a multi-megabyte log never has to be held in
|
|
4136
4136
|
* memory. `raw` asks for the unrendered harness stream instead.
|
|
4137
4137
|
*/
|
|
4138
|
-
getRunLogFull: (
|
|
4138
|
+
getRunLogFull: (id2, opts = {}) => raw("GET", `/api/v1/runs/${id2}/log${opts.raw ? "?raw=1" : ""}`, {
|
|
4139
4139
|
headers: { accept: "text/plain" }
|
|
4140
4140
|
}),
|
|
4141
4141
|
/** Daemon-only: uploads the raw harness stream for a settled run. */
|
|
4142
|
-
putRunLogRaw: (
|
|
4142
|
+
putRunLogRaw: (id2, body) => raw("PUT", `/api/v1/runs/${id2}/log/raw`, {
|
|
4143
4143
|
body,
|
|
4144
4144
|
headers: {
|
|
4145
4145
|
"content-type": "application/x-ndjson",
|
|
4146
4146
|
"content-length": String(body.byteLength)
|
|
4147
4147
|
}
|
|
4148
4148
|
}),
|
|
4149
|
-
cancelRun: (
|
|
4149
|
+
cancelRun: (id2) => request("POST", `/api/v1/runs/${id2}/cancel`),
|
|
4150
4150
|
// Routing rules (one per exact scope; responses carry shadow hints)
|
|
4151
4151
|
listRoutingRules: () => get("/api/v1/routing-rules"),
|
|
4152
4152
|
createRoutingRule: (body) => request("POST", "/api/v1/routing-rules", body),
|
|
4153
|
-
updateRoutingRule: (
|
|
4154
|
-
deleteRoutingRule: (
|
|
4153
|
+
updateRoutingRule: (id2, body) => request("PATCH", `/api/v1/routing-rules/${id2}`, body),
|
|
4154
|
+
deleteRoutingRule: (id2) => request("DELETE", `/api/v1/routing-rules/${id2}`),
|
|
4155
4155
|
// Supervisor settings
|
|
4156
4156
|
getPreferences: () => get("/api/v1/preferences"),
|
|
4157
4157
|
updatePreferences: (body) => request("PATCH", "/api/v1/preferences", body),
|
|
@@ -4161,15 +4161,117 @@ function createApiClient(options) {
|
|
|
4161
4161
|
// API keys (create/revoke require a browser session, not a key)
|
|
4162
4162
|
listApiKeys: (filters = {}) => get(`/api/v1/api-keys${query(filters)}`),
|
|
4163
4163
|
createApiKey: (body) => request("POST", "/api/v1/api-keys", body),
|
|
4164
|
-
revokeApiKey: (
|
|
4164
|
+
revokeApiKey: (id2) => request("DELETE", `/api/v1/api-keys/${id2}`),
|
|
4165
|
+
exportWorkflowPackage: (id2, opts = {}) => {
|
|
4166
|
+
const params = new URLSearchParams();
|
|
4167
|
+
if (opts.source_project_id) params.set("source_project_id", opts.source_project_id);
|
|
4168
|
+
for (const id3 of opts.schedule_ids ?? []) params.append("schedule_id", id3);
|
|
4169
|
+
for (const tier of opts.tiers ?? []) params.append("tier", JSON.stringify(tier));
|
|
4170
|
+
if (opts.authoring) params.set("authoring", JSON.stringify(opts.authoring));
|
|
4171
|
+
return get(
|
|
4172
|
+
`/api/v1/workflows/${encodeURIComponent(id2)}/export${params.size ? "?" + params : ""}`
|
|
4173
|
+
);
|
|
4174
|
+
},
|
|
4175
|
+
prepareWorkflowPackage: (body) => request(
|
|
4176
|
+
"POST",
|
|
4177
|
+
"/api/v1/library/prepare",
|
|
4178
|
+
body
|
|
4179
|
+
),
|
|
4180
|
+
installWorkflowPackage: (body) => request(
|
|
4181
|
+
"POST",
|
|
4182
|
+
"/api/v1/library/install",
|
|
4183
|
+
body
|
|
4184
|
+
),
|
|
4185
|
+
getWorkflowPackageReceipt: (planId) => get(
|
|
4186
|
+
`/api/v1/library/installs/${encodeURIComponent(planId)}`
|
|
4187
|
+
),
|
|
4188
|
+
validateLibrary: (body) => request(
|
|
4189
|
+
"POST",
|
|
4190
|
+
"/api/v1/library/validate",
|
|
4191
|
+
body
|
|
4192
|
+
),
|
|
4165
4193
|
// Library export / import (workflows + context; no tracker data, no secrets)
|
|
4166
|
-
exportLibrary: (opts = {}) => get(
|
|
4194
|
+
exportLibrary: (opts = {}) => get(
|
|
4195
|
+
`/api/v1/export${query(opts)}`
|
|
4196
|
+
),
|
|
4167
4197
|
/** Plan-then-apply; `dry_run: true` returns the preview the apply follows. */
|
|
4168
4198
|
importLibrary: (body) => request("POST", "/api/v1/import", body)
|
|
4169
4199
|
};
|
|
4170
4200
|
}
|
|
4171
4201
|
|
|
4172
4202
|
// ../shared/src/schedule.ts
|
|
4203
|
+
var ScheduleInputError = class extends Error {
|
|
4204
|
+
constructor(message3) {
|
|
4205
|
+
super(message3);
|
|
4206
|
+
this.name = "ScheduleInputError";
|
|
4207
|
+
}
|
|
4208
|
+
};
|
|
4209
|
+
function parseField(spec, fieldName, min, max, normalize = (n) => n) {
|
|
4210
|
+
const values = /* @__PURE__ */ new Set();
|
|
4211
|
+
let restricted = false;
|
|
4212
|
+
const fail = (why) => {
|
|
4213
|
+
throw new ScheduleInputError(`Invalid cron ${fieldName} field "${spec}": ${why}`);
|
|
4214
|
+
};
|
|
4215
|
+
for (const item of spec.split(",")) {
|
|
4216
|
+
const match = item.match(/^(\*|\d+|\d+-\d+)(?:\/(\d+))?$/);
|
|
4217
|
+
if (!match) fail(`"${item}" is not a number, range, "*", or step`);
|
|
4218
|
+
const [, base, stepRaw] = match;
|
|
4219
|
+
const step = stepRaw === void 0 ? 1 : Number.parseInt(stepRaw, 10);
|
|
4220
|
+
if (step < 1) fail("step must be at least 1");
|
|
4221
|
+
let lo;
|
|
4222
|
+
let hi;
|
|
4223
|
+
if (base === "*") {
|
|
4224
|
+
lo = min;
|
|
4225
|
+
hi = max;
|
|
4226
|
+
if (stepRaw !== void 0) restricted = true;
|
|
4227
|
+
} else if (base.includes("-")) {
|
|
4228
|
+
const [a, b] = base.split("-").map((n) => Number.parseInt(n, 10));
|
|
4229
|
+
lo = a;
|
|
4230
|
+
hi = b;
|
|
4231
|
+
restricted = true;
|
|
4232
|
+
} else {
|
|
4233
|
+
lo = hi = Number.parseInt(base, 10);
|
|
4234
|
+
restricted = true;
|
|
4235
|
+
if (stepRaw !== void 0) fail('a step needs a range or "*" before the "/"');
|
|
4236
|
+
}
|
|
4237
|
+
if (lo < min || hi > max) fail(`values must be between ${min} and ${max}`);
|
|
4238
|
+
if (lo > hi) fail(`range ${lo}-${hi} is backwards`);
|
|
4239
|
+
for (let v = lo; v <= hi; v += step) values.add(normalize(v));
|
|
4240
|
+
}
|
|
4241
|
+
return { values, restricted };
|
|
4242
|
+
}
|
|
4243
|
+
function parseCron(expr) {
|
|
4244
|
+
const fields = expr.trim().split(/\s+/);
|
|
4245
|
+
if (fields.length !== 5) {
|
|
4246
|
+
throw new ScheduleInputError(
|
|
4247
|
+
`Cron expression "${expr.trim()}" must have 5 fields (minute hour day-of-month month day-of-week), got ${fields.length}`
|
|
4248
|
+
);
|
|
4249
|
+
}
|
|
4250
|
+
const [m, h, dom, mon, dow] = fields;
|
|
4251
|
+
const minutes = parseField(m, "minute", 0, 59);
|
|
4252
|
+
const hours = parseField(h, "hour", 0, 23);
|
|
4253
|
+
const days = parseField(dom, "day-of-month", 1, 31);
|
|
4254
|
+
const months = parseField(mon, "month", 1, 12);
|
|
4255
|
+
const weekdays = parseField(dow, "day-of-week", 0, 7, (n) => n % 7);
|
|
4256
|
+
return {
|
|
4257
|
+
minutes: minutes.values,
|
|
4258
|
+
hours: hours.values,
|
|
4259
|
+
days: days.values,
|
|
4260
|
+
months: months.values,
|
|
4261
|
+
weekdays: weekdays.values,
|
|
4262
|
+
dayRestricted: days.restricted,
|
|
4263
|
+
weekdayRestricted: weekdays.restricted
|
|
4264
|
+
};
|
|
4265
|
+
}
|
|
4266
|
+
function validateScheduleCron(expr) {
|
|
4267
|
+
const parsed = parseCron(expr);
|
|
4268
|
+
if (parsed.minutes.size > 1) {
|
|
4269
|
+
throw new ScheduleInputError(
|
|
4270
|
+
`Cron expression "${expr.trim()}" would fire more often than once per hour; the minute field must be a single value`
|
|
4271
|
+
);
|
|
4272
|
+
}
|
|
4273
|
+
return parsed;
|
|
4274
|
+
}
|
|
4173
4275
|
var WEEKDAY_NAMES = [
|
|
4174
4276
|
"Sunday",
|
|
4175
4277
|
"Monday",
|
|
@@ -4179,24 +4281,79 @@ var WEEKDAY_NAMES = [
|
|
|
4179
4281
|
"Friday",
|
|
4180
4282
|
"Saturday"
|
|
4181
4283
|
];
|
|
4182
|
-
function
|
|
4183
|
-
|
|
4184
|
-
|
|
4284
|
+
function parseTimeOfDay(time) {
|
|
4285
|
+
const match = typeof time === "string" ? time.match(/^(\d{1,2}):(\d{2})$/) : null;
|
|
4286
|
+
if (match) {
|
|
4287
|
+
const hour = Number.parseInt(match[1], 10);
|
|
4288
|
+
const minute = Number.parseInt(match[2], 10);
|
|
4289
|
+
if (hour <= 23 && minute <= 59) return { hour, minute };
|
|
4290
|
+
}
|
|
4291
|
+
throw new ScheduleInputError(`Preset time must be "HH:MM" (24-hour), got "${String(time)}"`);
|
|
4292
|
+
}
|
|
4293
|
+
function compilePreset(preset2) {
|
|
4294
|
+
if (preset2.kind === "hourly") {
|
|
4295
|
+
const every = preset2.every_hours;
|
|
4296
|
+
if (typeof every !== "number" || !Number.isInteger(every) || every < 1 || every > 23) {
|
|
4297
|
+
throw new ScheduleInputError("Hourly preset needs an every_hours between 1 and 23");
|
|
4298
|
+
}
|
|
4299
|
+
const minute2 = preset2.minute ?? 0;
|
|
4300
|
+
if (typeof minute2 !== "number" || !Number.isInteger(minute2) || minute2 < 0 || minute2 > 59) {
|
|
4301
|
+
throw new ScheduleInputError("Hourly preset minute must be between 0 and 59");
|
|
4302
|
+
}
|
|
4303
|
+
return every === 1 ? `${minute2} * * * *` : `${minute2} */${every} * * *`;
|
|
4304
|
+
}
|
|
4305
|
+
const { hour, minute } = parseTimeOfDay(preset2.time);
|
|
4306
|
+
switch (preset2.kind) {
|
|
4307
|
+
case "daily":
|
|
4308
|
+
return `${minute} ${hour} * * *`;
|
|
4309
|
+
case "weekly": {
|
|
4310
|
+
const weekday = preset2.weekday;
|
|
4311
|
+
if (typeof weekday !== "number" || !Number.isInteger(weekday) || weekday < 0 || weekday > 6) {
|
|
4312
|
+
throw new ScheduleInputError(
|
|
4313
|
+
"Weekly preset needs a weekday between 0 (Sunday) and 6 (Saturday)"
|
|
4314
|
+
);
|
|
4315
|
+
}
|
|
4316
|
+
return `${minute} ${hour} * * ${weekday}`;
|
|
4317
|
+
}
|
|
4318
|
+
case "monthly": {
|
|
4319
|
+
const day = preset2.day_of_month;
|
|
4320
|
+
if (typeof day !== "number" || !Number.isInteger(day) || day < 1 || day > 31) {
|
|
4321
|
+
throw new ScheduleInputError("Monthly preset needs a day_of_month between 1 and 31");
|
|
4322
|
+
}
|
|
4323
|
+
return `${minute} ${hour} ${day} * *`;
|
|
4324
|
+
}
|
|
4325
|
+
default:
|
|
4326
|
+
throw new ScheduleInputError(
|
|
4327
|
+
`Unknown preset kind "${String(preset2.kind)}"; expected hourly, daily, weekly, or monthly`
|
|
4328
|
+
);
|
|
4329
|
+
}
|
|
4330
|
+
}
|
|
4331
|
+
function describeRecurrence(preset2, cron) {
|
|
4332
|
+
if (preset2) {
|
|
4333
|
+
switch (preset2.kind) {
|
|
4185
4334
|
case "hourly": {
|
|
4186
|
-
const every =
|
|
4187
|
-
const at =
|
|
4335
|
+
const every = preset2.every_hours ?? 1;
|
|
4336
|
+
const at = preset2.minute ? ` at :${String(preset2.minute).padStart(2, "0")}` : "";
|
|
4188
4337
|
return every === 1 ? `Every hour${at}` : `Every ${every} hours${at}`;
|
|
4189
4338
|
}
|
|
4190
4339
|
case "daily":
|
|
4191
|
-
return `Every day at ${
|
|
4340
|
+
return `Every day at ${preset2.time}`;
|
|
4192
4341
|
case "weekly":
|
|
4193
|
-
return `Every ${WEEKDAY_NAMES[
|
|
4342
|
+
return `Every ${WEEKDAY_NAMES[preset2.weekday ?? 0]} at ${preset2.time}`;
|
|
4194
4343
|
case "monthly":
|
|
4195
|
-
return `Monthly on day ${
|
|
4344
|
+
return `Monthly on day ${preset2.day_of_month} at ${preset2.time}`;
|
|
4196
4345
|
}
|
|
4197
4346
|
}
|
|
4198
4347
|
return `Cron \u201C${cron}\u201D`;
|
|
4199
4348
|
}
|
|
4349
|
+
function validateTimezone(tz) {
|
|
4350
|
+
try {
|
|
4351
|
+
new Intl.DateTimeFormat("en-US", { timeZone: tz });
|
|
4352
|
+
return tz;
|
|
4353
|
+
} catch {
|
|
4354
|
+
throw new ScheduleInputError(`Unknown timezone "${tz}"; use an IANA name like "Europe/London"`);
|
|
4355
|
+
}
|
|
4356
|
+
}
|
|
4200
4357
|
var PLACEHOLDER_DESCRIPTIONS = {
|
|
4201
4358
|
date: "run date, e.g. 2026-08-23",
|
|
4202
4359
|
time: "run time, e.g. 09:30",
|
|
@@ -4242,6 +4399,136 @@ async function listAll(fetchPage, opts = {}) {
|
|
|
4242
4399
|
// ../shared/src/routing.ts
|
|
4243
4400
|
var INHERIT_RUNNER_ID = "*";
|
|
4244
4401
|
|
|
4402
|
+
// ../shared/src/library/types.ts
|
|
4403
|
+
var LibraryValidationError = class extends Error {
|
|
4404
|
+
constructor(diagnostics) {
|
|
4405
|
+
super(diagnostics[0]?.message ?? "Invalid library document");
|
|
4406
|
+
this.diagnostics = diagnostics;
|
|
4407
|
+
this.name = "LibraryValidationError";
|
|
4408
|
+
}
|
|
4409
|
+
diagnostics;
|
|
4410
|
+
};
|
|
4411
|
+
|
|
4412
|
+
// ../shared/src/library/schema.ts
|
|
4413
|
+
var pointer = (path2, key) => `${path2}/${String(key).replaceAll("~", "~0").replaceAll("/", "~1")}`;
|
|
4414
|
+
function invalid(path2, code, message3) {
|
|
4415
|
+
throw new LibraryValidationError([{ path: path2, code, message: message3 }]);
|
|
4416
|
+
}
|
|
4417
|
+
function validateUnicode(value, path2) {
|
|
4418
|
+
for (let i = 0; i < value.length; i++) {
|
|
4419
|
+
const unit = value.charCodeAt(i);
|
|
4420
|
+
if (unit >= 55296 && unit <= 56319) {
|
|
4421
|
+
const next = value.charCodeAt(++i);
|
|
4422
|
+
if (!(next >= 56320 && next <= 57343))
|
|
4423
|
+
invalid(path2, "invalid_unicode", "Lone UTF-16 surrogate is not allowed");
|
|
4424
|
+
} else if (unit >= 56320 && unit <= 57343)
|
|
4425
|
+
invalid(path2, "invalid_unicode", "Lone UTF-16 surrogate is not allowed");
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
var text2 = (max, nonempty = false) => (v, p) => {
|
|
4429
|
+
if (typeof v !== "string") invalid(p, "invalid_type", "Expected a string");
|
|
4430
|
+
validateUnicode(v, p);
|
|
4431
|
+
if (v.length > max || nonempty && !v.trim())
|
|
4432
|
+
invalid(
|
|
4433
|
+
p,
|
|
4434
|
+
"invalid_field",
|
|
4435
|
+
`Expected ${nonempty ? "non-empty " : ""}text of at most ${max} characters`
|
|
4436
|
+
);
|
|
4437
|
+
};
|
|
4438
|
+
var bool = (v, p) => {
|
|
4439
|
+
if (typeof v !== "boolean") invalid(p, "invalid_type", "Expected a boolean");
|
|
4440
|
+
};
|
|
4441
|
+
var integer = (v, p) => {
|
|
4442
|
+
if (!Number.isSafeInteger(v) || v < 0)
|
|
4443
|
+
invalid(p, "invalid_integer", "Expected a non-negative safe integer");
|
|
4444
|
+
};
|
|
4445
|
+
var oneOf = (values) => (v, p) => {
|
|
4446
|
+
if (!values.includes(v)) invalid(p, "invalid_value", `Expected one of ${values.join(", ")}`);
|
|
4447
|
+
};
|
|
4448
|
+
var nullable = (check) => (v, p) => {
|
|
4449
|
+
if (v !== null) check(v, p);
|
|
4450
|
+
};
|
|
4451
|
+
function object(v, p) {
|
|
4452
|
+
if (!v || typeof v !== "object" || Array.isArray(v) || ![null, Object.prototype].includes(Object.getPrototypeOf(v)))
|
|
4453
|
+
invalid(p, "invalid_type", "Expected a plain object");
|
|
4454
|
+
return v;
|
|
4455
|
+
}
|
|
4456
|
+
var shape = (required, optional = {}) => (v, p) => {
|
|
4457
|
+
const o = object(v, p);
|
|
4458
|
+
for (const key of Object.keys(o)) {
|
|
4459
|
+
validateUnicode(key, pointer(p, key));
|
|
4460
|
+
if (!Object.hasOwn(required, key) && !Object.hasOwn(optional, key))
|
|
4461
|
+
invalid(pointer(p, key), "unknown_field", `Unknown field ${key}`);
|
|
4462
|
+
}
|
|
4463
|
+
for (const [key, check] of Object.entries(required)) {
|
|
4464
|
+
if (!Object.hasOwn(o, key))
|
|
4465
|
+
invalid(pointer(p, key), "missing_field", `Missing required field ${key}`);
|
|
4466
|
+
check(o[key], pointer(p, key));
|
|
4467
|
+
}
|
|
4468
|
+
for (const [key, check] of Object.entries(optional))
|
|
4469
|
+
if (Object.hasOwn(o, key)) check(o[key], pointer(p, key));
|
|
4470
|
+
};
|
|
4471
|
+
var discriminated = (key, variants) => (v, p) => {
|
|
4472
|
+
const o = object(v, p);
|
|
4473
|
+
if (typeof o[key] !== "string" || !Object.hasOwn(variants, o[key]))
|
|
4474
|
+
invalid(pointer(p, key), "invalid_discriminator", `Unknown ${key}`);
|
|
4475
|
+
variants[o[key]](v, p);
|
|
4476
|
+
};
|
|
4477
|
+
var id = (v, p) => {
|
|
4478
|
+
text2(80, true)(v, p);
|
|
4479
|
+
if (!/^[A-Za-z0-9:_-]{1,80}$/.test(v))
|
|
4480
|
+
invalid(p, "invalid_local_id", "Invalid document-local ID");
|
|
4481
|
+
};
|
|
4482
|
+
var bundledState = shape({ kind: oneOf(["bundled_state"]), state_id: id });
|
|
4483
|
+
var systemState = shape({
|
|
4484
|
+
kind: oneOf(["system_state"]),
|
|
4485
|
+
workflow: oneOf(["Standard"]),
|
|
4486
|
+
state_name: text2(100, true)
|
|
4487
|
+
});
|
|
4488
|
+
var bundledWorkflow = shape({ kind: oneOf(["bundled_workflow"]), workflow_id: id });
|
|
4489
|
+
var projectRef = shape({ kind: oneOf(["input_project"]), input_id: id });
|
|
4490
|
+
var preset = discriminated("kind", {
|
|
4491
|
+
hourly: shape({ kind: oneOf(["hourly"]), every_hours: integer }, { minute: integer }),
|
|
4492
|
+
daily: shape({ kind: oneOf(["daily"]), time: text2(5, true) }),
|
|
4493
|
+
weekly: shape({ kind: oneOf(["weekly"]), time: text2(5, true), weekday: integer }),
|
|
4494
|
+
monthly: shape({ kind: oneOf(["monthly"]), time: text2(5, true), day_of_month: integer })
|
|
4495
|
+
});
|
|
4496
|
+
var recurrence = (v, p) => {
|
|
4497
|
+
discriminated("kind", {
|
|
4498
|
+
preset: shape({ kind: oneOf(["preset"]), preset }),
|
|
4499
|
+
cron: shape({ kind: oneOf(["cron"]), cron: text2(100, true) })
|
|
4500
|
+
})(v, p);
|
|
4501
|
+
const o = v;
|
|
4502
|
+
try {
|
|
4503
|
+
validateScheduleCron(o.kind === "preset" ? compilePreset(o.preset) : o.cron);
|
|
4504
|
+
} catch (e) {
|
|
4505
|
+
invalid(p, "invalid_recurrence", e.message);
|
|
4506
|
+
}
|
|
4507
|
+
};
|
|
4508
|
+
var timezone = (v, p) => {
|
|
4509
|
+
text2(100, true)(v, p);
|
|
4510
|
+
try {
|
|
4511
|
+
validateTimezone(v);
|
|
4512
|
+
} catch (e) {
|
|
4513
|
+
invalid(p, "invalid_timezone", e.message);
|
|
4514
|
+
}
|
|
4515
|
+
};
|
|
4516
|
+
var schedule = shape({
|
|
4517
|
+
id,
|
|
4518
|
+
workflow: bundledWorkflow,
|
|
4519
|
+
project: projectRef,
|
|
4520
|
+
name: text2(200, true),
|
|
4521
|
+
title_template: text2(500, true),
|
|
4522
|
+
description_template: text2(1e5),
|
|
4523
|
+
recurrence,
|
|
4524
|
+
timezone,
|
|
4525
|
+
require_all_closed: bool,
|
|
4526
|
+
start_state: nullable(bundledState)
|
|
4527
|
+
});
|
|
4528
|
+
|
|
4529
|
+
// ../shared/src/library/choices.ts
|
|
4530
|
+
var PACKAGE_CHOICES_MAX_BYTES = 512 * 1024;
|
|
4531
|
+
|
|
4245
4532
|
// src/format.ts
|
|
4246
4533
|
function timestamp(ms) {
|
|
4247
4534
|
return new Date(ms).toISOString().replace("T", " ").slice(0, 19);
|
|
@@ -4258,8 +4545,8 @@ function contextItemSummary(item) {
|
|
|
4258
4545
|
return item.artifact_type ?? "artifact";
|
|
4259
4546
|
}
|
|
4260
4547
|
}
|
|
4261
|
-
function recurrenceLabel(
|
|
4262
|
-
return `${describeRecurrence(
|
|
4548
|
+
function recurrenceLabel(schedule2) {
|
|
4549
|
+
return `${describeRecurrence(schedule2.preset, schedule2.cron)}, ${schedule2.timezone}`;
|
|
4263
4550
|
}
|
|
4264
4551
|
function issueRef(ref) {
|
|
4265
4552
|
return `${ref.project_name}/${ref.number}`;
|
|
@@ -4365,7 +4652,7 @@ function ruleTargetsLabel(rule) {
|
|
|
4365
4652
|
function quotaLabel(quota, stateName) {
|
|
4366
4653
|
if (quota.type === "global_cap") return `global cap: at most ${quota.limit} concurrent runs`;
|
|
4367
4654
|
const overrides = Object.entries(quota.overrides).map(
|
|
4368
|
-
([
|
|
4655
|
+
([id2, limit]) => `${stateName ? stateName(id2) : id2}=${limit}`
|
|
4369
4656
|
);
|
|
4370
4657
|
return `state roster: default ${quota.default_limit} per state${overrides.length > 0 ? `, overrides: ${overrides.join(", ")}` : ""}`;
|
|
4371
4658
|
}
|
|
@@ -4899,8 +5186,8 @@ function register(program3) {
|
|
|
4899
5186
|
);
|
|
4900
5187
|
withCommon(
|
|
4901
5188
|
context.command("show <id>").description("Show a context item (skills include their files)")
|
|
4902
|
-
).action(async (
|
|
4903
|
-
const item = await client(opts).getContextItem(
|
|
5189
|
+
).action(async (id2, opts) => {
|
|
5190
|
+
const item = await client(opts).getContextItem(id2);
|
|
4904
5191
|
if (opts.json) return printJson(item);
|
|
4905
5192
|
printContextItem(item);
|
|
4906
5193
|
});
|
|
@@ -4954,7 +5241,7 @@ function register(program3) {
|
|
|
4954
5241
|
)
|
|
4955
5242
|
)
|
|
4956
5243
|
).action(
|
|
4957
|
-
async (
|
|
5244
|
+
async (id2, opts) => {
|
|
4958
5245
|
const api = client(opts);
|
|
4959
5246
|
const body = {};
|
|
4960
5247
|
if (opts.expectVersion !== void 0) body.expected_version = opts.expectVersion;
|
|
@@ -4971,7 +5258,7 @@ function register(program3) {
|
|
|
4971
5258
|
}
|
|
4972
5259
|
if (opts.body !== void 0) body.body = readBodyValue(opts.body);
|
|
4973
5260
|
if (opts.file.length > 0 || opts.removeFile.length > 0) {
|
|
4974
|
-
const current = await api.getContextItem(
|
|
5261
|
+
const current = await api.getContextItem(id2);
|
|
4975
5262
|
if (current.kind !== "skill")
|
|
4976
5263
|
die(`--file/--remove-file only apply to skills (this is a ${current.kind})`);
|
|
4977
5264
|
if (body.expected_version === void 0) body.expected_version = current.version;
|
|
@@ -4997,16 +5284,16 @@ function register(program3) {
|
|
|
4997
5284
|
"nothing to update: pass payload flags, --name/--description, scope flags, and/or --unset"
|
|
4998
5285
|
);
|
|
4999
5286
|
}
|
|
5000
|
-
const item = await api.updateContextItem(
|
|
5287
|
+
const item = await api.updateContextItem(id2, body);
|
|
5001
5288
|
if (opts.json) return printJson(item);
|
|
5002
5289
|
console.log(`updated ${item.kind} "${item.name}" (${item.id}) \u2014 scope: ${item.scope.label}`);
|
|
5003
5290
|
}
|
|
5004
5291
|
);
|
|
5005
5292
|
withCommon(context.command("delete <id>").description("Delete a context item")).action(
|
|
5006
|
-
async (
|
|
5293
|
+
async (id2, opts) => {
|
|
5007
5294
|
const api = client(opts);
|
|
5008
|
-
const item = await api.getContextItem(
|
|
5009
|
-
await api.deleteContextItem(
|
|
5295
|
+
const item = await api.getContextItem(id2);
|
|
5296
|
+
await api.deleteContextItem(id2);
|
|
5010
5297
|
console.log(`deleted ${item.kind} "${item.name}" (${item.id}) \u2014 scope: ${item.scope.label}`);
|
|
5011
5298
|
}
|
|
5012
5299
|
);
|
|
@@ -5145,9 +5432,9 @@ function conflictLines(preview) {
|
|
|
5145
5432
|
]) {
|
|
5146
5433
|
if (!context.conflicts.length) lines.push(`${label}: none`);
|
|
5147
5434
|
for (const conflict of context.conflicts) {
|
|
5148
|
-
const participants = conflict.item_ids.map((
|
|
5149
|
-
const repo = context.repos.find((item) => item.item_id ===
|
|
5150
|
-
return repo ? `${repo.name} (${repo.scope.label})` :
|
|
5435
|
+
const participants = conflict.item_ids.map((id2) => {
|
|
5436
|
+
const repo = context.repos.find((item) => item.item_id === id2);
|
|
5437
|
+
return repo ? `${repo.name} (${repo.scope.label})` : id2;
|
|
5151
5438
|
}).join(", ");
|
|
5152
5439
|
lines.push(`${label}: ${conflict.dir} \u2014 ${participants}`);
|
|
5153
5440
|
}
|
|
@@ -5920,17 +6207,17 @@ function register2(program3) {
|
|
|
5920
6207
|
[]
|
|
5921
6208
|
)
|
|
5922
6209
|
).action(
|
|
5923
|
-
async (
|
|
6210
|
+
async (projectRef2, opts) => {
|
|
5924
6211
|
const description = opts.description !== void 0 ? readBodyValue(opts.description) : void 0;
|
|
5925
6212
|
const api = client(opts);
|
|
5926
|
-
const project = await resolveProject(api,
|
|
6213
|
+
const project = await resolveProject(api, projectRef2);
|
|
5927
6214
|
const workflowId = opts.workflow ? (await resolveWorkflow(api, opts.workflow)).id : void 0;
|
|
5928
|
-
const
|
|
5929
|
-
if (!
|
|
6215
|
+
const recurrence2 = buildRecurrence(opts);
|
|
6216
|
+
if (!recurrence2 && (opts.ifClosed !== void 0 || opts.scheduleName !== void 0)) {
|
|
5930
6217
|
die('--if-closed/--schedule-name need a recurrence: add --every \u2026 or --cron "<expr>"');
|
|
5931
6218
|
}
|
|
5932
|
-
const
|
|
5933
|
-
...
|
|
6219
|
+
const schedule2 = recurrence2 ? {
|
|
6220
|
+
...recurrence2,
|
|
5934
6221
|
name: opts.scheduleName,
|
|
5935
6222
|
timezone: opts.tz ?? systemTimezone(),
|
|
5936
6223
|
require_all_closed: opts.ifClosed ?? false
|
|
@@ -5940,7 +6227,7 @@ function register2(program3) {
|
|
|
5940
6227
|
description,
|
|
5941
6228
|
workflow_id: workflowId,
|
|
5942
6229
|
state: opts.state,
|
|
5943
|
-
schedule,
|
|
6230
|
+
schedule: schedule2,
|
|
5944
6231
|
labels: opts.label
|
|
5945
6232
|
});
|
|
5946
6233
|
if (opts.json) return printJson(issue);
|
|
@@ -6014,9 +6301,9 @@ function register2(program3) {
|
|
|
6014
6301
|
const destination = await resolveProject(api, opts.project);
|
|
6015
6302
|
let preview = await api.previewIssueTransfer(issue.id, destination.id);
|
|
6016
6303
|
if (opts.inspect !== void 0) {
|
|
6017
|
-
const
|
|
6018
|
-
if (opts.json) return printJson({ ...preview, inspected:
|
|
6019
|
-
return console.log(
|
|
6304
|
+
const text4 = formatTransferItem(preview, Number(opts.inspect));
|
|
6305
|
+
if (opts.json) return printJson({ ...preview, inspected: text4 });
|
|
6306
|
+
return console.log(text4);
|
|
6020
6307
|
}
|
|
6021
6308
|
if (opts.dryRun) {
|
|
6022
6309
|
if (opts.json) return printJson(preview);
|
|
@@ -6047,7 +6334,7 @@ function register2(program3) {
|
|
|
6047
6334
|
}
|
|
6048
6335
|
const rl = interactive ? createInterface({ input: process.stdin, output: process.stderr }) : null;
|
|
6049
6336
|
const terminal = {
|
|
6050
|
-
write: (
|
|
6337
|
+
write: (text4) => process.stderr.write(text4),
|
|
6051
6338
|
ask: (question) => rl.question(question).catch(() => null)
|
|
6052
6339
|
};
|
|
6053
6340
|
try {
|
|
@@ -6719,12 +7006,12 @@ start one: tines journal append ${issue.project_name}/${issue.number} "- <date>:
|
|
|
6719
7006
|
).action(
|
|
6720
7007
|
async (ref, markdown, opts, command) => {
|
|
6721
7008
|
if (helpGuard(command, markdown)) return;
|
|
6722
|
-
const
|
|
7009
|
+
const text4 = readBodyValue(markdown);
|
|
6723
7010
|
const api = client(opts);
|
|
6724
7011
|
const { scope, note, item } = await resolveJournal(api, ref, opts.state);
|
|
6725
7012
|
printNote(note);
|
|
6726
7013
|
if (item) {
|
|
6727
|
-
const updated = await api.appendContextItem(item.id, { text:
|
|
7014
|
+
const updated = await api.appendContextItem(item.id, { text: text4 });
|
|
6728
7015
|
if (opts.json) return printJson(updated);
|
|
6729
7016
|
return console.log(`appended to the ${scope.label} journal (now v${updated.version})`);
|
|
6730
7017
|
}
|
|
@@ -6734,7 +7021,7 @@ start one: tines journal append ${issue.project_name}/${issue.number} "- <date>:
|
|
|
6734
7021
|
name: JOURNAL_NAME,
|
|
6735
7022
|
project_id: scope.project_id ?? void 0,
|
|
6736
7023
|
workflow_state_id: scope.workflow_state_id ?? void 0,
|
|
6737
|
-
body:
|
|
7024
|
+
body: text4.trim()
|
|
6738
7025
|
});
|
|
6739
7026
|
if (opts.json) return printJson(created);
|
|
6740
7027
|
console.log(`started the ${scope.label} journal (${created.id})`);
|
|
@@ -6742,7 +7029,7 @@ start one: tines journal append ${issue.project_name}/${issue.number} "- <date>:
|
|
|
6742
7029
|
if (!(err instanceof ApiError) || err.code !== "duplicate_context_name") throw err;
|
|
6743
7030
|
const { item: fresh } = await resolveJournal(api, ref, opts.state);
|
|
6744
7031
|
if (!fresh) throw err;
|
|
6745
|
-
const updated = await api.appendContextItem(fresh.id, { text:
|
|
7032
|
+
const updated = await api.appendContextItem(fresh.id, { text: text4 });
|
|
6746
7033
|
if (opts.json) return printJson(updated);
|
|
6747
7034
|
console.log(`appended to the ${scope.label} journal (now v${updated.version})`);
|
|
6748
7035
|
}
|
|
@@ -7462,10 +7749,10 @@ var ClaudeStreamRenderer = class {
|
|
|
7462
7749
|
};
|
|
7463
7750
|
|
|
7464
7751
|
// src/daemon/codex-stream.ts
|
|
7465
|
-
function
|
|
7752
|
+
function object2(value) {
|
|
7466
7753
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
7467
7754
|
}
|
|
7468
|
-
function
|
|
7755
|
+
function text3(value) {
|
|
7469
7756
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
7470
7757
|
}
|
|
7471
7758
|
function renderCodexEvent(event) {
|
|
@@ -7474,35 +7761,35 @@ function renderCodexEvent(event) {
|
|
|
7474
7761
|
if (type === "turn.started") return ["[session] turn started"];
|
|
7475
7762
|
if (type === "turn.completed") return ["[session] turn completed"];
|
|
7476
7763
|
if (type === "turn.failed") {
|
|
7477
|
-
const error =
|
|
7478
|
-
return [`[error] ${clip(
|
|
7764
|
+
const error = object2(event.error);
|
|
7765
|
+
return [`[error] ${clip(text3(error?.message) ?? text3(event.message) ?? "turn failed", 2e3)}`];
|
|
7479
7766
|
}
|
|
7480
|
-
if (type === "error") return [`[error] ${clip(
|
|
7767
|
+
if (type === "error") return [`[error] ${clip(text3(event.message) ?? "unknown error", 2e3)}`];
|
|
7481
7768
|
if (type !== "item.completed") return [];
|
|
7482
|
-
const item =
|
|
7769
|
+
const item = object2(event.item);
|
|
7483
7770
|
if (!item) return [];
|
|
7484
7771
|
switch (item.type) {
|
|
7485
7772
|
case "agent_message":
|
|
7486
|
-
return
|
|
7773
|
+
return text3(item.text) ? [`[agent] ${clip(text3(item.text), 2e3)}`] : [];
|
|
7487
7774
|
case "command_execution": {
|
|
7488
|
-
const command =
|
|
7775
|
+
const command = text3(item.command) ?? "command";
|
|
7489
7776
|
const failed = validMetric(item.exit_code) && item.exit_code !== 0;
|
|
7490
|
-
const output = failed ?
|
|
7777
|
+
const output = failed ? text3(item.aggregated_output) : void 0;
|
|
7491
7778
|
return [
|
|
7492
7779
|
`[tool] ${clip(command, 300)}${failed ? ` (exit ${item.exit_code}${output ? `: ${clip(output, 300)}` : ""})` : ""}`
|
|
7493
7780
|
];
|
|
7494
7781
|
}
|
|
7495
7782
|
case "file_change": {
|
|
7496
7783
|
const changes = Array.isArray(item.changes) ? item.changes : [];
|
|
7497
|
-
const paths = changes.map((change) =>
|
|
7784
|
+
const paths = changes.map((change) => text3(object2(change)?.path)).filter((path2) => Boolean(path2));
|
|
7498
7785
|
return [`[tool] file change${paths.length ? `: ${clip(paths.join(", "), 300)}` : ""}`];
|
|
7499
7786
|
}
|
|
7500
7787
|
case "mcp_tool_call":
|
|
7501
7788
|
return [
|
|
7502
|
-
`[tool] ${clip([
|
|
7789
|
+
`[tool] ${clip([text3(item.server), text3(item.tool)].filter(Boolean).join("/") || "MCP call", 300)}`
|
|
7503
7790
|
];
|
|
7504
7791
|
case "web_search":
|
|
7505
|
-
return [`[tool] web search${
|
|
7792
|
+
return [`[tool] web search${text3(item.query) ? `: ${clip(text3(item.query), 300)}` : ""}`];
|
|
7506
7793
|
default:
|
|
7507
7794
|
return [];
|
|
7508
7795
|
}
|
|
@@ -7539,7 +7826,7 @@ var CodexStreamRenderer = class {
|
|
|
7539
7826
|
let event;
|
|
7540
7827
|
try {
|
|
7541
7828
|
const parsed = JSON.parse(trimmed);
|
|
7542
|
-
const parsedObject =
|
|
7829
|
+
const parsedObject = object2(parsed);
|
|
7543
7830
|
if (!parsedObject) return;
|
|
7544
7831
|
event = parsedObject;
|
|
7545
7832
|
} catch {
|
|
@@ -7556,7 +7843,7 @@ var CodexStreamRenderer = class {
|
|
|
7556
7843
|
this.collected.providerSessionId = event.thread_id;
|
|
7557
7844
|
}
|
|
7558
7845
|
if (event.type !== "turn.completed") return;
|
|
7559
|
-
const raw =
|
|
7846
|
+
const raw = object2(event.usage);
|
|
7560
7847
|
if (!raw) return;
|
|
7561
7848
|
const totalInput = validMetric(raw.input_tokens) ? raw.input_tokens : void 0;
|
|
7562
7849
|
const rawCached = validMetric(raw.cached_input_tokens) ? raw.cached_input_tokens : void 0;
|
|
@@ -7673,8 +7960,8 @@ function zonedDate(zone, at) {
|
|
|
7673
7960
|
return { y: get("year"), m: get("month") - 1, d: get("day") };
|
|
7674
7961
|
}
|
|
7675
7962
|
var DURATION = /(\d+)\s*([dhms])/g;
|
|
7676
|
-
function parseResetTime(
|
|
7677
|
-
const raw =
|
|
7963
|
+
function parseResetTime(text4, now) {
|
|
7964
|
+
const raw = text4.trim();
|
|
7678
7965
|
if (!raw) return null;
|
|
7679
7966
|
const relative = raw.match(/^in\s+(.+)$/i);
|
|
7680
7967
|
if (relative) {
|
|
@@ -7954,9 +8241,9 @@ var LogBatcher = class {
|
|
|
7954
8241
|
seq = 0;
|
|
7955
8242
|
/** Chunks awaiting a successful send, oldest first. */
|
|
7956
8243
|
pending = [];
|
|
7957
|
-
append(
|
|
7958
|
-
if (!
|
|
7959
|
-
this.buffer +=
|
|
8244
|
+
append(text4) {
|
|
8245
|
+
if (!text4) return;
|
|
8246
|
+
this.buffer += text4;
|
|
7960
8247
|
if (Buffer.byteLength(this.buffer, "utf8") >= (this.opts.maxBytes ?? 32 * 1024)) {
|
|
7961
8248
|
void this.flush();
|
|
7962
8249
|
} else if (!this.timer) {
|
|
@@ -8688,9 +8975,9 @@ async function runDaemon(opts) {
|
|
|
8688
8975
|
child.stdout?.on("data", (data) => run.batcher.append(data.toString("utf8")));
|
|
8689
8976
|
}
|
|
8690
8977
|
child.stderr?.on("data", (data) => {
|
|
8691
|
-
const
|
|
8692
|
-
run.batcher.append(
|
|
8693
|
-
run.limiter?.noteStderr(
|
|
8978
|
+
const text4 = data.toString("utf8");
|
|
8979
|
+
run.batcher.append(text4);
|
|
8980
|
+
run.limiter?.noteStderr(text4);
|
|
8694
8981
|
});
|
|
8695
8982
|
run.timeout = setTimeout(() => {
|
|
8696
8983
|
if (run.settled) return;
|
|
@@ -9280,9 +9567,9 @@ function register8(program3) {
|
|
|
9280
9567
|
withCommon(
|
|
9281
9568
|
runsCmd.command("show <id>").description("Show a run; --logs prints the captured log tail, --logs --full the whole log").option("--logs", "print the log tail").option("--full", "with --logs: print the complete log, not the 256 KB tail").option("--raw", "with --logs --full: print the unrendered harness stream instead")
|
|
9282
9569
|
).action(
|
|
9283
|
-
async (
|
|
9570
|
+
async (id2, opts) => {
|
|
9284
9571
|
const api = client(opts);
|
|
9285
|
-
const run = await api.getRun(
|
|
9572
|
+
const run = await api.getRun(id2);
|
|
9286
9573
|
if (opts.json) return printJson(run);
|
|
9287
9574
|
console.log(
|
|
9288
9575
|
`${run.id} ${run.status} on ${run.runner_name}${run.resumed_from_run_id ? ` \xB7 resumed run ${run.resumed_from_run_id}` : ""}`
|
|
@@ -9314,7 +9601,7 @@ function register8(program3) {
|
|
|
9314
9601
|
if (opts.logs) {
|
|
9315
9602
|
console.log("");
|
|
9316
9603
|
if (opts.full || opts.raw) {
|
|
9317
|
-
const res = await api.getRunLogFull(
|
|
9604
|
+
const res = await api.getRunLogFull(id2, { raw: opts.raw });
|
|
9318
9605
|
const body = res.body;
|
|
9319
9606
|
if (!body) return;
|
|
9320
9607
|
const reader = body.getReader();
|
|
@@ -9338,9 +9625,9 @@ function register8(program3) {
|
|
|
9338
9625
|
);
|
|
9339
9626
|
withCommon(
|
|
9340
9627
|
runsCmd.command("cancel <id>").description("Cancel a run (judged like any other end: usually a strike)")
|
|
9341
|
-
).action(async (
|
|
9628
|
+
).action(async (id2, opts) => {
|
|
9342
9629
|
const api = client(opts);
|
|
9343
|
-
const run = await api.cancelRun(
|
|
9630
|
+
const run = await api.cancelRun(id2);
|
|
9344
9631
|
if (opts.json) return printJson(run);
|
|
9345
9632
|
console.log(
|
|
9346
9633
|
`canceled ${run.id}${run.issue_ref ? ` on ${issueRef(run.issue_ref)}` : ""} (was on ${run.runner_name})`
|
|
@@ -9411,10 +9698,10 @@ function register9(program3) {
|
|
|
9411
9698
|
schedules.command("show <ref>").description("Show a schedule (<project>/<name>): config, next/last run, recent instances")
|
|
9412
9699
|
).action(async (ref, opts) => {
|
|
9413
9700
|
const api = client(opts);
|
|
9414
|
-
const
|
|
9415
|
-
if (opts.json) return printJson(
|
|
9416
|
-
printScheduleDetail(
|
|
9417
|
-
const { items } = await api.listIssues({ schedule:
|
|
9701
|
+
const schedule2 = await resolveSchedule(api, ref);
|
|
9702
|
+
if (opts.json) return printJson(schedule2);
|
|
9703
|
+
printScheduleDetail(schedule2);
|
|
9704
|
+
const { items } = await api.listIssues({ schedule: schedule2.id, limit: 10 });
|
|
9418
9705
|
if (items.length > 0) {
|
|
9419
9706
|
console.log(`
|
|
9420
9707
|
recent instances:`);
|
|
@@ -9451,16 +9738,16 @@ recent instances:`);
|
|
|
9451
9738
|
async (ref, opts) => {
|
|
9452
9739
|
const descriptionTemplate = opts.description !== void 0 ? readBodyValue(opts.description) : void 0;
|
|
9453
9740
|
const api = client(opts);
|
|
9454
|
-
const
|
|
9741
|
+
const schedule2 = await resolveSchedule(api, ref);
|
|
9455
9742
|
const body = {};
|
|
9456
9743
|
if (opts.title !== void 0) body.title_template = opts.title;
|
|
9457
9744
|
if (descriptionTemplate !== void 0) body.description_template = descriptionTemplate;
|
|
9458
9745
|
if (opts.workflow !== void 0)
|
|
9459
9746
|
body.workflow_id = (await resolveWorkflow(api, opts.workflow)).id;
|
|
9460
9747
|
if (opts.state !== void 0) body.state = opts.state;
|
|
9461
|
-
const
|
|
9462
|
-
if (
|
|
9463
|
-
if (
|
|
9748
|
+
const recurrence2 = buildRecurrence(opts);
|
|
9749
|
+
if (recurrence2?.preset) body.preset = recurrence2.preset;
|
|
9750
|
+
if (recurrence2?.cron !== void 0) body.cron = recurrence2.cron;
|
|
9464
9751
|
if (opts.tz !== void 0) body.timezone = opts.tz;
|
|
9465
9752
|
if (opts.ifClosed !== void 0) body.require_all_closed = opts.ifClosed;
|
|
9466
9753
|
if (opts.name !== void 0) body.name = opts.name;
|
|
@@ -9469,7 +9756,7 @@ recent instances:`);
|
|
|
9469
9756
|
"nothing to update: pass --title, --description, --workflow, --state, --every/--at/--on, --cron, --tz, --[no-]if-closed, and/or --name"
|
|
9470
9757
|
);
|
|
9471
9758
|
}
|
|
9472
|
-
const updated = await api.updateSchedule(
|
|
9759
|
+
const updated = await api.updateSchedule(schedule2.id, body);
|
|
9473
9760
|
if (opts.json) return printJson(updated);
|
|
9474
9761
|
console.log(`updated schedule "${scheduleRef(updated)}"
|
|
9475
9762
|
`);
|
|
@@ -9480,8 +9767,8 @@ recent instances:`);
|
|
|
9480
9767
|
schedules.command("pause <ref>").description("Pause a schedule (keeps config and history)")
|
|
9481
9768
|
).action(async (ref, opts) => {
|
|
9482
9769
|
const api = client(opts);
|
|
9483
|
-
const
|
|
9484
|
-
const updated = await api.updateSchedule(
|
|
9770
|
+
const schedule2 = await resolveSchedule(api, ref);
|
|
9771
|
+
const updated = await api.updateSchedule(schedule2.id, { enabled: false });
|
|
9485
9772
|
if (opts.json) return printJson(updated);
|
|
9486
9773
|
console.log(`paused schedule "${scheduleRef(updated)}"`);
|
|
9487
9774
|
});
|
|
@@ -9489,8 +9776,8 @@ recent instances:`);
|
|
|
9489
9776
|
schedules.command("resume <ref>").description("Resume a paused schedule (recomputes the next occurrence from now)")
|
|
9490
9777
|
).action(async (ref, opts) => {
|
|
9491
9778
|
const api = client(opts);
|
|
9492
|
-
const
|
|
9493
|
-
const updated = await api.updateSchedule(
|
|
9779
|
+
const schedule2 = await resolveSchedule(api, ref);
|
|
9780
|
+
const updated = await api.updateSchedule(schedule2.id, { enabled: true });
|
|
9494
9781
|
if (opts.json) return printJson(updated);
|
|
9495
9782
|
console.log(
|
|
9496
9783
|
`resumed schedule "${scheduleRef(updated)}" \u2014 next run ${timestamp(updated.next_run_at)}`
|
|
@@ -9500,8 +9787,8 @@ recent instances:`);
|
|
|
9500
9787
|
schedules.command("run <ref>").description("Create an instance now (respects the only-when-closed gate)")
|
|
9501
9788
|
).action(async (ref, opts) => {
|
|
9502
9789
|
const api = client(opts);
|
|
9503
|
-
const
|
|
9504
|
-
const issue = await api.runSchedule(
|
|
9790
|
+
const schedule2 = await resolveSchedule(api, ref);
|
|
9791
|
+
const issue = await api.runSchedule(schedule2.id);
|
|
9505
9792
|
if (opts.json) return printJson(issue);
|
|
9506
9793
|
console.log(
|
|
9507
9794
|
`created ${issue.project_name}/#${issue.number} "${issue.title}" in state "${issue.state.name}"`
|
|
@@ -9511,17 +9798,17 @@ recent instances:`);
|
|
|
9511
9798
|
schedules.command("delete <ref>").description("Delete a schedule (existing issues are kept)").option("-y, --yes", "skip the confirmation prompt")
|
|
9512
9799
|
).action(async (ref, opts) => {
|
|
9513
9800
|
const api = client(opts);
|
|
9514
|
-
const
|
|
9801
|
+
const schedule2 = await resolveSchedule(api, ref);
|
|
9515
9802
|
if (!opts.yes) {
|
|
9516
9803
|
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
9517
9804
|
const answer = await rl.question(
|
|
9518
|
-
`Delete schedule "${scheduleRef(
|
|
9805
|
+
`Delete schedule "${scheduleRef(schedule2)}"? Its ${schedule2.run_count} existing issue${schedule2.run_count === 1 ? "" : "s"} will be kept. [y/N] `
|
|
9519
9806
|
);
|
|
9520
9807
|
rl.close();
|
|
9521
9808
|
if (!/^y(es)?$/i.test(answer.trim())) die("aborted");
|
|
9522
9809
|
}
|
|
9523
|
-
await api.deleteSchedule(
|
|
9524
|
-
console.log(`deleted schedule "${scheduleRef(
|
|
9810
|
+
await api.deleteSchedule(schedule2.id);
|
|
9811
|
+
console.log(`deleted schedule "${scheduleRef(schedule2)}" (issues kept)`);
|
|
9525
9812
|
});
|
|
9526
9813
|
}
|
|
9527
9814
|
|
|
@@ -9640,9 +9927,9 @@ function register10(program3) {
|
|
|
9640
9927
|
console.log(
|
|
9641
9928
|
`automation: ${settings.enabled ? "ON" : "OFF (kill switch \u2014 nothing dispatches)"}`
|
|
9642
9929
|
);
|
|
9643
|
-
console.log(quotaLabel(settings.quota, (
|
|
9930
|
+
console.log(quotaLabel(settings.quota, (id2) => stateNames.get(id2) ?? id2));
|
|
9644
9931
|
console.log(
|
|
9645
|
-
`utilization: ${utilizationLabel(settings.quota, activeRunItems, (
|
|
9932
|
+
`utilization: ${utilizationLabel(settings.quota, activeRunItems, (id2) => stateNames.get(id2) ?? id2)}`
|
|
9646
9933
|
);
|
|
9647
9934
|
console.log(`attempt limit: ${settings.attempt_limit} strikes, then the issue parks`);
|
|
9648
9935
|
if (queue.waiting === 0) {
|
|
@@ -9737,7 +10024,7 @@ function register10(program3) {
|
|
|
9737
10024
|
for (const wf of workflows.items) {
|
|
9738
10025
|
for (const s of wf.states) stateNames.set(s.id, `${wf.name}/${s.name}`);
|
|
9739
10026
|
}
|
|
9740
|
-
console.log(quotaLabel(settings.quota, (
|
|
10027
|
+
console.log(quotaLabel(settings.quota, (id2) => stateNames.get(id2) ?? id2));
|
|
9741
10028
|
});
|
|
9742
10029
|
}
|
|
9743
10030
|
|
|
@@ -9838,9 +10125,9 @@ async function loadLibrary(api) {
|
|
|
9838
10125
|
return { workflows, states, children };
|
|
9839
10126
|
}
|
|
9840
10127
|
var qualify = (entry) => `${entry.workflow.name} / ${entry.state.name}`;
|
|
9841
|
-
function stateLabel(lib,
|
|
9842
|
-
const entry = lib.states.get(
|
|
9843
|
-
return entry ? qualify(entry) :
|
|
10128
|
+
function stateLabel(lib, id2) {
|
|
10129
|
+
const entry = lib.states.get(id2);
|
|
10130
|
+
return entry ? qualify(entry) : id2;
|
|
9844
10131
|
}
|
|
9845
10132
|
function inheritanceLines(lib, state) {
|
|
9846
10133
|
const lines = [];
|