@hivefloor/cli 0.1.1 → 0.1.3
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/{chunk-76HDATOB.js → chunk-3YOTXIFP.js} +13 -13
- package/dist/{chunk-Q2TS3GT3.js → chunk-DQV6FAJU.js} +2 -2
- package/dist/{chunk-MMWX62ZU.js → chunk-DWHMBUCA.js} +2 -2
- package/dist/{chunk-NCRQGIJY.js → chunk-E4V47VEV.js} +3 -9
- package/dist/{chunk-WO7NALQO.js → chunk-HT5KXWXM.js} +1 -1
- package/dist/{chunk-WLHRUZTR.js → chunk-KHHSRIMU.js} +2 -1
- package/dist/{chunk-WHHV2NZA.js → chunk-NKMVO5BP.js} +4 -10
- package/dist/{chunk-YCZ7XJJF.js → chunk-NLZXB26Y.js} +2 -2
- package/dist/{chunk-SGDM7MAT.js → chunk-O2TC3WSS.js} +68 -2
- package/dist/{chunk-U7PMOZGI.js → chunk-O6VSA2JT.js} +4 -3
- package/dist/{chunk-3IMV5EHP.js → chunk-T7TG6WA4.js} +1 -1
- package/dist/{chunk-ZYRPQPGL.js → chunk-TH4ANHSG.js} +333 -190
- package/dist/{chunk-WNDUGQDX.js → chunk-VNCQFFQO.js} +8 -0
- package/dist/{chunk-CWEEIRW2.js → chunk-YRNMECUF.js} +1 -1
- package/dist/{cli-FFAZRKLR.js → cli-MAHYTCYV.js} +13 -10
- package/dist/connect-QA3QIEGL.js +23 -0
- package/dist/{disconnect-VWUOUZP6.js → disconnect-FI76IEZJ.js} +10 -10
- package/dist/{hook-WSJXG2XU.js → hook-N4ZTQEWM.js} +53 -19
- package/dist/index.js +2 -2
- package/dist/{link-TFITMC6H.js → link-5WSZHKBE.js} +9 -9
- package/dist/{machine-connect-I3OZCTUZ.js → machine-connect-GQJ4SB3D.js} +24 -24
- package/dist/{mcp-47WTNQNN.js → mcp-EUBTVJNX.js} +7 -7
- package/dist/run-BEE2ATEM.js +1989 -0
- package/dist/{status-GXZ267BD.js → status-SMAVPW4D.js} +14 -14
- package/dist/{token-C4K23KXH.js → token-AUEAWQDH.js} +4 -4
- package/dist/where-7NI7UEEF.js +70 -0
- package/package.json +1 -1
- package/dist/connect-FM4BXTQQ.js +0 -23
- package/dist/run-JO4NEHWG.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);
|
|
@@ -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,
|
|
@@ -20264,7 +20206,7 @@ var taskStatusLineQuerySchema = external_exports.object({
|
|
|
20264
20206
|
}).strict();
|
|
20265
20207
|
var taskResultSchema = external_exports.object({ task: taskCardSchema });
|
|
20266
20208
|
var answerBodySchema = external_exports.object({ text: external_exports.string().trim().min(1).max(500) });
|
|
20267
|
-
var NOTIFICATION_KINDS = ["task_done", "task_blocked", "agent_waiting", "invite_received", "member_added", "repo_link_requested", "agent_question", "feedback"];
|
|
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"];
|
|
20268
20210
|
var notificationKindSchema = external_exports.enum(NOTIFICATION_KINDS);
|
|
20269
20211
|
var notificationViewSchema = external_exports.object({
|
|
20270
20212
|
id: entityIdSchema,
|
|
@@ -20357,50 +20299,6 @@ var releaseBody = external_exports.object({
|
|
|
20357
20299
|
}).strict();
|
|
20358
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();
|
|
20359
20301
|
|
|
20360
|
-
// ../shared/src/api/memory.ts
|
|
20361
|
-
var CONTEXT_DECISIONS = 10;
|
|
20362
|
-
var MEMORY_KINDS = ["handoff", "decision"];
|
|
20363
|
-
var memoryKindSchema = external_exports.enum(MEMORY_KINDS);
|
|
20364
|
-
var memoryEntrySchema = external_exports.object({
|
|
20365
|
-
id: entityIdSchema,
|
|
20366
|
-
kind: memoryKindSchema,
|
|
20367
|
-
/** The task the entry is about; always set for a handoff. */
|
|
20368
|
-
task_id: entityIdSchema.nullable(),
|
|
20369
|
-
/** The task as people write it (`HF-12`). */
|
|
20370
|
-
task_key: external_exports.string().nullable(),
|
|
20371
|
-
text: external_exports.string(),
|
|
20372
|
-
author: external_exports.object({ type: external_exports.enum(["agent", "user", "system"]), name: external_exports.string() }),
|
|
20373
|
-
created_at: isoTimeSchema
|
|
20374
|
-
});
|
|
20375
|
-
var memoryContextSchema = external_exports.object({
|
|
20376
|
-
handoff: memoryEntrySchema.nullable(),
|
|
20377
|
-
decisions: external_exports.array(memoryEntrySchema).max(CONTEXT_DECISIONS)
|
|
20378
|
-
});
|
|
20379
|
-
var memoryListSchema = external_exports.object({
|
|
20380
|
-
items: external_exports.array(memoryEntrySchema),
|
|
20381
|
-
next_cursor: external_exports.string().nullable()
|
|
20382
|
-
});
|
|
20383
|
-
var taskIdSchema2 = external_exports.union([external_exports.string().regex(/^[0-9]{1,15}$/), external_exports.number().int().positive()]).transform((v) => String(v));
|
|
20384
|
-
var sessionRef2 = external_exports.string().trim().min(1).max(200);
|
|
20385
|
-
var addDecisionBody = external_exports.object({
|
|
20386
|
-
project: projectRefSchema.optional(),
|
|
20387
|
-
/** The task the decision is about (optional). */
|
|
20388
|
-
task_id: taskIdSchema2.optional(),
|
|
20389
|
-
text: external_exports.string().min(1).max(2e3),
|
|
20390
|
-
session: sessionRef2.optional()
|
|
20391
|
-
}).strict();
|
|
20392
|
-
var getContextBody = external_exports.object({
|
|
20393
|
-
project: projectRefSchema.optional(),
|
|
20394
|
-
/** The task whose last handoff to include. */
|
|
20395
|
-
task_id: taskIdSchema2.optional()
|
|
20396
|
-
}).strict();
|
|
20397
|
-
var humanDecisionBody = external_exports.object({
|
|
20398
|
-
text: external_exports.string().trim().min(1).max(2e3),
|
|
20399
|
-
/** The task number (not the id) the decision is about. */
|
|
20400
|
-
task_num: external_exports.number().int().positive().max(2e9).optional()
|
|
20401
|
-
}).strict();
|
|
20402
|
-
var decisionResultSchema = external_exports.object({ entry: memoryEntrySchema });
|
|
20403
|
-
|
|
20404
20302
|
// ../shared/src/api/usage.ts
|
|
20405
20303
|
var isoTime = external_exports.iso.datetime({ offset: true });
|
|
20406
20304
|
var USAGE_PROVIDERS = [
|
|
@@ -20522,6 +20420,210 @@ var taskUsageSchema = external_exports.object({
|
|
|
20522
20420
|
agents: external_exports.array(taskUsageAgentSchema).max(50)
|
|
20523
20421
|
}).strict();
|
|
20524
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
|
+
|
|
20525
20627
|
// ../shared/src/api/floor.ts
|
|
20526
20628
|
var FLOOR_TOOLS = ["claude", "codex", "cursor", "gemini", "grok", "other"];
|
|
20527
20629
|
var floorToolSchema = external_exports.enum(FLOOR_TOOLS);
|
|
@@ -20549,8 +20651,12 @@ var floorSessionSchema = external_exports.object({
|
|
|
20549
20651
|
agent_id: entityIdSchema,
|
|
20550
20652
|
parent_id: entityIdSchema.nullable(),
|
|
20551
20653
|
state: floorSessionStateSchema,
|
|
20552
|
-
/** 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`. */
|
|
20553
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(),
|
|
20554
20660
|
/** The tool's own session id (what `claude --resume` takes), main sessions only. */
|
|
20555
20661
|
tool_session_id: external_exports.string().nullable(),
|
|
20556
20662
|
model: external_exports.string().nullable(),
|
|
@@ -20578,7 +20684,15 @@ var floorPodSchema = external_exports.object({
|
|
|
20578
20684
|
agents: external_exports.array(external_exports.object({ agent: floorAgentSchema, sessions: external_exports.array(floorSessionSchema) }))
|
|
20579
20685
|
});
|
|
20580
20686
|
var floorSnapshotSchema = external_exports.object({
|
|
20581
|
-
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
|
+
}),
|
|
20582
20696
|
pods: external_exports.array(floorPodSchema),
|
|
20583
20697
|
shelves: external_exports.object({
|
|
20584
20698
|
/** Every ready task, most urgent first (at most 200). */
|
|
@@ -20715,6 +20829,8 @@ var projectAgentSchema = external_exports.object({
|
|
|
20715
20829
|
...agentBaseShape,
|
|
20716
20830
|
/** True when the signed-in person owns the agent (they may revoke it even as a viewer). */
|
|
20717
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(),
|
|
20718
20834
|
sessions: external_exports.array(floorSessionSchema)
|
|
20719
20835
|
});
|
|
20720
20836
|
var projectAgentList = listOf(projectAgentSchema);
|
|
@@ -20737,7 +20853,7 @@ var LOOP_NO_CHANGE_SEC = 30 * 60;
|
|
|
20737
20853
|
var LOOP_LEASE_FRESH_SEC = 5 * 60;
|
|
20738
20854
|
|
|
20739
20855
|
// ../shared/src/api/webhooks.ts
|
|
20740
|
-
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"];
|
|
20741
20857
|
var webhookEventSchema = external_exports.enum(WEBHOOK_EVENTS);
|
|
20742
20858
|
var putWebhookBody = external_exports.object({
|
|
20743
20859
|
url: external_exports.string().trim().min(1).max(2048),
|
|
@@ -20762,31 +20878,6 @@ var webhookGetResponse = external_exports.object({ webhook: webhookViewSchema.nu
|
|
|
20762
20878
|
var webhookPutResponse = external_exports.object({ webhook: webhookViewSchema, secret: external_exports.string().optional() }).strict();
|
|
20763
20879
|
var webhookTestResponse = external_exports.object({ ok: external_exports.literal(true), queued: external_exports.literal(true) }).strict();
|
|
20764
20880
|
|
|
20765
|
-
// ../shared/src/usage.ts
|
|
20766
|
-
var MIN_SPAN_MS = 5 * 6e4;
|
|
20767
|
-
var MAX_ETA_MS = 31 * 24 * 36e5;
|
|
20768
|
-
var USAGE_COUNTERS = ["tokens_in", "tokens_out", "cost_usd"];
|
|
20769
|
-
function isUsageCounter(value) {
|
|
20770
|
-
return USAGE_COUNTERS.includes(value);
|
|
20771
|
-
}
|
|
20772
|
-
function parseUsageKey(key2) {
|
|
20773
|
-
const parts = key2.split(":");
|
|
20774
|
-
if (parts.length < 3) return null;
|
|
20775
|
-
const tool = parts[0];
|
|
20776
|
-
const profile = parts[1];
|
|
20777
|
-
if (!TOOLS.includes(tool)) return null;
|
|
20778
|
-
if (!PROFILE_KEY_RE.test(profile)) return null;
|
|
20779
|
-
if (parts.length === 3) {
|
|
20780
|
-
const counter2 = parts[2];
|
|
20781
|
-
return isUsageCounter(counter2) ? { tool, profile, session: null, counter: counter2 } : null;
|
|
20782
|
-
}
|
|
20783
|
-
if (parts[2] !== "s" || parts.length < 5) return null;
|
|
20784
|
-
const session = parts.slice(3, -1).join(":");
|
|
20785
|
-
const counter = parts[parts.length - 1];
|
|
20786
|
-
if (!session || !isUsageCounter(counter)) return null;
|
|
20787
|
-
return { tool, profile, session, counter };
|
|
20788
|
-
}
|
|
20789
|
-
|
|
20790
20881
|
// ../shared/src/api/inbox.ts
|
|
20791
20882
|
var INBOX_KINDS = ["blocked_task", "waiting", "question"];
|
|
20792
20883
|
var inboxKindSchema = external_exports.enum(INBOX_KINDS);
|
|
@@ -20801,7 +20892,9 @@ var inboxItemSchema = external_exports.object({
|
|
|
20801
20892
|
text: external_exports.string(),
|
|
20802
20893
|
waiting_since: isoTimeSchema,
|
|
20803
20894
|
/** Whether the caller may answer it (role, the project's answer setting, and for a member: owning the agent). */
|
|
20804
|
-
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()
|
|
20805
20898
|
});
|
|
20806
20899
|
var inboxListSchema = external_exports.object({
|
|
20807
20900
|
items: external_exports.array(inboxItemSchema),
|
|
@@ -21089,6 +21182,31 @@ var digestAgentItemSchema = external_exports.object({
|
|
|
21089
21182
|
/** A short-lived run agent (a mirrored fleet/vq lane, or named `*-run-*` / `vq-*`). */
|
|
21090
21183
|
is_run: external_exports.boolean()
|
|
21091
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()
|
|
21209
|
+
}).strict();
|
|
21092
21210
|
var digestBucketSchema = (item) => external_exports.object({
|
|
21093
21211
|
count: external_exports.number().int().nonnegative(),
|
|
21094
21212
|
items: external_exports.array(item).max(DIGEST_ITEMS_LIMIT)
|
|
@@ -21112,7 +21230,11 @@ var meDigestResponseSchema = external_exports.object({
|
|
|
21112
21230
|
prs_merged: digestBucketSchema(digestTaskItemSchema),
|
|
21113
21231
|
tasks_blocked: digestBucketSchema(digestTaskItemSchema),
|
|
21114
21232
|
needs_you: digestBucketSchema(digestNeedsYouItemSchema),
|
|
21115
|
-
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()
|
|
21116
21238
|
}).strict();
|
|
21117
21239
|
var meDigestSeenBodySchema = external_exports.object({
|
|
21118
21240
|
before: isoTimeSchema.optional()
|
|
@@ -21157,6 +21279,24 @@ var feedbackListSchema = external_exports.object({
|
|
|
21157
21279
|
total: external_exports.number().int().min(0)
|
|
21158
21280
|
});
|
|
21159
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
|
+
|
|
21160
21300
|
// ../shared/src/index.ts
|
|
21161
21301
|
var ROLES = ["owner", "admin", "member", "viewer"];
|
|
21162
21302
|
var roleSchema2 = external_exports.enum(ROLES);
|
|
@@ -21268,7 +21408,10 @@ export {
|
|
|
21268
21408
|
CLI_INSTALL_COMMAND,
|
|
21269
21409
|
cliNpxCommand,
|
|
21270
21410
|
redact,
|
|
21411
|
+
usageReadingSchema,
|
|
21271
21412
|
parseUsageKey,
|
|
21413
|
+
routeProviderFromParam,
|
|
21414
|
+
usageRouteSchema,
|
|
21272
21415
|
DEFAULT_HOST,
|
|
21273
21416
|
defaultCtx,
|
|
21274
21417
|
hostFromEnv,
|