@lorekit/cli 1.55.2 → 1.55.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lorekit/cli",
3
- "version": "1.55.2",
3
+ "version": "1.55.3",
4
4
  "description": "Install the LoreKit shared-memory skill and run health checks for the LoreKit MCP server.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -365,7 +365,7 @@ export function advertise(dispatch) {
365
365
  if (!def) {
366
366
  throw new Error(
367
367
  `mcp-server dispatches "${name}", which the tool catalog does not declare. `
368
- + 'Add it to packages/schemas/src/shared/tool-catalog.ts (and regenerate: node scripts/gen-surfaces.mjs).',
368
+ + 'Add it to packages/schemas/src/shared/tool-catalog.ts (and regenerate: node scripts/codegen/gen-surfaces.mjs).',
369
369
  );
370
370
  }
371
371
  return def;
@@ -19,7 +19,7 @@
19
19
  // `--json`). An agent loop must not be able to trigger one by omission.
20
20
  //
21
21
  // 3. A SCOPED KEY IS REFUSED BY THE SERVER, and that refusal is passed through
22
- // verbatim. `_shared/account-wide-tools.ts` refuses these two operations for
22
+ // verbatim. `_shared/auth/account-wide-tools.ts` refuses these two operations for
23
23
  // any token carrying a scope allowlist — a key narrowed to one repo has no
24
24
  // business sweeping the whole account. The CLI makes exactly one request and
25
25
  // reports the server's answer; it never retries, never splits the sweep and
@@ -10,7 +10,10 @@
10
10
  // you can copy-paste a key directly from list output)
11
11
  // show <scope> <key> — the explicit two-positional form
12
12
  // show --scope <s> --key <k>
13
- // — flags win; the only way to name a key containing `::`
13
+ // — flags win; an explicit override that skips the `::`
14
+ // split (the shorthand already carries a namespaced
15
+ // key, since the split lands at the first valid-scope
16
+ // prefix — see `resolveScopeArg`)
14
17
  //
15
18
  // Uses each store's real `read({scope, key})` method (both stores expose it),
16
19
  // not a filtered `list` — a single-record lookup is what `read` is for, and it
@@ -60,8 +63,9 @@ export async function show(args) {
60
63
  // Positional shapes (all resolved by the shared, validity-gated parser):
61
64
  // show <scope::key> — canonical shorthand, mirrors `list` output
62
65
  // show <scope> <key> — explicit two-positional form
63
- // show --scope <s> --key <k> — flags win; the escape hatch for a key
64
- // containing `::`
66
+ // show --scope <s> --key <k> — flags win; an explicit override that skips
67
+ // the `::` split (the shorthand handles a
68
+ // namespaced key on its own now)
65
69
  const positionals = args._.slice(1);
66
70
  const { scope, key, consumed } = resolveScopeKeyArgs(positionals, {
67
71
  scope: args.scope,
@@ -122,23 +122,29 @@ export function isScopeString(s) {
122
122
  // Split a single `<scope>::<key>` argument, or fall back to treating the whole
123
123
  // argument as a scope.
124
124
  //
125
- // The rule: split at the LAST `::` and take it as `<scope>::<key>` ONLY when the
126
- // left side is itself a COMPLETE valid scope — otherwise the whole arg is the
127
- // scope. Splitting on the last `::` (not the first) keeps a multi-segment scope
128
- // whole (`repo::owner/name::key` scope `repo::owner/name`, key `key`); gating
129
- // on a valid left side means a bare `repo::owner/name` is NOT mis-split, because
130
- // its left part `repo` is not a valid scope. This is the fix for the prior
131
- // first-`::` split, which turned `link repo::acme/widget` into scope="repo" plus
132
- // a bogus `acme/widget` key — breaking the shorthand for EVERY non-`global`
133
- // scope. A malformed arg falls through to the scope, never a fabricated key.
125
+ // The rule: scan the `::` boundaries left-to-right and split at the FIRST one
126
+ // whose left side is a COMPLETE valid scope — otherwise the whole arg is the
127
+ // scope. Because `::` is RESERVED as the segment separator (no scope segment may
128
+ // contain it, enforced by `scopeIssue`), no valid scope is a `::`-boundary
129
+ // prefix of another, so the earliest valid-scope prefix is unambiguously THE
130
+ // scope and everything after it is the key even a key that itself contains
131
+ // `::` (a namespaced key like `implement-suggestion-lessons::documenting-…`).
132
+ //
133
+ // This first-valid scan superseded a plain last-`::` split, which broke exactly
134
+ // that case: `global::foo-lessons::bar` split at the last `::` gave the left
135
+ // side `global::foo-lessons`, not a valid scope, so the whole arg fell through
136
+ // to the scope and `scopeIssue` rejected it. Gating on a valid left side is what
137
+ // keeps a bare `repo::owner/name` from mis-splitting (its `repo` prefix is not a
138
+ // valid scope) and a multi-segment scope whole (`branch::o/n::main::key` → scope
139
+ // `branch::o/n::main`, key `key`, since the shorter prefixes are all invalid). A
140
+ // malformed arg falls through to the scope, never a fabricated key.
134
141
  //
135
142
  // `isScope` is injected rather than closed over so the module stays trivially
136
143
  // testable with a stub predicate; callers pass `isScopeString`.
137
144
  export function resolveScopeArg(arg, isScope = isScopeString) {
138
145
  const s = typeof arg === 'string' ? arg.trim() : '';
139
146
  if (!s) return { scope: null, key: null };
140
- const idx = s.lastIndexOf('::');
141
- if (idx !== -1) {
147
+ for (let idx = s.indexOf('::'); idx !== -1; idx = s.indexOf('::', idx + 2)) {
142
148
  const left = s.slice(0, idx).trim();
143
149
  const right = s.slice(idx + 2).trim();
144
150
  if (right && isScope(left)) return { scope: left, key: right };
@@ -159,7 +159,7 @@ export function mcpToRestBase(mcpEndpointUrl) {
159
159
  /**
160
160
  * Normalise a client-supplied usage correlation id (a PR ref, session id, or CI
161
161
  * job id). Bounded + charset-restricted to match the server's `parseCorrelationId`
162
- * (supabase/functions/_shared/usage-stats.ts); returns null for empty/over-long/
162
+ * (supabase/functions/_shared/telemetry/usage-stats.ts); returns null for empty/over-long/
163
163
  * out-of-charset input so a bad value is simply not sent. Zero-dep (the CLI does
164
164
  * not import mcp-core), so the small regex is duplicated intentionally.
165
165
  */
@@ -1,6 +1,6 @@
1
1
  // GENERATED — do not edit.
2
2
  // Source: packages/schemas/src/shared/tool-catalog.ts
3
- // Regenerate: node scripts/gen-surfaces.mjs
3
+ // Regenerate: node scripts/codegen/gen-surfaces.mjs
4
4
  //
5
5
  // Edit the catalog's `surfaces` bindings, not this file. `--check` fails CI
6
6
  // when the two disagree.
@@ -4,7 +4,7 @@
4
4
  // source tree and nothing secret is ever committed to git. The release workflow
5
5
  // (.github/workflows/release.yml → publish-cli) overwrites this file at publish
6
6
  // time from the LOREKIT_TELEMETRY_TOKEN secret via
7
- // scripts/inject-telemetry-token.mjs, so only the *published npm tarball*
7
+ // scripts/telemetry/inject-telemetry-token.mjs, so only the *published npm tarball*
8
8
  // carries the token.
9
9
  //
10
10
  // The token is public by design once published (anyone can unpack the tarball),
@@ -183,7 +183,7 @@ export function resolveTelemetryTokenSource(env = process.env) {
183
183
  return 'none';
184
184
  }
185
185
 
186
- // ── ID + value helpers (mirror _shared/otel.ts) ───────────────────────────────
186
+ // ── ID + value helpers (mirror _shared/telemetry/otel.ts) ───────────────────────────────
187
187
 
188
188
  export function randHex(bytes) {
189
189
  const b = new Uint8Array(bytes);
@@ -236,7 +236,7 @@ export function normalizeHostArch(arch) {
236
236
  * the attribute by default. It is emitted ONLY when explicitly overridden via
237
237
  * `DEPLOYMENT_ENVIRONMENT` (falling back to `OTEL_DEPLOYMENT_ENVIRONMENT`) — the
238
238
  * same single, env-driven knob the edge honours, which the correlated-trace
239
- * harness (`scripts/emit-correlated-trace.mts`) uses to stamp `test`.
239
+ * harness (`scripts/telemetry/emit-correlated-trace.mts`) uses to stamp `test`.
240
240
  * @param {object} [env] defaults to process.env
241
241
  */
242
242
  export function resolveDeploymentEnvironment(env = process.env) {