loki-mode 11.84.0 → 11.86.0

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.
Files changed (76) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/grill.sh +8 -3
  4. package/autonomy/lib/check_author.py +191 -2
  5. package/autonomy/lib/claude-flags.sh +10 -4
  6. package/autonomy/prd-checklist.sh +162 -0
  7. package/autonomy/run.sh +4 -4
  8. package/autonomy/spec.sh +87 -0
  9. package/dashboard/__init__.py +1 -1
  10. package/docs/CLI-REFERENCE.md +1 -1
  11. package/docs/INSTALLATION.md +1 -1
  12. package/loki-ts/data/child-env.json +1 -0
  13. package/loki-ts/dist/loki.js +1504 -1388
  14. package/mcp/__init__.py +1 -1
  15. package/package.json +2 -2
  16. package/packages/control-plane/dist/ask-tools-server.js +145 -20
  17. package/packages/control-plane/dist/server.js +17153 -15919
  18. package/packages/control-plane/src/server/integrity.ts +22 -4
  19. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  20. package/web-app/dist/assets/{AdminPage-CXLv81So.js → AdminPage-CXRvxMO_.js} +1 -1
  21. package/web-app/dist/assets/{Avatar-Dkquf4s9.js → Avatar-Bk9K6OnI.js} +1 -1
  22. package/web-app/dist/assets/{Badge-BPlO-Wiw.js → Badge-CDePJKKg.js} +1 -1
  23. package/web-app/dist/assets/{Button-BO-JvVyh.js → Button-DMzR-FT4.js} +1 -1
  24. package/web-app/dist/assets/{CockpitPage-DCuXv1OL.js → CockpitPage-Cfh42owC.js} +1 -1
  25. package/web-app/dist/assets/{ComparePage-zVSpiuEp.js → ComparePage-Oft34xnR.js} +1 -1
  26. package/web-app/dist/assets/{ErrorBoundary-Ci4wqP2a.js → ErrorBoundary-DlXBbQDo.js} +1 -1
  27. package/web-app/dist/assets/{EvidenceReceiptPanel-CEBhqO60.js → EvidenceReceiptPanel-C0LKef5y.js} +1 -1
  28. package/web-app/dist/assets/{GitHubIssuesPanel-UR6xkpVn.js → GitHubIssuesPanel-CyqsExTP.js} +1 -1
  29. package/web-app/dist/assets/{GitHubPRsPanel-BspmPZ6K.js → GitHubPRsPanel-BC7ExtnE.js} +1 -1
  30. package/web-app/dist/assets/{HomePage-DchBOs8o.js → HomePage-CmYisyjJ.js} +2 -2
  31. package/web-app/dist/assets/{LoginPage-BldlfUlE.js → LoginPage-Cunt-wYH.js} +1 -1
  32. package/web-app/dist/assets/{MagicPage-CVnhnrh6.js → MagicPage-lvGAbDEv.js} +1 -1
  33. package/web-app/dist/assets/{MetricsPage-I_Ye6IjS.js → MetricsPage-DPvRVQU7.js} +1 -1
  34. package/web-app/dist/assets/{NotFoundPage-CCDI4T7K.js → NotFoundPage-DDGT6teS.js} +1 -1
  35. package/web-app/dist/assets/{ProjectPage-DuyA8Qz7.js → ProjectPage-Bf6fTvjD.js} +3 -3
  36. package/web-app/dist/assets/{ProjectsPage-BF2JSz1r.js → ProjectsPage-DL2gvN_V.js} +1 -1
  37. package/web-app/dist/assets/{SettingsPage-B_5LeF6K.js → SettingsPage-DV-X99VB.js} +1 -1
  38. package/web-app/dist/assets/{ShowcasePage-lE5cIgbU.js → ShowcasePage-B3eyQWQJ.js} +1 -1
  39. package/web-app/dist/assets/{SystemSettingsPage-v2DJyogx.js → SystemSettingsPage-DIUT7aYr.js} +1 -1
  40. package/web-app/dist/assets/{TeamsPage-eXMmORI1.js → TeamsPage-BJpeWszJ.js} +1 -1
  41. package/web-app/dist/assets/{TemplatesPage-CkHulSrT.js → TemplatesPage-Cqo6IMUO.js} +1 -1
  42. package/web-app/dist/assets/{TerminalOutput-DJwjzb2Y.js → TerminalOutput-B7NsTAYn.js} +1 -1
  43. package/web-app/dist/assets/{activity-CAtLpfNe.js → activity-Bpy5MefF.js} +1 -1
  44. package/web-app/dist/assets/{bell-CL-IIbCA.js → bell-BwXuuFea.js} +1 -1
  45. package/web-app/dist/assets/{bot-fT57nwl5.js → bot-Cij-5kEZ.js} +1 -1
  46. package/web-app/dist/assets/{check-hWhzzw0m.js → check-YWtXU6Zo.js} +1 -1
  47. package/web-app/dist/assets/{chevron-left-BLHNp2u-.js → chevron-left-MxOda7Z9.js} +1 -1
  48. package/web-app/dist/assets/{circle-alert-BiPOqU-L.js → circle-alert-w9za8rUy.js} +1 -1
  49. package/web-app/dist/assets/{clock-Cqcvrmkj.js → clock-Bp3AU4Nx.js} +1 -1
  50. package/web-app/dist/assets/{cloud-DUijmoIE.js → cloud-BFuxyAYb.js} +1 -1
  51. package/web-app/dist/assets/{code-xml-CHpO2Oxh.js → code-xml-B3jPToQW.js} +1 -1
  52. package/web-app/dist/assets/{database-DggasNHP.js → database-D85Q7ufb.js} +1 -1
  53. package/web-app/dist/assets/{dollar-sign-CXxG_8K6.js → dollar-sign-C0hEZ3BL.js} +1 -1
  54. package/web-app/dist/assets/{file-code-corner-xfVvREvW.js → file-code-corner-DeMr0sSL.js} +1 -1
  55. package/web-app/dist/assets/{file-plus-CxboFD8a.js → file-plus-BtBan_QU.js} +1 -1
  56. package/web-app/dist/assets/{globe-uQo7wmFo.js → globe-DLHflM3B.js} +1 -1
  57. package/web-app/dist/assets/{hammer-DpmqB3Jc.js → hammer-BLoZn0OU.js} +1 -1
  58. package/web-app/dist/assets/{index-DSecwFL3.js → index-q6GEQ6U8.js} +3 -3
  59. package/web-app/dist/assets/{layers-DAhv2mJy.js → layers-Cac5ZHvD.js} +1 -1
  60. package/web-app/dist/assets/{loader-circle-DlfD5ae4.js → loader-circle-C7UMl5I-.js} +1 -1
  61. package/web-app/dist/assets/{lock-Bp9L8WT9.js → lock-BC3v0P7Z.js} +1 -1
  62. package/web-app/dist/assets/{package-YoE2sWU8.js → package-CFsriyik.js} +1 -1
  63. package/web-app/dist/assets/{plus-DdcvjiWR.js → plus-CSi88k0-.js} +1 -1
  64. package/web-app/dist/assets/{refresh-cw-DlhQH4A4.js → refresh-cw-BBBOc6SY.js} +1 -1
  65. package/web-app/dist/assets/{rotate-ccw-BMskUWd9.js → rotate-ccw-D_dHBG_h.js} +1 -1
  66. package/web-app/dist/assets/{scroll-text-wq9VgYsu.js → scroll-text-z4CcL8tu.js} +1 -1
  67. package/web-app/dist/assets/{server-BvBfqjcL.js → server-Dsl-ujtv.js} +1 -1
  68. package/web-app/dist/assets/{shield-alert-Ctv17L9P.js → shield-alert-CXuzPi9-.js} +1 -1
  69. package/web-app/dist/assets/{thumbs-up-Bppr-IMM.js → thumbs-up-CNkCfkkx.js} +1 -1
  70. package/web-app/dist/assets/{trash-2-C__rfpz0.js → trash-2-rCtL1tv8.js} +1 -1
  71. package/web-app/dist/assets/{trending-down-CA0bokwG.js → trending-down-0wlGANoa.js} +1 -1
  72. package/web-app/dist/assets/{trending-up-BFh3twff.js → trending-up-C9iCihGe.js} +1 -1
  73. package/web-app/dist/assets/{upload-DABSXWW6.js → upload-DdKjc6-R.js} +1 -1
  74. package/web-app/dist/assets/{usePolling-DcTxi6kF.js → usePolling-Dyqa_HZa.js} +1 -1
  75. package/web-app/dist/assets/{user-y8K-uMqG.js → user-D1NeTikp.js} +1 -1
  76. package/web-app/dist/index.html +1 -1
package/mcp/__init__.py CHANGED
@@ -75,4 +75,4 @@ try:
75
75
  except ImportError:
76
76
  __all__ = ['mcp']
77
77
 
78
- __version__ = '11.84.0'
78
+ __version__ = '11.86.0'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "loki-mode",
3
3
  "mcpName": "io.github.asklokesh/loki-mode",
4
- "version": "11.84.0",
4
+ "version": "11.86.0",
5
5
  "description": "An autonomous software factory that knows what it is supposed to deliver, and proves it did.",
6
6
  "keywords": [
7
7
  "agent",
@@ -160,5 +160,5 @@
160
160
  "dependencies": {
161
161
  "@resvg/resvg-wasm": "^2.6.2"
162
162
  },
163
- "gitHead": "78a2000ae0b427da4211b2400af32826ed8876b6"
163
+ "gitHead": "715fcbd93223f7908bffd8e50d4cf114d85041cc"
164
164
  }
@@ -38908,7 +38908,7 @@ var askEvents = sqliteTable("ask_events", {
38908
38908
 
38909
38909
  // src/ask/tools.ts
38910
38910
  import { realpathSync as realpathSync3 } from "fs";
38911
- import { join as join5, sep as sep3 } from "path";
38911
+ import { join as join6, sep as sep3 } from "path";
38912
38912
 
38913
38913
  // node_modules/hono/dist/request/constants.js
38914
38914
  var GET_MATCH_RESULT = Symbol();
@@ -40771,7 +40771,7 @@ function hardenCredentialEnv(env, fresh = false) {
40771
40771
 
40772
40772
  // ../../loki-ts/src/util/safe_git.ts
40773
40773
  import { execFileSync, spawnSync } from "child_process";
40774
- var SAFE_GIT_CONFIG = ["-c", "core.fsmonitor=", "-c", "core.hooksPath=/dev/null", "-c", "core.sshCommand=", "-c", "protocol.ext.allow=never", "-c", "credential.helper="];
40774
+ var SAFE_GIT_CONFIG = ["-c", "core.fsmonitor=", "-c", "core.hooksPath=/dev/null", "-c", "core.sshCommand=", "-c", "protocol.ext.allow=never", "-c", "credential.helper=", "-c", "core.trustctime=true", "-c", "core.checkStat=default"];
40775
40775
  var CREDENTIAL_CONFIG = ["-c", "core.fsmonitor=", "-c", "core.hooksPath=/dev/null", "-c", "protocol.ext.allow=never"];
40776
40776
  var DRIVER_CONFIG = ["-c", "diff.external=", "-c", "commit.gpgSign=false", "-c", "core.attributesFile=/dev/null"];
40777
40777
  var ATTRS_OFF = "core.attributesFile=/dev/null";
@@ -40935,6 +40935,139 @@ var SKIP_DIRS = new Set([
40935
40935
  ".next"
40936
40936
  ]);
40937
40937
 
40938
+ // ../../loki-ts/src/runner/budget.ts
40939
+ import { existsSync as existsSync2, mkdirSync, readdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
40940
+ import { dirname as dirname2, join as join4, resolve as resolve2 } from "path";
40941
+ import { fileURLToPath as fileURLToPath2 } from "url";
40942
+
40943
+ // ../../loki-ts/src/util/atomic.ts
40944
+ var STALE_TMP_MS = 60 * 60 * 1000;
40945
+ var _appendChains = new Map;
40946
+
40947
+ // ../../loki-ts/src/util/paths.ts
40948
+ import { resolve, dirname } from "path";
40949
+ import { fileURLToPath } from "url";
40950
+ import { existsSync } from "fs";
40951
+ var HERE = dirname(fileURLToPath(import.meta.url));
40952
+ function findRepoRoot() {
40953
+ let dir = HERE;
40954
+ for (let i = 0;i < 6; i++) {
40955
+ if (existsSync(resolve(dir, "VERSION")) && existsSync(resolve(dir, "autonomy/run.sh"))) {
40956
+ return dir;
40957
+ }
40958
+ const parent = dirname(dir);
40959
+ if (parent === dir)
40960
+ break;
40961
+ dir = parent;
40962
+ }
40963
+ return resolve(HERE, "..", "..", "..");
40964
+ }
40965
+ var REPO_ROOT = findRepoRoot();
40966
+
40967
+ // ../../loki-ts/src/util/cost_breakdown.ts
40968
+ var CACHE_TTL_5M_MS = 5 * 60000;
40969
+ var CACHE_TTL_1H_MS = 60 * 60000;
40970
+
40971
+ // ../../loki-ts/src/providers/price_table.ts
40972
+ var PRICE_TABLE = Object.freeze({
40973
+ "gpt-5.3-codex": { input: 1.75, output: 14, cachedInput: 0.175 },
40974
+ "gpt-5-codex": { input: 1.25, output: 10, cachedInput: 0.125 },
40975
+ "gpt-5-mini": { input: 0.25, output: 2, cachedInput: 0.025 },
40976
+ "gpt-5-nano": { input: 0.05, output: 0.4, cachedInput: 0.005 },
40977
+ "gpt-4.1-mini": { input: 0.4, output: 1.6, cachedInput: 0.1 },
40978
+ "gpt-4.1-nano": { input: 0.1, output: 0.4, cachedInput: 0.025 },
40979
+ "gpt-4o-mini": { input: 0.15, output: 0.6, cachedInput: 0.075 },
40980
+ "gpt-5": { input: 1.25, output: 10, cachedInput: 0.125 },
40981
+ "gpt-4.1": { input: 2, output: 8, cachedInput: 0.5 },
40982
+ "gpt-4o": { input: 2.5, output: 10, cachedInput: 1.25 },
40983
+ "o4-mini": { input: 1.1, output: 4.4, cachedInput: 0.275 },
40984
+ o3: { input: 2, output: 8, cachedInput: 0.5 },
40985
+ "claude-opus": { input: 4, output: 20, cachedInput: 0.2 },
40986
+ "claude-sonnet": { input: 2, output: 10, cachedInput: 0.1 },
40987
+ "claude-haiku": { input: 0.1, output: 0.5, cachedInput: 0.01 },
40988
+ "gemini-2.5-pro": { input: 1.25, output: 10 },
40989
+ gemini: { input: 1.25, output: 10 },
40990
+ deepseek: { input: 0.28, output: 0.42 },
40991
+ minimax: { input: 0.3, output: 1.2 }
40992
+ });
40993
+
40994
+ // ../../loki-ts/src/providers/provider_cost.ts
40995
+ var ESTIMATED_PROVIDERS = new Set(["codex", "cline", "aider", "opencode"]);
40996
+ // ../../loki-ts/src/runner/budget.ts
40997
+ var _FALLBACK_PRICING = {
40998
+ fable: { input: 10, output: 50, cache_read: 0.25, cache_write: 12.5, cache_write_5m: 12.5, cache_write_1h: 20 },
40999
+ opus: { input: 4, output: 20, cache_read: 0.2, cache_write: 5, cache_write_5m: 5, cache_write_1h: 8 },
41000
+ sonnet: { input: 2, output: 10, cache_read: 0.1, cache_write: 2.5, cache_write_5m: 2.5, cache_write_1h: 4 },
41001
+ haiku: {
41002
+ input: 0.1,
41003
+ output: 0.5,
41004
+ cache_read: 0.01,
41005
+ cache_write: 0.125,
41006
+ cache_write_5m: 0.125,
41007
+ cache_write_1h: 0.2,
41008
+ over_100k: { input: 0.5, output: 2.5, cache_read: 0.05, cache_write: 0.625, cache_write_5m: 0.625, cache_write_1h: 1 }
41009
+ },
41010
+ "claude-haiku-4-5": { input: 1, output: 5, cache_read: 0.1, cache_write: 1.25, cache_write_5m: 1.25, cache_write_1h: 2 },
41011
+ "claude-haiku-5-5": {
41012
+ input: 0.1,
41013
+ output: 0.5,
41014
+ cache_read: 0.01,
41015
+ cache_write: 0.125,
41016
+ over_100k: { input: 0.5, output: 2.5, cache_read: 0.05, cache_write: 0.625 }
41017
+ },
41018
+ "gpt-5.3-codex": { input: 1.75, output: 14, cache_read: 0.175, cache_write: 2.1875 }
41019
+ };
41020
+ function _loadPricing() {
41021
+ try {
41022
+ const moduleDir = dirname2(fileURLToPath2(import.meta.url));
41023
+ const jsonPath = resolve2(moduleDir, "..", "..", "data", "model-pricing.json");
41024
+ if (!existsSync2(jsonPath))
41025
+ return _FALLBACK_PRICING;
41026
+ const raw2 = JSON.parse(readFileSync2(jsonPath, "utf8"));
41027
+ const pricing = raw2["pricing"];
41028
+ if (!pricing || typeof pricing !== "object")
41029
+ return _FALLBACK_PRICING;
41030
+ const out2 = {};
41031
+ for (const [key, value] of Object.entries(pricing)) {
41032
+ if (value !== null && typeof value === "object" && typeof value.input === "number" && typeof value.output === "number") {
41033
+ const _e = value;
41034
+ out2[key] = {
41035
+ input: _e.input,
41036
+ output: _e.output,
41037
+ ...typeof _e.cache_read === "number" ? { cache_read: _e.cache_read } : {},
41038
+ ...typeof _e.cache_write === "number" ? { cache_write: _e.cache_write } : {},
41039
+ ...typeof _e.cache_write_5m === "number" ? { cache_write_5m: _e.cache_write_5m } : {},
41040
+ ...typeof _e.cache_write_1h === "number" ? { cache_write_1h: _e.cache_write_1h } : {},
41041
+ ..._e.over_100k && typeof _e.over_100k.input === "number" && typeof _e.over_100k.output === "number" ? { over_100k: _e.over_100k } : {}
41042
+ };
41043
+ }
41044
+ }
41045
+ for (const k of Object.keys(_FALLBACK_PRICING)) {
41046
+ if (!(k in out2))
41047
+ return _FALLBACK_PRICING;
41048
+ }
41049
+ return out2;
41050
+ } catch {
41051
+ return _FALLBACK_PRICING;
41052
+ }
41053
+ }
41054
+ var PRICING = Object.freeze(_loadPricing());
41055
+ var warnedCorruptBudget = new Set;
41056
+
41057
+ // ../../loki-ts/src/util/child_ledger.ts
41058
+ function costUsdOf(events2) {
41059
+ let usd = 0, saw = false;
41060
+ for (const e of events2) {
41061
+ if (e.type !== "cost")
41062
+ continue;
41063
+ saw = true;
41064
+ if (typeof e.data["usd"] !== "number")
41065
+ return null;
41066
+ usd += e.data["usd"];
41067
+ }
41068
+ return saw ? usd : null;
41069
+ }
41070
+
40938
41071
  // ../../loki-ts/src/engine10/events.ts
40939
41072
  function fold(events2) {
40940
41073
  const f = {
@@ -40944,9 +41077,6 @@ function fold(events2) {
40944
41077
  cost: { usd: null, inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheCreationTokens: 0 },
40945
41078
  lastSeq: -1
40946
41079
  };
40947
- let usd = 0;
40948
- let sawCost = false;
40949
- let unmeasured = false;
40950
41080
  for (const e of events2) {
40951
41081
  f.lastSeq = Math.max(f.lastSeq, e.seq);
40952
41082
  if (e.stage !== null)
@@ -40963,11 +41093,6 @@ function fold(events2) {
40963
41093
  else if (e.type === "tamper.detected")
40964
41094
  f.run.tampered = true;
40965
41095
  else if (e.type === "cost") {
40966
- sawCost = true;
40967
- if (typeof e.data.usd === "number")
40968
- usd += e.data.usd;
40969
- else
40970
- unmeasured = true;
40971
41096
  if (typeof e.data.input_tokens === "number")
40972
41097
  f.cost.inputTokens += e.data.input_tokens;
40973
41098
  if (typeof e.data.output_tokens === "number")
@@ -40978,7 +41103,7 @@ function fold(events2) {
40978
41103
  f.cost.cacheCreationTokens += e.data.cache_creation_tokens;
40979
41104
  }
40980
41105
  }
40981
- f.cost.usd = sawCost && !unmeasured ? usd : null;
41106
+ f.cost.usd = costUsdOf(events2);
40982
41107
  return f;
40983
41108
  }
40984
41109
  var conflictReasonOf = (events2) => {
@@ -41009,7 +41134,7 @@ function blockedQuestion(evs, verdict) {
41009
41134
 
41010
41135
  // src/server/diffstat.ts
41011
41136
  import { closeSync as closeSync2, fstatSync as fstatSync2, openSync as openSync2, readSync as readSync2, realpathSync as realpathSync2 } from "fs";
41012
- import { join as join4, sep as sep2 } from "path";
41137
+ import { join as join5, sep as sep2 } from "path";
41013
41138
  var ID2 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
41014
41139
  var SHA = /^[0-9a-f]{40,64}$/;
41015
41140
  var MAX_RECEIPT_BYTES = 1024 * 1024;
@@ -41033,7 +41158,7 @@ function parseNumstat(out2) {
41033
41158
  function readReceipt(runDir) {
41034
41159
  let fd;
41035
41160
  try {
41036
- fd = openSync2(join4(runDir, "receipt.json"), "r");
41161
+ fd = openSync2(join5(runDir, "receipt.json"), "r");
41037
41162
  } catch {
41038
41163
  return null;
41039
41164
  }
@@ -41064,12 +41189,12 @@ function diffStatFor(db, source, run) {
41064
41189
  let repoReal, runsRoot, runDir;
41065
41190
  try {
41066
41191
  repoReal = realpathSync2(repo.p);
41067
- runsRoot = realpathSync2(join4(repoReal, ".loki", "runs"));
41068
- runDir = realpathSync2(join4(runsRoot, run));
41192
+ runsRoot = realpathSync2(join5(repoReal, ".loki", "runs"));
41193
+ runDir = realpathSync2(join5(runsRoot, run));
41069
41194
  } catch {
41070
41195
  return null;
41071
41196
  }
41072
- if (runDir !== join4(runsRoot, run) || !runDir.startsWith(runsRoot + sep2))
41197
+ if (runDir !== join5(runsRoot, run) || !runDir.startsWith(runsRoot + sep2))
41073
41198
  return null;
41074
41199
  const r = readReceipt(runDir);
41075
41200
  const base = typeof r?.base_sha === "string" ? r.base_sha : "", head = typeof r?.head_sha === "string" ? r.head_sha : "";
@@ -41315,11 +41440,11 @@ function runArtifact(db, a) {
41315
41440
  if (!repo)
41316
41441
  return err("artifact not available");
41317
41442
  try {
41318
- const runsRoot = realpathSync3(join5(repo.p, ".loki", "runs"));
41319
- const runDir = realpathSync3(join5(runsRoot, a.run_id));
41320
- if (runDir !== join5(runsRoot, a.run_id))
41443
+ const runsRoot = realpathSync3(join6(repo.p, ".loki", "runs"));
41444
+ const runDir = realpathSync3(join6(runsRoot, a.run_id));
41445
+ if (runDir !== join6(runsRoot, a.run_id))
41321
41446
  return err("artifact not found");
41322
- const file2 = realpathSync3(join5(runDir, a.name));
41447
+ const file2 = realpathSync3(join6(runDir, a.name));
41323
41448
  if (!file2.startsWith(runDir + sep3))
41324
41449
  return err("artifact not found");
41325
41450
  const r = readCapped(file2);