@cavelang/cli 0.34.0 → 0.35.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/README.md +2 -2
- package/dist/internal/automate/main.d.ts.map +1 -1
- package/dist/internal/automate/main.js +2 -0
- package/dist/internal/automate/main.js.map +1 -1
- package/dist/internal/connect/declared.d.ts +225 -0
- package/dist/internal/connect/declared.d.ts.map +1 -0
- package/dist/internal/connect/declared.js +521 -0
- package/dist/internal/connect/declared.js.map +1 -0
- package/dist/internal/connect/index.d.ts +4 -2
- package/dist/internal/connect/index.d.ts.map +1 -1
- package/dist/internal/connect/index.js +3 -1
- package/dist/internal/connect/index.js.map +1 -1
- package/dist/internal/connect/main.d.ts.map +1 -1
- package/dist/internal/connect/main.js +352 -10
- package/dist/internal/connect/main.js.map +1 -1
- package/dist/internal/connect/run.d.ts +47 -1
- package/dist/internal/connect/run.d.ts.map +1 -1
- package/dist/internal/connect/run.js +81 -33
- package/dist/internal/connect/run.js.map +1 -1
- package/dist/internal/connect/source.d.ts +33 -2
- package/dist/internal/connect/source.d.ts.map +1 -1
- package/dist/internal/connect/source.js +168 -8
- package/dist/internal/connect/source.js.map +1 -1
- package/dist/internal/connect/template.d.ts +18 -0
- package/dist/internal/connect/template.d.ts.map +1 -1
- package/dist/internal/connect/template.js +28 -0
- package/dist/internal/connect/template.js.map +1 -1
- package/dist/internal/ingest/main.d.ts.map +1 -1
- package/dist/internal/ingest/main.js +2 -1
- package/dist/internal/ingest/main.js.map +1 -1
- package/dist/internal/mcp/main.d.ts.map +1 -1
- package/dist/internal/mcp/main.js +2 -0
- package/dist/internal/mcp/main.js.map +1 -1
- package/dist/internal/rules/rule.d.ts.map +1 -1
- package/dist/internal/rules/rule.js +1 -22
- package/dist/internal/rules/rule.js.map +1 -1
- package/dist/internal/view/main.d.ts.map +1 -1
- package/dist/internal/view/main.js +2 -1
- package/dist/internal/view/main.js.map +1 -1
- package/dist/src/cli.d.ts +14 -0
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +161 -38
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands.d.ts +2 -2
- package/dist/src/commands.js +2 -2
- package/dist/src/commands.js.map +1 -1
- package/dist/src/dispatch.d.ts.map +1 -1
- package/dist/src/dispatch.js +7 -1
- package/dist/src/dispatch.js.map +1 -1
- package/dist/src/doctor.d.ts +1 -1
- package/dist/src/doctor.d.ts.map +1 -1
- package/dist/src/doctor.js +26 -1
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/package.json +19 -19
- package/src/cli.ts +187 -36
- package/src/commands.ts +2 -2
- package/src/dispatch.ts +7 -1
- package/src/doctor.ts +28 -2
- package/src/index.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cavelang/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "cave — CLI for parsing, storing, querying and exporting CAVE knowledge.",
|
|
6
6
|
"keywords": [
|
|
@@ -97,26 +97,26 @@
|
|
|
97
97
|
"@modelcontextprotocol/server": "2.0.0",
|
|
98
98
|
"@mozilla/readability": "^0.6.0",
|
|
99
99
|
"linkedom": "^0.18.13",
|
|
100
|
-
"@cavelang/canonical": "0.
|
|
101
|
-
"@cavelang/fusion": "0.
|
|
102
|
-
"@cavelang/
|
|
103
|
-
"@cavelang/
|
|
104
|
-
"@cavelang/parser": "0.
|
|
105
|
-
"@cavelang/query": "0.
|
|
106
|
-
"@cavelang/store": "0.
|
|
100
|
+
"@cavelang/canonical": "0.35.0",
|
|
101
|
+
"@cavelang/fusion": "0.35.0",
|
|
102
|
+
"@cavelang/core": "0.35.0",
|
|
103
|
+
"@cavelang/highlight": "0.35.0",
|
|
104
|
+
"@cavelang/parser": "0.35.0",
|
|
105
|
+
"@cavelang/query": "0.35.0",
|
|
106
|
+
"@cavelang/store": "0.35.0"
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
|
-
"@cavelang/act": "0.
|
|
110
|
-
"@cavelang/
|
|
111
|
-
"@cavelang/
|
|
112
|
-
"@cavelang/
|
|
113
|
-
"@cavelang/
|
|
114
|
-
"@cavelang/
|
|
115
|
-
"@cavelang/rules": "0.
|
|
116
|
-
"@cavelang/
|
|
117
|
-
"@cavelang/
|
|
118
|
-
"@cavelang/
|
|
119
|
-
"@cavelang/
|
|
109
|
+
"@cavelang/act": "0.35.0",
|
|
110
|
+
"@cavelang/automate": "0.35.0",
|
|
111
|
+
"@cavelang/eval": "0.35.0",
|
|
112
|
+
"@cavelang/connect": "0.35.0",
|
|
113
|
+
"@cavelang/ingest": "0.35.0",
|
|
114
|
+
"@cavelang/loop": "0.35.0",
|
|
115
|
+
"@cavelang/rules": "0.35.0",
|
|
116
|
+
"@cavelang/shape": "0.35.0",
|
|
117
|
+
"@cavelang/mcp": "0.35.0",
|
|
118
|
+
"@cavelang/sync": "0.35.0",
|
|
119
|
+
"@cavelang/view": "0.35.0"
|
|
120
120
|
},
|
|
121
121
|
"scripts": {
|
|
122
122
|
"build": "tsc -b && node scripts/consolidate.mjs",
|
package/src/cli.ts
CHANGED
|
@@ -41,8 +41,9 @@ import { parseArgs } from 'node:util'
|
|
|
41
41
|
import { Version } from '@cavelang/core'
|
|
42
42
|
import { parseDocument, Token } from '@cavelang/parser'
|
|
43
43
|
import { Registry, standardRegistry } from '@cavelang/canonical'
|
|
44
|
-
import {
|
|
44
|
+
import { backup as backupStore, defaultDbPath, kindOf, LocateError, openAt, restoreBackup, Sensitivity, verifyBackup } from '@cavelang/store'
|
|
45
45
|
import type { OpenIntent, Store } from '@cavelang/store'
|
|
46
|
+
import { Declared, assemble as assembleSources } from '@cavelang/connect'
|
|
46
47
|
import { defaultLimit as defaultQueryLimit, maxLimit as maxQueryLimit, page as caveQueryPage } from '@cavelang/query'
|
|
47
48
|
import {
|
|
48
49
|
check as caveCheck, defaultMinScore, defaultStaleDays, gatedIngest, judgePrompt, parseJudgeReply,
|
|
@@ -252,7 +253,7 @@ Examples:
|
|
|
252
253
|
query: `cave query — run a CAVE-Q pattern against a store
|
|
253
254
|
|
|
254
255
|
Usage:
|
|
255
|
-
cave query [--db <path>] <pattern> [WHERE <filter>] [--limit <n>] [--cursor <token>] [--json] [--all] [--aliases] [--as-of <t>] [--at <t>] [--resolve] [--no-prelude]
|
|
256
|
+
cave query [--db <path>] <pattern> [WHERE <filter>] [--limit <n>] [--cursor <token>] [--json] [--all] [--aliases] [--as-of <t>] [--at <t>] [--resolve] [--sources] [--no-prelude]
|
|
256
257
|
|
|
257
258
|
Options:
|
|
258
259
|
${dbHelp}
|
|
@@ -278,6 +279,12 @@ Options:
|
|
|
278
279
|
collapse to the row the resolution policy picks
|
|
279
280
|
(precedence class, reliability-weighted confidence, tx);
|
|
280
281
|
incompatible with --all
|
|
282
|
+
--sources overlay the store's declared sources (spec §23.4) inside a
|
|
283
|
+
rolled-back transaction — federation-lite: external data is
|
|
284
|
+
consulted at query time, nothing persists. The answer is
|
|
285
|
+
whole (no --cursor, --limit is not a page size); a text
|
|
286
|
+
store followed its local sources on open, so only URL
|
|
287
|
+
sources are loaded here
|
|
281
288
|
--no-prelude open the store without the standard verb registry
|
|
282
289
|
|
|
283
290
|
Patterns are claim triples with ?variables and optional metadata filters
|
|
@@ -297,6 +304,7 @@ Examples:
|
|
|
297
304
|
cave query --db k.db 'revenue IS' --at 2026-07
|
|
298
305
|
cave query --db k.db 'alice WORKS-AT ?org' --at 2021
|
|
299
306
|
cave query --db k.db 'service HAS owner: ?who' --resolve
|
|
307
|
+
cave query --db k.db '?who WORKS-AT acme' --sources
|
|
300
308
|
cave query --db k.db '?x ?verb ?y @production' --json`,
|
|
301
309
|
|
|
302
310
|
search: `cave search — full-text search over claims and comments (spec §13.2)
|
|
@@ -797,9 +805,45 @@ const readStdin = (): string => {
|
|
|
797
805
|
const openDb = (values: { db?: string, 'no-prelude'?: boolean }, intent: OpenIntent): Store =>
|
|
798
806
|
openAt(values.db ?? defaultDbPath(), {
|
|
799
807
|
intent,
|
|
808
|
+
// A text store follows its declared sources on open (spec §23.4).
|
|
809
|
+
assemble: assembleSources,
|
|
800
810
|
...values['no-prelude'] === true ? { registry: Registry.empty } : {}
|
|
801
811
|
})
|
|
802
812
|
|
|
813
|
+
const sourcesRollback = Symbol('cave query --sources rollback')
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Runs `body` with the store's declared sources overlaid (spec §23.4): the
|
|
817
|
+
* sources, loaded beforehand (URLs included), append inside a transaction
|
|
818
|
+
* that always rolls back, so external data is consulted at query time and
|
|
819
|
+
* nothing persists, digests included.
|
|
820
|
+
*/
|
|
821
|
+
const withSources = <T>(store: Store, discovered: Declared.Discovery, body: () => T): undefined | { value: T } => {
|
|
822
|
+
let result: undefined | { value: T }
|
|
823
|
+
try {
|
|
824
|
+
store.transaction(() => {
|
|
825
|
+
// Discovered on a snapshot: if a writer changed the declarations
|
|
826
|
+
// since, the sequence is stale and the caller rediscovers.
|
|
827
|
+
if (!Declared.sameDeclarations(discovered.baseline, Declared.declarationState(store))) {
|
|
828
|
+
throw sourcesRollback
|
|
829
|
+
}
|
|
830
|
+
for (const source of discovered.sequence) {
|
|
831
|
+
const report = Declared.run(store, source, { force: true })
|
|
832
|
+
if (report.failures.length > 0) {
|
|
833
|
+
throw new LocateError(`source/${source.declared.name}: ${report.failures.map(failure => `${failure.record}: ${failure.problems.join('; ')}`).join('; ')}`)
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
result = { value: body() }
|
|
837
|
+
throw sourcesRollback
|
|
838
|
+
})
|
|
839
|
+
} catch (error) {
|
|
840
|
+
if (error !== sourcesRollback) {
|
|
841
|
+
throw error
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
return result
|
|
845
|
+
}
|
|
846
|
+
|
|
803
847
|
const readInput = (files: readonly string[]): string =>
|
|
804
848
|
files.length === 0 || (files.length === 1 && files[0] === '-') ?
|
|
805
849
|
readStdin() :
|
|
@@ -929,39 +973,150 @@ export const addCommand = ingestCommand('add')
|
|
|
929
973
|
*/
|
|
930
974
|
export const importCommand = ingestCommand('import')
|
|
931
975
|
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
976
|
+
const queryOptions = {
|
|
977
|
+
db: { type: 'string' },
|
|
978
|
+
json: { type: 'boolean' },
|
|
979
|
+
all: { type: 'boolean' },
|
|
980
|
+
aliases: { type: 'boolean' },
|
|
981
|
+
'as-of': { type: 'string' },
|
|
982
|
+
at: { type: 'string' },
|
|
983
|
+
resolve: { type: 'boolean' },
|
|
984
|
+
sources: { type: 'boolean' },
|
|
985
|
+
limit: { type: 'string' },
|
|
986
|
+
cursor: { type: 'string' },
|
|
987
|
+
'no-prelude': { type: 'boolean' }
|
|
988
|
+
} as const
|
|
989
|
+
|
|
990
|
+
type QueryValues = {
|
|
991
|
+
db?: string
|
|
992
|
+
json?: boolean
|
|
993
|
+
all?: boolean
|
|
994
|
+
aliases?: boolean
|
|
995
|
+
'as-of'?: string
|
|
996
|
+
at?: string
|
|
997
|
+
resolve?: boolean
|
|
998
|
+
sources?: boolean
|
|
999
|
+
limit?: string
|
|
1000
|
+
cursor?: string
|
|
1001
|
+
'no-prelude'?: boolean
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
const parseQuery = (argv: readonly string[]): { values: QueryValues, pattern: string } | { failure: Output } => {
|
|
1005
|
+
const { values, positionals } = parseArgs({ args: [...argv], options: queryOptions, allowPositionals: true })
|
|
949
1006
|
if (positionals.length === 0) {
|
|
950
|
-
return fail('cave query: a pattern is required (spec §12.1)\n')
|
|
1007
|
+
return { failure: fail('cave query: a pattern is required (spec §12.1)\n') }
|
|
1008
|
+
}
|
|
1009
|
+
if (values.sources === true && values.cursor !== undefined) {
|
|
1010
|
+
return { failure: fail('cave query: --cursor does not apply to --sources — the overlay exists for one invocation and is answered whole\n') }
|
|
1011
|
+
}
|
|
1012
|
+
return { values, pattern: positionals.join('\n') }
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
/**
|
|
1016
|
+
* `cave query --sources` — the store with its declared sources overlaid
|
|
1017
|
+
* (spec §23.4). Asynchronous because the sources load first, URLs
|
|
1018
|
+
* included, before the overlay appends inside a transaction that rolls
|
|
1019
|
+
* back; the dispatcher routes `--sources` here. A text store followed its
|
|
1020
|
+
* local sources on open, so only what assembly could not follow — URL
|
|
1021
|
+
* sources and what they declare — is loaded. The overlay exists for this
|
|
1022
|
+
* invocation alone, so the answer is whole: pages are followed inside the
|
|
1023
|
+
* transaction and no cursor is handed out.
|
|
1024
|
+
*/
|
|
1025
|
+
export const querySourcesCommand = async (
|
|
1026
|
+
argv: readonly string[],
|
|
1027
|
+
runtime: { readonly fetchImpl?: Declared.DiscoverOptions['fetchImpl'] } = {}
|
|
1028
|
+
): Promise<Output> => {
|
|
1029
|
+
const parsed = parseQuery(argv)
|
|
1030
|
+
if ('failure' in parsed) {
|
|
1031
|
+
return parsed.failure
|
|
1032
|
+
}
|
|
1033
|
+
const { values, pattern } = parsed
|
|
1034
|
+
if (values.sources !== true) {
|
|
1035
|
+
return queryCommand(argv)
|
|
1036
|
+
}
|
|
1037
|
+
const root = values.db ?? defaultDbPath()
|
|
1038
|
+
// The overlay appends inside a transaction it rolls back: writable, but
|
|
1039
|
+
// never creating or migrating (spec §13.7).
|
|
1040
|
+
const store = openDb(values, 'scratch')
|
|
1041
|
+
try {
|
|
1042
|
+
for (let attempt = 0; attempt < Declared.overlayAttempts; attempt += 1) {
|
|
1043
|
+
const discovered = await Declared.discovery(store, root, {
|
|
1044
|
+
// The overlay applies every source it loads (force), so discovery
|
|
1045
|
+
// simulates that; a text store skips what assembly already followed.
|
|
1046
|
+
force: true,
|
|
1047
|
+
...kindOf(root) === 'text' ? { skipFollowed: true } : {},
|
|
1048
|
+
...runtime.fetchImpl === undefined ? {} : { fetchImpl: runtime.fetchImpl }
|
|
1049
|
+
})
|
|
1050
|
+
const page = withSources(store, discovered, () => wholeQuery(store, values, pattern))
|
|
1051
|
+
if (page !== undefined) {
|
|
1052
|
+
return renderQueryPage(store, values, pattern, () => page.value)
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
throw Declared.staleOverlay()
|
|
1056
|
+
} catch (error) {
|
|
1057
|
+
return fail(`${error instanceof Error ? error.message : String(error)}\n`)
|
|
1058
|
+
} finally {
|
|
1059
|
+
store.close()
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
export const queryCommand = (argv: readonly string[]): Output => {
|
|
1064
|
+
const parsed = parseQuery(argv)
|
|
1065
|
+
if ('failure' in parsed) {
|
|
1066
|
+
return parsed.failure
|
|
1067
|
+
}
|
|
1068
|
+
const { values, pattern } = parsed
|
|
1069
|
+
if (values.sources === true) {
|
|
1070
|
+
// Loading sources cannot be synchronous: the in-process entry for the
|
|
1071
|
+
// overlay is `querySourcesCommand`, which the dispatcher uses.
|
|
1072
|
+
return fail('cave query: --sources loads the declared sources first and runs asynchronously — use querySourcesCommand\n')
|
|
951
1073
|
}
|
|
952
|
-
const pattern = positionals.join('\n')
|
|
953
1074
|
const store = openDb(values, 'read')
|
|
954
1075
|
try {
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1076
|
+
return renderQueryPage(store, values, pattern, () => queryPage(store, values, pattern))
|
|
1077
|
+
} catch (error) {
|
|
1078
|
+
return fail(`${error instanceof Error ? error.message : String(error)}\n`)
|
|
1079
|
+
} finally {
|
|
1080
|
+
store.close()
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
/** Every match of the overlay: the pages are followed here, inside the transaction that holds it. */
|
|
1085
|
+
const wholeQuery = (store: Store, values: QueryValues, pattern: string): ReturnType<typeof caveQueryPage> => {
|
|
1086
|
+
const matches: ReturnType<typeof caveQueryPage>['matches'][number][] = []
|
|
1087
|
+
let first: undefined | ReturnType<typeof caveQueryPage>
|
|
1088
|
+
let cursor: undefined | string
|
|
1089
|
+
for (;;) {
|
|
1090
|
+
const page = queryPage(store, { ...values, limit: '1000', ...cursor === undefined ? {} : { cursor } }, pattern)
|
|
1091
|
+
first ??= page
|
|
1092
|
+
matches.push(...page.matches)
|
|
1093
|
+
if (page.next === undefined) {
|
|
1094
|
+
const { next: _next, ...rest } = first
|
|
1095
|
+
return { ...rest, matches }
|
|
1096
|
+
}
|
|
1097
|
+
cursor = page.next
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
const queryPage = (store: Store, values: QueryValues, pattern: string): ReturnType<typeof caveQueryPage> =>
|
|
1102
|
+
caveQueryPage(store, pattern, {
|
|
1103
|
+
all: values.all === true,
|
|
1104
|
+
aliases: values.aliases === true,
|
|
1105
|
+
resolve: values.resolve === true,
|
|
1106
|
+
limit: values.limit === undefined ? defaultQueryLimit : Number(values.limit),
|
|
1107
|
+
...values.cursor === undefined ? {} : { cursor: values.cursor },
|
|
1108
|
+
...values['as-of'] === undefined ? {} : { asOf: values['as-of'] },
|
|
1109
|
+
...values.at === undefined ? {} : { at: values.at }
|
|
1110
|
+
})
|
|
1111
|
+
|
|
1112
|
+
const renderQueryPage = (
|
|
1113
|
+
store: Store,
|
|
1114
|
+
values: QueryValues,
|
|
1115
|
+
pattern: string,
|
|
1116
|
+
page: () => ReturnType<typeof caveQueryPage>
|
|
1117
|
+
): Output => {
|
|
1118
|
+
{
|
|
1119
|
+
const result = page()
|
|
965
1120
|
if (values.json === true) {
|
|
966
1121
|
return ok(`${JSON.stringify(result, undefined, 2)}\n`)
|
|
967
1122
|
}
|
|
@@ -990,10 +1145,6 @@ export const queryCommand = (argv: readonly string[]): Output => {
|
|
|
990
1145
|
line
|
|
991
1146
|
})
|
|
992
1147
|
return ok(`${lines.join('\n')}\n${result.next === undefined ? '' : `next: ${result.next}\n`}`)
|
|
993
|
-
} catch (error) {
|
|
994
|
-
return fail(`${error instanceof Error ? error.message : String(error)}\n`)
|
|
995
|
-
} finally {
|
|
996
|
-
store.close()
|
|
997
1148
|
}
|
|
998
1149
|
}
|
|
999
1150
|
|
|
@@ -1482,7 +1633,7 @@ export const backupCommand = (argv: readonly string[]): Output => {
|
|
|
1482
1633
|
if (sameFile(dbPath, values.out)) {
|
|
1483
1634
|
return fail(`cave backup: --out '${values.out}' is the source database — refusing to overwrite it\n`)
|
|
1484
1635
|
}
|
|
1485
|
-
const store = openAt(dbPath, { intent: 'read' })
|
|
1636
|
+
const store = openAt(dbPath, { intent: 'read', assemble: assembleSources })
|
|
1486
1637
|
try {
|
|
1487
1638
|
return ok(snapshotLine('created', backupStore(store, values.out, { force: values.force === true })))
|
|
1488
1639
|
} finally {
|
package/src/commands.ts
CHANGED
|
@@ -18,7 +18,7 @@ export const commandRegistry = [
|
|
|
18
18
|
{ name: 'highlight', importantOptions: [] },
|
|
19
19
|
{ name: 'add', importantOptions: ['--strict', '--check', '--no-prelude', '--no-src'] },
|
|
20
20
|
{ name: 'import', importantOptions: ['--strict', '--no-prelude'] },
|
|
21
|
-
{ name: 'query', importantOptions: ['--json', '--limit', '--cursor', '--all', '--aliases', '--as-of', '--at', '--resolve', '--no-prelude'] },
|
|
21
|
+
{ name: 'query', importantOptions: ['--json', '--limit', '--cursor', '--all', '--aliases', '--as-of', '--at', '--resolve', '--sources', '--no-prelude'] },
|
|
22
22
|
{ name: 'search', importantOptions: ['--raw', '--limit', '--json', '--no-prelude'] },
|
|
23
23
|
{ name: 'resolve', importantOptions: ['--aliases', '--policy', '--json', '--no-prelude'] },
|
|
24
24
|
{ name: 'derive', importantOptions: ['--dry-run', '--full', '--aliases', '--min-conf', '--max-passes', '--list', '--retract', '--json', '--no-prelude'] },
|
|
@@ -36,7 +36,7 @@ export const commandRegistry = [
|
|
|
36
36
|
{ name: 'mcp', importantOptions: ['--read-only', '--permissions', '--tools', '--hooks', '--no-prelude', '--src', '--no-src'], delegated: true },
|
|
37
37
|
{ name: 'ingest', importantOptions: ['--agent', '--stdout', '--lenient', '--plan', '--dry-run', '--json', '--no-prelude'], delegated: true },
|
|
38
38
|
{ name: 'eval', importantOptions: ['--agent', '--judge', '--runs', '--stdout', '--min', '--json', '--no-prelude'], delegated: true },
|
|
39
|
-
{ name: 'connect', importantOptions: ['--map', '--key', '--watch', '--prune', '--query', '--dry-run', '--no-prelude'], delegated: true },
|
|
39
|
+
{ name: 'connect', importantOptions: ['--map', '--key', '--watch', '--prune', '--query', '--dry-run', '--list', '--no-prelude'], delegated: true },
|
|
40
40
|
{ name: 'reconstruct', importantOptions: ['--query', '--agent', '--steps', '--claims', '--timeout', '--trace', '--no-prelude'] },
|
|
41
41
|
{ name: 'doctor', importantOptions: ['--hooks', '--json'] },
|
|
42
42
|
{ name: 'demo', importantOptions: [] },
|
package/src/dispatch.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** One promise-based command dispatcher and process lifecycle for every command. */
|
|
2
2
|
|
|
3
|
-
import { cave, highlightCommand, reconstructCommand, suggestAliasCommand } from './cli.ts'
|
|
3
|
+
import { cave, highlightCommand, querySourcesCommand, reconstructCommand, suggestAliasCommand } from './cli.ts'
|
|
4
4
|
import { delegatedCommandNames } from './commands.ts'
|
|
5
5
|
import type { Output } from './cli.ts'
|
|
6
6
|
|
|
@@ -78,6 +78,12 @@ const execute = async (raw: readonly string[], runtime: CommandRuntime): Promise
|
|
|
78
78
|
const { runServe } = await import('@cavelang/view')
|
|
79
79
|
return await runServe(rest, context)
|
|
80
80
|
}
|
|
81
|
+
case 'q':
|
|
82
|
+
case 'query':
|
|
83
|
+
if (rest.includes('--sources')) {
|
|
84
|
+
return await runOutput(runtime, argv, querySourcesCommand)
|
|
85
|
+
}
|
|
86
|
+
break
|
|
81
87
|
case 'reconstruct':
|
|
82
88
|
return await runOutput(runtime, argv,
|
|
83
89
|
args => reconstructCommand(args, { ...runtime.signal === undefined ? {} : { signal: runtime.signal } }))
|
package/src/doctor.ts
CHANGED
|
@@ -6,7 +6,8 @@ import { dirname, join, parse } from 'node:path'
|
|
|
6
6
|
import { parseArgs } from 'node:util'
|
|
7
7
|
import { Version } from '@cavelang/core'
|
|
8
8
|
import { directCommand, runProcessSync } from '@cavelang/loop'
|
|
9
|
-
import { Schema, defaultDbPath } from '@cavelang/store'
|
|
9
|
+
import { LocateError, Schema, defaultDbPath, kindOf, openText } from '@cavelang/store'
|
|
10
|
+
import { assemble } from '@cavelang/connect'
|
|
10
11
|
import { nodeSqliteAdapter } from '@cavelang/store/adapter/node'
|
|
11
12
|
import type { SqliteDatabase } from '@cavelang/store/adapter'
|
|
12
13
|
|
|
@@ -32,7 +33,7 @@ export type DoctorReport = {
|
|
|
32
33
|
readonly configuration: {
|
|
33
34
|
readonly database: {
|
|
34
35
|
readonly source: 'flag' | 'environment' | 'default'
|
|
35
|
-
readonly kind: 'memory' | 'file'
|
|
36
|
+
readonly kind: 'memory' | 'file' | 'text'
|
|
36
37
|
readonly exists: boolean
|
|
37
38
|
readonly schemaVersion?: number
|
|
38
39
|
readonly claims?: number
|
|
@@ -216,6 +217,31 @@ const inspectDatabase = (path: string, source: DatabaseConfiguration['source']):
|
|
|
216
217
|
'Run cave add to create it, or pass --db for an existing store.')]
|
|
217
218
|
}
|
|
218
219
|
}
|
|
220
|
+
if (!memory && kindOf(path) === 'text') {
|
|
221
|
+
// A CAVE text file is a read-only store assembled in memory (spec
|
|
222
|
+
// §13.7, §23.4): replay it, sources included, and count what it holds.
|
|
223
|
+
const configuration: DatabaseConfiguration = { ...base, kind: 'text' }
|
|
224
|
+
try {
|
|
225
|
+
const store = openText(path, { assemble })
|
|
226
|
+
try {
|
|
227
|
+
const claims = store.currentBeliefs().filter(row => row.conf > 0).length
|
|
228
|
+
return {
|
|
229
|
+
configuration: { ...configuration, claims },
|
|
230
|
+
checks: [check('store.database', 'pass',
|
|
231
|
+
`CAVE text store assembled in memory (${claims} current claim(s)); text stores are read-only`)]
|
|
232
|
+
}
|
|
233
|
+
} finally {
|
|
234
|
+
store.close()
|
|
235
|
+
}
|
|
236
|
+
} catch (error) {
|
|
237
|
+
return {
|
|
238
|
+
configuration,
|
|
239
|
+
checks: [check('store.database', 'fail',
|
|
240
|
+
`The CAVE text store does not load: ${error instanceof LocateError ? error.message.split('\n')[0] : error instanceof Error ? error.message : String(error)}`,
|
|
241
|
+
'Fix the file (cave parse) or the source it declares; a text store is read-only.')]
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
219
245
|
|
|
220
246
|
let db: SqliteDatabase | undefined
|
|
221
247
|
let observed = base
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* and `runCli` expose the shared awaited command lifecycle.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
export { actCommand, addCommand, backupCommand, cave, checkCommand, commandHelp, demoCommand, deriveCommand, exportCommand, generateCommand, helpCommand, highlightCommand, importCommand, parseCommand, queryCommand, reconstructCommand, reportCommand, resolveCommand, restoreCommand, searchCommand, suggestAliasCommand, syncCommand, usage, versionCommand } from './cli.ts'
|
|
7
|
+
export { actCommand, addCommand, backupCommand, cave, checkCommand, commandHelp, demoCommand, deriveCommand, exportCommand, generateCommand, helpCommand, highlightCommand, importCommand, parseCommand, queryCommand, querySourcesCommand, reconstructCommand, reportCommand, resolveCommand, restoreCommand, searchCommand, suggestAliasCommand, syncCommand, usage, versionCommand } from './cli.ts'
|
|
8
8
|
export { dispatch, runCli } from './dispatch.ts'
|
|
9
9
|
export type { CommandRuntime } from './dispatch.ts'
|
|
10
10
|
export { commandRegistry } from './commands.ts'
|