@brainervirus/workit-codex 8.27.0 → 8.28.1
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/.codex-plugin/plugin.json +1 -1
- package/dist/launch-mcp.js +185 -93
- package/dist/{workit-hook-sza2zvq6.js → workit-hook-0vzd6e1j.js} +191 -16
- package/dist/workit-hook-27bwpc4a.js +9 -0
- package/dist/{workit-hook-vhz9yrcw.js → workit-hook-2m8a4m5j.js} +4 -64
- package/dist/workit-hook-jy7y0gdx.js +70 -0
- package/dist/workit-hook-mk64s4fk.js +19 -0
- package/dist/workit-hook.js +36 -6
- package/package.json +3 -3
package/dist/launch-mcp.js
CHANGED
|
@@ -13570,8 +13570,9 @@ function flatOperationJsonSchema(family, options = {}) {
|
|
|
13570
13570
|
};
|
|
13571
13571
|
const properties = { action: { type: "string", enum: actions } };
|
|
13572
13572
|
const readField = (name) => name === "taskId" || (family === "task" ? READ_TASK_FIELDS.has(name) : family === "policy");
|
|
13573
|
+
const taken = (name) => family === "policy" || actions.some((action) => actionKeys(family, action)?.accepted.has(name));
|
|
13573
13574
|
for (const [name, field] of Object.entries({ ...COMMON, ...spec.fields }))
|
|
13574
|
-
if (options.readOnly ? readField(name) :
|
|
13575
|
+
if (options.readOnly ? readField(name) : taken(name))
|
|
13575
13576
|
properties[name] = property(field);
|
|
13576
13577
|
return {
|
|
13577
13578
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -13813,6 +13814,98 @@ function normalizeOperationInput(family, input, host) {
|
|
|
13813
13814
|
request[key] = strings(request[key]);
|
|
13814
13815
|
return request;
|
|
13815
13816
|
}
|
|
13817
|
+
var defOf = (node) => node._zod.def;
|
|
13818
|
+
var unwrap = (node) => {
|
|
13819
|
+
let inner = node;
|
|
13820
|
+
while (["optional", "nullable"].includes(defOf(inner).type) && defOf(inner).innerType)
|
|
13821
|
+
inner = defOf(inner).innerType;
|
|
13822
|
+
return inner;
|
|
13823
|
+
};
|
|
13824
|
+
var FLAT_NAME = {
|
|
13825
|
+
authorityRefs: "refs",
|
|
13826
|
+
contentRefs: "refs",
|
|
13827
|
+
statedChoice: "choice",
|
|
13828
|
+
reviewContext: "reviewSession"
|
|
13829
|
+
};
|
|
13830
|
+
var NOT_FLAT = new Set(["schemaVersion", "action", "workspaceId"]);
|
|
13831
|
+
function actionKeys(family, action) {
|
|
13832
|
+
const options = advertisedOperationSchemas[family].options;
|
|
13833
|
+
const option = options.find((item) => {
|
|
13834
|
+
const literal = defOf(item).shape?.action;
|
|
13835
|
+
return literal._zod.def.values.includes(action);
|
|
13836
|
+
});
|
|
13837
|
+
if (!option)
|
|
13838
|
+
return null;
|
|
13839
|
+
const out = { accepted: new Set, required: [] };
|
|
13840
|
+
const walk = (shape, nested) => {
|
|
13841
|
+
for (const [key, node] of Object.entries(shape)) {
|
|
13842
|
+
if (NOT_FLAT.has(key) || nested && key === "taskId")
|
|
13843
|
+
continue;
|
|
13844
|
+
const inner = unwrap(node);
|
|
13845
|
+
const type = defOf(inner).type;
|
|
13846
|
+
const needed = !["optional", "nullable"].includes(defOf(node).type);
|
|
13847
|
+
if (key === "scope")
|
|
13848
|
+
for (const name of ["scope", "paths", "exclusions"])
|
|
13849
|
+
out.accepted.add(name);
|
|
13850
|
+
else if (type === "object" && key !== "bundle" && !(key in FLAT_NAME)) {
|
|
13851
|
+
out.accepted.add(key);
|
|
13852
|
+
walk(defOf(inner).shape, true);
|
|
13853
|
+
} else {
|
|
13854
|
+
const name = FLAT_NAME[key] ?? key;
|
|
13855
|
+
out.accepted.add(name);
|
|
13856
|
+
if (needed && type !== "array" && type !== "record" && !out.required.includes(name))
|
|
13857
|
+
out.required.push(name);
|
|
13858
|
+
}
|
|
13859
|
+
}
|
|
13860
|
+
};
|
|
13861
|
+
walk(defOf(option).shape, false);
|
|
13862
|
+
return out;
|
|
13863
|
+
}
|
|
13864
|
+
function exampleOperation(family, action) {
|
|
13865
|
+
const keys = actionKeys(family, action);
|
|
13866
|
+
const example = { action };
|
|
13867
|
+
for (const name of keys?.required ?? [])
|
|
13868
|
+
example[name] = FLAT[family].fields[name]?.enum?.[0] ?? `<${name}>`;
|
|
13869
|
+
if (family === "policy" && !keys?.required.length && action !== "explain")
|
|
13870
|
+
example.riskTier = "normal";
|
|
13871
|
+
return example;
|
|
13872
|
+
}
|
|
13873
|
+
var oneOf = (values) => values.join(" | ");
|
|
13874
|
+
function invalidOperation(family, input, error) {
|
|
13875
|
+
const request = isObject2(input) ? input : {};
|
|
13876
|
+
const action = typeof request.action === "string" ? request.action : "";
|
|
13877
|
+
const actions = OPERATION_ACTIONS[family];
|
|
13878
|
+
if (!actions.includes(action))
|
|
13879
|
+
return failure2("invalid_input", `${family}: action must be one of ${oneOf(actions)}`, {
|
|
13880
|
+
fields: [{ path: "action", reason: `got ${JSON.stringify(request.action ?? null)}` }]
|
|
13881
|
+
});
|
|
13882
|
+
const own = actionKeys(family, action);
|
|
13883
|
+
const fields = [];
|
|
13884
|
+
const sentence = [];
|
|
13885
|
+
for (const issue of error.issues) {
|
|
13886
|
+
if (issue.code === "unrecognized_keys") {
|
|
13887
|
+
for (const key of issue.keys) {
|
|
13888
|
+
const home = actions.find((other) => other !== action && actionKeys(family, other).accepted.has(key));
|
|
13889
|
+
const reason = home ? `${key} belongs to action: ${home}` : `${key} is not a field of ${family} ${action}; it takes ${[...own.accepted].join(", ")}`;
|
|
13890
|
+
fields.push({ path: key, reason });
|
|
13891
|
+
sentence.push(reason);
|
|
13892
|
+
}
|
|
13893
|
+
continue;
|
|
13894
|
+
}
|
|
13895
|
+
const last = String(issue.path.at(-1) ?? "");
|
|
13896
|
+
const name = Object.entries(FLAT_NAME).find(([contract]) => contract === last)?.[1] ?? last;
|
|
13897
|
+
const missing = issue.code === "invalid_type" && /received undefined/.test(issue.message);
|
|
13898
|
+
const absent = own.required.filter((key) => !(key in request));
|
|
13899
|
+
const needs = missing && issue.path.length === 1 && absent.length ? absent.join(", ") : name;
|
|
13900
|
+
const reason = missing ? `${family} ${action} requires ${needs}` : `${name}: ${issue.message}`;
|
|
13901
|
+
fields.push({ path: issue.path.join("."), reason });
|
|
13902
|
+
sentence.push(reason);
|
|
13903
|
+
}
|
|
13904
|
+
const example = JSON.stringify(exampleOperation(family, action));
|
|
13905
|
+
return failure2("invalid_input", `${[...new Set(sentence)].join("; ")}. Example: ${example}`, {
|
|
13906
|
+
fields
|
|
13907
|
+
});
|
|
13908
|
+
}
|
|
13816
13909
|
function parseAdvertisedOperation(family, input, host) {
|
|
13817
13910
|
const request = normalizeOperationInput(family, input, host);
|
|
13818
13911
|
if (isObject2(request) && request.schemaVersion !== SCHEMA_VERSION)
|
|
@@ -13820,12 +13913,7 @@ function parseAdvertisedOperation(family, input, host) {
|
|
|
13820
13913
|
const parsed = advertisedOperationSchemas[family].safeParse(request);
|
|
13821
13914
|
if (parsed.success)
|
|
13822
13915
|
return success(null, null, request);
|
|
13823
|
-
return
|
|
13824
|
-
fields: parsed.error.issues.map((issue) => ({
|
|
13825
|
-
path: issue.code === "unrecognized_keys" ? issue.keys.join(".") : issue.path.join("."),
|
|
13826
|
-
reason: issue.message
|
|
13827
|
-
}))
|
|
13828
|
-
});
|
|
13916
|
+
return invalidOperation(family, request, parsed.error);
|
|
13829
13917
|
}
|
|
13830
13918
|
// packages/workit-core/src/core/task-store.ts
|
|
13831
13919
|
import { createHash as createHash8, randomUUID as randomUUID3 } from "node:crypto";
|
|
@@ -28202,6 +28290,96 @@ var WRITE_TOOLS = new Set([
|
|
|
28202
28290
|
]);
|
|
28203
28291
|
// packages/workit-core/src/hooks/standing.ts
|
|
28204
28292
|
var sinceStart = new Map;
|
|
28293
|
+
// packages/workit-core/src/core/role-models.ts
|
|
28294
|
+
var MODEL_ROLES = [
|
|
28295
|
+
"decider",
|
|
28296
|
+
"implementer",
|
|
28297
|
+
"verifier",
|
|
28298
|
+
"reviewer",
|
|
28299
|
+
"explore",
|
|
28300
|
+
"babysit"
|
|
28301
|
+
];
|
|
28302
|
+
var MODEL_TIERS = ["mundane", "standard", "hard"];
|
|
28303
|
+
var HOST_KEYS = new Set([
|
|
28304
|
+
"claude_code",
|
|
28305
|
+
"opencode",
|
|
28306
|
+
"codex",
|
|
28307
|
+
"codex_cli",
|
|
28308
|
+
"codex_desktop",
|
|
28309
|
+
"cursor",
|
|
28310
|
+
"pi",
|
|
28311
|
+
"default"
|
|
28312
|
+
]);
|
|
28313
|
+
var BUILT_IN_CLAUDE_CODE = {
|
|
28314
|
+
decider: { model: "fable", effort: "high" },
|
|
28315
|
+
"implementer.hard": { model: "opus" },
|
|
28316
|
+
"implementer.standard": { model: "sonnet" },
|
|
28317
|
+
"implementer.mundane": { model: "haiku" },
|
|
28318
|
+
verifier: { model: "sonnet" },
|
|
28319
|
+
reviewer: { model: "opus" },
|
|
28320
|
+
explore: { model: "haiku" },
|
|
28321
|
+
babysit: { model: "haiku" }
|
|
28322
|
+
};
|
|
28323
|
+
var isObject7 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
28324
|
+
var name = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
|
|
28325
|
+
var leaf = (value) => {
|
|
28326
|
+
const text = name(value);
|
|
28327
|
+
if (text)
|
|
28328
|
+
return { model: text, effort: null };
|
|
28329
|
+
if (!isObject7(value))
|
|
28330
|
+
return null;
|
|
28331
|
+
const model = name(value.model);
|
|
28332
|
+
return model ? { model, effort: name(value.effort) } : null;
|
|
28333
|
+
};
|
|
28334
|
+
var isFlat = (value) => typeof value === "string" || isObject7(value) && Object.hasOwn(value, "model");
|
|
28335
|
+
var forHost = (value, host) => {
|
|
28336
|
+
if (isFlat(value))
|
|
28337
|
+
return leaf(value);
|
|
28338
|
+
if (!isObject7(value))
|
|
28339
|
+
return null;
|
|
28340
|
+
const family = host ? hostFamily(host) : null;
|
|
28341
|
+
for (const key of [family, host, "default"])
|
|
28342
|
+
if (key && Object.hasOwn(value, key)) {
|
|
28343
|
+
const found = leaf(value[key]);
|
|
28344
|
+
if (found)
|
|
28345
|
+
return found;
|
|
28346
|
+
}
|
|
28347
|
+
return null;
|
|
28348
|
+
};
|
|
28349
|
+
var rolesOf = (models) => isObject7(models) && isObject7(models.roles) ? models.roles : null;
|
|
28350
|
+
var resolveRoleModel = (cwd, selector, host, dir) => {
|
|
28351
|
+
const { role, tier } = selector;
|
|
28352
|
+
for (const source of modelSources(cwd, dir)) {
|
|
28353
|
+
const where = source.global ? "the global default" : `workspace ${source.name}`;
|
|
28354
|
+
const roles = rolesOf(source.models);
|
|
28355
|
+
const configured = roles && Object.hasOwn(roles, role) ? roles[role] : undefined;
|
|
28356
|
+
const fromRoles = role === "implementer" ? tier && isObject7(configured) && Object.hasOwn(configured, tier) ? forHost(configured[tier], host) : null : forHost(configured, host);
|
|
28357
|
+
if (fromRoles)
|
|
28358
|
+
return { ...fromRoles, source: `models.roles in ${where}` };
|
|
28359
|
+
if (role === "implementer" && tier && isObject7(source.tierModels)) {
|
|
28360
|
+
const fromTiers = Object.hasOwn(source.tierModels, tier) ? forHost(source.tierModels[tier], host) : null;
|
|
28361
|
+
if (fromTiers)
|
|
28362
|
+
return { model: fromTiers.model, effort: null, source: `fanout.tierModels in ${where}` };
|
|
28363
|
+
}
|
|
28364
|
+
}
|
|
28365
|
+
if (host && hostFamily(host) === "claude_code") {
|
|
28366
|
+
const builtIn = BUILT_IN_CLAUDE_CODE[tier ? `${role}.${tier}` : role];
|
|
28367
|
+
if (builtIn)
|
|
28368
|
+
return { model: builtIn.model, effort: builtIn.effort ?? null, source: "built-in" };
|
|
28369
|
+
}
|
|
28370
|
+
return null;
|
|
28371
|
+
};
|
|
28372
|
+
var uniformImplementerModel = (cwd, host, dir) => {
|
|
28373
|
+
const tiers = MODEL_TIERS.map((tier) => resolveRoleModel(cwd, { role: "implementer", tier }, host, dir));
|
|
28374
|
+
const [first] = tiers;
|
|
28375
|
+
return first && tiers.every((t) => t?.model === first.model && t.effort === first.effort) ? first : null;
|
|
28376
|
+
};
|
|
28377
|
+
var ROLE_SELECTORS = MODEL_ROLES.flatMap((role) => role === "implementer" ? MODEL_TIERS.map((tier) => ({ role, tier })) : [{ role }]);
|
|
28378
|
+
|
|
28379
|
+
// packages/workit-core/src/hooks/agent-model.ts
|
|
28380
|
+
var MODELS = new Set(["sonnet", "opus", "haiku", "fable"]);
|
|
28381
|
+
var EFFORTS = new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
28382
|
+
|
|
28205
28383
|
// packages/workit-core/src/hooks/cwd-normalize.ts
|
|
28206
28384
|
var DIR = String.raw`[A-Za-z0-9_./@%+:,=-]+|'[^'$${"`"}\\\n]*'|"[^"$${"`"}\\!\n]*"`;
|
|
28207
28385
|
var COMPOUND = new RegExp(String.raw`^\s*cd\s+(${DIR})\s*&&\s*(workit(?:\s[\s\S]*)?)$`, "u");
|
|
@@ -28375,92 +28553,6 @@ var codexCapabilities = (host, availability = {}) => capabilitiesFor(codexDescri
|
|
|
28375
28553
|
if (false)
|
|
28376
28554
|
;
|
|
28377
28555
|
|
|
28378
|
-
// packages/workit-core/src/core/role-models.ts
|
|
28379
|
-
var MODEL_ROLES = [
|
|
28380
|
-
"decider",
|
|
28381
|
-
"implementer",
|
|
28382
|
-
"verifier",
|
|
28383
|
-
"reviewer",
|
|
28384
|
-
"explore",
|
|
28385
|
-
"babysit"
|
|
28386
|
-
];
|
|
28387
|
-
var MODEL_TIERS = ["mundane", "standard", "hard"];
|
|
28388
|
-
var HOST_KEYS = new Set([
|
|
28389
|
-
"claude_code",
|
|
28390
|
-
"opencode",
|
|
28391
|
-
"codex",
|
|
28392
|
-
"codex_cli",
|
|
28393
|
-
"codex_desktop",
|
|
28394
|
-
"cursor",
|
|
28395
|
-
"pi",
|
|
28396
|
-
"default"
|
|
28397
|
-
]);
|
|
28398
|
-
var BUILT_IN_CLAUDE_CODE = {
|
|
28399
|
-
decider: { model: "fable", effort: "high" },
|
|
28400
|
-
"implementer.hard": { model: "opus" },
|
|
28401
|
-
"implementer.standard": { model: "sonnet" },
|
|
28402
|
-
"implementer.mundane": { model: "haiku" },
|
|
28403
|
-
verifier: { model: "sonnet" },
|
|
28404
|
-
reviewer: { model: "opus" },
|
|
28405
|
-
explore: { model: "haiku" },
|
|
28406
|
-
babysit: { model: "haiku" }
|
|
28407
|
-
};
|
|
28408
|
-
var isObject7 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
28409
|
-
var name = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
|
|
28410
|
-
var leaf = (value) => {
|
|
28411
|
-
const text = name(value);
|
|
28412
|
-
if (text)
|
|
28413
|
-
return { model: text, effort: null };
|
|
28414
|
-
if (!isObject7(value))
|
|
28415
|
-
return null;
|
|
28416
|
-
const model = name(value.model);
|
|
28417
|
-
return model ? { model, effort: name(value.effort) } : null;
|
|
28418
|
-
};
|
|
28419
|
-
var isFlat = (value) => typeof value === "string" || isObject7(value) && Object.hasOwn(value, "model");
|
|
28420
|
-
var forHost = (value, host) => {
|
|
28421
|
-
if (isFlat(value))
|
|
28422
|
-
return leaf(value);
|
|
28423
|
-
if (!isObject7(value))
|
|
28424
|
-
return null;
|
|
28425
|
-
const family = host ? hostFamily(host) : null;
|
|
28426
|
-
for (const key of [family, host, "default"])
|
|
28427
|
-
if (key && Object.hasOwn(value, key)) {
|
|
28428
|
-
const found = leaf(value[key]);
|
|
28429
|
-
if (found)
|
|
28430
|
-
return found;
|
|
28431
|
-
}
|
|
28432
|
-
return null;
|
|
28433
|
-
};
|
|
28434
|
-
var rolesOf = (models) => isObject7(models) && isObject7(models.roles) ? models.roles : null;
|
|
28435
|
-
var resolveRoleModel = (cwd, selector, host, dir) => {
|
|
28436
|
-
const { role, tier } = selector;
|
|
28437
|
-
for (const source of modelSources(cwd, dir)) {
|
|
28438
|
-
const where = source.global ? "the global default" : `workspace ${source.name}`;
|
|
28439
|
-
const roles = rolesOf(source.models);
|
|
28440
|
-
const configured = roles && Object.hasOwn(roles, role) ? roles[role] : undefined;
|
|
28441
|
-
const fromRoles = role === "implementer" ? tier && isObject7(configured) && Object.hasOwn(configured, tier) ? forHost(configured[tier], host) : null : forHost(configured, host);
|
|
28442
|
-
if (fromRoles)
|
|
28443
|
-
return { ...fromRoles, source: `models.roles in ${where}` };
|
|
28444
|
-
if (role === "implementer" && tier && isObject7(source.tierModels)) {
|
|
28445
|
-
const fromTiers = Object.hasOwn(source.tierModels, tier) ? forHost(source.tierModels[tier], host) : null;
|
|
28446
|
-
if (fromTiers)
|
|
28447
|
-
return { model: fromTiers.model, effort: null, source: `fanout.tierModels in ${where}` };
|
|
28448
|
-
}
|
|
28449
|
-
}
|
|
28450
|
-
if (host && hostFamily(host) === "claude_code") {
|
|
28451
|
-
const builtIn = BUILT_IN_CLAUDE_CODE[tier ? `${role}.${tier}` : role];
|
|
28452
|
-
if (builtIn)
|
|
28453
|
-
return { model: builtIn.model, effort: builtIn.effort ?? null, source: "built-in" };
|
|
28454
|
-
}
|
|
28455
|
-
return null;
|
|
28456
|
-
};
|
|
28457
|
-
var uniformImplementerModel = (cwd, host, dir) => {
|
|
28458
|
-
const tiers = MODEL_TIERS.map((tier) => resolveRoleModel(cwd, { role: "implementer", tier }, host, dir));
|
|
28459
|
-
const [first] = tiers;
|
|
28460
|
-
return first && tiers.every((t) => t?.model === first.model && t.effort === first.effort) ? first : null;
|
|
28461
|
-
};
|
|
28462
|
-
var ROLE_SELECTORS = MODEL_ROLES.flatMap((role) => role === "implementer" ? MODEL_TIERS.map((tier) => ({ role, tier })) : [{ role }]);
|
|
28463
|
-
|
|
28464
28556
|
// packages/workit-codex/scripts/agents.ts
|
|
28465
28557
|
import {
|
|
28466
28558
|
existsSync as existsSync10,
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
gitStoreDir2,
|
|
4
|
+
standingSeenFile2,
|
|
5
|
+
readStandingRev2,
|
|
6
|
+
readStandingSeen2,
|
|
7
|
+
writeStandingSeen2
|
|
8
|
+
} from "./workit-hook-jy7y0gdx.js";
|
|
2
9
|
import {
|
|
3
10
|
CHECKS_FILE,
|
|
4
11
|
repoHeavyCommands,
|
|
@@ -6,13 +13,8 @@ import {
|
|
|
6
13
|
matchesNamedCheck,
|
|
7
14
|
gateCheckNames,
|
|
8
15
|
checkCommand,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
standingSeenFile,
|
|
12
|
-
readStandingRev,
|
|
13
|
-
readStandingSeen,
|
|
14
|
-
writeStandingSeen
|
|
15
|
-
} from "./workit-hook-vhz9yrcw.js";
|
|
16
|
+
maybeHeavy2
|
|
17
|
+
} from "./workit-hook-2m8a4m5j.js";
|
|
16
18
|
// packages/workit-core/src/hooks/descriptor.ts
|
|
17
19
|
var support = (descriptor, axis) => {
|
|
18
20
|
if (axis.startsWith("event:"))
|
|
@@ -8814,6 +8816,34 @@ var workspaceTrailers = (cwd, dir) => {
|
|
|
8814
8816
|
};
|
|
8815
8817
|
};
|
|
8816
8818
|
var workspaceLiveSessionGuard = (cwd, dir) => inheritedSetting(cwd, dir, (entry) => typeof entry.liveSessionGuard === "boolean")?.source?.liveSessionGuard !== false;
|
|
8819
|
+
var modelSources = (cwd, dir) => {
|
|
8820
|
+
const out = [];
|
|
8821
|
+
try {
|
|
8822
|
+
const matched = matchRuntimeWorkspace(cwd, dir);
|
|
8823
|
+
if (matched) {
|
|
8824
|
+
const enclosing = matched.matches.filter((entry) => entry !== matched.selected).toSorted((a, b) => globSpecificity(b.glob) - globSpecificity(a.glob));
|
|
8825
|
+
for (const entry of [matched.selected, ...enclosing])
|
|
8826
|
+
out.push({
|
|
8827
|
+
name: entry.name,
|
|
8828
|
+
global: false,
|
|
8829
|
+
models: entry.models,
|
|
8830
|
+
tierModels: entry.fanout?.tierModels
|
|
8831
|
+
});
|
|
8832
|
+
}
|
|
8833
|
+
} catch {}
|
|
8834
|
+
try {
|
|
8835
|
+
const document = JSON.parse(readFileSync2(path6.join(dir ?? configDir(), "workspaces.json"), "utf8"));
|
|
8836
|
+
if (document && typeof document === "object" && !Array.isArray(document))
|
|
8837
|
+
out.push({
|
|
8838
|
+
name: "global",
|
|
8839
|
+
global: true,
|
|
8840
|
+
models: document.models,
|
|
8841
|
+
tierModels: undefined
|
|
8842
|
+
});
|
|
8843
|
+
} catch {}
|
|
8844
|
+
return out;
|
|
8845
|
+
};
|
|
8846
|
+
var hostFamily = (host) => host.replace(/_(?:cli|desktop)$/u, "");
|
|
8817
8847
|
var TIER_KEYS = new Set(["mundane", "standard", "hard"]);
|
|
8818
8848
|
var TIER_HOSTS = new Set([
|
|
8819
8849
|
"claude_code",
|
|
@@ -9571,11 +9601,16 @@ var branchPolicySnapshotFor = (workspaceRoot) => {
|
|
|
9571
9601
|
fingerprint
|
|
9572
9602
|
};
|
|
9573
9603
|
};
|
|
9604
|
+
var rethrowRuntimeBug = (error) => {
|
|
9605
|
+
if (error instanceof TypeError || error instanceof ReferenceError)
|
|
9606
|
+
throw error;
|
|
9607
|
+
};
|
|
9574
9608
|
var validateBranchNameFor = (workspaceRoot, name) => {
|
|
9575
9609
|
try {
|
|
9576
9610
|
const resolved = branchPolicySnapshotFor(workspaceRoot);
|
|
9577
9611
|
return validateBranchNamePolicy(name, resolved.namePolicy, resolved.source);
|
|
9578
9612
|
} catch (error) {
|
|
9613
|
+
rethrowRuntimeBug(error);
|
|
9579
9614
|
const correction = "repair or select a valid workspace policy before creating a branch";
|
|
9580
9615
|
return {
|
|
9581
9616
|
ok: false,
|
|
@@ -15196,6 +15231,7 @@ function normalizeOperationInput(family, input, host) {
|
|
|
15196
15231
|
request[key] = strings(request[key]);
|
|
15197
15232
|
return request;
|
|
15198
15233
|
}
|
|
15234
|
+
var NOT_FLAT = new Set(["schemaVersion", "action", "workspaceId"]);
|
|
15199
15235
|
|
|
15200
15236
|
// packages/workit-core/src/core/policy/judgment.ts
|
|
15201
15237
|
var isObject6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -20492,7 +20528,7 @@ var rulesFor = (host, cwd, env) => {
|
|
|
20492
20528
|
function heavyGate(cwd, command, options) {
|
|
20493
20529
|
const env = options.env ?? process.env;
|
|
20494
20530
|
try {
|
|
20495
|
-
if (env.WORKIT_HEAVY_GATE === "0" || !
|
|
20531
|
+
if (env.WORKIT_HEAVY_GATE === "0" || !maybeHeavy2(command, cwd, env) || !workitOnPath(env))
|
|
20496
20532
|
return { kind: "none" };
|
|
20497
20533
|
return heavyPlan(command, {
|
|
20498
20534
|
cwd,
|
|
@@ -21871,11 +21907,11 @@ var standingFor = (input, store, rev) => {
|
|
|
21871
21907
|
return { rev, orders, rows };
|
|
21872
21908
|
};
|
|
21873
21909
|
var located = (input) => {
|
|
21874
|
-
const store = input.session.id ?
|
|
21875
|
-
const rev = store ?
|
|
21910
|
+
const store = input.session.id ? gitStoreDir2(input.cwd) : null;
|
|
21911
|
+
const rev = store ? readStandingRev2(store) : null;
|
|
21876
21912
|
if (!store || rev === null)
|
|
21877
21913
|
return null;
|
|
21878
|
-
return { store, rev, file:
|
|
21914
|
+
return { store, rev, file: standingSeenFile2(store, input.session.id, input.session.agentId) };
|
|
21879
21915
|
};
|
|
21880
21916
|
var seedStanding = (input) => {
|
|
21881
21917
|
try {
|
|
@@ -21883,7 +21919,7 @@ var seedStanding = (input) => {
|
|
|
21883
21919
|
if (!where)
|
|
21884
21920
|
return;
|
|
21885
21921
|
const now = standingFor(input, where.store, where.rev);
|
|
21886
|
-
|
|
21922
|
+
writeStandingSeen2(where.file, { rev: where.rev, ids: [...now.orders.keys()] });
|
|
21887
21923
|
} catch {}
|
|
21888
21924
|
};
|
|
21889
21925
|
var fanoutOf = (row) => typeof row.fanout === "string" ? row.fanout : "?";
|
|
@@ -21910,17 +21946,144 @@ var standingDelta = (input) => {
|
|
|
21910
21946
|
const where = located(input);
|
|
21911
21947
|
if (!where)
|
|
21912
21948
|
return null;
|
|
21913
|
-
const seen =
|
|
21949
|
+
const seen = readStandingSeen2(where.file);
|
|
21914
21950
|
if (seen.rev === where.rev)
|
|
21915
21951
|
return null;
|
|
21916
21952
|
const now = standingFor(input, where.store, where.rev);
|
|
21917
|
-
|
|
21953
|
+
writeStandingSeen2(where.file, { rev: where.rev, ids: [...now.orders.keys()] });
|
|
21918
21954
|
return changedSince(now, seen.ids);
|
|
21919
21955
|
} catch {
|
|
21920
21956
|
return null;
|
|
21921
21957
|
}
|
|
21922
21958
|
};
|
|
21923
21959
|
var sinceStart = new Map;
|
|
21960
|
+
// packages/workit-core/src/core/role-models.ts
|
|
21961
|
+
var MODEL_ROLES = [
|
|
21962
|
+
"decider",
|
|
21963
|
+
"implementer",
|
|
21964
|
+
"verifier",
|
|
21965
|
+
"reviewer",
|
|
21966
|
+
"explore",
|
|
21967
|
+
"babysit"
|
|
21968
|
+
];
|
|
21969
|
+
var MODEL_TIERS = ["mundane", "standard", "hard"];
|
|
21970
|
+
var HOST_KEYS = new Set([
|
|
21971
|
+
"claude_code",
|
|
21972
|
+
"opencode",
|
|
21973
|
+
"codex",
|
|
21974
|
+
"codex_cli",
|
|
21975
|
+
"codex_desktop",
|
|
21976
|
+
"cursor",
|
|
21977
|
+
"pi",
|
|
21978
|
+
"default"
|
|
21979
|
+
]);
|
|
21980
|
+
var BUILT_IN_CLAUDE_CODE = {
|
|
21981
|
+
decider: { model: "fable", effort: "high" },
|
|
21982
|
+
"implementer.hard": { model: "opus" },
|
|
21983
|
+
"implementer.standard": { model: "sonnet" },
|
|
21984
|
+
"implementer.mundane": { model: "haiku" },
|
|
21985
|
+
verifier: { model: "sonnet" },
|
|
21986
|
+
reviewer: { model: "opus" },
|
|
21987
|
+
explore: { model: "haiku" },
|
|
21988
|
+
babysit: { model: "haiku" }
|
|
21989
|
+
};
|
|
21990
|
+
var isObject7 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
21991
|
+
var name = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
|
|
21992
|
+
var leaf = (value) => {
|
|
21993
|
+
const text = name(value);
|
|
21994
|
+
if (text)
|
|
21995
|
+
return { model: text, effort: null };
|
|
21996
|
+
if (!isObject7(value))
|
|
21997
|
+
return null;
|
|
21998
|
+
const model = name(value.model);
|
|
21999
|
+
return model ? { model, effort: name(value.effort) } : null;
|
|
22000
|
+
};
|
|
22001
|
+
var isFlat = (value) => typeof value === "string" || isObject7(value) && Object.hasOwn(value, "model");
|
|
22002
|
+
var forHost = (value, host) => {
|
|
22003
|
+
if (isFlat(value))
|
|
22004
|
+
return leaf(value);
|
|
22005
|
+
if (!isObject7(value))
|
|
22006
|
+
return null;
|
|
22007
|
+
const family = host ? hostFamily(host) : null;
|
|
22008
|
+
for (const key of [family, host, "default"])
|
|
22009
|
+
if (key && Object.hasOwn(value, key)) {
|
|
22010
|
+
const found = leaf(value[key]);
|
|
22011
|
+
if (found)
|
|
22012
|
+
return found;
|
|
22013
|
+
}
|
|
22014
|
+
return null;
|
|
22015
|
+
};
|
|
22016
|
+
var rolesOf = (models) => isObject7(models) && isObject7(models.roles) ? models.roles : null;
|
|
22017
|
+
var resolveRoleModel = (cwd, selector, host, dir) => {
|
|
22018
|
+
const { role, tier } = selector;
|
|
22019
|
+
for (const source of modelSources(cwd, dir)) {
|
|
22020
|
+
const where = source.global ? "the global default" : `workspace ${source.name}`;
|
|
22021
|
+
const roles = rolesOf(source.models);
|
|
22022
|
+
const configured = roles && Object.hasOwn(roles, role) ? roles[role] : undefined;
|
|
22023
|
+
const fromRoles = role === "implementer" ? tier && isObject7(configured) && Object.hasOwn(configured, tier) ? forHost(configured[tier], host) : null : forHost(configured, host);
|
|
22024
|
+
if (fromRoles)
|
|
22025
|
+
return { ...fromRoles, source: `models.roles in ${where}` };
|
|
22026
|
+
if (role === "implementer" && tier && isObject7(source.tierModels)) {
|
|
22027
|
+
const fromTiers = Object.hasOwn(source.tierModels, tier) ? forHost(source.tierModels[tier], host) : null;
|
|
22028
|
+
if (fromTiers)
|
|
22029
|
+
return { model: fromTiers.model, effort: null, source: `fanout.tierModels in ${where}` };
|
|
22030
|
+
}
|
|
22031
|
+
}
|
|
22032
|
+
if (host && hostFamily(host) === "claude_code") {
|
|
22033
|
+
const builtIn = BUILT_IN_CLAUDE_CODE[tier ? `${role}.${tier}` : role];
|
|
22034
|
+
if (builtIn)
|
|
22035
|
+
return { model: builtIn.model, effort: builtIn.effort ?? null, source: "built-in" };
|
|
22036
|
+
}
|
|
22037
|
+
return null;
|
|
22038
|
+
};
|
|
22039
|
+
var ROLE_SELECTORS = MODEL_ROLES.flatMap((role) => role === "implementer" ? MODEL_TIERS.map((tier) => ({ role, tier })) : [{ role }]);
|
|
22040
|
+
var roleForAgentType = (agentType, prompt) => {
|
|
22041
|
+
switch (agentType) {
|
|
22042
|
+
case "workit:implementer": {
|
|
22043
|
+
const tier = typeof prompt === "string" ? /^[ \t]*TIER:[ \t]*(mundane|standard|hard)\b/im.exec(prompt)?.[1] : undefined;
|
|
22044
|
+
return { role: "implementer", tier: tier?.toLowerCase() ?? "standard" };
|
|
22045
|
+
}
|
|
22046
|
+
case "workit:verifier":
|
|
22047
|
+
return { role: "verifier" };
|
|
22048
|
+
case "workit:reviewer":
|
|
22049
|
+
return { role: "reviewer" };
|
|
22050
|
+
case "Explore":
|
|
22051
|
+
return { role: "explore" };
|
|
22052
|
+
default:
|
|
22053
|
+
return null;
|
|
22054
|
+
}
|
|
22055
|
+
};
|
|
22056
|
+
|
|
22057
|
+
// packages/workit-core/src/hooks/agent-model.ts
|
|
22058
|
+
var MODELS = new Set(["sonnet", "opus", "haiku", "fable"]);
|
|
22059
|
+
var EFFORTS = new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
22060
|
+
var given = (value) => typeof value === "string" && value.trim() !== "";
|
|
22061
|
+
var agentModelDecision = (cwd, tool, env = process.env) => {
|
|
22062
|
+
if (given(tool.model) || env.CLAUDE_CODE_SUBAGENT_MODEL_FORCE)
|
|
22063
|
+
return { kind: "none" };
|
|
22064
|
+
const selector = roleForAgentType(tool.subagent_type, tool.prompt);
|
|
22065
|
+
if (!selector)
|
|
22066
|
+
return { kind: "none" };
|
|
22067
|
+
const resolved = resolveRoleModel(cwd, selector, "claude_code");
|
|
22068
|
+
if (!resolved)
|
|
22069
|
+
return { kind: "none" };
|
|
22070
|
+
const model = resolved.model.toLowerCase();
|
|
22071
|
+
const effort = resolved.effort?.toLowerCase() ?? null;
|
|
22072
|
+
const input = { ...tool };
|
|
22073
|
+
if (MODELS.has(model))
|
|
22074
|
+
input.model = model;
|
|
22075
|
+
if (effort && EFFORTS.has(effort) && !given(tool.effort))
|
|
22076
|
+
input.effort = effort;
|
|
22077
|
+
if (input.model === undefined && input.effort === tool.effort)
|
|
22078
|
+
return { kind: "none" };
|
|
22079
|
+
const label = selector.tier ? `${selector.role} ${selector.tier}` : selector.role;
|
|
22080
|
+
return {
|
|
22081
|
+
kind: "update-input",
|
|
22082
|
+
input,
|
|
22083
|
+
text: `Workit set ${String(input.model ?? "no model")}${input.effort !== tool.effort ? ` (effort ${String(input.effort)})` : ""} on this ${String(tool.subagent_type)} spawn: role ${label}, ${resolved.source}. Name a model to choose another.`
|
|
22084
|
+
};
|
|
22085
|
+
};
|
|
22086
|
+
|
|
21924
22087
|
// packages/workit-core/src/hooks/cwd-normalize.ts
|
|
21925
22088
|
var DIR = String.raw`[A-Za-z0-9_./@%+:,=-]+|'[^'$${"`"}\\\n]*'|"[^"$${"`"}\\!\n]*"`;
|
|
21926
22089
|
var COMPOUND = new RegExp(String.raw`^\s*cd\s+(${DIR})\s*&&\s*(workit(?:\s[\s\S]*)?)$`, "u");
|
|
@@ -22284,7 +22447,7 @@ function handleHook(input, deps) {
|
|
|
22284
22447
|
const delta = standingDelta(input);
|
|
22285
22448
|
if (!delta)
|
|
22286
22449
|
return decision;
|
|
22287
|
-
return decision.kind === "rewrite" ? { ...decision, text: [decision.text, delta].filter(Boolean).join(`
|
|
22450
|
+
return decision.kind === "rewrite" || decision.kind === "update-input" ? { ...decision, text: [decision.text, delta].filter(Boolean).join(`
|
|
22288
22451
|
`) } : withContextLine(decision, delta);
|
|
22289
22452
|
}
|
|
22290
22453
|
function decide(input, deps) {
|
|
@@ -22397,6 +22560,8 @@ function decide(input, deps) {
|
|
|
22397
22560
|
case "tool.pre":
|
|
22398
22561
|
if (event.skill)
|
|
22399
22562
|
recordSkillLoad(input, event.skill, "tool");
|
|
22563
|
+
if (event.agentInput && input.host === "claude_code")
|
|
22564
|
+
return agentModelDecision(input.cwd, event.agentInput);
|
|
22400
22565
|
return NONE6;
|
|
22401
22566
|
case "stop":
|
|
22402
22567
|
return usable2(descriptor.events.stop.support) ? stopDecision(input, descriptor) : NONE6;
|
|
@@ -22680,6 +22845,16 @@ var eventOf = (name, value) => {
|
|
|
22680
22845
|
skill: isRecord5(value.tool_input) ? optionalText(value.tool_input.skill) : null
|
|
22681
22846
|
}
|
|
22682
22847
|
};
|
|
22848
|
+
if (value.tool_name === "Agent" || value.tool_name === "Task")
|
|
22849
|
+
return {
|
|
22850
|
+
ok: true,
|
|
22851
|
+
event: {
|
|
22852
|
+
kind: "tool.pre",
|
|
22853
|
+
tool: value.tool_name,
|
|
22854
|
+
toolUseId,
|
|
22855
|
+
...isRecord5(value.tool_input) ? { agentInput: value.tool_input } : {}
|
|
22856
|
+
}
|
|
22857
|
+
};
|
|
22683
22858
|
if (!SHELL_TOOLS.has(value.tool_name))
|
|
22684
22859
|
return { ok: true, event: { kind: "tool.pre", tool: value.tool_name, toolUseId } };
|
|
22685
22860
|
const command = toolCommand(value);
|
|
@@ -22756,7 +22931,7 @@ var CONTEXT_EVENTS = new Set([
|
|
|
22756
22931
|
"PostToolUse"
|
|
22757
22932
|
]);
|
|
22758
22933
|
var render = (decision, native) => {
|
|
22759
|
-
if (decision.kind === "rewrite" && native === "PreToolUse" && decision.input)
|
|
22934
|
+
if ((decision.kind === "rewrite" || decision.kind === "update-input") && native === "PreToolUse" && decision.input)
|
|
22760
22935
|
return {
|
|
22761
22936
|
json: {
|
|
22762
22937
|
hookSpecificOutput: {
|
|
@@ -235,7 +235,7 @@ function checkCommand(args, version, onPath = workitAvailable()) {
|
|
|
235
235
|
// packages/workit-core/src/core/heavy-words.ts
|
|
236
236
|
var HEAVY_WORDS = new Set(("npm npx pnpm pnpx yarn bun bunx deno corepack make gmake docker podman nerdctl " + "python python3 py uv poetry pdm pipenv hatch rye bundle rake nx " + "jest vitest mocha ava tap karma jasmine nyc c8 tsc vue-tsc svelte-check eslint stylelint " + "tslint webpack webpack-cli rollup parcel tsup vite next nuxt nuxi astro ng react-scripts " + "playwright cypress wdio testcafe turbo lerna sonar-scanner sonarless sonarless-mcp go " + "golangci-lint gotestsum staticcheck cargo mvn mvnw gradle gradlew ant sbt bazel bazelisk " + "buck2 dotnet msbuild pytest py.test tox nox mypy pyright pylint coverage maturin pip pip3 " + "rspec rails phpunit pest phpstan psalm composer mix swift xcodebuild flutter dart pod cmake " + "ninja meson ctest scons docker-compose buildah earthly").split(" "));
|
|
237
237
|
var wordsOf = (command) => command.split(/[\s;&|()<>`'"]+/u).map((word) => (word.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat)$/u, "")).filter(Boolean);
|
|
238
|
-
var
|
|
238
|
+
var stateDir2 = (env) => {
|
|
239
239
|
if (env.WORKFLOW_TOOLKIT_STATE)
|
|
240
240
|
return env.WORKFLOW_TOOLKIT_STATE;
|
|
241
241
|
if (env.XDG_STATE_HOME)
|
|
@@ -256,7 +256,7 @@ var readJson = (file) => {
|
|
|
256
256
|
};
|
|
257
257
|
var patternWords = (cwd, env) => {
|
|
258
258
|
const patterns = [];
|
|
259
|
-
const machine = readJson(path2.join(
|
|
259
|
+
const machine = readJson(path2.join(stateDir2(env), "heavy-commands.json"));
|
|
260
260
|
if (Array.isArray(machine?.patterns))
|
|
261
261
|
patterns.push(...machine.patterns);
|
|
262
262
|
for (let dir = path2.resolve(cwd);; dir = path2.dirname(dir)) {
|
|
@@ -278,7 +278,7 @@ var patternWords = (cwd, env) => {
|
|
|
278
278
|
}
|
|
279
279
|
return words;
|
|
280
280
|
};
|
|
281
|
-
function
|
|
281
|
+
function maybeHeavy2(command, cwd, env = process.env) {
|
|
282
282
|
try {
|
|
283
283
|
const words = wordsOf(command);
|
|
284
284
|
if (words.some((word) => HEAVY_WORDS.has(word) || /^python[\d.]*$/u.test(word)))
|
|
@@ -290,64 +290,4 @@ function maybeHeavy(command, cwd, env = process.env) {
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
|
|
294
|
-
import { createHash } from "node:crypto";
|
|
295
|
-
import fs3 from "node:fs";
|
|
296
|
-
import path3 from "node:path";
|
|
297
|
-
var gitStoreDir = (cwd) => {
|
|
298
|
-
try {
|
|
299
|
-
for (let dir = path3.resolve(cwd);; dir = path3.dirname(dir)) {
|
|
300
|
-
const dotGit = path3.join(dir, ".git");
|
|
301
|
-
if (fs3.existsSync(dotGit)) {
|
|
302
|
-
let gitDir = dotGit;
|
|
303
|
-
if (fs3.statSync(dotGit).isFile()) {
|
|
304
|
-
const target = /^gitdir:\s*(.+)$/mu.exec(fs3.readFileSync(dotGit, "utf8"))?.[1]?.trim();
|
|
305
|
-
if (!target)
|
|
306
|
-
return null;
|
|
307
|
-
gitDir = path3.resolve(dir, target);
|
|
308
|
-
const common = path3.join(gitDir, "commondir");
|
|
309
|
-
if (fs3.existsSync(common))
|
|
310
|
-
gitDir = path3.resolve(gitDir, fs3.readFileSync(common, "utf8").trim());
|
|
311
|
-
}
|
|
312
|
-
return path3.join(gitDir, "workit");
|
|
313
|
-
}
|
|
314
|
-
if (path3.dirname(dir) === dir)
|
|
315
|
-
return null;
|
|
316
|
-
}
|
|
317
|
-
} catch {
|
|
318
|
-
return null;
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
var standingRevFile = (store) => path3.join(store, "standing", "rev");
|
|
322
|
-
var standingSeenFile = (store, session, agentId) => path3.join(store, "standing", "seen", `${createHash("sha256").update(`${session}\x00${agentId ?? ""}`).digest("hex").slice(0, 32)}.json`);
|
|
323
|
-
var readStandingRev = (store) => {
|
|
324
|
-
try {
|
|
325
|
-
return fs3.readFileSync(standingRevFile(store), "utf8").trim() || null;
|
|
326
|
-
} catch {
|
|
327
|
-
return null;
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
var readStandingSeen = (file) => {
|
|
331
|
-
try {
|
|
332
|
-
const value = JSON.parse(fs3.readFileSync(file, "utf8"));
|
|
333
|
-
return {
|
|
334
|
-
rev: typeof value.rev === "string" ? value.rev : null,
|
|
335
|
-
ids: Array.isArray(value.ids) ? value.ids.filter((id) => typeof id === "string") : []
|
|
336
|
-
};
|
|
337
|
-
} catch {
|
|
338
|
-
return { rev: null, ids: [] };
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
var writeStandingSeen = (file, seen) => {
|
|
342
|
-
try {
|
|
343
|
-
fs3.mkdirSync(path3.dirname(file), { recursive: true });
|
|
344
|
-
fs3.writeFileSync(file, JSON.stringify(seen));
|
|
345
|
-
} catch {}
|
|
346
|
-
};
|
|
347
|
-
var standingPending = (cwd, session, agentId) => {
|
|
348
|
-
const store = gitStoreDir(cwd);
|
|
349
|
-
const rev = store ? readStandingRev(store) : null;
|
|
350
|
-
return rev !== null && readStandingSeen(standingSeenFile(store, session, agentId)).rev !== rev;
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
export { CHECKS_FILE, repoHeavyCommands, loadCheckConfig, matchesNamedCheck, gateCheckNames, checkCommand, stateDir, maybeHeavy, gitStoreDir, standingSeenFile, readStandingRev, readStandingSeen, writeStandingSeen, standingPending };
|
|
293
|
+
export { CHECKS_FILE, repoHeavyCommands, loadCheckConfig, matchesNamedCheck, gateCheckNames, checkCommand, stateDir2, maybeHeavy2 };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// packages/workit-core/src/hooks/standing-signal.ts
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
var gitStoreDir2 = (cwd) => {
|
|
8
|
+
try {
|
|
9
|
+
for (let dir = path.resolve(cwd);; dir = path.dirname(dir)) {
|
|
10
|
+
const dotGit = path.join(dir, ".git");
|
|
11
|
+
if (fs.existsSync(dotGit)) {
|
|
12
|
+
let gitDir = dotGit;
|
|
13
|
+
if (fs.statSync(dotGit).isFile()) {
|
|
14
|
+
const target = /^gitdir:\s*(.+)$/mu.exec(fs.readFileSync(dotGit, "utf8"))?.[1]?.trim();
|
|
15
|
+
if (!target)
|
|
16
|
+
return null;
|
|
17
|
+
gitDir = path.resolve(dir, target);
|
|
18
|
+
const common = path.join(gitDir, "commondir");
|
|
19
|
+
if (fs.existsSync(common))
|
|
20
|
+
gitDir = path.resolve(gitDir, fs.readFileSync(common, "utf8").trim());
|
|
21
|
+
}
|
|
22
|
+
return path.join(gitDir, "workit");
|
|
23
|
+
}
|
|
24
|
+
if (path.dirname(dir) === dir)
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
var standingRevFile = (store) => path.join(store, "standing", "rev");
|
|
32
|
+
var standingSeenFile2 = (store, session, agentId) => path.join(store, "standing", "seen", `${createHash("sha256").update(`${session}\x00${agentId ?? ""}`).digest("hex").slice(0, 32)}.json`);
|
|
33
|
+
var readStandingRev2 = (store) => {
|
|
34
|
+
try {
|
|
35
|
+
return fs.readFileSync(standingRevFile(store), "utf8").trim() || null;
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var readStandingSeen2 = (file) => {
|
|
41
|
+
try {
|
|
42
|
+
const value = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
43
|
+
return {
|
|
44
|
+
rev: typeof value.rev === "string" ? value.rev : null,
|
|
45
|
+
ids: Array.isArray(value.ids) ? value.ids.filter((id) => typeof id === "string") : []
|
|
46
|
+
};
|
|
47
|
+
} catch {
|
|
48
|
+
return { rev: null, ids: [] };
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var writeStandingSeen2 = (file, seen) => {
|
|
52
|
+
try {
|
|
53
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
54
|
+
fs.writeFileSync(file, JSON.stringify(seen));
|
|
55
|
+
} catch {}
|
|
56
|
+
};
|
|
57
|
+
var bumpStandingRev2 = (store, rev) => {
|
|
58
|
+
try {
|
|
59
|
+
fs.mkdirSync(path.join(store, "standing"), { recursive: true });
|
|
60
|
+
fs.writeFileSync(standingRevFile(store), `${rev}
|
|
61
|
+
`);
|
|
62
|
+
} catch {}
|
|
63
|
+
};
|
|
64
|
+
var standingPending2 = (cwd, session, agentId) => {
|
|
65
|
+
const store = gitStoreDir2(cwd);
|
|
66
|
+
const rev = store ? readStandingRev2(store) : null;
|
|
67
|
+
return rev !== null && readStandingSeen2(standingSeenFile2(store, session, agentId)).rev !== rev;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { gitStoreDir2, standingSeenFile2, readStandingRev2, readStandingSeen2, writeStandingSeen2, bumpStandingRev2, standingPending2 };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
gitStoreDir2,
|
|
4
|
+
standingSeenFile2,
|
|
5
|
+
readStandingRev2,
|
|
6
|
+
readStandingSeen2,
|
|
7
|
+
writeStandingSeen2,
|
|
8
|
+
bumpStandingRev2,
|
|
9
|
+
standingPending2
|
|
10
|
+
} from "./workit-hook-jy7y0gdx.js";
|
|
11
|
+
export {
|
|
12
|
+
bumpStandingRev2 as bumpStandingRev,
|
|
13
|
+
gitStoreDir2 as gitStoreDir,
|
|
14
|
+
readStandingRev2 as readStandingRev,
|
|
15
|
+
readStandingSeen2 as readStandingSeen,
|
|
16
|
+
standingPending2 as standingPending,
|
|
17
|
+
standingSeenFile2 as standingSeenFile,
|
|
18
|
+
writeStandingSeen2 as writeStandingSeen
|
|
19
|
+
};
|
package/dist/workit-hook.js
CHANGED
|
@@ -1,11 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
stateDir,
|
|
4
|
-
maybeHeavy,
|
|
5
|
-
standingPending
|
|
6
|
-
} from "./workit-hook-vhz9yrcw.js";
|
|
7
2
|
|
|
8
3
|
// packages/workit-codex/hooks/launcher.ts
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
var nodeFloorMessage = () => {
|
|
8
|
+
try {
|
|
9
|
+
const found = process.env.WORKIT_HOOK_NODE_VERSION || process.versions.node;
|
|
10
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
+
const range = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8")).engines?.node;
|
|
12
|
+
const min = /^>=\s*(\d+)(?:\.(\d+))?(?:\.(\d+))?/.exec(String(range ?? ""));
|
|
13
|
+
if (!min)
|
|
14
|
+
return null;
|
|
15
|
+
const need = [min[1], min[2] ?? 0, min[3] ?? 0].map(Number);
|
|
16
|
+
const have = String(found).replace(/^v/, "").split(".").map(Number);
|
|
17
|
+
for (let i = 0;i < 3; i++) {
|
|
18
|
+
const a = have[i] ?? 0;
|
|
19
|
+
if (Number.isNaN(a))
|
|
20
|
+
return null;
|
|
21
|
+
if (a !== need[i])
|
|
22
|
+
return a < need[i] ? `needs Node ${range}, found ${found}` : null;
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var tooOld = nodeFloorMessage();
|
|
30
|
+
if (tooOld) {
|
|
31
|
+
process.stderr.write(`[workit] Codex hook unavailable: ${tooOld}
|
|
32
|
+
`);
|
|
33
|
+
process.stdout.write(`{}
|
|
34
|
+
`);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
var { maybeHeavy, stateDir } = await import("./workit-hook-27bwpc4a.js");
|
|
38
|
+
var { standingPending } = await import("./workit-hook-mk64s4fk.js");
|
|
9
39
|
var payload = "";
|
|
10
40
|
for await (const chunk of process.stdin)
|
|
11
41
|
payload += String(chunk);
|
|
@@ -49,6 +79,6 @@ if (quiet)
|
|
|
49
79
|
process.stdout.write(`${JSON.stringify({ hookSpecificOutput: { hookEventName: quiet } })}
|
|
50
80
|
`);
|
|
51
81
|
else {
|
|
52
|
-
const { runCodexHook } = await import("./workit-hook-
|
|
82
|
+
const { runCodexHook } = await import("./workit-hook-0vzd6e1j.js");
|
|
53
83
|
await runCodexHook([payload]);
|
|
54
84
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-codex",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.28.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit Codex CLI/desktop plugin — shared MCP transport, hooks, method skills, and verifier/reviewer/implementer agents",
|
|
6
6
|
"keywords": [
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"build": "bun scripts/build.ts"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@brainervirus/workit-core": "^8.
|
|
43
|
-
"@brainervirus/workit-mcp": "^8.
|
|
42
|
+
"@brainervirus/workit-core": "^8.28.1",
|
|
43
|
+
"@brainervirus/workit-mcp": "^8.28.1"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
46
|
"node": ">=24"
|