@brainervirus/workit-pi 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/dist/worker.js CHANGED
@@ -6668,6 +6668,7 @@ var ENVELOPE = new Set([
6668
6668
  "expectedWorkspaceRevision",
6669
6669
  "judgment"
6670
6670
  ]);
6671
+ var NOT_FLAT = new Set(["schemaVersion", "action", "workspaceId"]);
6671
6672
  // packages/workit-core/src/core/config.ts
6672
6673
  import {
6673
6674
  copyFileSync,
package/dist/workit.js CHANGED
@@ -7105,8 +7105,9 @@ function flatOperationJsonSchema(family, options = {}) {
7105
7105
  };
7106
7106
  const properties = { action: { type: "string", enum: actions } };
7107
7107
  const readField = (name) => name === "taskId" || (family === "task" ? READ_TASK_FIELDS.has(name) : family === "policy");
7108
+ const taken = (name) => family === "policy" || actions.some((action) => actionKeys(family, action)?.accepted.has(name));
7108
7109
  for (const [name, field] of Object.entries({ ...COMMON, ...spec.fields }))
7109
- if (options.readOnly ? readField(name) : !(family === "state" && name === "expectedRevision"))
7110
+ if (options.readOnly ? readField(name) : taken(name))
7110
7111
  properties[name] = property(field);
7111
7112
  return {
7112
7113
  $schema: "https://json-schema.org/draft/2020-12/schema",
@@ -7348,6 +7349,98 @@ function normalizeOperationInput(family, input, host) {
7348
7349
  request[key] = strings(request[key]);
7349
7350
  return request;
7350
7351
  }
7352
+ var defOf = (node) => node._zod.def;
7353
+ var unwrap = (node) => {
7354
+ let inner = node;
7355
+ while (["optional", "nullable"].includes(defOf(inner).type) && defOf(inner).innerType)
7356
+ inner = defOf(inner).innerType;
7357
+ return inner;
7358
+ };
7359
+ var FLAT_NAME = {
7360
+ authorityRefs: "refs",
7361
+ contentRefs: "refs",
7362
+ statedChoice: "choice",
7363
+ reviewContext: "reviewSession"
7364
+ };
7365
+ var NOT_FLAT = new Set(["schemaVersion", "action", "workspaceId"]);
7366
+ function actionKeys(family, action) {
7367
+ const options = advertisedOperationSchemas[family].options;
7368
+ const option = options.find((item) => {
7369
+ const literal = defOf(item).shape?.action;
7370
+ return literal._zod.def.values.includes(action);
7371
+ });
7372
+ if (!option)
7373
+ return null;
7374
+ const out = { accepted: new Set, required: [] };
7375
+ const walk = (shape, nested) => {
7376
+ for (const [key, node] of Object.entries(shape)) {
7377
+ if (NOT_FLAT.has(key) || nested && key === "taskId")
7378
+ continue;
7379
+ const inner = unwrap(node);
7380
+ const type = defOf(inner).type;
7381
+ const needed = !["optional", "nullable"].includes(defOf(node).type);
7382
+ if (key === "scope")
7383
+ for (const name of ["scope", "paths", "exclusions"])
7384
+ out.accepted.add(name);
7385
+ else if (type === "object" && key !== "bundle" && !(key in FLAT_NAME)) {
7386
+ out.accepted.add(key);
7387
+ walk(defOf(inner).shape, true);
7388
+ } else {
7389
+ const name = FLAT_NAME[key] ?? key;
7390
+ out.accepted.add(name);
7391
+ if (needed && type !== "array" && type !== "record" && !out.required.includes(name))
7392
+ out.required.push(name);
7393
+ }
7394
+ }
7395
+ };
7396
+ walk(defOf(option).shape, false);
7397
+ return out;
7398
+ }
7399
+ function exampleOperation(family, action) {
7400
+ const keys = actionKeys(family, action);
7401
+ const example = { action };
7402
+ for (const name of keys?.required ?? [])
7403
+ example[name] = FLAT[family].fields[name]?.enum?.[0] ?? `<${name}>`;
7404
+ if (family === "policy" && !keys?.required.length && action !== "explain")
7405
+ example.riskTier = "normal";
7406
+ return example;
7407
+ }
7408
+ var oneOf = (values) => values.join(" | ");
7409
+ function invalidOperation(family, input, error) {
7410
+ const request = isObject2(input) ? input : {};
7411
+ const action = typeof request.action === "string" ? request.action : "";
7412
+ const actions = OPERATION_ACTIONS[family];
7413
+ if (!actions.includes(action))
7414
+ return failure2("invalid_input", `${family}: action must be one of ${oneOf(actions)}`, {
7415
+ fields: [{ path: "action", reason: `got ${JSON.stringify(request.action ?? null)}` }]
7416
+ });
7417
+ const own = actionKeys(family, action);
7418
+ const fields = [];
7419
+ const sentence = [];
7420
+ for (const issue of error.issues) {
7421
+ if (issue.code === "unrecognized_keys") {
7422
+ for (const key of issue.keys) {
7423
+ const home = actions.find((other) => other !== action && actionKeys(family, other).accepted.has(key));
7424
+ const reason = home ? `${key} belongs to action: ${home}` : `${key} is not a field of ${family} ${action}; it takes ${[...own.accepted].join(", ")}`;
7425
+ fields.push({ path: key, reason });
7426
+ sentence.push(reason);
7427
+ }
7428
+ continue;
7429
+ }
7430
+ const last = String(issue.path.at(-1) ?? "");
7431
+ const name = Object.entries(FLAT_NAME).find(([contract]) => contract === last)?.[1] ?? last;
7432
+ const missing = issue.code === "invalid_type" && /received undefined/.test(issue.message);
7433
+ const absent = own.required.filter((key) => !(key in request));
7434
+ const needs = missing && issue.path.length === 1 && absent.length ? absent.join(", ") : name;
7435
+ const reason = missing ? `${family} ${action} requires ${needs}` : `${name}: ${issue.message}`;
7436
+ fields.push({ path: issue.path.join("."), reason });
7437
+ sentence.push(reason);
7438
+ }
7439
+ const example = JSON.stringify(exampleOperation(family, action));
7440
+ return failure2("invalid_input", `${[...new Set(sentence)].join("; ")}. Example: ${example}`, {
7441
+ fields
7442
+ });
7443
+ }
7351
7444
  function parseAdvertisedOperation(family, input, host) {
7352
7445
  const request = normalizeOperationInput(family, input, host);
7353
7446
  if (isObject2(request) && request.schemaVersion !== SCHEMA_VERSION)
@@ -7355,12 +7448,7 @@ function parseAdvertisedOperation(family, input, host) {
7355
7448
  const parsed = advertisedOperationSchemas[family].safeParse(request);
7356
7449
  if (parsed.success)
7357
7450
  return success(null, null, request);
7358
- return failure2("invalid_input", "operation input is invalid", {
7359
- fields: parsed.error.issues.map((issue) => ({
7360
- path: issue.code === "unrecognized_keys" ? issue.keys.join(".") : issue.path.join("."),
7361
- reason: issue.message
7362
- }))
7363
- });
7451
+ return invalidOperation(family, request, parsed.error);
7364
7452
  }
7365
7453
  // packages/workit-core/src/core/task-store.ts
7366
7454
  import { createHash as createHash9, randomUUID as randomUUID3 } from "node:crypto";
@@ -10013,11 +10101,16 @@ var branchPolicySnapshotFor = (workspaceRoot) => {
10013
10101
  fingerprint
10014
10102
  };
10015
10103
  };
10104
+ var rethrowRuntimeBug = (error) => {
10105
+ if (error instanceof TypeError || error instanceof ReferenceError)
10106
+ throw error;
10107
+ };
10016
10108
  var validateBranchNameFor = (workspaceRoot, name) => {
10017
10109
  try {
10018
10110
  const resolved = branchPolicySnapshotFor(workspaceRoot);
10019
10111
  return validateBranchNamePolicy(name, resolved.namePolicy, resolved.source);
10020
10112
  } catch (error) {
10113
+ rethrowRuntimeBug(error);
10021
10114
  const correction = "repair or select a valid workspace policy before creating a branch";
10022
10115
  return {
10023
10116
  ok: false,
@@ -23839,6 +23932,138 @@ var standingDelta = (input) => {
23839
23932
  }
23840
23933
  };
23841
23934
  var sinceStart = new Map;
23935
+ // packages/workit-core/src/core/role-models.ts
23936
+ var MODEL_ROLES = [
23937
+ "decider",
23938
+ "implementer",
23939
+ "verifier",
23940
+ "reviewer",
23941
+ "explore",
23942
+ "babysit"
23943
+ ];
23944
+ var MODEL_TIERS = ["mundane", "standard", "hard"];
23945
+ var HOST_KEYS = new Set([
23946
+ "claude_code",
23947
+ "opencode",
23948
+ "codex",
23949
+ "codex_cli",
23950
+ "codex_desktop",
23951
+ "cursor",
23952
+ "pi",
23953
+ "default"
23954
+ ]);
23955
+ var BUILT_IN_CLAUDE_CODE = {
23956
+ decider: { model: "fable", effort: "high" },
23957
+ "implementer.hard": { model: "opus" },
23958
+ "implementer.standard": { model: "sonnet" },
23959
+ "implementer.mundane": { model: "haiku" },
23960
+ verifier: { model: "sonnet" },
23961
+ reviewer: { model: "opus" },
23962
+ explore: { model: "haiku" },
23963
+ babysit: { model: "haiku" }
23964
+ };
23965
+ var isObject7 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
23966
+ var name = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
23967
+ var leaf = (value) => {
23968
+ const text = name(value);
23969
+ if (text)
23970
+ return { model: text, effort: null };
23971
+ if (!isObject7(value))
23972
+ return null;
23973
+ const model = name(value.model);
23974
+ return model ? { model, effort: name(value.effort) } : null;
23975
+ };
23976
+ var isFlat = (value) => typeof value === "string" || isObject7(value) && Object.hasOwn(value, "model");
23977
+ var forHost = (value, host) => {
23978
+ if (isFlat(value))
23979
+ return leaf(value);
23980
+ if (!isObject7(value))
23981
+ return null;
23982
+ const family = host ? hostFamily(host) : null;
23983
+ for (const key of [family, host, "default"])
23984
+ if (key && Object.hasOwn(value, key)) {
23985
+ const found = leaf(value[key]);
23986
+ if (found)
23987
+ return found;
23988
+ }
23989
+ return null;
23990
+ };
23991
+ var rolesOf = (models) => isObject7(models) && isObject7(models.roles) ? models.roles : null;
23992
+ var resolveRoleModel = (cwd, selector, host, dir) => {
23993
+ const { role, tier } = selector;
23994
+ for (const source of modelSources(cwd, dir)) {
23995
+ const where = source.global ? "the global default" : `workspace ${source.name}`;
23996
+ const roles = rolesOf(source.models);
23997
+ const configured = roles && Object.hasOwn(roles, role) ? roles[role] : undefined;
23998
+ const fromRoles = role === "implementer" ? tier && isObject7(configured) && Object.hasOwn(configured, tier) ? forHost(configured[tier], host) : null : forHost(configured, host);
23999
+ if (fromRoles)
24000
+ return { ...fromRoles, source: `models.roles in ${where}` };
24001
+ if (role === "implementer" && tier && isObject7(source.tierModels)) {
24002
+ const fromTiers = Object.hasOwn(source.tierModels, tier) ? forHost(source.tierModels[tier], host) : null;
24003
+ if (fromTiers)
24004
+ return { model: fromTiers.model, effort: null, source: `fanout.tierModels in ${where}` };
24005
+ }
24006
+ }
24007
+ if (host && hostFamily(host) === "claude_code") {
24008
+ const builtIn = BUILT_IN_CLAUDE_CODE[tier ? `${role}.${tier}` : role];
24009
+ if (builtIn)
24010
+ return { model: builtIn.model, effort: builtIn.effort ?? null, source: "built-in" };
24011
+ }
24012
+ return null;
24013
+ };
24014
+ var uniformImplementerModel = (cwd, host, dir) => {
24015
+ const tiers = MODEL_TIERS.map((tier) => resolveRoleModel(cwd, { role: "implementer", tier }, host, dir));
24016
+ const [first] = tiers;
24017
+ return first && tiers.every((t) => t?.model === first.model && t.effort === first.effort) ? first : null;
24018
+ };
24019
+ var ROLE_SELECTORS = MODEL_ROLES.flatMap((role) => role === "implementer" ? MODEL_TIERS.map((tier) => ({ role, tier })) : [{ role }]);
24020
+ var roleForAgentType = (agentType, prompt) => {
24021
+ switch (agentType) {
24022
+ case "workit:implementer": {
24023
+ const tier = typeof prompt === "string" ? /^[ \t]*TIER:[ \t]*(mundane|standard|hard)\b/im.exec(prompt)?.[1] : undefined;
24024
+ return { role: "implementer", tier: tier?.toLowerCase() ?? "standard" };
24025
+ }
24026
+ case "workit:verifier":
24027
+ return { role: "verifier" };
24028
+ case "workit:reviewer":
24029
+ return { role: "reviewer" };
24030
+ case "Explore":
24031
+ return { role: "explore" };
24032
+ default:
24033
+ return null;
24034
+ }
24035
+ };
24036
+
24037
+ // packages/workit-core/src/hooks/agent-model.ts
24038
+ var MODELS = new Set(["sonnet", "opus", "haiku", "fable"]);
24039
+ var EFFORTS = new Set(["low", "medium", "high", "xhigh", "max"]);
24040
+ var given = (value) => typeof value === "string" && value.trim() !== "";
24041
+ var agentModelDecision = (cwd, tool, env = process.env) => {
24042
+ if (given(tool.model) || env.CLAUDE_CODE_SUBAGENT_MODEL_FORCE)
24043
+ return { kind: "none" };
24044
+ const selector = roleForAgentType(tool.subagent_type, tool.prompt);
24045
+ if (!selector)
24046
+ return { kind: "none" };
24047
+ const resolved = resolveRoleModel(cwd, selector, "claude_code");
24048
+ if (!resolved)
24049
+ return { kind: "none" };
24050
+ const model = resolved.model.toLowerCase();
24051
+ const effort = resolved.effort?.toLowerCase() ?? null;
24052
+ const input = { ...tool };
24053
+ if (MODELS.has(model))
24054
+ input.model = model;
24055
+ if (effort && EFFORTS.has(effort) && !given(tool.effort))
24056
+ input.effort = effort;
24057
+ if (input.model === undefined && input.effort === tool.effort)
24058
+ return { kind: "none" };
24059
+ const label = selector.tier ? `${selector.role} ${selector.tier}` : selector.role;
24060
+ return {
24061
+ kind: "update-input",
24062
+ input,
24063
+ 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.`
24064
+ };
24065
+ };
24066
+
23842
24067
  // packages/workit-core/src/hooks/cwd-normalize.ts
23843
24068
  var DIR = String.raw`[A-Za-z0-9_./@%+:,=-]+|'[^'$${"`"}\\\n]*'|"[^"$${"`"}\\!\n]*"`;
23844
24069
  var COMPOUND = new RegExp(String.raw`^\s*cd\s+(${DIR})\s*&&\s*(workit(?:\s[\s\S]*)?)$`, "u");
@@ -24202,7 +24427,7 @@ function handleHook(input, deps) {
24202
24427
  const delta = standingDelta(input);
24203
24428
  if (!delta)
24204
24429
  return decision;
24205
- return decision.kind === "rewrite" ? { ...decision, text: [decision.text, delta].filter(Boolean).join(`
24430
+ return decision.kind === "rewrite" || decision.kind === "update-input" ? { ...decision, text: [decision.text, delta].filter(Boolean).join(`
24206
24431
  `) } : withContextLine(decision, delta);
24207
24432
  }
24208
24433
  function decide(input, deps) {
@@ -24315,6 +24540,8 @@ function decide(input, deps) {
24315
24540
  case "tool.pre":
24316
24541
  if (event.skill)
24317
24542
  recordSkillLoad(input, event.skill, "tool");
24543
+ if (event.agentInput && input.host === "claude_code")
24544
+ return agentModelDecision(input.cwd, event.agentInput);
24318
24545
  return NONE6;
24319
24546
  case "stop":
24320
24547
  return usable2(descriptor.events.stop.support) ? stopDecision(input, descriptor) : NONE6;
@@ -24697,92 +24924,6 @@ var cancelHint = (workerId) => `cancel it first: workit_worker {"action":"cancel
24697
24924
  import { spawn as nodeSpawn } from "node:child_process";
24698
24925
  import { randomUUID as randomUUID4 } from "node:crypto";
24699
24926
 
24700
- // packages/workit-core/src/core/role-models.ts
24701
- var MODEL_ROLES = [
24702
- "decider",
24703
- "implementer",
24704
- "verifier",
24705
- "reviewer",
24706
- "explore",
24707
- "babysit"
24708
- ];
24709
- var MODEL_TIERS = ["mundane", "standard", "hard"];
24710
- var HOST_KEYS = new Set([
24711
- "claude_code",
24712
- "opencode",
24713
- "codex",
24714
- "codex_cli",
24715
- "codex_desktop",
24716
- "cursor",
24717
- "pi",
24718
- "default"
24719
- ]);
24720
- var BUILT_IN_CLAUDE_CODE = {
24721
- decider: { model: "fable", effort: "high" },
24722
- "implementer.hard": { model: "opus" },
24723
- "implementer.standard": { model: "sonnet" },
24724
- "implementer.mundane": { model: "haiku" },
24725
- verifier: { model: "sonnet" },
24726
- reviewer: { model: "opus" },
24727
- explore: { model: "haiku" },
24728
- babysit: { model: "haiku" }
24729
- };
24730
- var isObject7 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
24731
- var name = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
24732
- var leaf = (value) => {
24733
- const text = name(value);
24734
- if (text)
24735
- return { model: text, effort: null };
24736
- if (!isObject7(value))
24737
- return null;
24738
- const model = name(value.model);
24739
- return model ? { model, effort: name(value.effort) } : null;
24740
- };
24741
- var isFlat = (value) => typeof value === "string" || isObject7(value) && Object.hasOwn(value, "model");
24742
- var forHost = (value, host) => {
24743
- if (isFlat(value))
24744
- return leaf(value);
24745
- if (!isObject7(value))
24746
- return null;
24747
- const family = host ? hostFamily(host) : null;
24748
- for (const key of [family, host, "default"])
24749
- if (key && Object.hasOwn(value, key)) {
24750
- const found = leaf(value[key]);
24751
- if (found)
24752
- return found;
24753
- }
24754
- return null;
24755
- };
24756
- var rolesOf = (models) => isObject7(models) && isObject7(models.roles) ? models.roles : null;
24757
- var resolveRoleModel = (cwd, selector, host, dir) => {
24758
- const { role, tier } = selector;
24759
- for (const source of modelSources(cwd, dir)) {
24760
- const where = source.global ? "the global default" : `workspace ${source.name}`;
24761
- const roles = rolesOf(source.models);
24762
- const configured = roles && Object.hasOwn(roles, role) ? roles[role] : undefined;
24763
- const fromRoles = role === "implementer" ? tier && isObject7(configured) && Object.hasOwn(configured, tier) ? forHost(configured[tier], host) : null : forHost(configured, host);
24764
- if (fromRoles)
24765
- return { ...fromRoles, source: `models.roles in ${where}` };
24766
- if (role === "implementer" && tier && isObject7(source.tierModels)) {
24767
- const fromTiers = Object.hasOwn(source.tierModels, tier) ? forHost(source.tierModels[tier], host) : null;
24768
- if (fromTiers)
24769
- return { model: fromTiers.model, effort: null, source: `fanout.tierModels in ${where}` };
24770
- }
24771
- }
24772
- if (host && hostFamily(host) === "claude_code") {
24773
- const builtIn = BUILT_IN_CLAUDE_CODE[tier ? `${role}.${tier}` : role];
24774
- if (builtIn)
24775
- return { model: builtIn.model, effort: builtIn.effort ?? null, source: "built-in" };
24776
- }
24777
- return null;
24778
- };
24779
- var uniformImplementerModel = (cwd, host, dir) => {
24780
- const tiers = MODEL_TIERS.map((tier) => resolveRoleModel(cwd, { role: "implementer", tier }, host, dir));
24781
- const [first] = tiers;
24782
- return first && tiers.every((t) => t?.model === first.model && t.effort === first.effort) ? first : null;
24783
- };
24784
- var ROLE_SELECTORS = MODEL_ROLES.flatMap((role) => role === "implementer" ? MODEL_TIERS.map((tier) => ({ role, tier })) : [{ role }]);
24785
-
24786
24927
  // packages/workit-pi/src/worker-protocol.ts
24787
24928
  var MAX_WORKER_LINE_BYTES = 64 * 1024;
24788
24929
  var MAX_WORKER_STDERR_BYTES = 64 * 1024;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-pi",
3
- "version": "8.27.0",
3
+ "version": "8.28.1",
4
4
  "description": "Workit native extension for Pi — tools, method skills, and session continuity",
5
5
  "keywords": [
6
6
  "agentic-coding",