@hivefloor/cli 0.1.0 → 0.1.2
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/LICENSE +1 -1
- package/README.md +1 -1
- package/dist/{chunk-4A5WOW2D.js → chunk-DQV6FAJU.js} +2 -2
- package/dist/{chunk-BAB4DPCN.js → chunk-DWHMBUCA.js} +2 -2
- package/dist/{chunk-M3PLXINO.js → chunk-E4V47VEV.js} +3 -9
- package/dist/{chunk-UPRHMVYJ.js → chunk-HT5KXWXM.js} +1 -1
- package/dist/{chunk-IEYWMDXA.js → chunk-LF2NWQ4B.js} +8 -3
- package/dist/{chunk-DIW4VIU7.js → chunk-NKMVO5BP.js} +4 -10
- package/dist/{chunk-LHF4KCEA.js → chunk-NLZXB26Y.js} +2 -2
- package/dist/{chunk-SGDM7MAT.js → chunk-O2TC3WSS.js} +68 -2
- package/dist/{chunk-6UZBZ7LR.js → chunk-O6VSA2JT.js} +4 -3
- package/dist/{chunk-4OFN5KHY.js → chunk-OOMBZN4M.js} +13 -13
- package/dist/{chunk-3IMV5EHP.js → chunk-T7TG6WA4.js} +1 -1
- package/dist/{chunk-RE2EQZWL.js → chunk-TH4ANHSG.js} +394 -198
- package/dist/{chunk-WNDUGQDX.js → chunk-VNCQFFQO.js} +8 -0
- package/dist/{chunk-OQ6QVFSH.js → chunk-YRNMECUF.js} +1 -1
- package/dist/{cli-7CIYC6A3.js → cli-F3F7SQLV.js} +13 -10
- package/dist/connect-TG2H5SMB.js +23 -0
- package/dist/{disconnect-NRYU6W5P.js → disconnect-FI76IEZJ.js} +10 -10
- package/dist/{hook-B2I42GE3.js → hook-N4ZTQEWM.js} +53 -19
- package/dist/index.js +2 -2
- package/dist/{link-EPWADGYT.js → link-JX4YLF2Z.js} +9 -9
- package/dist/{machine-connect-RWNZ77NO.js → machine-connect-NOQ3VZOO.js} +24 -24
- package/dist/{mcp-QX6VMTOD.js → mcp-EUBTVJNX.js} +7 -7
- package/dist/run-CKNHDPNX.js +1883 -0
- package/dist/{status-HADESN2E.js → status-SMAVPW4D.js} +14 -14
- package/dist/{token-SM5MDJKY.js → token-AUEAWQDH.js} +4 -4
- package/dist/where-7NI7UEEF.js +70 -0
- package/package.json +7 -3
- package/dist/connect-R3PMIY7G.js +0 -23
- package/dist/run-64ZYCJU2.js +0 -629
|
@@ -19786,14 +19786,21 @@ var hookEventSchema = external_exports.object({
|
|
|
19786
19786
|
model: external_exports.string().min(1).max(200).optional(),
|
|
19787
19787
|
repo: repoInfoSchema.optional(),
|
|
19788
19788
|
/** ISO time on the client; display only (the server clock decides). */
|
|
19789
|
-
client_at: external_exports.iso.datetime({ offset: true })
|
|
19789
|
+
client_at: external_exports.iso.datetime({ offset: true }),
|
|
19790
|
+
/** The CLI sets it on the event it posts for a hook whose output the tool reads as context (Claude's UserPromptSubmit and the like): only then does the answer carry the session's pending nudges. */
|
|
19791
|
+
deliver: external_exports.boolean().optional()
|
|
19790
19792
|
});
|
|
19791
19793
|
var hookBatchSchema = external_exports.object({ events: external_exports.array(hookEventSchema).min(1).max(HOOK_BATCH_MAX) });
|
|
19792
19794
|
var hookBatchResponseSchema = external_exports.object({
|
|
19793
19795
|
accepted: external_exports.number().int().nonnegative(),
|
|
19794
|
-
dropped: external_exports.number().int().nonnegative()
|
|
19796
|
+
dropped: external_exports.number().int().nonnegative(),
|
|
19797
|
+
/** F2: nudges a person sent to the sessions of a `deliver` event, by the tool's own session id. The runner prints the text as the hook's `additionalContext`. */
|
|
19798
|
+
nudges: external_exports.array(external_exports.object({ session_id: external_exports.string(), text: external_exports.string() })).optional()
|
|
19795
19799
|
});
|
|
19796
19800
|
|
|
19801
|
+
// ../shared/src/machine-health.ts
|
|
19802
|
+
var MACHINE_HEALTH_RULES = ["offline_with_claims", "disk_full", "disk_high", "memory_high", "cli_behind"];
|
|
19803
|
+
|
|
19797
19804
|
// ../shared/src/api/projects.ts
|
|
19798
19805
|
var idSchema = external_exports.string().regex(/^[0-9]{1,15}$/, "must be a numeric id");
|
|
19799
19806
|
var projectNameSchema = external_exports.string().trim().min(1).max(100);
|
|
@@ -19818,7 +19825,7 @@ var logoutBody = external_exports.object({ everywhere: external_exports.boolean(
|
|
|
19818
19825
|
var isoSchema = external_exports.string();
|
|
19819
19826
|
var roleEnum = external_exports.enum(["owner", "admin", "member", "viewer"]);
|
|
19820
19827
|
var okResponse = external_exports.object({ ok: external_exports.literal(true) }).strict();
|
|
19821
|
-
var listOf = (item) => external_exports.object({ items: external_exports.array(item), next_cursor: external_exports.string().nullable() }).strict();
|
|
19828
|
+
var listOf = (item) => external_exports.object({ items: external_exports.array(item), next_cursor: external_exports.string().nullable(), total: external_exports.number().int().nonnegative().optional() }).strict();
|
|
19822
19829
|
var publicConfigResponse = external_exports.object({ dev_login: external_exports.boolean(), github: external_exports.boolean(), github_app: external_exports.boolean(), push: external_exports.object({ enabled: external_exports.boolean(), public_key: external_exports.string().nullable() }).optional() }).strict();
|
|
19823
19830
|
var publicUserSchema = external_exports.object({ id: idSchema, login: external_exports.string(), name: external_exports.string().nullable(), avatar_url: external_exports.string().nullable() }).strict();
|
|
19824
19831
|
var projectBriefSchema = external_exports.object({ id: idSchema, key: external_exports.string(), name: external_exports.string(), role: roleEnum }).strict();
|
|
@@ -19964,6 +19971,10 @@ var machineAgentSchema = external_exports.object({
|
|
|
19964
19971
|
live_sessions: external_exports.number().int().nonnegative(),
|
|
19965
19972
|
last_seen_at: external_exports.string().nullable()
|
|
19966
19973
|
});
|
|
19974
|
+
var machineHealthViewSchema = external_exports.object({
|
|
19975
|
+
level: external_exports.enum(["warn", "critical"]),
|
|
19976
|
+
findings: external_exports.array(external_exports.object({ rule: external_exports.enum(MACHINE_HEALTH_RULES), level: external_exports.enum(["warn", "critical"]), text: external_exports.string() }))
|
|
19977
|
+
});
|
|
19967
19978
|
var machineSchema = external_exports.object({
|
|
19968
19979
|
id: external_exports.string(),
|
|
19969
19980
|
name: external_exports.string(),
|
|
@@ -19975,7 +19986,9 @@ var machineSchema = external_exports.object({
|
|
|
19975
19986
|
default_project_id: external_exports.string().nullable(),
|
|
19976
19987
|
projects: external_exports.array(external_exports.object({ id: external_exports.string(), key: external_exports.string(), name: external_exports.string(), default: external_exports.boolean() })),
|
|
19977
19988
|
stats: machineStatsSchema.nullable(),
|
|
19978
|
-
agents: external_exports.array(machineAgentSchema)
|
|
19989
|
+
agents: external_exports.array(machineAgentSchema),
|
|
19990
|
+
/** The rules that fire for this machine; null or absent when healthy (older servers omit it). */
|
|
19991
|
+
health: machineHealthViewSchema.nullable().optional()
|
|
19979
19992
|
});
|
|
19980
19993
|
var patchMachineBody = external_exports.object({
|
|
19981
19994
|
name: external_exports.string().trim().min(1).max(100).optional(),
|
|
@@ -19995,121 +20008,44 @@ function cliNpxCommand(args = "", opts = {}) {
|
|
|
19995
20008
|
}
|
|
19996
20009
|
var CLI_CONNECT_COMMAND = cliNpxCommand("connect");
|
|
19997
20010
|
|
|
19998
|
-
// ../shared/src/
|
|
19999
|
-
var
|
|
20000
|
-
var
|
|
20001
|
-
|
|
20002
|
-
|
|
20003
|
-
|
|
20004
|
-
function normalizeRemote(remote) {
|
|
20005
|
-
let s = remote.trim();
|
|
20006
|
-
if (!s || s.length > 2048 || /[\s\0]/.test(s)) return null;
|
|
20007
|
-
let host2;
|
|
20008
|
-
let path;
|
|
20009
|
-
if (SCHEME.test(s)) {
|
|
20010
|
-
s = s.replace(SCHEME, "");
|
|
20011
|
-
const slash = s.indexOf("/");
|
|
20012
|
-
if (slash < 0) return null;
|
|
20013
|
-
host2 = s.slice(0, slash);
|
|
20014
|
-
path = s.slice(slash + 1);
|
|
20015
|
-
} else {
|
|
20016
|
-
const colon = s.indexOf(":");
|
|
20017
|
-
const slash = s.indexOf("/");
|
|
20018
|
-
if (colon >= 0 && (slash < 0 || colon < slash)) {
|
|
20019
|
-
host2 = s.slice(0, colon);
|
|
20020
|
-
path = s.slice(colon + 1);
|
|
20021
|
-
} else if (slash >= 0) {
|
|
20022
|
-
host2 = s.slice(0, slash);
|
|
20023
|
-
path = s.slice(slash + 1);
|
|
20024
|
-
} else {
|
|
20025
|
-
return null;
|
|
20026
|
-
}
|
|
20027
|
-
}
|
|
20028
|
-
const at = host2.lastIndexOf("@");
|
|
20029
|
-
if (at >= 0) host2 = host2.slice(at + 1);
|
|
20030
|
-
host2 = host2.replace(/:\d*$/, "").toLowerCase();
|
|
20031
|
-
if (!/^[a-z0-9]([a-z0-9.-]*[a-z0-9])?$/.test(host2)) return null;
|
|
20032
|
-
path = path.replace(/[?#].*$/, "");
|
|
20033
|
-
const parts = path.split("/").filter((p) => p.length > 0);
|
|
20034
|
-
if (parts.length < 2) return null;
|
|
20035
|
-
let name = parts[parts.length - 1];
|
|
20036
|
-
if (name.toLowerCase().endsWith(".git")) name = name.slice(0, -4);
|
|
20037
|
-
const ownerParts = parts.slice(0, -1);
|
|
20038
|
-
if (!name || [...ownerParts, name].some((p) => p === "." || p === ".." || !/^[A-Za-z0-9_.@+-]+$/.test(p))) return null;
|
|
20039
|
-
return { host: host2, owner: ownerParts.join("/"), name };
|
|
20040
|
-
}
|
|
20041
|
-
function formatRemote(r) {
|
|
20042
|
-
return `${r.host}/${r.owner}/${r.name}`;
|
|
20043
|
-
}
|
|
20044
|
-
|
|
20045
|
-
// ../shared/src/redact.ts
|
|
20046
|
-
var tag = (kind) => `[redacted:${kind}]`;
|
|
20047
|
-
function isPlaceholder(value) {
|
|
20048
|
-
const v = value.replace(/^["']|["']$/g, "");
|
|
20049
|
-
return v === "" || /^(\$|<|\{|%|\*+$|x+$|\.\.\.|\[redacted)/i.test(v) || /^(process\.env|os\.environ|env\.|ENV\[|config\.|settings\.)/i.test(v) || /^(null|none|undefined|true|false|changeme|example|your[_-])/i.test(v);
|
|
20050
|
-
}
|
|
20051
|
-
var KEY_PREFIX = String.raw`(?<![A-Za-z0-9])`;
|
|
20052
|
-
var VALUE = String.raw`("[^"\r\n]*"|'[^'\r\n]*'|[^\s,;"'&)}\]]+)`;
|
|
20053
|
-
var RULES = [
|
|
20054
|
-
{ kind: "pem", re: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z0-9 ]*PRIVATE KEY-----|$)/g },
|
|
20055
|
-
{ kind: "github", re: /\bgithub_pat_[A-Za-z0-9_]{20,}/g },
|
|
20056
|
-
{ kind: "github", re: /\bgh[pousr]_[A-Za-z0-9]{20,}/g },
|
|
20057
|
-
{ kind: "anthropic", re: /\bsk-ant-[A-Za-z0-9_-]{10,}/g },
|
|
20058
|
-
// sk- keys are random base62; the digit lookahead keeps hyphenated words ("sk-learn-compatible-...") out.
|
|
20059
|
-
{ kind: "openai", re: /\bsk-(?=[A-Za-z0-9_-]*\d)[A-Za-z0-9_-]{20,}/g },
|
|
20060
|
-
{ kind: "aws", re: /\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g },
|
|
20061
|
-
{ kind: "slack", re: /\bxox[abprs]-[A-Za-z0-9-]{10,}/g },
|
|
20062
|
-
// hf_ tokens are 32 random bytes in base64url: long, with a digit or capital. Snake_case identifiers have neither.
|
|
20063
|
-
{ kind: "hivefloor", re: /\bhf_(?=[A-Za-z0-9_-]*[A-Z0-9])[A-Za-z0-9_-]{32,}/g },
|
|
20064
|
-
// A fleet push token (hff_ + 32 random bytes) or machine token (hfm_ + 32 random bytes): must never end up in a status line or a title.
|
|
20065
|
-
{ kind: "hivefloor", re: /\bhf[fm]_[A-Za-z0-9_-]{20,}/g },
|
|
20066
|
-
{ kind: "webhook", re: /\bwhsec_[A-Za-z0-9_-]{16,}/g },
|
|
20067
|
-
{ kind: "vqb", re: /\bvqb_[A-Za-z0-9_-]{16,}/g },
|
|
20068
|
-
{ kind: "jwt", re: /\beyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]*/g },
|
|
20069
|
-
{
|
|
20070
|
-
kind: "bearer",
|
|
20071
|
-
re: /\b(Bearer)\s+(?=[A-Za-z0-9._~+/=-]*\d)[A-Za-z0-9._~+/=-]{20,}/g,
|
|
20072
|
-
replace: (_m, word) => `${word} ${tag("bearer")}`
|
|
20073
|
-
},
|
|
20074
|
-
// password=hunter2, "passwd": "x", DB_PASSWORD='x'. Any non-placeholder value counts.
|
|
20075
|
-
{
|
|
20076
|
-
kind: "password",
|
|
20077
|
-
re: new RegExp(String.raw`${KEY_PREFIX}(password|passwd|pwd)(["']?\s*[:=]\s*)${VALUE}`, "gi"),
|
|
20078
|
-
replace: (m, _key, sep = "", value = "") => isAssignedSecret(sep, value, 1) ? `${m.slice(0, m.length - value.length)}${tag("password")}` : null
|
|
20079
|
-
},
|
|
20080
|
-
// token=..., client_secret: ..., api_key=...: the value has to be long enough to be a credential.
|
|
20081
|
-
{
|
|
20082
|
-
kind: "secret",
|
|
20083
|
-
re: new RegExp(String.raw`${KEY_PREFIX}(secret|token|api[_-]?key|apikey)(["']?\s*[:=]\s*)${VALUE}`, "gi"),
|
|
20084
|
-
replace: (m, _key, sep = "", value = "") => isAssignedSecret(sep, value, 8) ? `${m.slice(0, m.length - value.length)}${tag("secret")}` : null
|
|
20085
|
-
}
|
|
20086
|
-
];
|
|
20087
|
-
function isAssignedSecret(sep, value, minLen) {
|
|
20088
|
-
if (isPlaceholder(value)) return false;
|
|
20089
|
-
const quoted = /^["']/.test(value);
|
|
20090
|
-
const v = value.replace(/^["']|["']$/g, "");
|
|
20091
|
-
if (v.length < minLen) return false;
|
|
20092
|
-
if (sep.includes("=") || quoted) return true;
|
|
20093
|
-
return v.length >= 6 && /[^A-Za-z]/.test(v);
|
|
20011
|
+
// ../shared/src/usage.ts
|
|
20012
|
+
var MIN_SPAN_MS = 5 * 6e4;
|
|
20013
|
+
var MAX_ETA_MS = 31 * 24 * 36e5;
|
|
20014
|
+
var USAGE_COUNTERS = ["tokens_in", "tokens_out", "cost_usd"];
|
|
20015
|
+
function isUsageCounter(value) {
|
|
20016
|
+
return USAGE_COUNTERS.includes(value);
|
|
20094
20017
|
}
|
|
20095
|
-
function
|
|
20096
|
-
|
|
20097
|
-
|
|
20098
|
-
|
|
20099
|
-
|
|
20100
|
-
|
|
20101
|
-
|
|
20102
|
-
|
|
20103
|
-
|
|
20104
|
-
|
|
20105
|
-
return out;
|
|
20106
|
-
});
|
|
20018
|
+
function parseUsageKey(key2) {
|
|
20019
|
+
const parts = key2.split(":");
|
|
20020
|
+
if (parts.length < 3) return null;
|
|
20021
|
+
const tool = parts[0];
|
|
20022
|
+
const profile = parts[1];
|
|
20023
|
+
if (!TOOLS.includes(tool)) return null;
|
|
20024
|
+
if (!PROFILE_KEY_RE.test(profile)) return null;
|
|
20025
|
+
if (parts.length === 3) {
|
|
20026
|
+
const counter2 = parts[2];
|
|
20027
|
+
return isUsageCounter(counter2) ? { tool, profile, session: null, counter: counter2 } : null;
|
|
20107
20028
|
}
|
|
20108
|
-
|
|
20029
|
+
if (parts[2] !== "s" || parts.length < 5) return null;
|
|
20030
|
+
const session = parts.slice(3, -1).join(":");
|
|
20031
|
+
const counter = parts[parts.length - 1];
|
|
20032
|
+
if (!session || !isUsageCounter(counter)) return null;
|
|
20033
|
+
return { tool, profile, session, counter };
|
|
20109
20034
|
}
|
|
20110
20035
|
|
|
20036
|
+
// ../shared/src/usage-alerts.ts
|
|
20037
|
+
var WASTE_WITHIN_MS = 3 * 36e5;
|
|
20038
|
+
|
|
20039
|
+
// ../shared/src/task-status.ts
|
|
20040
|
+
var TASK_STATUSES = ["backlog", "ready", "claimed", "in_review", "done", "blocked", "parked"];
|
|
20041
|
+
var taskStatusSchema = external_exports.enum(TASK_STATUSES);
|
|
20042
|
+
|
|
20111
20043
|
// ../shared/src/health.ts
|
|
20112
|
-
var
|
|
20044
|
+
var PARKED_AFTER_SEC = 20 * 60;
|
|
20045
|
+
var WAITING_LONG_AFTER_SEC = 15 * 60;
|
|
20046
|
+
var MIN_STALL_THRESHOLD_SEC = 60;
|
|
20047
|
+
var MAX_STALL_THRESHOLD_SEC = 7 * 24 * 3600;
|
|
20048
|
+
var SESSION_HEALTH = ["ok", "stalled", "lost", "looping", "parked", "waiting_long"];
|
|
20113
20049
|
|
|
20114
20050
|
// ../shared/src/api/rules.ts
|
|
20115
20051
|
var entityId = external_exports.string().regex(/^\d{1,20}$/, "an id is a decimal string");
|
|
@@ -20134,6 +20070,10 @@ var rulesConfigSchema = external_exports.object({
|
|
|
20134
20070
|
wip_per_agent: cap,
|
|
20135
20071
|
wip_per_machine: cap,
|
|
20136
20072
|
stall_release_seconds: external_exports.number().int().min(MIN_STALL_RELEASE_SECONDS).max(MAX_STALL_RELEASE_SECONDS).nullable(),
|
|
20073
|
+
/** Seconds an idle session holds a claim before it shows as parked (default 20 min); null or omitted = default. An omitted field keeps what is stored. */
|
|
20074
|
+
parked_after_seconds: external_exports.number().int().min(MIN_STALL_THRESHOLD_SEC).max(MAX_STALL_THRESHOLD_SEC).nullable().optional(),
|
|
20075
|
+
/** Seconds a wait on a person lasts before it shows as waiting_long and the owner is pushed again (default 15 min); the admins hear at 4 times this. */
|
|
20076
|
+
waiting_long_after_seconds: external_exports.number().int().min(MIN_STALL_THRESHOLD_SEC).max(MAX_STALL_THRESHOLD_SEC).nullable().optional(),
|
|
20137
20077
|
rules: external_exports.array(ruleSchema).max(MAX_RULES).refine((rs) => new Set(rs.map((r) => r.id)).size === rs.length, "rule ids must be unique")
|
|
20138
20078
|
}).strict();
|
|
20139
20079
|
var steerBody = external_exports.object({
|
|
@@ -20204,9 +20144,11 @@ var taskCardSchema = external_exports.object({
|
|
|
20204
20144
|
done_at: isoTimeSchema.nullable(),
|
|
20205
20145
|
archived_at: isoTimeSchema.nullable(),
|
|
20206
20146
|
/** Tasks this one waits on (stage 2). It is claimable only when every one of them is done. */
|
|
20207
|
-
blocked_by: external_exports.array(blockerRefSchema).default([])
|
|
20147
|
+
blocked_by: external_exports.array(blockerRefSchema).default([]),
|
|
20148
|
+
/** A claimed task whose holder's machine is offline: the work may be stuck there. Absent or false otherwise. */
|
|
20149
|
+
at_risk: external_exports.boolean().optional()
|
|
20208
20150
|
});
|
|
20209
|
-
var TASK_TIMELINE_KINDS = ["created", "claimed", "note", "blocked", "released", "lease_expired", "pr", "in_review", "done", "answered", "archived", "unarchived", "unblocked", "steered"];
|
|
20151
|
+
var TASK_TIMELINE_KINDS = ["created", "claimed", "note", "blocked", "released", "lease_expired", "pr", "in_review", "done", "answered", "archived", "unarchived", "unblocked", "steered", "nudged"];
|
|
20210
20152
|
var taskTimelineKindSchema = external_exports.enum(TASK_TIMELINE_KINDS);
|
|
20211
20153
|
var taskTimelineEventSchema = external_exports.object({
|
|
20212
20154
|
id: entityIdSchema,
|
|
@@ -20222,9 +20164,12 @@ var taskTimelineEventSchema = external_exports.object({
|
|
|
20222
20164
|
});
|
|
20223
20165
|
var taskListSchema = external_exports.object({
|
|
20224
20166
|
items: external_exports.array(taskCardSchema),
|
|
20225
|
-
next_cursor: external_exports.string().nullable()
|
|
20167
|
+
next_cursor: external_exports.string().nullable(),
|
|
20168
|
+
/** Matching tasks across all pages. Only present when the request used `offset` (page-number lists). */
|
|
20169
|
+
total: external_exports.number().int().nonnegative().optional()
|
|
20226
20170
|
});
|
|
20227
20171
|
var queryId = external_exports.string().regex(/^[1-9][0-9]{0,14}$/);
|
|
20172
|
+
var queryOffset = external_exports.string().regex(/^(0|[1-9][0-9]{0,5})$/).transform(Number);
|
|
20228
20173
|
var queryLimit = external_exports.string().regex(/^[1-9][0-9]{0,2}$/).transform(Number).pipe(external_exports.number().int().max(200));
|
|
20229
20174
|
var replayCursor = external_exports.string().max(100).regex(/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{6}Z_[1-9][0-9]{0,14}$/).refine((value) => isoTimeSchema.safeParse(value.split("_")[0]).success, "invalid cursor time");
|
|
20230
20175
|
var queryStatus = external_exports.string().min(1).max(80).transform((value) => value.split(",").map((status) => status.trim())).pipe(external_exports.array(taskStatusSchema).min(1).max(7)).refine((values) => new Set(values).size === values.length, "statuses must be distinct");
|
|
@@ -20240,8 +20185,10 @@ var taskListQuerySchema = external_exports.object({
|
|
|
20240
20185
|
parent: queryId.optional(),
|
|
20241
20186
|
archived: external_exports.enum(["0", "1", "all", "false", "true"]).optional(),
|
|
20242
20187
|
limit: queryLimit.optional(),
|
|
20243
|
-
cursor: external_exports.union([queryId, replayCursor]).optional()
|
|
20244
|
-
|
|
20188
|
+
cursor: external_exports.union([queryId, replayCursor]).optional(),
|
|
20189
|
+
/** Page-number paging (the Done page): skip this many tasks and also return `total`. Not combinable with `cursor`. */
|
|
20190
|
+
offset: queryOffset.optional()
|
|
20191
|
+
}).strict().refine((value) => value.offset === void 0 || value.cursor === void 0, "use offset or cursor").refine((value) => value.agent === void 0 || value.holder_agent === void 0, "use agent or holder_agent");
|
|
20245
20192
|
var agentTaskListQuerySchema = taskListQuerySchema.safeExtend({ project: projectRefSchema.optional() });
|
|
20246
20193
|
var taskStatusLineSchema = external_exports.object({
|
|
20247
20194
|
id: entityIdSchema,
|
|
@@ -20259,7 +20206,7 @@ var taskStatusLineQuerySchema = external_exports.object({
|
|
|
20259
20206
|
}).strict();
|
|
20260
20207
|
var taskResultSchema = external_exports.object({ task: taskCardSchema });
|
|
20261
20208
|
var answerBodySchema = external_exports.object({ text: external_exports.string().trim().min(1).max(500) });
|
|
20262
|
-
var NOTIFICATION_KINDS = ["task_done", "task_blocked", "agent_waiting", "invite_received", "member_added", "repo_link_requested", "agent_question"];
|
|
20209
|
+
var NOTIFICATION_KINDS = ["task_done", "task_blocked", "agent_waiting", "invite_received", "member_added", "repo_link_requested", "agent_question", "feedback", "usage_waste", "usage_high", "wait_escalated", "machine_unhealthy"];
|
|
20263
20210
|
var notificationKindSchema = external_exports.enum(NOTIFICATION_KINDS);
|
|
20264
20211
|
var notificationViewSchema = external_exports.object({
|
|
20265
20212
|
id: entityIdSchema,
|
|
@@ -20352,50 +20299,6 @@ var releaseBody = external_exports.object({
|
|
|
20352
20299
|
}).strict();
|
|
20353
20300
|
var completeBody = external_exports.object({ claim_token: claimToken.optional(), summary: external_exports.string().min(1).max(5e3), pr_url: external_exports.string().max(1e3).optional(), session: sessionRef.optional() }).strict();
|
|
20354
20301
|
|
|
20355
|
-
// ../shared/src/api/memory.ts
|
|
20356
|
-
var CONTEXT_DECISIONS = 10;
|
|
20357
|
-
var MEMORY_KINDS = ["handoff", "decision"];
|
|
20358
|
-
var memoryKindSchema = external_exports.enum(MEMORY_KINDS);
|
|
20359
|
-
var memoryEntrySchema = external_exports.object({
|
|
20360
|
-
id: entityIdSchema,
|
|
20361
|
-
kind: memoryKindSchema,
|
|
20362
|
-
/** The task the entry is about; always set for a handoff. */
|
|
20363
|
-
task_id: entityIdSchema.nullable(),
|
|
20364
|
-
/** The task as people write it (`HF-12`). */
|
|
20365
|
-
task_key: external_exports.string().nullable(),
|
|
20366
|
-
text: external_exports.string(),
|
|
20367
|
-
author: external_exports.object({ type: external_exports.enum(["agent", "user", "system"]), name: external_exports.string() }),
|
|
20368
|
-
created_at: isoTimeSchema
|
|
20369
|
-
});
|
|
20370
|
-
var memoryContextSchema = external_exports.object({
|
|
20371
|
-
handoff: memoryEntrySchema.nullable(),
|
|
20372
|
-
decisions: external_exports.array(memoryEntrySchema).max(CONTEXT_DECISIONS)
|
|
20373
|
-
});
|
|
20374
|
-
var memoryListSchema = external_exports.object({
|
|
20375
|
-
items: external_exports.array(memoryEntrySchema),
|
|
20376
|
-
next_cursor: external_exports.string().nullable()
|
|
20377
|
-
});
|
|
20378
|
-
var taskIdSchema2 = external_exports.union([external_exports.string().regex(/^[0-9]{1,15}$/), external_exports.number().int().positive()]).transform((v) => String(v));
|
|
20379
|
-
var sessionRef2 = external_exports.string().trim().min(1).max(200);
|
|
20380
|
-
var addDecisionBody = external_exports.object({
|
|
20381
|
-
project: projectRefSchema.optional(),
|
|
20382
|
-
/** The task the decision is about (optional). */
|
|
20383
|
-
task_id: taskIdSchema2.optional(),
|
|
20384
|
-
text: external_exports.string().min(1).max(2e3),
|
|
20385
|
-
session: sessionRef2.optional()
|
|
20386
|
-
}).strict();
|
|
20387
|
-
var getContextBody = external_exports.object({
|
|
20388
|
-
project: projectRefSchema.optional(),
|
|
20389
|
-
/** The task whose last handoff to include. */
|
|
20390
|
-
task_id: taskIdSchema2.optional()
|
|
20391
|
-
}).strict();
|
|
20392
|
-
var humanDecisionBody = external_exports.object({
|
|
20393
|
-
text: external_exports.string().trim().min(1).max(2e3),
|
|
20394
|
-
/** The task number (not the id) the decision is about. */
|
|
20395
|
-
task_num: external_exports.number().int().positive().max(2e9).optional()
|
|
20396
|
-
}).strict();
|
|
20397
|
-
var decisionResultSchema = external_exports.object({ entry: memoryEntrySchema });
|
|
20398
|
-
|
|
20399
20302
|
// ../shared/src/api/usage.ts
|
|
20400
20303
|
var isoTime = external_exports.iso.datetime({ offset: true });
|
|
20401
20304
|
var USAGE_PROVIDERS = [
|
|
@@ -20517,6 +20420,210 @@ var taskUsageSchema = external_exports.object({
|
|
|
20517
20420
|
agents: external_exports.array(taskUsageAgentSchema).max(50)
|
|
20518
20421
|
}).strict();
|
|
20519
20422
|
|
|
20423
|
+
// ../shared/src/usage-route.ts
|
|
20424
|
+
var ROUTE_HORIZON_MS = 2 * 36e5;
|
|
20425
|
+
function usageProviderForTool(tool) {
|
|
20426
|
+
switch (tool) {
|
|
20427
|
+
case "claude":
|
|
20428
|
+
case "codex":
|
|
20429
|
+
case "cursor":
|
|
20430
|
+
case "gemini":
|
|
20431
|
+
case "grok":
|
|
20432
|
+
return tool;
|
|
20433
|
+
default:
|
|
20434
|
+
return null;
|
|
20435
|
+
}
|
|
20436
|
+
}
|
|
20437
|
+
function routeProviderFromParam(param) {
|
|
20438
|
+
const v = param.trim().toLowerCase();
|
|
20439
|
+
const fromTool = usageProviderForTool(v);
|
|
20440
|
+
if (fromTool) return fromTool;
|
|
20441
|
+
const p = usageProviderSchema.safeParse(v);
|
|
20442
|
+
return p.success ? p.data : null;
|
|
20443
|
+
}
|
|
20444
|
+
var isoTime2 = external_exports.iso.datetime({ offset: true });
|
|
20445
|
+
var routeAccountSchema = external_exports.object({
|
|
20446
|
+
id: external_exports.string().max(120),
|
|
20447
|
+
label: external_exports.string().max(60),
|
|
20448
|
+
plan: external_exports.string().max(40).optional(),
|
|
20449
|
+
usable: external_exports.boolean(),
|
|
20450
|
+
score: external_exports.number().nullable(),
|
|
20451
|
+
window: external_exports.string().max(40).optional(),
|
|
20452
|
+
percent_left: external_exports.number().min(0).max(100).optional(),
|
|
20453
|
+
resets_at: isoTime2.optional(),
|
|
20454
|
+
live_sessions: external_exports.number().int().nonnegative(),
|
|
20455
|
+
waste: external_exports.boolean(),
|
|
20456
|
+
reason: external_exports.string().max(200)
|
|
20457
|
+
}).strict();
|
|
20458
|
+
var routeProviderSchema = external_exports.object({
|
|
20459
|
+
provider: usageProviderSchema,
|
|
20460
|
+
name: external_exports.string().max(40),
|
|
20461
|
+
/** The account to use next: the first of `accounts` when it is usable, else null. */
|
|
20462
|
+
best: external_exports.string().max(120).nullable(),
|
|
20463
|
+
accounts: external_exports.array(routeAccountSchema).max(100)
|
|
20464
|
+
}).strict();
|
|
20465
|
+
var usageRouteSchema = external_exports.object({
|
|
20466
|
+
generated_at: isoTime2,
|
|
20467
|
+
/** The provider asked for, or null for all of them. */
|
|
20468
|
+
provider: usageProviderSchema.nullable(),
|
|
20469
|
+
providers: external_exports.array(routeProviderSchema).max(USAGE_PROVIDERS.length),
|
|
20470
|
+
/** Live sessions that could not be counted against an account (no label, unknown label, a tool with no usage). */
|
|
20471
|
+
unlinked_sessions: external_exports.number().int().nonnegative()
|
|
20472
|
+
}).strict();
|
|
20473
|
+
|
|
20474
|
+
// ../shared/src/remote.ts
|
|
20475
|
+
var SCHEME = /^([a-z][a-z0-9+.-]*):\/\//i;
|
|
20476
|
+
function normalizeRemote(remote) {
|
|
20477
|
+
let s = remote.trim();
|
|
20478
|
+
if (!s || s.length > 2048 || /[\s\0]/.test(s)) return null;
|
|
20479
|
+
let host2;
|
|
20480
|
+
let path;
|
|
20481
|
+
if (SCHEME.test(s)) {
|
|
20482
|
+
s = s.replace(SCHEME, "");
|
|
20483
|
+
const slash = s.indexOf("/");
|
|
20484
|
+
if (slash < 0) return null;
|
|
20485
|
+
host2 = s.slice(0, slash);
|
|
20486
|
+
path = s.slice(slash + 1);
|
|
20487
|
+
} else {
|
|
20488
|
+
const colon = s.indexOf(":");
|
|
20489
|
+
const slash = s.indexOf("/");
|
|
20490
|
+
if (colon >= 0 && (slash < 0 || colon < slash)) {
|
|
20491
|
+
host2 = s.slice(0, colon);
|
|
20492
|
+
path = s.slice(colon + 1);
|
|
20493
|
+
} else if (slash >= 0) {
|
|
20494
|
+
host2 = s.slice(0, slash);
|
|
20495
|
+
path = s.slice(slash + 1);
|
|
20496
|
+
} else {
|
|
20497
|
+
return null;
|
|
20498
|
+
}
|
|
20499
|
+
}
|
|
20500
|
+
const at = host2.lastIndexOf("@");
|
|
20501
|
+
if (at >= 0) host2 = host2.slice(at + 1);
|
|
20502
|
+
host2 = host2.replace(/:\d*$/, "").toLowerCase();
|
|
20503
|
+
if (!/^[a-z0-9]([a-z0-9.-]*[a-z0-9])?$/.test(host2)) return null;
|
|
20504
|
+
path = path.replace(/[?#].*$/, "");
|
|
20505
|
+
const parts = path.split("/").filter((p) => p.length > 0);
|
|
20506
|
+
if (parts.length < 2) return null;
|
|
20507
|
+
let name = parts[parts.length - 1];
|
|
20508
|
+
if (name.toLowerCase().endsWith(".git")) name = name.slice(0, -4);
|
|
20509
|
+
const ownerParts = parts.slice(0, -1);
|
|
20510
|
+
if (!name || [...ownerParts, name].some((p) => p === "." || p === ".." || !/^[A-Za-z0-9_.@+-]+$/.test(p))) return null;
|
|
20511
|
+
return { host: host2, owner: ownerParts.join("/"), name };
|
|
20512
|
+
}
|
|
20513
|
+
function formatRemote(r) {
|
|
20514
|
+
return `${r.host}/${r.owner}/${r.name}`;
|
|
20515
|
+
}
|
|
20516
|
+
|
|
20517
|
+
// ../shared/src/redact.ts
|
|
20518
|
+
var tag = (kind) => `[redacted:${kind}]`;
|
|
20519
|
+
function isPlaceholder(value) {
|
|
20520
|
+
const v = value.replace(/^["']|["']$/g, "");
|
|
20521
|
+
return v === "" || /^(\$|<|\{|%|\*+$|x+$|\.\.\.|\[redacted)/i.test(v) || /^(process\.env|os\.environ|env\.|ENV\[|config\.|settings\.)/i.test(v) || /^(null|none|undefined|true|false|changeme|example|your[_-])/i.test(v);
|
|
20522
|
+
}
|
|
20523
|
+
var KEY_PREFIX = String.raw`(?<![A-Za-z0-9])`;
|
|
20524
|
+
var VALUE = String.raw`("[^"\r\n]*"|'[^'\r\n]*'|[^\s,;"'&)}\]]+)`;
|
|
20525
|
+
var RULES = [
|
|
20526
|
+
{ kind: "pem", re: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z0-9 ]*PRIVATE KEY-----|$)/g },
|
|
20527
|
+
{ kind: "github", re: /\bgithub_pat_[A-Za-z0-9_]{20,}/g },
|
|
20528
|
+
{ kind: "github", re: /\bgh[pousr]_[A-Za-z0-9]{20,}/g },
|
|
20529
|
+
{ kind: "anthropic", re: /\bsk-ant-[A-Za-z0-9_-]{10,}/g },
|
|
20530
|
+
// sk- keys are random base62; the digit lookahead keeps hyphenated words ("sk-learn-compatible-...") out.
|
|
20531
|
+
{ kind: "openai", re: /\bsk-(?=[A-Za-z0-9_-]*\d)[A-Za-z0-9_-]{20,}/g },
|
|
20532
|
+
{ kind: "aws", re: /\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g },
|
|
20533
|
+
{ kind: "slack", re: /\bxox[abprs]-[A-Za-z0-9-]{10,}/g },
|
|
20534
|
+
// hf_ tokens are 32 random bytes in base64url: long, with a digit or capital. Snake_case identifiers have neither.
|
|
20535
|
+
{ kind: "hivefloor", re: /\bhf_(?=[A-Za-z0-9_-]*[A-Z0-9])[A-Za-z0-9_-]{32,}/g },
|
|
20536
|
+
// A fleet push token (hff_ + 32 random bytes) or machine token (hfm_ + 32 random bytes): must never end up in a status line or a title.
|
|
20537
|
+
{ kind: "hivefloor", re: /\bhf[fm]_[A-Za-z0-9_-]{20,}/g },
|
|
20538
|
+
{ kind: "webhook", re: /\bwhsec_[A-Za-z0-9_-]{16,}/g },
|
|
20539
|
+
{ kind: "vqb", re: /\bvqb_[A-Za-z0-9_-]{16,}/g },
|
|
20540
|
+
{ kind: "jwt", re: /\beyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]*/g },
|
|
20541
|
+
{
|
|
20542
|
+
kind: "bearer",
|
|
20543
|
+
re: /\b(Bearer)\s+(?=[A-Za-z0-9._~+/=-]*\d)[A-Za-z0-9._~+/=-]{20,}/g,
|
|
20544
|
+
replace: (_m, word) => `${word} ${tag("bearer")}`
|
|
20545
|
+
},
|
|
20546
|
+
// password=hunter2, "passwd": "x", DB_PASSWORD='x'. Any non-placeholder value counts.
|
|
20547
|
+
{
|
|
20548
|
+
kind: "password",
|
|
20549
|
+
re: new RegExp(String.raw`${KEY_PREFIX}(password|passwd|pwd)(["']?\s*[:=]\s*)${VALUE}`, "gi"),
|
|
20550
|
+
replace: (m, _key, sep = "", value = "") => isAssignedSecret(sep, value, 1) ? `${m.slice(0, m.length - value.length)}${tag("password")}` : null
|
|
20551
|
+
},
|
|
20552
|
+
// token=..., client_secret: ..., api_key=...: the value has to be long enough to be a credential.
|
|
20553
|
+
{
|
|
20554
|
+
kind: "secret",
|
|
20555
|
+
re: new RegExp(String.raw`${KEY_PREFIX}(secret|token|api[_-]?key|apikey)(["']?\s*[:=]\s*)${VALUE}`, "gi"),
|
|
20556
|
+
replace: (m, _key, sep = "", value = "") => isAssignedSecret(sep, value, 8) ? `${m.slice(0, m.length - value.length)}${tag("secret")}` : null
|
|
20557
|
+
}
|
|
20558
|
+
];
|
|
20559
|
+
function isAssignedSecret(sep, value, minLen) {
|
|
20560
|
+
if (isPlaceholder(value)) return false;
|
|
20561
|
+
const quoted = /^["']/.test(value);
|
|
20562
|
+
const v = value.replace(/^["']|["']$/g, "");
|
|
20563
|
+
if (v.length < minLen) return false;
|
|
20564
|
+
if (sep.includes("=") || quoted) return true;
|
|
20565
|
+
return v.length >= 6 && /[^A-Za-z]/.test(v);
|
|
20566
|
+
}
|
|
20567
|
+
function redact(input2) {
|
|
20568
|
+
let text2 = input2;
|
|
20569
|
+
let count = 0;
|
|
20570
|
+
for (const rule of RULES) {
|
|
20571
|
+
text2 = text2.replace(rule.re, (...args) => {
|
|
20572
|
+
const match = args[0];
|
|
20573
|
+
const groups = args.slice(1, -2).filter((g) => typeof g === "string");
|
|
20574
|
+
const out = rule.replace ? rule.replace(match, ...groups) : tag(rule.kind);
|
|
20575
|
+
if (out === null) return match;
|
|
20576
|
+
count += 1;
|
|
20577
|
+
return out;
|
|
20578
|
+
});
|
|
20579
|
+
}
|
|
20580
|
+
return { text: text2, count };
|
|
20581
|
+
}
|
|
20582
|
+
|
|
20583
|
+
// ../shared/src/api/memory.ts
|
|
20584
|
+
var CONTEXT_DECISIONS = 10;
|
|
20585
|
+
var MEMORY_KINDS = ["handoff", "decision"];
|
|
20586
|
+
var memoryKindSchema = external_exports.enum(MEMORY_KINDS);
|
|
20587
|
+
var memoryEntrySchema = external_exports.object({
|
|
20588
|
+
id: entityIdSchema,
|
|
20589
|
+
kind: memoryKindSchema,
|
|
20590
|
+
/** The task the entry is about; always set for a handoff. */
|
|
20591
|
+
task_id: entityIdSchema.nullable(),
|
|
20592
|
+
/** The task as people write it (`HF-12`). */
|
|
20593
|
+
task_key: external_exports.string().nullable(),
|
|
20594
|
+
text: external_exports.string(),
|
|
20595
|
+
author: external_exports.object({ type: external_exports.enum(["agent", "user", "system"]), name: external_exports.string() }),
|
|
20596
|
+
created_at: isoTimeSchema
|
|
20597
|
+
});
|
|
20598
|
+
var memoryContextSchema = external_exports.object({
|
|
20599
|
+
handoff: memoryEntrySchema.nullable(),
|
|
20600
|
+
decisions: external_exports.array(memoryEntrySchema).max(CONTEXT_DECISIONS)
|
|
20601
|
+
});
|
|
20602
|
+
var memoryListSchema = external_exports.object({
|
|
20603
|
+
items: external_exports.array(memoryEntrySchema),
|
|
20604
|
+
next_cursor: external_exports.string().nullable()
|
|
20605
|
+
});
|
|
20606
|
+
var taskIdSchema2 = external_exports.union([external_exports.string().regex(/^[0-9]{1,15}$/), external_exports.number().int().positive()]).transform((v) => String(v));
|
|
20607
|
+
var sessionRef2 = external_exports.string().trim().min(1).max(200);
|
|
20608
|
+
var addDecisionBody = external_exports.object({
|
|
20609
|
+
project: projectRefSchema.optional(),
|
|
20610
|
+
/** The task the decision is about (optional). */
|
|
20611
|
+
task_id: taskIdSchema2.optional(),
|
|
20612
|
+
text: external_exports.string().min(1).max(2e3),
|
|
20613
|
+
session: sessionRef2.optional()
|
|
20614
|
+
}).strict();
|
|
20615
|
+
var getContextBody = external_exports.object({
|
|
20616
|
+
project: projectRefSchema.optional(),
|
|
20617
|
+
/** The task whose last handoff to include. */
|
|
20618
|
+
task_id: taskIdSchema2.optional()
|
|
20619
|
+
}).strict();
|
|
20620
|
+
var humanDecisionBody = external_exports.object({
|
|
20621
|
+
text: external_exports.string().trim().min(1).max(2e3),
|
|
20622
|
+
/** The task number (not the id) the decision is about. */
|
|
20623
|
+
task_num: external_exports.number().int().positive().max(2e9).optional()
|
|
20624
|
+
}).strict();
|
|
20625
|
+
var decisionResultSchema = external_exports.object({ entry: memoryEntrySchema });
|
|
20626
|
+
|
|
20520
20627
|
// ../shared/src/api/floor.ts
|
|
20521
20628
|
var FLOOR_TOOLS = ["claude", "codex", "cursor", "gemini", "grok", "other"];
|
|
20522
20629
|
var floorToolSchema = external_exports.enum(FLOOR_TOOLS);
|
|
@@ -20544,8 +20651,12 @@ var floorSessionSchema = external_exports.object({
|
|
|
20544
20651
|
agent_id: entityIdSchema,
|
|
20545
20652
|
parent_id: entityIdSchema.nullable(),
|
|
20546
20653
|
state: floorSessionStateSchema,
|
|
20547
|
-
/** Derived from the clock (`stalled`: a working session gone quiet; `lost`: a subagent that never reported done; `looping`: the same error repeating, or no status change while the claim keeps being extended). See `sessionHealth`. */
|
|
20654
|
+
/** Derived from the clock (`stalled`: a working session gone quiet; `lost`: a subagent that never reported done; `looping`: the same error repeating, or no status change while the claim keeps being extended; `parked`: idle for a while holding a claim; `waiting_long`: waiting on a person past the threshold). See `sessionHealth`. */
|
|
20548
20655
|
health: external_exports.enum(SESSION_HEALTH),
|
|
20656
|
+
/** When the state or status line last changed: the start of the current wait or park (age labels count from it). Older servers omit it; use `last_event_at`. */
|
|
20657
|
+
state_since: isoTimeSchema.optional(),
|
|
20658
|
+
/** For a `waiting` session: false once somebody answered this very wait. Older servers omit it (read as true). */
|
|
20659
|
+
wait_open: external_exports.boolean().optional(),
|
|
20549
20660
|
/** The tool's own session id (what `claude --resume` takes), main sessions only. */
|
|
20550
20661
|
tool_session_id: external_exports.string().nullable(),
|
|
20551
20662
|
model: external_exports.string().nullable(),
|
|
@@ -20573,7 +20684,15 @@ var floorPodSchema = external_exports.object({
|
|
|
20573
20684
|
agents: external_exports.array(external_exports.object({ agent: floorAgentSchema, sessions: external_exports.array(floorSessionSchema) }))
|
|
20574
20685
|
});
|
|
20575
20686
|
var floorSnapshotSchema = external_exports.object({
|
|
20576
|
-
project: external_exports.object({
|
|
20687
|
+
project: external_exports.object({
|
|
20688
|
+
id: entityIdSchema,
|
|
20689
|
+
key: external_exports.string(),
|
|
20690
|
+
name: external_exports.string(),
|
|
20691
|
+
/** The project's thresholds for parked and waiting_long, seconds (the defaults when it sets none). The browser judges health with them. */
|
|
20692
|
+
stall: external_exports.object({ parked_after_sec: external_exports.number(), waiting_long_after_sec: external_exports.number() }).optional(),
|
|
20693
|
+
/** Health of the machines this project's agents run on, by machine name; only machines with something to report. Older servers omit it. */
|
|
20694
|
+
machine_health: external_exports.record(external_exports.string(), machineHealthViewSchema).optional()
|
|
20695
|
+
}),
|
|
20577
20696
|
pods: external_exports.array(floorPodSchema),
|
|
20578
20697
|
shelves: external_exports.object({
|
|
20579
20698
|
/** Every ready task, most urgent first (at most 200). */
|
|
@@ -20710,6 +20829,8 @@ var projectAgentSchema = external_exports.object({
|
|
|
20710
20829
|
...agentBaseShape,
|
|
20711
20830
|
/** True when the signed-in person owns the agent (they may revoke it even as a viewer). */
|
|
20712
20831
|
mine: external_exports.boolean(),
|
|
20832
|
+
/** The tool profile (the AI account) the agent runs under, when known; older servers omit it. */
|
|
20833
|
+
profile: external_exports.string().nullable().optional(),
|
|
20713
20834
|
sessions: external_exports.array(floorSessionSchema)
|
|
20714
20835
|
});
|
|
20715
20836
|
var projectAgentList = listOf(projectAgentSchema);
|
|
@@ -20732,7 +20853,7 @@ var LOOP_NO_CHANGE_SEC = 30 * 60;
|
|
|
20732
20853
|
var LOOP_LEASE_FRESH_SEC = 5 * 60;
|
|
20733
20854
|
|
|
20734
20855
|
// ../shared/src/api/webhooks.ts
|
|
20735
|
-
var WEBHOOK_EVENTS = ["needs_you", "task_done", "agent_lost"];
|
|
20856
|
+
var WEBHOOK_EVENTS = ["needs_you", "task_done", "agent_lost", "usage_waste", "usage_high", "machine_unhealthy"];
|
|
20736
20857
|
var webhookEventSchema = external_exports.enum(WEBHOOK_EVENTS);
|
|
20737
20858
|
var putWebhookBody = external_exports.object({
|
|
20738
20859
|
url: external_exports.string().trim().min(1).max(2048),
|
|
@@ -20757,31 +20878,6 @@ var webhookGetResponse = external_exports.object({ webhook: webhookViewSchema.nu
|
|
|
20757
20878
|
var webhookPutResponse = external_exports.object({ webhook: webhookViewSchema, secret: external_exports.string().optional() }).strict();
|
|
20758
20879
|
var webhookTestResponse = external_exports.object({ ok: external_exports.literal(true), queued: external_exports.literal(true) }).strict();
|
|
20759
20880
|
|
|
20760
|
-
// ../shared/src/usage.ts
|
|
20761
|
-
var MIN_SPAN_MS = 5 * 6e4;
|
|
20762
|
-
var MAX_ETA_MS = 31 * 24 * 36e5;
|
|
20763
|
-
var USAGE_COUNTERS = ["tokens_in", "tokens_out", "cost_usd"];
|
|
20764
|
-
function isUsageCounter(value) {
|
|
20765
|
-
return USAGE_COUNTERS.includes(value);
|
|
20766
|
-
}
|
|
20767
|
-
function parseUsageKey(key2) {
|
|
20768
|
-
const parts = key2.split(":");
|
|
20769
|
-
if (parts.length < 3) return null;
|
|
20770
|
-
const tool = parts[0];
|
|
20771
|
-
const profile = parts[1];
|
|
20772
|
-
if (!TOOLS.includes(tool)) return null;
|
|
20773
|
-
if (!PROFILE_KEY_RE.test(profile)) return null;
|
|
20774
|
-
if (parts.length === 3) {
|
|
20775
|
-
const counter2 = parts[2];
|
|
20776
|
-
return isUsageCounter(counter2) ? { tool, profile, session: null, counter: counter2 } : null;
|
|
20777
|
-
}
|
|
20778
|
-
if (parts[2] !== "s" || parts.length < 5) return null;
|
|
20779
|
-
const session = parts.slice(3, -1).join(":");
|
|
20780
|
-
const counter = parts[parts.length - 1];
|
|
20781
|
-
if (!session || !isUsageCounter(counter)) return null;
|
|
20782
|
-
return { tool, profile, session, counter };
|
|
20783
|
-
}
|
|
20784
|
-
|
|
20785
20881
|
// ../shared/src/api/inbox.ts
|
|
20786
20882
|
var INBOX_KINDS = ["blocked_task", "waiting", "question"];
|
|
20787
20883
|
var inboxKindSchema = external_exports.enum(INBOX_KINDS);
|
|
@@ -20796,12 +20892,18 @@ var inboxItemSchema = external_exports.object({
|
|
|
20796
20892
|
text: external_exports.string(),
|
|
20797
20893
|
waiting_since: isoTimeSchema,
|
|
20798
20894
|
/** Whether the caller may answer it (role, the project's answer setting, and for a member: owning the agent). */
|
|
20799
|
-
can_answer: external_exports.boolean()
|
|
20895
|
+
can_answer: external_exports.boolean(),
|
|
20896
|
+
/** Whether the caller may nudge the item's session now (F2): owner or admin, and the session is stalled, parked, waiting too long or looping. */
|
|
20897
|
+
can_nudge: external_exports.boolean().optional()
|
|
20800
20898
|
});
|
|
20801
20899
|
var inboxListSchema = external_exports.object({
|
|
20802
20900
|
items: external_exports.array(inboxItemSchema),
|
|
20803
20901
|
/** Items the caller can answer: the sidebar badge. */
|
|
20804
|
-
count: external_exports.number().int().min(0)
|
|
20902
|
+
count: external_exports.number().int().min(0),
|
|
20903
|
+
/** Every item the caller can see, answerable or not (`items` is one page of them). */
|
|
20904
|
+
total: external_exports.number().int().min(0).optional(),
|
|
20905
|
+
/** Offset of the next page, null on the last one. */
|
|
20906
|
+
next_cursor: external_exports.string().nullable().optional()
|
|
20805
20907
|
});
|
|
20806
20908
|
var inboxAnswerBodySchema = external_exports.object({
|
|
20807
20909
|
text: external_exports.string().trim().min(1).max(4e3),
|
|
@@ -20872,7 +20974,12 @@ var teamMemberSchema = external_exports.object({
|
|
|
20872
20974
|
member: teamUserSchema.omit({ avatar_url: true })
|
|
20873
20975
|
}).strict())
|
|
20874
20976
|
}).strict();
|
|
20875
|
-
var teamViewSchema = external_exports.object({
|
|
20977
|
+
var teamViewSchema = external_exports.object({
|
|
20978
|
+
members: external_exports.array(teamMemberSchema),
|
|
20979
|
+
/** Members of the project, over every page (`members` is one page: `?limit=` default 12, `?cursor=` an offset). */
|
|
20980
|
+
total: external_exports.number().int().min(0).optional(),
|
|
20981
|
+
next_cursor: external_exports.string().nullable().optional()
|
|
20982
|
+
}).strict();
|
|
20876
20983
|
|
|
20877
20984
|
// ../shared/src/api/fleet.ts
|
|
20878
20985
|
var FLEET_STATES = ["working", "idle", "waiting", "paused", "stopped", "unknown"];
|
|
@@ -21071,7 +21178,34 @@ var digestAgentItemSchema = external_exports.object({
|
|
|
21071
21178
|
machine: external_exports.string().nullable(),
|
|
21072
21179
|
account_label: external_exports.string().nullable(),
|
|
21073
21180
|
owner_login: external_exports.string(),
|
|
21074
|
-
created_at: isoTimeSchema
|
|
21181
|
+
created_at: isoTimeSchema,
|
|
21182
|
+
/** A short-lived run agent (a mirrored fleet/vq lane, or named `*-run-*` / `vq-*`). */
|
|
21183
|
+
is_run: external_exports.boolean()
|
|
21184
|
+
}).strict();
|
|
21185
|
+
var digestWaitItemSchema = external_exports.object({
|
|
21186
|
+
session_id: idSchema,
|
|
21187
|
+
project_id: idSchema,
|
|
21188
|
+
project_key: external_exports.string(),
|
|
21189
|
+
agent_name: external_exports.string(),
|
|
21190
|
+
machine: external_exports.string().nullable(),
|
|
21191
|
+
/** `waiting` = a wait on a person (or blocked); `parked` = idle while holding a claimed task. */
|
|
21192
|
+
kind: external_exports.enum(["waiting", "parked"]),
|
|
21193
|
+
/** How long the wait has lasted so far (whole seconds). */
|
|
21194
|
+
seconds: external_exports.number().int().nonnegative(),
|
|
21195
|
+
/** Always true today: only waits still open are known (no state history is kept). */
|
|
21196
|
+
open: external_exports.boolean()
|
|
21197
|
+
}).strict();
|
|
21198
|
+
var digestLostTimeSchema = external_exports.object({
|
|
21199
|
+
waiting_hours: external_exports.number().nonnegative(),
|
|
21200
|
+
parked_hours: external_exports.number().nonnegative(),
|
|
21201
|
+
longest_waits: external_exports.array(digestWaitItemSchema).max(3)
|
|
21202
|
+
}).strict();
|
|
21203
|
+
var digestWastedAccountSchema = external_exports.object({ account: external_exports.string(), unused_points: external_exports.number().nonnegative(), resets: external_exports.number().int().positive() }).strict();
|
|
21204
|
+
var digestQuotaSchema = external_exports.object({
|
|
21205
|
+
wasted_points: external_exports.number().nonnegative(),
|
|
21206
|
+
accounts: external_exports.array(digestWastedAccountSchema).max(DIGEST_ITEMS_LIMIT),
|
|
21207
|
+
alerts_waste: external_exports.number().int().nonnegative(),
|
|
21208
|
+
alerts_high: external_exports.number().int().nonnegative()
|
|
21075
21209
|
}).strict();
|
|
21076
21210
|
var digestBucketSchema = (item) => external_exports.object({
|
|
21077
21211
|
count: external_exports.number().int().nonnegative(),
|
|
@@ -21082,7 +21216,9 @@ var digestCountsSchema = external_exports.object({
|
|
|
21082
21216
|
prs_merged: external_exports.number().int().nonnegative(),
|
|
21083
21217
|
tasks_blocked: external_exports.number().int().nonnegative(),
|
|
21084
21218
|
needs_you: external_exports.number().int().nonnegative(),
|
|
21085
|
-
new_agents: external_exports.number().int().nonnegative()
|
|
21219
|
+
new_agents: external_exports.number().int().nonnegative(),
|
|
21220
|
+
/** `new_agents` without the short-lived run agents (`is_run`). */
|
|
21221
|
+
new_agents_persistent: external_exports.number().int().nonnegative()
|
|
21086
21222
|
}).strict();
|
|
21087
21223
|
var meDigestResponseSchema = external_exports.object({
|
|
21088
21224
|
last_seen_at: isoTimeSchema.nullable(),
|
|
@@ -21094,7 +21230,11 @@ var meDigestResponseSchema = external_exports.object({
|
|
|
21094
21230
|
prs_merged: digestBucketSchema(digestTaskItemSchema),
|
|
21095
21231
|
tasks_blocked: digestBucketSchema(digestTaskItemSchema),
|
|
21096
21232
|
needs_you: digestBucketSchema(digestNeedsYouItemSchema),
|
|
21097
|
-
new_agents: digestBucketSchema(digestAgentItemSchema)
|
|
21233
|
+
new_agents: digestBucketSchema(digestAgentItemSchema),
|
|
21234
|
+
/** F7. `total` also counts one for each of `lost_time` and `quota` that has something to show. */
|
|
21235
|
+
lost_time: digestLostTimeSchema,
|
|
21236
|
+
/** Null on a project-scoped digest (accounts are not a project's). */
|
|
21237
|
+
quota: digestQuotaSchema.nullable()
|
|
21098
21238
|
}).strict();
|
|
21099
21239
|
var meDigestSeenBodySchema = external_exports.object({
|
|
21100
21240
|
before: isoTimeSchema.optional()
|
|
@@ -21104,6 +21244,59 @@ var meDigestSeenResponseSchema = external_exports.object({
|
|
|
21104
21244
|
last_seen_at: isoTimeSchema
|
|
21105
21245
|
}).strict();
|
|
21106
21246
|
|
|
21247
|
+
// ../shared/src/api/feedback.ts
|
|
21248
|
+
var FEEDBACK_CATEGORIES = ["question", "idea", "bug"];
|
|
21249
|
+
var feedbackCategorySchema = external_exports.enum(FEEDBACK_CATEGORIES);
|
|
21250
|
+
var FEEDBACK_MESSAGE_MIN = 3;
|
|
21251
|
+
var FEEDBACK_MESSAGE_MAX = 2e3;
|
|
21252
|
+
var FEEDBACK_EMAIL_MAX = 254;
|
|
21253
|
+
var FEEDBACK_HONEYPOT_FIELD = "website";
|
|
21254
|
+
var optionalEmail = external_exports.preprocess(
|
|
21255
|
+
(v) => typeof v === "string" && v.trim() === "" ? void 0 : v,
|
|
21256
|
+
external_exports.string().trim().max(FEEDBACK_EMAIL_MAX).pipe(external_exports.email("Enter a valid email address")).optional()
|
|
21257
|
+
);
|
|
21258
|
+
var feedbackBodySchema = external_exports.object({
|
|
21259
|
+
message: external_exports.string().trim().min(FEEDBACK_MESSAGE_MIN, `Write at least ${FEEDBACK_MESSAGE_MIN} characters`).max(FEEDBACK_MESSAGE_MAX, `At most ${FEEDBACK_MESSAGE_MAX} characters`),
|
|
21260
|
+
email: optionalEmail,
|
|
21261
|
+
category: feedbackCategorySchema.default("question"),
|
|
21262
|
+
/** Honeypot: stays empty for a person. */
|
|
21263
|
+
[FEEDBACK_HONEYPOT_FIELD]: external_exports.string().max(500).optional()
|
|
21264
|
+
}).strict();
|
|
21265
|
+
var feedbackSentSchema = external_exports.object({ ok: external_exports.literal(true) }).strict();
|
|
21266
|
+
var feedbackMeSchema = external_exports.object({ email: external_exports.string().nullable(), is_owner: external_exports.boolean() }).strict();
|
|
21267
|
+
var feedbackItemSchema = external_exports.object({
|
|
21268
|
+
id: entityIdSchema,
|
|
21269
|
+
category: feedbackCategorySchema,
|
|
21270
|
+
message: external_exports.string(),
|
|
21271
|
+
email: external_exports.string().nullable(),
|
|
21272
|
+
/** The GitHub login of a signed-in sender, else null. */
|
|
21273
|
+
from_login: external_exports.string().nullable(),
|
|
21274
|
+
created_at: isoTimeSchema
|
|
21275
|
+
});
|
|
21276
|
+
var feedbackListSchema = external_exports.object({
|
|
21277
|
+
items: external_exports.array(feedbackItemSchema),
|
|
21278
|
+
next_cursor: external_exports.string().nullable(),
|
|
21279
|
+
total: external_exports.number().int().min(0)
|
|
21280
|
+
});
|
|
21281
|
+
|
|
21282
|
+
// ../shared/src/api/nudge.ts
|
|
21283
|
+
var NUDGE_TTL_SEC = 24 * 3600;
|
|
21284
|
+
var NUDGE_NOTE_MAX = 300;
|
|
21285
|
+
var nudgeBody = external_exports.object({ note: external_exports.string().trim().max(NUDGE_NOTE_MAX).optional() }).strict();
|
|
21286
|
+
var nudgeResponse = external_exports.object({
|
|
21287
|
+
nudge: external_exports.object({
|
|
21288
|
+
id: external_exports.string(),
|
|
21289
|
+
session_id: external_exports.string(),
|
|
21290
|
+
created_at: isoTimeSchema,
|
|
21291
|
+
/** When the next nudge of this session is allowed. */
|
|
21292
|
+
next_allowed_at: isoTimeSchema,
|
|
21293
|
+
/** The owner got a push (with the resume command when the tool has one). */
|
|
21294
|
+
pushed: external_exports.boolean(),
|
|
21295
|
+
resume_command: external_exports.string().nullable()
|
|
21296
|
+
})
|
|
21297
|
+
});
|
|
21298
|
+
var agentNudgeSchema = external_exports.object({ id: external_exports.string(), text: external_exports.string(), sent_at: isoTimeSchema });
|
|
21299
|
+
|
|
21107
21300
|
// ../shared/src/index.ts
|
|
21108
21301
|
var ROLES = ["owner", "admin", "member", "viewer"];
|
|
21109
21302
|
var roleSchema2 = external_exports.enum(ROLES);
|
|
@@ -21215,7 +21408,10 @@ export {
|
|
|
21215
21408
|
CLI_INSTALL_COMMAND,
|
|
21216
21409
|
cliNpxCommand,
|
|
21217
21410
|
redact,
|
|
21411
|
+
usageReadingSchema,
|
|
21218
21412
|
parseUsageKey,
|
|
21413
|
+
routeProviderFromParam,
|
|
21414
|
+
usageRouteSchema,
|
|
21219
21415
|
DEFAULT_HOST,
|
|
21220
21416
|
defaultCtx,
|
|
21221
21417
|
hostFromEnv,
|