loki-mode 11.83.0 → 11.85.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.
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/grill.sh +8 -3
- package/autonomy/lib/check_author.py +191 -2
- package/autonomy/lib/claude-flags.sh +10 -4
- package/autonomy/prd-checklist.sh +162 -0
- package/autonomy/run.sh +4 -4
- package/autonomy/spec.sh +87 -0
- package/dashboard/__init__.py +1 -1
- package/docs/CLI-REFERENCE.md +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/loki-ts/data/child-env.json +1 -0
- package/loki-ts/dist/loki.js +1504 -1399
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/ask-tools-server.js +144 -19
- package/packages/control-plane/dist/server.js +12538 -11751
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-DpWNKWhs.js → AdminPage-CIcHJlAf.js} +1 -1
- package/web-app/dist/assets/{Avatar-BjGfE5Z2.js → Avatar-fSbN52Rn.js} +1 -1
- package/web-app/dist/assets/{Badge-BZzQgc5L.js → Badge-DV7TUsqR.js} +1 -1
- package/web-app/dist/assets/{Button-B4UFBoKo.js → Button-D16_Kixn.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-HrjOxPcp.js → CockpitPage-DqH6iBNN.js} +1 -1
- package/web-app/dist/assets/{ComparePage-rDB52mbC.js → ComparePage-D85PNjoa.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-BnGTHBD5.js → ErrorBoundary-BeT6cXcK.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-EWQ-AUvr.js → EvidenceReceiptPanel-CUH-iYKA.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-COCm9cnv.js → GitHubIssuesPanel-DWdiqzHn.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-ZYNmFQAR.js → GitHubPRsPanel-DsH26a3x.js} +1 -1
- package/web-app/dist/assets/{HomePage-CJXtxNhl.js → HomePage-z85a_1rL.js} +2 -2
- package/web-app/dist/assets/{LoginPage-CXG5HrnH.js → LoginPage-BVQ8VH-D.js} +1 -1
- package/web-app/dist/assets/{MagicPage-D_1k-qFR.js → MagicPage-Dn5JMfWl.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-Bh2OOgQW.js → MetricsPage-CbCGiyKZ.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-DYtJqd7q.js → NotFoundPage-j4jjSqMS.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-C0_lqGnI.js → ProjectPage-aOWsJjD9.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-C3ZDOF-i.js → ProjectsPage-B84wO9Cr.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-DNLBBiFb.js → SettingsPage-B2Ug7j2E.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-jxMrHvDJ.js → ShowcasePage-c-8uJKMj.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-C2ZPx8uP.js → SystemSettingsPage-tTg7Sn1W.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-CmSWv2WS.js → TeamsPage-CU9pwIFY.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-Cqcz3jC1.js → TemplatesPage-DSILwTWB.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-Cfy74R8E.js → TerminalOutput-BVBNxLfo.js} +1 -1
- package/web-app/dist/assets/{activity-DvB2Cewz.js → activity-D3dTgTol.js} +1 -1
- package/web-app/dist/assets/{bell-DFPKTgoZ.js → bell-nKHHBPy4.js} +1 -1
- package/web-app/dist/assets/{bot-Bf5xNfiN.js → bot-Cs1wMX37.js} +1 -1
- package/web-app/dist/assets/{check-BdqIiGKJ.js → check-DvE_DNJj.js} +1 -1
- package/web-app/dist/assets/{chevron-left-Q2RMHGjD.js → chevron-left-BafCbx7C.js} +1 -1
- package/web-app/dist/assets/{circle-alert-CSsLxjNX.js → circle-alert-CoVthuJC.js} +1 -1
- package/web-app/dist/assets/{clock-SUq-A-Pc.js → clock-D8xfN8aa.js} +1 -1
- package/web-app/dist/assets/{cloud-1Qu-bH4o.js → cloud-BL8Y_LIc.js} +1 -1
- package/web-app/dist/assets/{code-xml-B8tVFMMA.js → code-xml-BJC8Ey7k.js} +1 -1
- package/web-app/dist/assets/{database-BqqcDq2C.js → database-CGA6URCb.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-D3Q2UCG0.js → dollar-sign-CHRvwgyL.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-CRIBFOW5.js → file-code-corner-CQ3uLV2P.js} +1 -1
- package/web-app/dist/assets/{file-plus-Bv-fZPBA.js → file-plus-Sqdt7xLt.js} +1 -1
- package/web-app/dist/assets/{globe-C4B7SAB9.js → globe-BiXQ5FOy.js} +1 -1
- package/web-app/dist/assets/{hammer-y0Ikysax.js → hammer-CUwt2o7I.js} +1 -1
- package/web-app/dist/assets/{index-dNruR__0.js → index-BYowAgK4.js} +3 -3
- package/web-app/dist/assets/{layers-EgGWmhHw.js → layers-DXq9VSwW.js} +1 -1
- package/web-app/dist/assets/{loader-circle-Bt5dIF0I.js → loader-circle-Ctn_xD3_.js} +1 -1
- package/web-app/dist/assets/{lock-BGuyekU7.js → lock-nl9XJEyi.js} +1 -1
- package/web-app/dist/assets/{package-BkYbeAX3.js → package-98dbH_LD.js} +1 -1
- package/web-app/dist/assets/{plus-BzcgCbLN.js → plus-D7hmCkNi.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-Dm5Jp3fH.js → refresh-cw-DX3wUkhV.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-BwCcLLQd.js → rotate-ccw-XMHg_YgZ.js} +1 -1
- package/web-app/dist/assets/{scroll-text-ZdYcnYoT.js → scroll-text-CRfkubNP.js} +1 -1
- package/web-app/dist/assets/{server-BKLLV1vh.js → server-WcGRWROZ.js} +1 -1
- package/web-app/dist/assets/{shield-alert-BmdJ5RUP.js → shield-alert-Der-fmpH.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-BkgThloL.js → thumbs-up-CrBhUBj9.js} +1 -1
- package/web-app/dist/assets/{trash-2-CEGx8Si2.js → trash-2-Pi47j24F.js} +1 -1
- package/web-app/dist/assets/{trending-down-bDEP2c-J.js → trending-down-B6sr1-IB.js} +1 -1
- package/web-app/dist/assets/{trending-up-BTZtHq6z.js → trending-up-99SzxDxr.js} +1 -1
- package/web-app/dist/assets/{upload-CU4BNteU.js → upload-BREQadWi.js} +1 -1
- package/web-app/dist/assets/{usePolling-uzQ6JTcy.js → usePolling-CGDeEkDK.js} +1 -1
- package/web-app/dist/assets/{user-Bz1t2qnf.js → user-xN4ww_AA.js} +1 -1
- package/web-app/dist/index.html +1 -1
package/mcp/__init__.py
CHANGED
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.
|
|
4
|
+
"version": "11.85.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": "
|
|
163
|
+
"gitHead": "b4e18670c58839472a0cfa937bce8c74fd2ef5c9"
|
|
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
|
|
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();
|
|
@@ -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 =
|
|
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
|
|
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(
|
|
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(
|
|
41068
|
-
runDir = realpathSync2(
|
|
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 !==
|
|
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(
|
|
41319
|
-
const runDir = realpathSync3(
|
|
41320
|
-
if (runDir !==
|
|
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(
|
|
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);
|