@lore-co/cli 0.2.14 → 0.2.16
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/README.md +78 -4
- package/dist/capture-scope.d.ts +12 -0
- package/dist/capture-scope.d.ts.map +1 -0
- package/dist/capture-scope.js +45 -0
- package/dist/capture-scope.js.map +1 -0
- package/dist/cli.d.ts +7 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +126 -38
- package/dist/cli.js.map +1 -1
- package/dist/command-help.d.ts +2 -1
- package/dist/command-help.d.ts.map +1 -1
- package/dist/command-help.js +4 -1
- package/dist/command-help.js.map +1 -1
- package/dist/connect-project.d.ts +15 -0
- package/dist/connect-project.d.ts.map +1 -0
- package/dist/connect-project.js +87 -0
- package/dist/connect-project.js.map +1 -0
- package/dist/connections.d.ts +3 -1
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +6 -1
- package/dist/connections.js.map +1 -1
- package/dist/devin-cli.d.ts.map +1 -1
- package/dist/devin-cli.js +14 -6
- package/dist/devin-cli.js.map +1 -1
- package/dist/devin.d.ts.map +1 -1
- package/dist/devin.js +5 -2
- package/dist/devin.js.map +1 -1
- package/dist/generated-assets.d.ts +5 -4
- package/dist/generated-assets.d.ts.map +1 -1
- package/dist/generated-assets.js +5 -4
- package/dist/generated-assets.js.map +1 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +5 -5
- package/dist/host.js.map +1 -1
- package/dist/reliability-store.d.ts +5 -0
- package/dist/reliability-store.d.ts.map +1 -1
- package/dist/reliability-store.js +9 -1
- package/dist/reliability-store.js.map +1 -1
- package/dist/remember.d.ts.map +1 -1
- package/dist/remember.js +8 -1
- package/dist/remember.js.map +1 -1
- package/dist/retrieval-task.d.ts +20 -0
- package/dist/retrieval-task.d.ts.map +1 -0
- package/dist/retrieval-task.js +78 -0
- package/dist/retrieval-task.js.map +1 -0
- package/dist/runtime-redaction.d.ts +2 -0
- package/dist/runtime-redaction.d.ts.map +1 -0
- package/dist/runtime-redaction.js +69 -0
- package/dist/runtime-redaction.js.map +1 -0
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +129 -89
- package/dist/runtime.js.map +1 -1
- package/dist/self-host.d.ts +2 -1
- package/dist/self-host.d.ts.map +1 -1
- package/dist/self-host.js +4 -3
- package/dist/self-host.js.map +1 -1
- package/dist/signed-snapshot.d.ts.map +1 -1
- package/dist/signed-snapshot.js +2 -0
- package/dist/signed-snapshot.js.map +1 -1
- package/dist/skill-command.d.ts +20 -0
- package/dist/skill-command.d.ts.map +1 -0
- package/dist/skill-command.js +215 -0
- package/dist/skill-command.js.map +1 -0
- package/dist/skill-guidance.d.ts +2 -0
- package/dist/skill-guidance.d.ts.map +1 -0
- package/dist/skill-guidance.js +7 -0
- package/dist/skill-guidance.js.map +1 -0
- package/dist/skills.d.ts +16 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +126 -0
- package/dist/skills.js.map +1 -0
- package/dist/update.js +3 -3
- package/package.json +7 -3
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,8 @@ import { reportCommand, runTelemetryCommand, telemetryEnabled, trackedCommand, T
|
|
|
4
4
|
import { secureWindowsDirectory, windowsPermissionsArePrivate } from "./windows-permissions.js";
|
|
5
5
|
import { COMMAND_GUIDES, ROOT_HELP, helpTopic } from "./command-help.js";
|
|
6
6
|
import { runShareCommand } from "./share.js";
|
|
7
|
+
import { resolveConnectProject, validateConnectProjectOptions } from "./connect-project.js";
|
|
8
|
+
import { captureDirectories } from "./capture-scope.js";
|
|
7
9
|
import { prepareConnection, persistConnection, listConnections } from "./connections.js";
|
|
8
10
|
import { connectionReferences, resolveLocalConnection } from "./directory-policy.js";
|
|
9
11
|
import { withDirectoryLock } from "./reliability-store.js";
|
|
@@ -23,7 +25,9 @@ import { runHook, } from "./runtime.js";
|
|
|
23
25
|
import { readInvocationHealthWriteInput, runInvocationHealthWrite, } from "./invocation-health-writer.js";
|
|
24
26
|
import { runAskCommand } from "./ask.js";
|
|
25
27
|
import { runRememberCommand } from "./remember.js";
|
|
28
|
+
import { installLoreSkill, removeLoreSkill } from "./skills.js";
|
|
26
29
|
import { runApproachCommand } from "./approach.js";
|
|
30
|
+
import { runSkillCommand } from "./skill-command.js";
|
|
27
31
|
import { runGuardCommand } from "./guard.js";
|
|
28
32
|
import { runContinueCommand, runResumeCommand } from "./handoff.js";
|
|
29
33
|
import { disableRecovery, prepareAutomaticRecovery, prepareRecoveryInstallation, runRecoveryCommand, runRecoveryHook, runWrappedAgent } from "./recovery.js";
|
|
@@ -97,6 +101,11 @@ Usage:
|
|
|
97
101
|
|
|
98
102
|
Options:
|
|
99
103
|
--name <name> Name this account/workspace connection (e.g. work)
|
|
104
|
+
--current-project Confirm and record the current Git project
|
|
105
|
+
--choose-folder Open a folder picker on this machine
|
|
106
|
+
--repository <repo> Verify the selected folder matches this GitHub repository
|
|
107
|
+
--folder <path> Record only in this folder and subfolders (repeatable)
|
|
108
|
+
--all-projects Record in all projects allowed by your workspace
|
|
100
109
|
--url <url> Lore API base URL (default: https://api.uselore.co)
|
|
101
110
|
--dashboard-url <url> Lore dashboard URL (default: https://uselore.co for hosted Lore)
|
|
102
111
|
--login Approve access securely in the Lore dashboard
|
|
@@ -109,8 +118,12 @@ Options:
|
|
|
109
118
|
--json Print machine-readable output
|
|
110
119
|
--help Show this command's help
|
|
111
120
|
|
|
121
|
+
New connections stay paused until you choose a project, a folder, or --all-projects.
|
|
122
|
+
Reconnecting without a capture option keeps your saved folder rules.
|
|
123
|
+
Folder choices control capture; learning scope controls where knowledge applies.
|
|
124
|
+
|
|
112
125
|
Examples:
|
|
113
|
-
lore connect --login --agent claude
|
|
126
|
+
lore connect --login --agent claude --folder .
|
|
114
127
|
lore connect --login --agent cowork
|
|
115
128
|
lore connect --token "$LORE_WORKSPACE_TOKEN" --agent claude
|
|
116
129
|
lore connect --url http://localhost:3004 --token dev-token --agent codex
|
|
@@ -1418,10 +1431,15 @@ async function installRuntime(paths) {
|
|
|
1418
1431
|
rm(paths.runtimeSignedSnapshot, { force: true }),
|
|
1419
1432
|
rm(paths.runtimeCanonicalJson, { force: true }),
|
|
1420
1433
|
rm(resolve(dirname(paths.runtime), "guard-evaluation.js"), { force: true }),
|
|
1434
|
+
rm(resolve(dirname(paths.runtime), "capture-conflict.js"), { force: true }),
|
|
1421
1435
|
rm(resolve(dirname(paths.runtime), "image-bytes.js"), { force: true }),
|
|
1422
1436
|
rm(resolve(dirname(paths.runtime), "image-capture.js"), { force: true }),
|
|
1423
1437
|
rm(resolve(dirname(paths.runtime), "retained-context.js"), { force: true }),
|
|
1438
|
+
rm(resolve(dirname(paths.runtime), "retrieval-task.js"), { force: true }),
|
|
1439
|
+
rm(resolve(dirname(paths.runtime), "runtime-redaction.js"), { force: true }),
|
|
1440
|
+
rm(resolve(dirname(paths.runtime), "user-message.js"), { force: true }),
|
|
1424
1441
|
rm(resolve(dirname(paths.runtime), "approach-guidance.js"), { force: true }),
|
|
1442
|
+
rm(resolve(dirname(paths.runtime), "skill-guidance.js"), { force: true }),
|
|
1425
1443
|
rm(paths.runtimeContextFallback, { force: true }),
|
|
1426
1444
|
rm(paths.runtimeInvocationHealthWriter, { force: true }),
|
|
1427
1445
|
rm(paths.runtimeVersion, { force: true }),
|
|
@@ -1449,12 +1467,17 @@ async function installRuntime(paths) {
|
|
|
1449
1467
|
}
|
|
1450
1468
|
const runtimeVersion = `export const RUNTIME_VERSION = ${JSON.stringify(LORE_VERSION)};\n`;
|
|
1451
1469
|
const runtimeFiles = {
|
|
1452
|
-
"lore-hook.mjs": runtime.replaceAll("@lore-co/core/guard-evaluation", "./guard-evaluation.js"),
|
|
1470
|
+
"lore-hook.mjs": runtime.replaceAll("@lore-co/core/guard-evaluation", "./guard-evaluation.js").replaceAll("@lore-co/core/capture-conflict", "./capture-conflict.js"),
|
|
1453
1471
|
"guard-evaluation.js": guardEvaluation,
|
|
1472
|
+
"capture-conflict.js": await readFile(fileURLToPath(import.meta.resolve("@lore-co/core/capture-conflict")), "utf8"),
|
|
1454
1473
|
"image-bytes.js": imageBytes,
|
|
1455
1474
|
"image-capture.js": imageCapture,
|
|
1456
1475
|
"retained-context.js": await readFile(resolve(sourceDirectory, "retained-context.js"), "utf8"),
|
|
1476
|
+
"retrieval-task.js": (await readFile(resolve(sourceDirectory, "retrieval-task.js"), "utf8")).replaceAll("@lore-co/core/user-message", "./user-message.js"),
|
|
1477
|
+
"runtime-redaction.js": await readFile(resolve(sourceDirectory, "runtime-redaction.js"), "utf8"),
|
|
1478
|
+
"user-message.js": await readFile(fileURLToPath(import.meta.resolve("@lore-co/core/user-message")), "utf8"),
|
|
1457
1479
|
"approach-guidance.js": await readFile(resolve(sourceDirectory, "approach-guidance.js"), "utf8"),
|
|
1480
|
+
"skill-guidance.js": await readFile(resolve(sourceDirectory, "skill-guidance.js"), "utf8"),
|
|
1458
1481
|
"repository.js": repository,
|
|
1459
1482
|
"repository-address.js": await readFile(resolve(dirname(fileURLToPath(import.meta.resolve("@lore-co/core/repository-location"))), "repository-address.js"), "utf8"),
|
|
1460
1483
|
"directory-policy.js": (await readFile(fileURLToPath(import.meta.resolve("@lore-co/core/local-scope")), "utf8")).replaceAll("./repository-location.js", "./repository.js"),
|
|
@@ -1478,10 +1501,15 @@ async function installRuntime(paths) {
|
|
|
1478
1501
|
};
|
|
1479
1502
|
await Promise.all([
|
|
1480
1503
|
atomicWrite(resolve(dirname(paths.runtime), "guard-evaluation.js"), guardEvaluation, 0o600),
|
|
1504
|
+
atomicWrite(resolve(dirname(paths.runtime), "capture-conflict.js"), runtimeFiles["capture-conflict.js"], 0o600),
|
|
1481
1505
|
atomicWrite(resolve(dirname(paths.runtime), "image-bytes.js"), imageBytes, 0o600),
|
|
1482
1506
|
atomicWrite(resolve(dirname(paths.runtime), "image-capture.js"), imageCapture, 0o600),
|
|
1483
1507
|
atomicWrite(resolve(dirname(paths.runtime), "retained-context.js"), runtimeFiles["retained-context.js"], 0o600),
|
|
1508
|
+
atomicWrite(resolve(dirname(paths.runtime), "retrieval-task.js"), runtimeFiles["retrieval-task.js"], 0o600),
|
|
1509
|
+
atomicWrite(resolve(dirname(paths.runtime), "runtime-redaction.js"), runtimeFiles["runtime-redaction.js"], 0o600),
|
|
1510
|
+
atomicWrite(resolve(dirname(paths.runtime), "user-message.js"), runtimeFiles["user-message.js"], 0o600),
|
|
1484
1511
|
atomicWrite(resolve(dirname(paths.runtime), "approach-guidance.js"), runtimeFiles["approach-guidance.js"], 0o600),
|
|
1512
|
+
atomicWrite(resolve(dirname(paths.runtime), "skill-guidance.js"), runtimeFiles["skill-guidance.js"], 0o600),
|
|
1485
1513
|
atomicWrite(paths.runtimeRepository, repository, 0o600),
|
|
1486
1514
|
atomicWrite(resolve(dirname(paths.runtime), "repository-address.js"), runtimeFiles["repository-address.js"], 0o600),
|
|
1487
1515
|
atomicWrite(resolve(dirname(paths.runtime), "directory-policy.js"), runtimeFiles["directory-policy.js"], 0o600),
|
|
@@ -1555,7 +1583,21 @@ function parseConnectArguments(args) {
|
|
|
1555
1583
|
parsed.recovery = false;
|
|
1556
1584
|
continue;
|
|
1557
1585
|
}
|
|
1558
|
-
if (argument
|
|
1586
|
+
if (argument === "--current-project") {
|
|
1587
|
+
parsed.currentProject = true;
|
|
1588
|
+
continue;
|
|
1589
|
+
}
|
|
1590
|
+
if (argument === "--choose-folder") {
|
|
1591
|
+
parsed.chooseFolder = true;
|
|
1592
|
+
continue;
|
|
1593
|
+
}
|
|
1594
|
+
if (argument === "--all-projects") {
|
|
1595
|
+
parsed.allProjects = true;
|
|
1596
|
+
continue;
|
|
1597
|
+
}
|
|
1598
|
+
if (argument !== "--repository" &&
|
|
1599
|
+
argument !== "--folder" &&
|
|
1600
|
+
argument !== "--name" &&
|
|
1559
1601
|
argument !== "--url" &&
|
|
1560
1602
|
argument !== "--dashboard-url" &&
|
|
1561
1603
|
argument !== "--token" &&
|
|
@@ -1566,7 +1608,13 @@ function parseConnectArguments(args) {
|
|
|
1566
1608
|
}
|
|
1567
1609
|
const [value, valueIndex] = valueAfter(args, index, argument);
|
|
1568
1610
|
index = valueIndex;
|
|
1569
|
-
if (argument === "--
|
|
1611
|
+
if (argument === "--repository") {
|
|
1612
|
+
parsed.repository = value;
|
|
1613
|
+
}
|
|
1614
|
+
else if (argument === "--folder") {
|
|
1615
|
+
(parsed.folders ??= []).push(value);
|
|
1616
|
+
}
|
|
1617
|
+
else if (argument === "--name") {
|
|
1570
1618
|
parsed.connectionName = value;
|
|
1571
1619
|
}
|
|
1572
1620
|
else if (argument === "--fallback") {
|
|
@@ -1597,6 +1645,7 @@ function parseConnectArguments(args) {
|
|
|
1597
1645
|
throw new Error("--agent must be claude, codex, copilot, copilot-cli, copilot-vscode, cowork, cursor, opencode, polytoken, or t3code");
|
|
1598
1646
|
}
|
|
1599
1647
|
}
|
|
1648
|
+
validateConnectProjectOptions(parsed);
|
|
1600
1649
|
if (parsed.login && parsed.token !== undefined) {
|
|
1601
1650
|
throw new Error("--login and --token cannot be used together");
|
|
1602
1651
|
}
|
|
@@ -1661,7 +1710,8 @@ async function connectWithCredentialLocked(options, identity) {
|
|
|
1661
1710
|
? existing.apiUrl === apiUrl && existing.token === token ? identity
|
|
1662
1711
|
: await authenticatedIdentity(existing.apiUrl, existing.token, timeoutMs).catch(() => undefined)
|
|
1663
1712
|
: undefined;
|
|
1664
|
-
const
|
|
1713
|
+
const directories = await captureDirectories(options, paths.home, options.cwd);
|
|
1714
|
+
const connection = await prepareConnection(paths, identity, { apiUrl, token, ...(directories === undefined ? {} : { directories }), ...(options.connectionName ? { connectionName: options.connectionName } : {}) }, previousIdentity);
|
|
1665
1715
|
await secureWindowsDirectory(paths.loreDirectory);
|
|
1666
1716
|
const recoveryEnv = options.home === undefined ? process.env : { ...process.env, ZDOTDIR: paths.home };
|
|
1667
1717
|
let recoveryWarning;
|
|
@@ -1708,6 +1758,31 @@ async function connectWithCredentialLocked(options, identity) {
|
|
|
1708
1758
|
cursorMcpDocuments.set(mcpPath, { document: mcp, merged: mergeLoreCursorMcp(mcp.exists ? mcp.value : {}, paths) });
|
|
1709
1759
|
}
|
|
1710
1760
|
}
|
|
1761
|
+
const agentConfigPaths = {};
|
|
1762
|
+
for (const agent of agents) {
|
|
1763
|
+
agentConfigPaths[agent] = installations
|
|
1764
|
+
.filter((installation) => installation.agent === agent)
|
|
1765
|
+
.map((installation) => installation.configPath);
|
|
1766
|
+
}
|
|
1767
|
+
const config = {
|
|
1768
|
+
...connection.fields,
|
|
1769
|
+
version: 2,
|
|
1770
|
+
apiUrl,
|
|
1771
|
+
...(dashboardUrl === undefined ? {} : { dashboardUrl }),
|
|
1772
|
+
workspaceId: identity.workspaceId,
|
|
1773
|
+
token: token.trim(),
|
|
1774
|
+
agents,
|
|
1775
|
+
agentConfigPaths,
|
|
1776
|
+
connectedAt: connection.profiles.find(value => value.connectionId === connection.fields.connectionId)?.connectedAt ?? now.toISOString(),
|
|
1777
|
+
timeoutMs,
|
|
1778
|
+
};
|
|
1779
|
+
const reliabilityStore = new ReliabilityStore(identity.workspaceId, {
|
|
1780
|
+
home: paths.home,
|
|
1781
|
+
connectionId: config.connectionId,
|
|
1782
|
+
});
|
|
1783
|
+
await reliabilityStore.initialize();
|
|
1784
|
+
// Folder restrictions must be durable before any new hook can run.
|
|
1785
|
+
await persistConnection(paths, config, connection.profiles);
|
|
1711
1786
|
if (installations.some((installation) => targetFor(installation.agent).runtimeRequired)) {
|
|
1712
1787
|
await installRuntime(paths);
|
|
1713
1788
|
}
|
|
@@ -1735,30 +1810,6 @@ async function connectWithCredentialLocked(options, identity) {
|
|
|
1735
1810
|
backups.push(result.backup);
|
|
1736
1811
|
}
|
|
1737
1812
|
}
|
|
1738
|
-
const agentConfigPaths = {};
|
|
1739
|
-
for (const agent of agents) {
|
|
1740
|
-
agentConfigPaths[agent] = installations
|
|
1741
|
-
.filter((installation) => installation.agent === agent)
|
|
1742
|
-
.map((installation) => installation.configPath);
|
|
1743
|
-
}
|
|
1744
|
-
const config = {
|
|
1745
|
-
...connection.fields,
|
|
1746
|
-
version: 2,
|
|
1747
|
-
apiUrl,
|
|
1748
|
-
...(dashboardUrl === undefined ? {} : { dashboardUrl }),
|
|
1749
|
-
workspaceId: identity.workspaceId,
|
|
1750
|
-
token: token.trim(),
|
|
1751
|
-
agents,
|
|
1752
|
-
agentConfigPaths,
|
|
1753
|
-
connectedAt: connection.profiles.find(value => value.connectionId === connection.fields.connectionId)?.connectedAt ?? now.toISOString(),
|
|
1754
|
-
timeoutMs,
|
|
1755
|
-
};
|
|
1756
|
-
const reliabilityStore = new ReliabilityStore(identity.workspaceId, {
|
|
1757
|
-
home: paths.home,
|
|
1758
|
-
connectionId: config.connectionId,
|
|
1759
|
-
});
|
|
1760
|
-
await reliabilityStore.initialize();
|
|
1761
|
-
await persistConnection(paths, config, connection.profiles);
|
|
1762
1813
|
if (existing && !existing.connectionId && existing.apiUrl === apiUrl && existing.token === token) {
|
|
1763
1814
|
await new ReliabilityStore(identity.workspaceId, { home: paths.home }).transferPendingTo(reliabilityStore);
|
|
1764
1815
|
await reliabilityStore.migrateLegacyQueue(paths.queue);
|
|
@@ -1778,7 +1829,10 @@ async function connectWithCredentialLocked(options, identity) {
|
|
|
1778
1829
|
.catch((error) => [`Host recovery setup: ${error.message}`]) : [];
|
|
1779
1830
|
if (options.recovery === false)
|
|
1780
1831
|
await disableRecovery(paths.home);
|
|
1832
|
+
const skills = await installLoreSkill(paths, installations);
|
|
1781
1833
|
return {
|
|
1834
|
+
capture: { folders: config.directories?.include ?? null, excludedFolders: config.directories?.exclude ?? [] },
|
|
1835
|
+
skillFiles: skills.files,
|
|
1782
1836
|
connected: true,
|
|
1783
1837
|
apiUrl: config.apiUrl,
|
|
1784
1838
|
identity,
|
|
@@ -1786,7 +1840,7 @@ async function connectWithCredentialLocked(options, identity) {
|
|
|
1786
1840
|
config: paths.config,
|
|
1787
1841
|
changedHookFiles,
|
|
1788
1842
|
backups,
|
|
1789
|
-
warnings: [...(connection.needsFolders ? [`Lore is off for ${config.connectionName} until you
|
|
1843
|
+
warnings: [...skills.warnings, ...(connection.needsFolders ? [`Lore is off for ${config.connectionName} until you choose where to record. Reconnect with --folder <path> or --all-projects, or run lore config open --connection ${config.connectionName}.`] : []), ...requestedExpansion.warnings, ...hostRecoveryWarnings, ...(agents.includes("codex")
|
|
1790
1844
|
? ["Codex requires hook approval. Open /hooks in Codex and review any new or changed Lore hooks, then start a fresh session. Run lore doctor to verify approval and the first invocation."]
|
|
1791
1845
|
: [])],
|
|
1792
1846
|
...(recoveryNotice ? { recoveryNotice } : {}),
|
|
@@ -1940,6 +1994,7 @@ async function connectCommand(args) {
|
|
|
1940
1994
|
if (parsed.login && hasProvidedToken) {
|
|
1941
1995
|
throw new Error("--login cannot be combined with an explicit or environment workspace token. Unset it or use the token directly.");
|
|
1942
1996
|
}
|
|
1997
|
+
const capture = await resolveConnectProject(parsed, paths.home);
|
|
1943
1998
|
const authorization = parsed.login
|
|
1944
1999
|
? await requestDeviceAuthorization({
|
|
1945
2000
|
apiUrl,
|
|
@@ -1953,6 +2008,7 @@ async function connectCommand(args) {
|
|
|
1953
2008
|
throw new Error("Workspace token is required. Use --login, --token <token>, LORE_WORKSPACE_TOKEN, or LORE_TOKEN.");
|
|
1954
2009
|
}
|
|
1955
2010
|
const result = await connectWithCredential({
|
|
2011
|
+
...capture,
|
|
1956
2012
|
...(parsed.connectionName === undefined ? {} : { connectionName: parsed.connectionName }),
|
|
1957
2013
|
...(parsed.fallback === undefined ? {} : { fallback: parsed.fallback }),
|
|
1958
2014
|
recovery: parsed.recovery ?? true,
|
|
@@ -1964,7 +2020,9 @@ async function connectCommand(args) {
|
|
|
1964
2020
|
});
|
|
1965
2021
|
if (authorization)
|
|
1966
2022
|
await acknowledgeDeviceAuthorization(apiUrl, authorization);
|
|
1967
|
-
|
|
2023
|
+
const captureSummary = result.capture.folders === null ? "all projects allowed by the workspace"
|
|
2024
|
+
: result.capture.folders.length ? result.capture.folders.join(", ") : "paused — choose folders with --folder <path>";
|
|
2025
|
+
writeResult(result, parsed.json, `access authorized; integrations installed: ${result.agents.join(", ")}\napi_url: ${result.apiUrl}\nconfig: ${result.config}\ncapture: ${captureSummary}${result.capture.excludedFolders.length ? `; excluded: ${result.capture.excludedFolders.join(", ")}` : ""}\nRestart your agent and complete a turn, then run lore doctor to verify recording.\n${result.skillFiles.length ? 'Choose lore in your agent’s skills to find knowledge or remember this session.\n' : ''}${result.recoveryNotice ? `${result.recoveryNotice}\n` : ""}${result.warnings.map((warning) => `warning: ${warning}\n`).join("")}`);
|
|
1968
2026
|
}
|
|
1969
2027
|
async function queueCount(paths) {
|
|
1970
2028
|
try {
|
|
@@ -2049,10 +2107,15 @@ async function inspectRuntimeInstallation(required, paths) {
|
|
|
2049
2107
|
const runtimeFiles = {
|
|
2050
2108
|
"lore-hook.mjs": paths.runtime,
|
|
2051
2109
|
"guard-evaluation.js": resolve(dirname(paths.runtime), "guard-evaluation.js"),
|
|
2110
|
+
"capture-conflict.js": resolve(dirname(paths.runtime), "capture-conflict.js"),
|
|
2052
2111
|
"image-bytes.js": resolve(dirname(paths.runtime), "image-bytes.js"),
|
|
2053
2112
|
"image-capture.js": resolve(dirname(paths.runtime), "image-capture.js"),
|
|
2054
2113
|
"retained-context.js": resolve(dirname(paths.runtime), "retained-context.js"),
|
|
2114
|
+
"retrieval-task.js": resolve(dirname(paths.runtime), "retrieval-task.js"),
|
|
2115
|
+
"runtime-redaction.js": resolve(dirname(paths.runtime), "runtime-redaction.js"),
|
|
2116
|
+
"user-message.js": resolve(dirname(paths.runtime), "user-message.js"),
|
|
2055
2117
|
"approach-guidance.js": resolve(dirname(paths.runtime), "approach-guidance.js"),
|
|
2118
|
+
"skill-guidance.js": resolve(dirname(paths.runtime), "skill-guidance.js"),
|
|
2056
2119
|
"repository.js": paths.runtimeRepository,
|
|
2057
2120
|
"repository-address.js": resolve(dirname(paths.runtime), "repository-address.js"),
|
|
2058
2121
|
"directory-policy.js": resolve(dirname(paths.runtime), "directory-policy.js"),
|
|
@@ -2238,8 +2301,18 @@ async function getAgentStatus(agent, config, paths, runtime) {
|
|
|
2238
2301
|
invocationError: invocation.error,
|
|
2239
2302
|
};
|
|
2240
2303
|
}
|
|
2304
|
+
// Diagnostics remain available when the current folder has capture disabled.
|
|
2305
|
+
// A fallback reads only the last saved connection; it never enables capture.
|
|
2306
|
+
async function diagnosticConfig(paths, cwd) {
|
|
2307
|
+
try {
|
|
2308
|
+
return await readConnectorConfig(paths, cwd);
|
|
2309
|
+
}
|
|
2310
|
+
catch {
|
|
2311
|
+
return readConnectorConfig(paths);
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2241
2314
|
async function statusData(paths, cwd) {
|
|
2242
|
-
const config = await
|
|
2315
|
+
const config = await diagnosticConfig(paths, cwd);
|
|
2243
2316
|
let configMode = null;
|
|
2244
2317
|
try {
|
|
2245
2318
|
const metadata = await stat(paths.config);
|
|
@@ -2256,6 +2329,7 @@ async function statusData(paths, cwd) {
|
|
|
2256
2329
|
Promise.all(CONFIGURED_AGENT_NAMES.map(async (agent) => getAgentStatus(agent, config, paths, runtime))),
|
|
2257
2330
|
]);
|
|
2258
2331
|
return {
|
|
2332
|
+
folderAccess: await checkDirectory(cwd, paths.home, config ?? undefined),
|
|
2259
2333
|
schemaVersion: "lore-cli-status-v1",
|
|
2260
2334
|
integrationContractVersion: RELIABILITY_INTEGRATION_CONTRACT_VERSION,
|
|
2261
2335
|
connected: config !== null,
|
|
@@ -2290,7 +2364,7 @@ async function statusCommand(args) {
|
|
|
2290
2364
|
const metricRate = (value) => value === null || value === undefined
|
|
2291
2365
|
? "-"
|
|
2292
2366
|
: `${(value * 100).toFixed(1)}%`;
|
|
2293
|
-
writeResult(data, parsed.json, `connected: ${data.connected ? "yes" : "no"}\napi_url: ${data.apiUrl ?? "-"}\nconfig_mode: ${data.configMode ?? "-"}\nruntime: ${data.runtimeRequired ? (data.runtimeInstalled ? `installed (${data.runtimeVersion})` : data.runtimeVersion === null ? "missing" : `stale (${data.runtimeVersion})`) : "not required"}\ndurable_outbox: ${data.reliability?.outbox.total ?? 0} ready=${data.reliability?.outbox.ready ?? 0} auth_blocked=${data.reliability?.outbox.authBlocked ?? 0} dead=${data.reliability?.outbox.dead ?? 0}\noldest_capture: ${data.reliability?.outbox.oldestEnqueuedAt ?? "-"}\ncontext_snapshots: ${data.reliability?.cache.context ?? 0}\noldest_context_snapshot: ${data.reliability?.cache.oldestContextWrittenAt ?? "-"}\npolicy_snapshots: ${data.reliability?.cache.policy ?? 0}\nlocal_context_fallback_rate: ${metricRate(data.reliability?.operational.retrieval.fallbackRate)}\nlocal_guard_coverage: ${metricRate(data.reliability?.operational.guard.coverageRate)}\nlocal_guard_failures: ${data.reliability?.operational.guard.failures ?? 0}\nlocal_retrieval_failures: ${data.reliability?.operational.retrieval.failed ?? 0}\n${data.reliabilityError === null ? "" : `reliability_error: ${data.reliabilityError}\n`}${agentLines}\n${externalSurfaceLines}\n`);
|
|
2367
|
+
writeResult(data, parsed.json, `connected: ${data.connected ? "yes" : "no"}\ncurrent_folder: ${data.folderAccess.allowed ? "allowed" : "off"} (${data.folderAccess.reason})\napi_url: ${data.apiUrl ?? "-"}\nconfig_mode: ${data.configMode ?? "-"}\nruntime: ${data.runtimeRequired ? (data.runtimeInstalled ? `installed (${data.runtimeVersion})` : data.runtimeVersion === null ? "missing" : `stale (${data.runtimeVersion})`) : "not required"}\ndurable_outbox: ${data.reliability?.outbox.total ?? 0} ready=${data.reliability?.outbox.ready ?? 0} auth_blocked=${data.reliability?.outbox.authBlocked ?? 0} dead=${data.reliability?.outbox.dead ?? 0}\noldest_capture: ${data.reliability?.outbox.oldestEnqueuedAt ?? "-"}\ncontext_snapshots: ${data.reliability?.cache.context ?? 0}\noldest_context_snapshot: ${data.reliability?.cache.oldestContextWrittenAt ?? "-"}\npolicy_snapshots: ${data.reliability?.cache.policy ?? 0}\nlocal_context_fallback_rate: ${metricRate(data.reliability?.operational.retrieval.fallbackRate)}\nlocal_guard_coverage: ${metricRate(data.reliability?.operational.guard.coverageRate)}\nlocal_guard_failures: ${data.reliability?.operational.guard.failures ?? 0}\nlocal_retrieval_failures: ${data.reliability?.operational.retrieval.failed ?? 0}\n${data.reliabilityError === null ? "" : `reliability_error: ${data.reliabilityError}\n`}${agentLines}\n${externalSurfaceLines}\n`);
|
|
2294
2368
|
}
|
|
2295
2369
|
async function disconnectCommand(args) {
|
|
2296
2370
|
const parsed = parseOutputArguments(args, DISCONNECT_HELP, "disconnect");
|
|
@@ -2336,6 +2410,7 @@ export async function disconnectInstallation(paths = getLorePaths(), preservePen
|
|
|
2336
2410
|
backups.push(result.backup);
|
|
2337
2411
|
}
|
|
2338
2412
|
}
|
|
2413
|
+
await removeLoreSkill(paths, installations);
|
|
2339
2414
|
await Promise.all([
|
|
2340
2415
|
rm(paths.config, { force: true }),
|
|
2341
2416
|
rm(resolve(paths.loreDirectory, "connections"), { recursive: true, force: true }),
|
|
@@ -2348,9 +2423,14 @@ export async function disconnectInstallation(paths = getLorePaths(), preservePen
|
|
|
2348
2423
|
rm(paths.runtimeCanonicalJson, { force: true }),
|
|
2349
2424
|
rm(paths.runtimeContextFallback, { force: true }),
|
|
2350
2425
|
rm(resolve(dirname(paths.runtime), "guard-evaluation.js"), { force: true }),
|
|
2426
|
+
rm(resolve(dirname(paths.runtime), "capture-conflict.js"), { force: true }),
|
|
2351
2427
|
rm(resolve(dirname(paths.runtime), "image-bytes.js"), { force: true }),
|
|
2352
2428
|
rm(resolve(dirname(paths.runtime), "image-capture.js"), { force: true }),
|
|
2353
2429
|
rm(resolve(dirname(paths.runtime), "retained-context.js"), { force: true }),
|
|
2430
|
+
rm(resolve(dirname(paths.runtime), "retrieval-task.js"), { force: true }),
|
|
2431
|
+
rm(resolve(dirname(paths.runtime), "runtime-redaction.js"), { force: true }),
|
|
2432
|
+
rm(resolve(dirname(paths.runtime), "user-message.js"), { force: true }),
|
|
2433
|
+
rm(resolve(dirname(paths.runtime), "skill-guidance.js"), { force: true }),
|
|
2354
2434
|
rm(paths.runtimeInvocationHealthWriter, { force: true }),
|
|
2355
2435
|
rm(paths.runtimeVersion, { force: true }),
|
|
2356
2436
|
rm(paths.runtimePackage, { force: true }),
|
|
@@ -2475,9 +2555,9 @@ async function doctorCommand(args) {
|
|
|
2475
2555
|
return;
|
|
2476
2556
|
}
|
|
2477
2557
|
const paths = getLorePaths();
|
|
2478
|
-
const config = await
|
|
2558
|
+
const config = await diagnosticConfig(paths, process.cwd());
|
|
2479
2559
|
const status = await statusData(paths, process.cwd());
|
|
2480
|
-
const checks = [];
|
|
2560
|
+
const checks = [{ name: "capture-folder", status: status.folderAccess.allowed ? "ok" : "warning", detail: status.folderAccess.allowed ? status.folderAccess.reason : `Recording is off here: ${status.folderAccess.reason}. Run lore scope check <folder> to verify a selected folder.` }];
|
|
2481
2561
|
checks.push({
|
|
2482
2562
|
name: "platform",
|
|
2483
2563
|
status: platform() === "darwin" || platform() === "linux" || isWindows() ? "ok" : "error",
|
|
@@ -2587,7 +2667,8 @@ async function doctorCommand(args) {
|
|
|
2587
2667
|
status.reliability.outbox.inFlight > 0
|
|
2588
2668
|
? "warning"
|
|
2589
2669
|
: "ok",
|
|
2590
|
-
detail: `${status.reliability.outbox.total} total; ${status.reliability.outbox.ready} ready, ${status.reliability.outbox.authBlocked} authentication-blocked, ${status.reliability.outbox.dead} dead-letter
|
|
2670
|
+
detail: `${status.reliability.outbox.total} total; ${status.reliability.outbox.ready} ready, ${status.reliability.outbox.authBlocked} authentication-blocked, ${status.reliability.outbox.dead} dead-letter` +
|
|
2671
|
+
(status.reliability.outbox.oldestFailure ? `; oldest failure (${status.reliability.outbox.oldestFailure.attempts} attempts): ${status.reliability.outbox.oldestFailure.message}` : ""),
|
|
2591
2672
|
});
|
|
2592
2673
|
checks.push({
|
|
2593
2674
|
name: "verified-snapshot-cache",
|
|
@@ -2664,6 +2745,9 @@ async function printCommandHelp(path) {
|
|
|
2664
2745
|
case "approach":
|
|
2665
2746
|
await runApproachCommand(args, null);
|
|
2666
2747
|
return;
|
|
2748
|
+
case "skill":
|
|
2749
|
+
await runSkillCommand(args, null);
|
|
2750
|
+
return;
|
|
2667
2751
|
case "guard":
|
|
2668
2752
|
await runGuardCommand(args, null);
|
|
2669
2753
|
return;
|
|
@@ -2752,8 +2836,8 @@ async function executeCli(args = process.argv.slice(2)) {
|
|
|
2752
2836
|
return;
|
|
2753
2837
|
}
|
|
2754
2838
|
const commandArgs = args.slice(1);
|
|
2755
|
-
if (["ask", "remember", "share", "resume", "continue", "approach"].includes(command)) {
|
|
2756
|
-
const decision = await checkDirectory(process.cwd(), getLorePaths(
|
|
2839
|
+
if (["ask", "remember", "share", "resume", "continue", "approach", "skill"].includes(command) && !(command === "skill" && commandArgs[0] === "discover")) {
|
|
2840
|
+
const decision = await checkDirectory(process.cwd(), getLorePaths(["approach", "skill"].includes(command) ? process.env.LORE_HOME : undefined).home);
|
|
2757
2841
|
if (!decision.allowed)
|
|
2758
2842
|
throw new Error(`Lore is off in this folder. ${decision.reason}`);
|
|
2759
2843
|
}
|
|
@@ -2798,6 +2882,9 @@ async function executeCli(args = process.argv.slice(2)) {
|
|
|
2798
2882
|
case "approach":
|
|
2799
2883
|
await runApproachCommand(commandArgs, await readConnectorConfig(getLorePaths(process.env.LORE_HOME), process.cwd()));
|
|
2800
2884
|
return;
|
|
2885
|
+
case "skill":
|
|
2886
|
+
await runSkillCommand(commandArgs, commandArgs[0] === "discover" ? null : await readConnectorConfig(getLorePaths(process.env.LORE_HOME), process.cwd()));
|
|
2887
|
+
return;
|
|
2801
2888
|
case "guard":
|
|
2802
2889
|
await runGuardCommand(commandArgs, await readConnectorConfig(getLorePaths(), process.cwd()));
|
|
2803
2890
|
return;
|
|
@@ -2863,6 +2950,7 @@ async function executeCli(args = process.argv.slice(2)) {
|
|
|
2863
2950
|
});
|
|
2864
2951
|
return {
|
|
2865
2952
|
agents: connected.agents,
|
|
2953
|
+
warnings: connected.warnings,
|
|
2866
2954
|
verified: await verifyConnectedInstallation(),
|
|
2867
2955
|
};
|
|
2868
2956
|
},
|