@yeseh/cortex-cli 0.6.0 → 0.6.4
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/package.json +3 -3
- package/src/category/commands/create.ts +7 -3
- package/src/context.ts +15 -20
- package/src/memory/commands/add.ts +2 -1
- package/src/memory/commands/list.ts +2 -1
- package/src/memory/commands/move.ts +6 -2
- package/src/memory/commands/remove.ts +6 -2
- package/src/memory/commands/show.ts +3 -2
- package/src/memory/commands/update.ts +2 -1
- package/src/observability.spec.ts +8 -21
- package/src/observability.ts +26 -7
- package/src/program.ts +1 -1
- package/src/run.ts +0 -0
- package/src/store/commands/init.spec.ts +62 -78
- package/src/store/commands/init.ts +31 -15
- package/src/store/commands/prune.ts +4 -4
- package/src/store/commands/reindexs.ts +4 -3
- package/src/tests/cli.integration.spec.ts +136 -0
- package/src/utils/input.ts +9 -4
- package/src/utils/resolve-default-store.spec.ts +135 -0
- package/src/utils/resolve-default-store.ts +74 -0
- package/dist/category/commands/create.d.ts +0 -44
- package/dist/category/commands/create.d.ts.map +0 -1
- package/dist/category/commands/create.spec.d.ts +0 -7
- package/dist/category/commands/create.spec.d.ts.map +0 -1
- package/dist/category/index.d.ts +0 -19
- package/dist/category/index.d.ts.map +0 -1
- package/dist/commands/init.d.ts +0 -58
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.spec.d.ts +0 -2
- package/dist/commands/init.spec.d.ts.map +0 -1
- package/dist/context.d.ts +0 -18
- package/dist/context.d.ts.map +0 -1
- package/dist/context.spec.d.ts +0 -2
- package/dist/context.spec.d.ts.map +0 -1
- package/dist/create-cli-command.d.ts +0 -23
- package/dist/create-cli-command.d.ts.map +0 -1
- package/dist/create-cli-command.spec.d.ts +0 -10
- package/dist/create-cli-command.spec.d.ts.map +0 -1
- package/dist/errors.d.ts +0 -57
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.spec.d.ts +0 -2
- package/dist/errors.spec.d.ts.map +0 -1
- package/dist/input.d.ts +0 -42
- package/dist/input.d.ts.map +0 -1
- package/dist/input.spec.d.ts +0 -2
- package/dist/input.spec.d.ts.map +0 -1
- package/dist/memory/commands/add.d.ts +0 -62
- package/dist/memory/commands/add.d.ts.map +0 -1
- package/dist/memory/commands/add.spec.d.ts +0 -7
- package/dist/memory/commands/add.spec.d.ts.map +0 -1
- package/dist/memory/commands/definitions.spec.d.ts +0 -10
- package/dist/memory/commands/definitions.spec.d.ts.map +0 -1
- package/dist/memory/commands/handlers.spec.d.ts +0 -2
- package/dist/memory/commands/handlers.spec.d.ts.map +0 -1
- package/dist/memory/commands/list.d.ts +0 -119
- package/dist/memory/commands/list.d.ts.map +0 -1
- package/dist/memory/commands/list.spec.d.ts +0 -2
- package/dist/memory/commands/list.spec.d.ts.map +0 -1
- package/dist/memory/commands/move.d.ts +0 -42
- package/dist/memory/commands/move.d.ts.map +0 -1
- package/dist/memory/commands/move.spec.d.ts +0 -2
- package/dist/memory/commands/move.spec.d.ts.map +0 -1
- package/dist/memory/commands/remove.d.ts +0 -41
- package/dist/memory/commands/remove.d.ts.map +0 -1
- package/dist/memory/commands/remove.spec.d.ts +0 -2
- package/dist/memory/commands/remove.spec.d.ts.map +0 -1
- package/dist/memory/commands/show.d.ts +0 -81
- package/dist/memory/commands/show.d.ts.map +0 -1
- package/dist/memory/commands/show.spec.d.ts +0 -2
- package/dist/memory/commands/show.spec.d.ts.map +0 -1
- package/dist/memory/commands/test-helpers.spec.d.ts +0 -19
- package/dist/memory/commands/test-helpers.spec.d.ts.map +0 -1
- package/dist/memory/commands/update.d.ts +0 -73
- package/dist/memory/commands/update.d.ts.map +0 -1
- package/dist/memory/commands/update.spec.d.ts +0 -2
- package/dist/memory/commands/update.spec.d.ts.map +0 -1
- package/dist/memory/index.d.ts +0 -29
- package/dist/memory/index.d.ts.map +0 -1
- package/dist/memory/index.spec.d.ts +0 -10
- package/dist/memory/index.spec.d.ts.map +0 -1
- package/dist/memory/parsing.d.ts +0 -3
- package/dist/memory/parsing.d.ts.map +0 -1
- package/dist/memory/parsing.spec.d.ts +0 -7
- package/dist/memory/parsing.spec.d.ts.map +0 -1
- package/dist/output.d.ts +0 -87
- package/dist/output.d.ts.map +0 -1
- package/dist/output.spec.d.ts +0 -2
- package/dist/output.spec.d.ts.map +0 -1
- package/dist/paths.d.ts +0 -27
- package/dist/paths.d.ts.map +0 -1
- package/dist/paths.spec.d.ts +0 -7
- package/dist/paths.spec.d.ts.map +0 -1
- package/dist/program.d.ts +0 -41
- package/dist/program.d.ts.map +0 -1
- package/dist/program.spec.d.ts +0 -11
- package/dist/program.spec.d.ts.map +0 -1
- package/dist/run.d.ts +0 -7
- package/dist/run.d.ts.map +0 -1
- package/dist/run.spec.d.ts +0 -12
- package/dist/run.spec.d.ts.map +0 -1
- package/dist/store/commands/add.d.ts +0 -73
- package/dist/store/commands/add.d.ts.map +0 -1
- package/dist/store/commands/add.spec.d.ts +0 -17
- package/dist/store/commands/add.spec.d.ts.map +0 -1
- package/dist/store/commands/init.d.ts +0 -75
- package/dist/store/commands/init.d.ts.map +0 -1
- package/dist/store/commands/init.spec.d.ts +0 -7
- package/dist/store/commands/init.spec.d.ts.map +0 -1
- package/dist/store/commands/list.d.ts +0 -62
- package/dist/store/commands/list.d.ts.map +0 -1
- package/dist/store/commands/list.spec.d.ts +0 -7
- package/dist/store/commands/list.spec.d.ts.map +0 -1
- package/dist/store/commands/prune.d.ts +0 -92
- package/dist/store/commands/prune.d.ts.map +0 -1
- package/dist/store/commands/prune.spec.d.ts +0 -7
- package/dist/store/commands/prune.spec.d.ts.map +0 -1
- package/dist/store/commands/reindexs.d.ts +0 -54
- package/dist/store/commands/reindexs.d.ts.map +0 -1
- package/dist/store/commands/reindexs.spec.d.ts +0 -7
- package/dist/store/commands/reindexs.spec.d.ts.map +0 -1
- package/dist/store/commands/remove.d.ts +0 -63
- package/dist/store/commands/remove.d.ts.map +0 -1
- package/dist/store/commands/remove.spec.d.ts +0 -17
- package/dist/store/commands/remove.spec.d.ts.map +0 -1
- package/dist/store/index.d.ts +0 -32
- package/dist/store/index.d.ts.map +0 -1
- package/dist/store/index.spec.d.ts +0 -9
- package/dist/store/index.spec.d.ts.map +0 -1
- package/dist/store/utils/resolve-store-name.d.ts +0 -30
- package/dist/store/utils/resolve-store-name.d.ts.map +0 -1
- package/dist/store/utils/resolve-store-name.spec.d.ts +0 -2
- package/dist/store/utils/resolve-store-name.spec.d.ts.map +0 -1
- package/dist/test-helpers.spec.d.ts +0 -224
- package/dist/test-helpers.spec.d.ts.map +0 -1
- package/dist/tests/cli.integration.spec.d.ts +0 -11
- package/dist/tests/cli.integration.spec.d.ts.map +0 -1
- package/dist/toon.d.ts +0 -197
- package/dist/toon.d.ts.map +0 -1
- package/dist/toon.spec.d.ts +0 -9
- package/dist/toon.spec.d.ts.map +0 -1
- package/dist/utils/git.d.ts +0 -20
- package/dist/utils/git.d.ts.map +0 -1
- package/dist/utils/git.spec.d.ts +0 -7
- package/dist/utils/git.spec.d.ts.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yeseh/cortex-cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"typescript": "^5"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@yeseh/cortex-core": "
|
|
38
|
-
"@yeseh/cortex-storage-fs": "
|
|
37
|
+
"@yeseh/cortex-core": "workspace:*",
|
|
38
|
+
"@yeseh/cortex-storage-fs": "workspace:*",
|
|
39
39
|
"@commander-js/extra-typings": "^14.0.0",
|
|
40
40
|
"@inquirer/prompts": "^8.0.0",
|
|
41
41
|
"@toon-format/toon": "^1.0.0",
|
|
@@ -22,6 +22,7 @@ import { type CortexContext, type Result } from '@yeseh/cortex-core';
|
|
|
22
22
|
import { createCliCommandContext } from '../../context.ts';
|
|
23
23
|
import { throwCliError } from '../../errors.ts';
|
|
24
24
|
import { serializeOutput, type OutputFormat } from '../../output.ts';
|
|
25
|
+
import { resolveDefaultStore } from '../../utils/resolve-default-store.ts';
|
|
25
26
|
|
|
26
27
|
/** Options parsed by Commander for the create command */
|
|
27
28
|
export interface CreateCommandOptions {
|
|
@@ -39,7 +40,7 @@ export interface CreateCommandOptions {
|
|
|
39
40
|
function writeCreateOutput(
|
|
40
41
|
payload: { path: string; created: boolean },
|
|
41
42
|
options: CreateCommandOptions,
|
|
42
|
-
stdout: NodeJS.WritableStream
|
|
43
|
+
stdout: NodeJS.WritableStream
|
|
43
44
|
): void {
|
|
44
45
|
const rawFormat = options.format;
|
|
45
46
|
|
|
@@ -49,7 +50,10 @@ function writeCreateOutput(
|
|
|
49
50
|
return;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
const serialized = serializeOutput(
|
|
53
|
+
const serialized = serializeOutput(
|
|
54
|
+
{ kind: 'created-category', value: payload },
|
|
55
|
+
rawFormat as OutputFormat
|
|
56
|
+
);
|
|
53
57
|
if (!serialized.ok()) {
|
|
54
58
|
throwCliError({ code: 'SERIALIZE_FAILED', message: serialized.error.message });
|
|
55
59
|
}
|
|
@@ -85,7 +89,7 @@ export async function handleCreate(
|
|
|
85
89
|
path: string,
|
|
86
90
|
options: CreateCommandOptions = {}
|
|
87
91
|
): Promise<void> {
|
|
88
|
-
const store = unwrapOrThrow(ctx.cortex.getStore(storeName
|
|
92
|
+
const store = unwrapOrThrow(ctx.cortex.getStore(resolveDefaultStore(ctx, storeName)));
|
|
89
93
|
const root = unwrapOrThrow(store.root());
|
|
90
94
|
const category = unwrapOrThrow(root.getCategory(path));
|
|
91
95
|
const result = unwrapOrThrow(await category.create());
|
package/src/context.ts
CHANGED
|
@@ -24,7 +24,7 @@ const makeAbsolute = (pathStr: string): string => {
|
|
|
24
24
|
|
|
25
25
|
export const validateStorePath = (
|
|
26
26
|
storePath: string,
|
|
27
|
-
storeName: string
|
|
27
|
+
storeName: string
|
|
28
28
|
): Result<void, ConfigValidationError> => {
|
|
29
29
|
if (!isAbsolute(storePath)) {
|
|
30
30
|
return err({
|
|
@@ -65,14 +65,19 @@ export const createCliAdapterFactory = (configAdapter: FilesystemConfigAdapter)
|
|
|
65
65
|
const stores = configAdapter.stores!;
|
|
66
66
|
const storeEntry = stores[storeName];
|
|
67
67
|
if (!storeEntry) {
|
|
68
|
+
const available = Object.keys(stores).join(', ') || 'none';
|
|
68
69
|
throw new Error(
|
|
69
|
-
`Store '${storeName}' not
|
|
70
|
+
`Store '${storeName}' is not registered. Available stores: ${available}. ` +
|
|
71
|
+
'Use --store to specify a registered store, or run `cortex store init` to create one.'
|
|
70
72
|
);
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
const storePath = storeEntry.properties?.path as string | undefined;
|
|
74
76
|
if (!storePath) {
|
|
75
|
-
throw new Error(
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Store '${storeName}' has no path configured. ` +
|
|
79
|
+
'Check your cortex config or re-run `cortex store init`.'
|
|
80
|
+
);
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
return new FilesystemStorageAdapter(configAdapter, {
|
|
@@ -82,10 +87,11 @@ export const createCliAdapterFactory = (configAdapter: FilesystemConfigAdapter)
|
|
|
82
87
|
};
|
|
83
88
|
|
|
84
89
|
export const createCliConfigContext = async (
|
|
85
|
-
options: CliContextOptions = {}
|
|
90
|
+
options: CliContextOptions = {}
|
|
86
91
|
): Promise<Result<CliConfigContext, any>> => {
|
|
87
92
|
const envConfigPath = process.env.CORTEX_CONFIG;
|
|
88
93
|
const envConfigDir = process.env.CORTEX_CONFIG_DIR;
|
|
94
|
+
const envConfigCwd = process.env.CORTEX_CONFIG_CWD;
|
|
89
95
|
|
|
90
96
|
const explicitConfigPath =
|
|
91
97
|
typeof envConfigPath === 'string' && envConfigPath.length > 0
|
|
@@ -93,10 +99,10 @@ export const createCliConfigContext = async (
|
|
|
93
99
|
: undefined;
|
|
94
100
|
|
|
95
101
|
const dir = options.configDir ?? envConfigDir ?? resolve(homedir(), '.config', 'cortex');
|
|
102
|
+
|
|
96
103
|
const absoluteDir = makeAbsolute(dir);
|
|
97
104
|
const configPath = explicitConfigPath ?? resolve(absoluteDir, 'config.yaml');
|
|
98
105
|
|
|
99
|
-
const envConfigCwd = process.env.CORTEX_CONFIG_CWD;
|
|
100
106
|
const effectiveCwd =
|
|
101
107
|
options.configCwd ??
|
|
102
108
|
(typeof envConfigCwd === 'string' && envConfigCwd.length > 0
|
|
@@ -109,20 +115,10 @@ export const createCliConfigContext = async (
|
|
|
109
115
|
return initResult;
|
|
110
116
|
}
|
|
111
117
|
|
|
112
|
-
const settingsResult = await configAdapter.getSettings();
|
|
113
|
-
if (!settingsResult.ok()) {
|
|
114
|
-
return settingsResult;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const storesResult = await configAdapter.getStores();
|
|
118
|
-
if (!storesResult.ok()) {
|
|
119
|
-
return storesResult;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
118
|
return ok({
|
|
123
119
|
configAdapter,
|
|
124
|
-
settings:
|
|
125
|
-
stores:
|
|
120
|
+
settings: configAdapter.settings!,
|
|
121
|
+
stores: configAdapter.stores!,
|
|
126
122
|
effectiveCwd,
|
|
127
123
|
});
|
|
128
124
|
};
|
|
@@ -131,7 +127,7 @@ export const createCliConfigContext = async (
|
|
|
131
127
|
* This function is used to create a context object that can be injected into command handlers for consistent access to the Cortex client and other utilities.
|
|
132
128
|
*/
|
|
133
129
|
export const createCliCommandContext = async (
|
|
134
|
-
configDir?: string
|
|
130
|
+
configDir?: string
|
|
135
131
|
): Promise<Result<CortexContext, any>> => {
|
|
136
132
|
try {
|
|
137
133
|
const configContextResult = await createCliConfigContext({
|
|
@@ -165,8 +161,7 @@ export const createCliCommandContext = async (
|
|
|
165
161
|
};
|
|
166
162
|
|
|
167
163
|
return ok(context);
|
|
168
|
-
}
|
|
169
|
-
catch (error) {
|
|
164
|
+
} catch (error) {
|
|
170
165
|
return err({
|
|
171
166
|
code: 'CONTEXT_CREATION_FAILED',
|
|
172
167
|
message: `Unexpected error creating CLI command context: ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -28,6 +28,7 @@ import { resolveInput as resolveCliContent } from '../../utils/input.ts';
|
|
|
28
28
|
import { parseExpiresAt, parseTags } from '../parsing.ts';
|
|
29
29
|
import { createCliCommandContext } from '../../context.ts';
|
|
30
30
|
import { serializeOutput, type OutputFormat } from '../../output.ts';
|
|
31
|
+
import { resolveDefaultStore } from '../../utils/resolve-default-store.ts';
|
|
31
32
|
|
|
32
33
|
/** Options parsed by Commander for the add command */
|
|
33
34
|
export interface AddCommandOptions {
|
|
@@ -77,7 +78,7 @@ export async function handleAdd(
|
|
|
77
78
|
const expiresAt = parseExpiresAt(options.expiresAt);
|
|
78
79
|
const citations = options.citations ?? [];
|
|
79
80
|
|
|
80
|
-
const storeResult = ctx.cortex.getStore(storeName
|
|
81
|
+
const storeResult = ctx.cortex.getStore(resolveDefaultStore(ctx, storeName));
|
|
81
82
|
if (!storeResult.ok()) {
|
|
82
83
|
throwCliError(storeResult.error);
|
|
83
84
|
}
|
|
@@ -36,6 +36,7 @@ import { serialize, type CortexContext } from '@yeseh/cortex-core';
|
|
|
36
36
|
import type { SubcategoryEntry } from '@yeseh/cortex-core/category';
|
|
37
37
|
import { type OutputFormat } from '../../output.ts';
|
|
38
38
|
import { createCliCommandContext } from '../../context.ts';
|
|
39
|
+
import { resolveDefaultStore } from '../../utils/resolve-default-store.ts';
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* Options for the list command.
|
|
@@ -116,7 +117,7 @@ export async function handleList(
|
|
|
116
117
|
throwCliError(categoryResult.error);
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
const storeResult = ctx.cortex.getStore(storeName
|
|
120
|
+
const storeResult = ctx.cortex.getStore(resolveDefaultStore(ctx, storeName));
|
|
120
121
|
if (!storeResult.ok()) {
|
|
121
122
|
throwCliError(storeResult.error);
|
|
122
123
|
}
|
|
@@ -17,6 +17,7 @@ import { throwCliError } from '../../errors.ts';
|
|
|
17
17
|
import { MemoryPath, type CortexContext } from '@yeseh/cortex-core';
|
|
18
18
|
import { createCliCommandContext } from '../../context.ts';
|
|
19
19
|
import { serializeOutput, type OutputFormat } from '../../output.ts';
|
|
20
|
+
import { resolveDefaultStore } from '../../utils/resolve-default-store.ts';
|
|
20
21
|
|
|
21
22
|
/** Options for the move command. */
|
|
22
23
|
export interface MoveCommandOptions {
|
|
@@ -50,7 +51,7 @@ export async function handleMove(
|
|
|
50
51
|
throwCliError(toResult.error);
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
const storeResult = ctx.cortex.getStore(storeName
|
|
54
|
+
const storeResult = ctx.cortex.getStore(resolveDefaultStore(ctx, storeName));
|
|
54
55
|
if (!storeResult.ok()) {
|
|
55
56
|
throwCliError(storeResult.error);
|
|
56
57
|
}
|
|
@@ -81,7 +82,10 @@ export async function handleMove(
|
|
|
81
82
|
} else {
|
|
82
83
|
const format = rawFormat as OutputFormat;
|
|
83
84
|
const serialized = serializeOutput(
|
|
84
|
-
{
|
|
85
|
+
{
|
|
86
|
+
kind: 'moved-memory',
|
|
87
|
+
value: { from: fromResult.value.toString(), to: toResult.value.toString() },
|
|
88
|
+
},
|
|
85
89
|
format
|
|
86
90
|
);
|
|
87
91
|
if (!serialized.ok()) {
|
|
@@ -18,6 +18,7 @@ import { throwCliError } from '../../errors.ts';
|
|
|
18
18
|
import { MemoryPath, type CortexContext } from '@yeseh/cortex-core';
|
|
19
19
|
import { createCliCommandContext } from '../../context.ts';
|
|
20
20
|
import { serializeOutput, type OutputFormat } from '../../output.ts';
|
|
21
|
+
import { resolveDefaultStore } from '../../utils/resolve-default-store.ts';
|
|
21
22
|
|
|
22
23
|
/** Options for the remove command. */
|
|
23
24
|
export interface RemoveCommandOptions {
|
|
@@ -44,7 +45,7 @@ export async function handleRemove(
|
|
|
44
45
|
throwCliError(pathResult.error);
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
const storeResult = ctx.cortex.getStore(storeName
|
|
48
|
+
const storeResult = ctx.cortex.getStore(resolveDefaultStore(ctx, storeName));
|
|
48
49
|
if (!storeResult.ok()) {
|
|
49
50
|
throwCliError(storeResult.error);
|
|
50
51
|
}
|
|
@@ -74,7 +75,10 @@ export async function handleRemove(
|
|
|
74
75
|
out.write(`Removed memory ${pathResult.value.toString()}.\n`);
|
|
75
76
|
} else {
|
|
76
77
|
const format = rawFormat as OutputFormat;
|
|
77
|
-
const serialized = serializeOutput(
|
|
78
|
+
const serialized = serializeOutput(
|
|
79
|
+
{ kind: 'path', value: { path: pathResult.value.toString() } },
|
|
80
|
+
format
|
|
81
|
+
);
|
|
78
82
|
if (!serialized.ok()) {
|
|
79
83
|
throwCliError({ code: 'SERIALIZE_FAILED', message: serialized.error.message });
|
|
80
84
|
}
|
|
@@ -28,6 +28,7 @@ import { defaultTokenizer, MemoryPath, type CortexContext } from '@yeseh/cortex-
|
|
|
28
28
|
import { type StoreClient } from '@yeseh/cortex-core/store';
|
|
29
29
|
import { serializeOutput, type OutputMemory, type OutputFormat } from '../../output.ts';
|
|
30
30
|
import { createCliCommandContext } from '../../context.ts';
|
|
31
|
+
import { resolveDefaultStore } from '../../utils/resolve-default-store.ts';
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Options for the show command.
|
|
@@ -80,7 +81,7 @@ export async function handleShow(
|
|
|
80
81
|
throwCliError(pathResult.error);
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
const storeResult = ctx.cortex.getStore(storeName
|
|
84
|
+
const storeResult = ctx.cortex.getStore(resolveDefaultStore(ctx, storeName));
|
|
84
85
|
if (!storeResult.ok()) {
|
|
85
86
|
throwCliError(storeResult.error);
|
|
86
87
|
}
|
|
@@ -126,7 +127,7 @@ export async function handleShow(
|
|
|
126
127
|
};
|
|
127
128
|
|
|
128
129
|
const format = (options.format as OutputFormat) ?? 'yaml';
|
|
129
|
-
const serialized = serializeOutput({kind: 'memory', value: outputMemory}, format);
|
|
130
|
+
const serialized = serializeOutput({ kind: 'memory', value: outputMemory }, format);
|
|
130
131
|
if (!serialized.ok()) {
|
|
131
132
|
throwCliError({ code: 'SERIALIZE_FAILED', message: serialized.error.message });
|
|
132
133
|
}
|
|
@@ -33,6 +33,7 @@ import { resolveInput as resolveCliContent } from '../../utils/input.ts';
|
|
|
33
33
|
import { parseExpiresAt, parseTags } from '../parsing.ts';
|
|
34
34
|
import { createCliCommandContext } from '../../context.ts';
|
|
35
35
|
import { serializeOutput, type OutputFormat } from '../../output.ts';
|
|
36
|
+
import { resolveDefaultStore } from '../../utils/resolve-default-store.ts';
|
|
36
37
|
|
|
37
38
|
/** Options parsed by Commander for the update command */
|
|
38
39
|
export interface UpdateCommandOptions {
|
|
@@ -148,7 +149,7 @@ export async function handleUpdate(
|
|
|
148
149
|
const expiresAt = parseUpdateExpiresAt(options.expiresAt);
|
|
149
150
|
const updates = buildUpdates(content, tags, expiresAt, options.citation);
|
|
150
151
|
|
|
151
|
-
const storeResult = ctx.cortex.getStore(storeName
|
|
152
|
+
const storeResult = ctx.cortex.getStore(resolveDefaultStore(ctx, storeName));
|
|
152
153
|
if (!storeResult.ok()) {
|
|
153
154
|
throwCliError(storeResult.error);
|
|
154
155
|
}
|
|
@@ -27,22 +27,17 @@ describe('createCliLogger', () => {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
describe('info()', () => {
|
|
30
|
-
it('should write info log to stderr
|
|
30
|
+
it('should write human-friendly info log to stderr', () => {
|
|
31
31
|
const logger = createCliLogger();
|
|
32
32
|
logger.info('hello world');
|
|
33
33
|
expect(stderrLines.length).toBe(1);
|
|
34
|
-
|
|
35
|
-
expect(parsed.level).toBe('info');
|
|
36
|
-
expect(parsed.msg).toBe('hello world');
|
|
37
|
-
expect(parsed.ts).toBeDefined();
|
|
34
|
+
expect(stderrLines[0]).toBe('INFO: hello world\n');
|
|
38
35
|
});
|
|
39
36
|
|
|
40
37
|
it('should include metadata in the log line', () => {
|
|
41
38
|
const logger = createCliLogger();
|
|
42
39
|
logger.info('test', { store: 'default', count: 5 });
|
|
43
|
-
|
|
44
|
-
expect(parsed.store).toBe('default');
|
|
45
|
-
expect(parsed.count).toBe(5);
|
|
40
|
+
expect(stderrLines[0]).toBe('INFO: test store=default count=5\n');
|
|
46
41
|
});
|
|
47
42
|
});
|
|
48
43
|
|
|
@@ -51,9 +46,7 @@ describe('createCliLogger', () => {
|
|
|
51
46
|
const logger = createCliLogger();
|
|
52
47
|
logger.warn('warning message');
|
|
53
48
|
expect(stderrLines.length).toBe(1);
|
|
54
|
-
|
|
55
|
-
expect(parsed.level).toBe('warn');
|
|
56
|
-
expect(parsed.msg).toBe('warning message');
|
|
49
|
+
expect(stderrLines[0]).toBe('WARN: warning message\n');
|
|
57
50
|
});
|
|
58
51
|
});
|
|
59
52
|
|
|
@@ -62,25 +55,20 @@ describe('createCliLogger', () => {
|
|
|
62
55
|
const logger = createCliLogger();
|
|
63
56
|
logger.error('something failed', new Error('boom'));
|
|
64
57
|
expect(stderrLines.length).toBe(1);
|
|
65
|
-
|
|
66
|
-
expect(parsed.level).toBe('error');
|
|
67
|
-
expect(parsed.msg).toBe('something failed');
|
|
68
|
-
expect(parsed.error).toBe('boom');
|
|
58
|
+
expect(stderrLines[0]).toBe('ERROR: something failed error=boom\n');
|
|
69
59
|
});
|
|
70
60
|
|
|
71
61
|
it('should handle string error argument', () => {
|
|
72
62
|
const logger = createCliLogger();
|
|
73
63
|
logger.error('failed', 'string error');
|
|
74
|
-
|
|
75
|
-
expect(parsed.error).toBe('string error');
|
|
64
|
+
expect(stderrLines[0]).toBe('ERROR: failed error="string error"\n');
|
|
76
65
|
});
|
|
77
66
|
|
|
78
67
|
it('should handle missing error argument', () => {
|
|
79
68
|
const logger = createCliLogger();
|
|
80
69
|
logger.error('failed');
|
|
81
70
|
expect(stderrLines.length).toBe(1);
|
|
82
|
-
|
|
83
|
-
expect(parsed.error).toBeUndefined();
|
|
71
|
+
expect(stderrLines[0]).toBe('ERROR: failed\n');
|
|
84
72
|
});
|
|
85
73
|
});
|
|
86
74
|
|
|
@@ -97,8 +85,7 @@ describe('createCliLogger', () => {
|
|
|
97
85
|
const logger = createCliLogger();
|
|
98
86
|
logger.debug('debug message');
|
|
99
87
|
expect(stderrLines.length).toBe(1);
|
|
100
|
-
|
|
101
|
-
expect(parsed.level).toBe('debug');
|
|
88
|
+
expect(stderrLines[0]).toBe('DEBUG: debug message\n');
|
|
102
89
|
});
|
|
103
90
|
|
|
104
91
|
it('should write debug output when DEBUG includes cortex alongside other values', () => {
|
package/src/observability.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI observability — plain ConsoleLogger writing
|
|
2
|
+
* CLI observability — plain ConsoleLogger writing human-readable lines to stderr.
|
|
3
3
|
*
|
|
4
4
|
* No OTel SDK dependency — keeps the CLI binary small.
|
|
5
5
|
* Debug output is gated by the `DEBUG=cortex` environment variable.
|
|
@@ -11,7 +11,7 @@ import type { Logger } from '@yeseh/cortex-core';
|
|
|
11
11
|
/**
|
|
12
12
|
* Creates a plain console logger for CLI usage.
|
|
13
13
|
*
|
|
14
|
-
* Writes
|
|
14
|
+
* Writes human-readable log lines to stderr (not stdout) to avoid
|
|
15
15
|
* polluting piped command output. Debug output is gated by the
|
|
16
16
|
* `DEBUG=cortex` environment variable.
|
|
17
17
|
*
|
|
@@ -21,7 +21,7 @@ import type { Logger } from '@yeseh/cortex-core';
|
|
|
21
21
|
* ```typescript
|
|
22
22
|
* const logger = createCliLogger();
|
|
23
23
|
* logger.info('Starting command', { store: 'global' });
|
|
24
|
-
* // →
|
|
24
|
+
* // → INFO: Starting command store=global
|
|
25
25
|
* ```
|
|
26
26
|
*
|
|
27
27
|
* @example
|
|
@@ -34,10 +34,27 @@ export const createCliLogger = (): Logger => {
|
|
|
34
34
|
const debugEnabled =
|
|
35
35
|
typeof process.env.DEBUG === 'string' && process.env.DEBUG.includes('cortex');
|
|
36
36
|
|
|
37
|
+
const stringifyMetaValue = (value: unknown): string => {
|
|
38
|
+
if (typeof value === 'string') {
|
|
39
|
+
return value.includes(' ') ? JSON.stringify(value) : value;
|
|
40
|
+
}
|
|
41
|
+
if (typeof value === 'number' || typeof value === 'boolean' || value === null) {
|
|
42
|
+
return String(value);
|
|
43
|
+
}
|
|
44
|
+
return JSON.stringify(value);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const formatMeta = (meta?: Record<string, unknown>): string => {
|
|
48
|
+
if (!meta || Object.keys(meta).length === 0) return '';
|
|
49
|
+
return Object.entries(meta)
|
|
50
|
+
.map(([key, value]) => `${key}=${stringifyMetaValue(value)}`)
|
|
51
|
+
.join(' ');
|
|
52
|
+
};
|
|
53
|
+
|
|
37
54
|
const write = (level: string, msg: string, meta?: Record<string, unknown>): void => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
);
|
|
55
|
+
const line = `${level.toUpperCase()}: ${msg}`;
|
|
56
|
+
const metaText = formatMeta(meta);
|
|
57
|
+
process.stderr.write(metaText.length > 0 ? `${line} ${metaText}\n` : `${line}\n`);
|
|
41
58
|
};
|
|
42
59
|
|
|
43
60
|
return {
|
|
@@ -53,7 +70,9 @@ export const createCliLogger = (): Logger => {
|
|
|
53
70
|
error(msg: string, err?: Error | unknown, meta?: Record<string, unknown>): void {
|
|
54
71
|
const errMeta =
|
|
55
72
|
err instanceof Error
|
|
56
|
-
?
|
|
73
|
+
? debugEnabled
|
|
74
|
+
? { error: err.message, stack: err.stack }
|
|
75
|
+
: { error: err.message }
|
|
57
76
|
: err !== null && err !== undefined
|
|
58
77
|
? { error: String(err) }
|
|
59
78
|
: {};
|
package/src/program.ts
CHANGED
|
@@ -65,7 +65,7 @@ export const runProgram = async (): Promise<void> => {
|
|
|
65
65
|
// This catch handles any unexpected errors that slip through.
|
|
66
66
|
const logger = createCliLogger();
|
|
67
67
|
if (error instanceof Error) {
|
|
68
|
-
logger.error(
|
|
68
|
+
logger.error(error.message);
|
|
69
69
|
}
|
|
70
70
|
else {
|
|
71
71
|
logger.error('An unexpected error occurred');
|
package/src/run.ts
CHANGED
|
File without changes
|