Skip to content

Commit d6d80b4

Browse files
jonathanMLDevzho
andauthored
feat: expose guided_query in core and document core/Alliance gate def… (#167)
* feat: expose guided_query in core and document core/Alliance gate defaults * addressed ai agent reviews --------- Co-authored-by: zho <jornathanm910923@gmail.com>
1 parent e36184b commit d6d80b4

17 files changed

Lines changed: 468 additions & 305 deletions

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Tagged releases are published to npm from GitHub Actions when a **GitHub Release
1010

1111
### Added
1212

13+
- `guided_query` tool registered by `setupCoreServer` / package-root import (core-layer handler; no Alliance URL generators or index defaults required).
1314
- `ServerContextComposition` interface plus `NamespaceCacheSeed` and `SuggestionFlowSeedEntry` types for dependency injection into `ServerContext`.
1415
- `createIsolatedContext(config, composition?)` factory for multi-tenant embedders (no process-global side effects).
1516
- Zod schemas for all nine MCP tool success responses (`queryResponseSchema`, `guidedQueryResponseSchema`, etc.) exported from the package root for client-side validation. Success payloads are runtime-validated before return.
@@ -22,7 +23,7 @@ Tagged releases are published to npm from GitHub Actions when a **GitHub Release
2223
- `createServer(config, composition?)` now accepts an optional composition object.
2324
- **Breaking (MCP):** Experimental tool response fields are nested under `experimental` on success payloads. Affected tools: `query`, `query_documents`, `guided_query`. Fields moved: `degraded`, `degradation_reason`, `hybrid_leg_failed`, `rerank_skipped_reason` (query-shaped tools); `decision_trace` (`guided_query`). Stable fields (`status`, `results`, `namespace`, etc.) are unchanged. See [MIGRATION.md](docs/MIGRATION.md#unreleased-stable-vs-experimental-response-fields).
2425
- **Breaking (core):** `resolveConfig` requires a Pinecone index name and no longer applies Alliance index/rerank defaults. Removed exported `DEFAULT_INDEX_NAME` and `DEFAULT_RERANK_MODEL` from the package root. Rerank is opt-in when `PINECONE_RERANK_MODEL` / `rerankModel` is unset.
25-
- **Breaking (core):** `setupCoreServer` MCP `instructions` use `CORE_SERVER_INSTRUCTIONS` (no `guided_query` / `suggest_query_params`). `resolveConfig` defaults `disableSuggestFlow` to `true` so `query` / `count` / `query_documents` work without Alliance tools. Alliance CLI / `resolveAllianceConfig` unchanged: gate on by default, `ALLIANCE_SERVER_INSTRUCTIONS`.
26+
- **Breaking (core):** `setupCoreServer` MCP `instructions` use `CORE_SERVER_INSTRUCTIONS` (includes `guided_query`; no `suggest_query_params`). `resolveConfig` defaults `disableSuggestFlow` to `true` so `query` / `count` / `query_documents` work without Alliance tools. Alliance CLI / `resolveAllianceConfig` unchanged: gate on by default, `ALLIANCE_SERVER_INSTRUCTIONS`.
2627
- **Alliance CLI / `resolveAllianceConfig`:** When index or rerank env/CLI values are omitted, defaults remain `rag-hybrid` and `bge-reranker-v2-m3` (API-key-only MCP configs unchanged). See [examples/alliance/.env.example](examples/alliance/.env.example).
2728
- **Breaking (library):** Trimmed public re-exports — `buildQueryExperimental` and `buildGuidedQueryExperimental` removed from package root and `/alliance` entry. See [MIGRATION.md](docs/MIGRATION.md#unreleased-trimmed-library-exports).
2829

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ To try the server on **your own** Pinecone project (free tier, no Alliance index
103103

104104
The codebase is split into two layers:
105105

106-
- **`src/core/`** — generic MCP–Pinecone bridge (`PineconeClient`, `resolveConfig`, core MCP tools). Import from `@will-cppa/pinecone-read-only-mcp` (package root).
107-
- **`src/alliance/`** — C++ Alliance app tools (`suggest_query_params`, `guided_query`, Boost/Slack URL builtins). Import from `@will-cppa/pinecone-read-only-mcp/alliance` and use `createServer(config)``ctx.setClient(...)``setupAllianceServer({ context: ctx })` for the full tool surface (what the CLI uses); see [Library embedding](#library-embedding) below.
106+
- **`src/core/`** — generic MCP–Pinecone bridge (`PineconeClient`, `resolveConfig`, eight MCP tools including `guided_query`). Import from `@will-cppa/pinecone-read-only-mcp` (package root).
107+
- **`src/alliance/`** — C++ Alliance app layer (`suggest_query_params`, Boost/Slack URL builtins). Import from `@will-cppa/pinecone-read-only-mcp/alliance` and use `createServer(config)``ctx.setClient(...)``setupAllianceServer({ context: ctx })` for the full tool surface (what the CLI uses); suggest-flow gate on by default. See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for core vs Alliance defaults and [Library embedding](#library-embedding) below.
108108

109109
## Configuration
110110

docs/CONFIGURATION.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ For the full Alliance tool surface (including `suggest_query_params`, `guided_qu
3737
| `resolveConfig` | Package root, `setupCoreServer`, quickstart | **Throws** | Omitted (no rerank) | Off (`disableSuggestFlow: true`) |
3838
| `resolveAllianceConfig` | Published CLI, `setupAllianceServer` | `rag-hybrid` | `bge-reranker-v2-m3` | On (`disableSuggestFlow: false`) |
3939

40+
**Warning:** Switching between `resolveConfig` / `setupCoreServer` (package root) and `resolveAllianceConfig` / `setupAllianceServer` changes suggest-flow gate behavior. Core defaults bypass the gate; Alliance defaults enforce it. Use `guided_query` (registered in both setups) for single-call retrieval without manual `suggest_query_params`, or align `disableSuggestFlow` explicitly when migrating between entry points.
41+
4042
C++ Alliance deployers can copy [examples/alliance/.env.example](../examples/alliance/.env.example). Constants: `ALLIANCE_DEFAULT_INDEX_NAME` / `ALLIANCE_DEFAULT_RERANK_MODEL` from `@will-cppa/pinecone-read-only-mcp/alliance`.
4143

4244
---

docs/MIGRATION.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,17 @@ Core `resolveConfig` throws `Missing Pinecone index name: …` when the index is
243243
- The binary uses `resolveAllianceConfig`; API-key-only configs still default to `rag-hybrid` and `bge-reranker-v2-m3`.
244244
- Explicit env overrides still win. Copy [examples/alliance/.env.example](../examples/alliance/.env.example) to document Alliance conventions.
245245

246+
### Suggest-flow gate (`disableSuggestFlow`) — intentional divergence
247+
248+
| Entry point | Default | Rationale |
249+
| ----------- | ------- | --------- |
250+
| `resolveConfig` / `setupCoreServer` | Gate **off** (`disableSuggestFlow: true`) | Generic embedders can call `query` / `count` / `query_documents` directly; `guided_query` is the recommended ceremony-free path |
251+
| `resolveAllianceConfig` / CLI | Gate **on** (`disableSuggestFlow: false`) | Production MCP safety: manual `query` requires `suggest_query_params` first |
252+
253+
**Decision (unchanged):** Exposing `guided_query` in core does **not** change the core gate default. Core keeps the gate off so direct tool access remains available; Alliance keeps the gate on for CLI/MCP deployments.
254+
255+
**When migrating entry points:** If you move from Alliance to core (or vice versa), query gate behavior changes unless you set `disableSuggestFlow` explicitly. Use `guided_query` to avoid the multi-step suggest flow in either setup.
256+
246257
---
247258

248259
## Migrating to v0.2.0

docs/TOOLS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ Promotion process: [deprecation-policy.md § Stable vs experimental](./deprecati
2424

2525
| Setup | Tools | MCP instructions |
2626
| ----- | ----- | ------------------ |
27-
| `setupCoreServer` (package root) | **7:** `list_namespaces`, `namespace_router`, `count`, `query`, `keyword_search`, `query_documents`, `generate_urls` | `CORE_SERVER_INSTRUCTIONS`no `guided_query` or `suggest_query_params` |
28-
| `setupAllianceServer` / published CLI | **9:** core tools plus `suggest_query_params`, `guided_query` | `ALLIANCE_SERVER_INSTRUCTIONS` — includes guided/suggest quickstart |
27+
| `setupCoreServer` (package root) | **8:** `list_namespaces`, `namespace_router`, `count`, `query`, `keyword_search`, `query_documents`, `generate_urls`, `guided_query` | `CORE_SERVER_INSTRUCTIONS`includes `guided_query`; no `suggest_query_params` |
28+
| `setupAllianceServer` / published CLI | **9:** core tools plus `suggest_query_params` | `ALLIANCE_SERVER_INSTRUCTIONS` — includes suggest-flow quickstart |
2929

3030
## Suggest-flow gate
3131

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { afterEach, describe, expect, it, vi } from 'vitest';
2+
import { setupAllianceServer } from '../alliance/setup.js';
3+
import { resolveAllianceConfig } from '../alliance/config.js';
4+
import { setPineconeClient } from '../core/index.js';
5+
import { resolveConfig } from '../core/config.js';
6+
import { getDefaultServerContext } from '../core/server/server-context.js';
7+
import * as guidedQueryTool from '../core/server/tools/guided-query-tool.js';
8+
import { registerQueryTool } from '../core/server/tools/query-tool.js';
9+
import {
10+
assertToolErrorCode,
11+
createMockServer,
12+
createTestServerContext,
13+
makeHybridQueryResult,
14+
parseToolJson,
15+
} from '../core/server/tools/test-helpers.js';
16+
import { setupCoreServer, teardownServer } from '../core/setup.js';
17+
import { PineconeClient } from '../core/pinecone-client.js';
18+
19+
describe('cross-entry-point: core vs Alliance defaults', () => {
20+
afterEach(() => {
21+
teardownServer();
22+
});
23+
24+
it('core entry point disables suggest-flow gate by default', () => {
25+
const cfg = resolveConfig(
26+
{ apiKey: 'sk-test', indexName: 'my-index' },
27+
{ PINECONE_API_KEY: 'sk-test', PINECONE_INDEX_NAME: 'my-index' }
28+
);
29+
expect(cfg.disableSuggestFlow).toBe(true);
30+
});
31+
32+
it('Alliance entry point enables suggest-flow gate by default', () => {
33+
const cfg = resolveAllianceConfig({ apiKey: 'sk-test' }, { PINECONE_API_KEY: 'sk-test' });
34+
expect(cfg.disableSuggestFlow).toBe(false);
35+
});
36+
37+
it('core-initialized server: query succeeds without prior suggest_query_params', async () => {
38+
const query = vi.fn().mockResolvedValue(makeHybridQueryResult());
39+
const ctx = createTestServerContext({
40+
config: {
41+
disableSuggestFlow: true,
42+
},
43+
client: { query } as never,
44+
});
45+
const server = createMockServer();
46+
registerQueryTool(server as never, ctx);
47+
const body = parseToolJson(
48+
await server.getHandler('query')!({
49+
query_text: 'hello',
50+
namespace: 'wg21',
51+
preset: 'fast',
52+
})
53+
);
54+
expect(body.status).toBe('success');
55+
expect(query).toHaveBeenCalledOnce();
56+
});
57+
58+
it('Alliance-initialized server: query returns FLOW_GATE without prior suggestion', async () => {
59+
const cfg = resolveAllianceConfig(
60+
{ apiKey: 'sk-test', indexName: 'my-index' },
61+
{ PINECONE_API_KEY: 'sk-test', PINECONE_INDEX_NAME: 'my-index' }
62+
);
63+
const ctx = createTestServerContext({
64+
config: cfg,
65+
client: { query: vi.fn() } as never,
66+
});
67+
const server = createMockServer();
68+
registerQueryTool(server as never, ctx);
69+
const raw = await server.getHandler('query')!({
70+
query_text: 'hello',
71+
namespace: 'wg21',
72+
preset: 'fast',
73+
});
74+
const err = assertToolErrorCode(raw, 'FLOW_GATE');
75+
expect(err.suggestion).toBe("Call suggest_query_params for namespace 'wg21' first");
76+
});
77+
78+
it('setupAllianceServer wires Alliance gate defaults: query returns FLOW_GATE', async () => {
79+
const cfg = resolveAllianceConfig(
80+
{ apiKey: 'sk-test', indexName: 'my-index' },
81+
{ PINECONE_API_KEY: 'sk-test', PINECONE_INDEX_NAME: 'my-index' }
82+
);
83+
setPineconeClient(
84+
new PineconeClient({
85+
apiKey: cfg.apiKey,
86+
indexName: cfg.indexName,
87+
defaultTopK: cfg.defaultTopK,
88+
})
89+
);
90+
await setupAllianceServer({ config: cfg });
91+
const ctx = getDefaultServerContext();
92+
expect(ctx.getConfig().disableSuggestFlow).toBe(false);
93+
94+
const server = createMockServer();
95+
registerQueryTool(server as never, ctx);
96+
const raw = await server.getHandler('query')!({
97+
query_text: 'hello',
98+
namespace: 'wg21',
99+
preset: 'fast',
100+
});
101+
assertToolErrorCode(raw, 'FLOW_GATE');
102+
});
103+
104+
it('core setup registers guided_query handler', async () => {
105+
const cfg = resolveConfig({ apiKey: 'sk-cross', indexName: 'test-index' });
106+
const ctx = createTestServerContext({
107+
config: cfg,
108+
client: new PineconeClient({
109+
apiKey: cfg.apiKey,
110+
indexName: cfg.indexName,
111+
defaultTopK: cfg.defaultTopK,
112+
}),
113+
});
114+
const registerSpy = vi.spyOn(guidedQueryTool, 'registerGuidedQueryTool');
115+
116+
await setupCoreServer({ context: ctx });
117+
118+
expect(registerSpy).toHaveBeenCalledOnce();
119+
expect(ctx.hasToolsRegistered()).toBe(true);
120+
registerSpy.mockRestore();
121+
});
122+
});

src/alliance/config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ export const DEFAULT_ALLIANCE_RERANK_MODEL = ALLIANCE_DEFAULT_RERANK_MODEL;
2323
* Build {@link ServerConfig} for Alliance CLI and `setupAllianceServer`.
2424
* Fills index and rerank from Alliance defaults when unset, then calls core `resolveConfig`.
2525
*
26+
* **Suggest-flow gate default:** After core resolution, `disableSuggestFlow` is overridden to
27+
* `false` (gate on) unless `PINECONE_DISABLE_SUGGEST_FLOW` or `disableSuggestFlow` in overrides
28+
* says otherwise. This differs from package-root {@link resolveConfig} (`true` / gate off).
29+
* Switching between core and Alliance entry points changes query gate behavior — use
30+
* `guided_query` (available in both) for ceremony-free retrieval, or call
31+
* `suggest_query_params` before gated tools when the gate is on.
32+
*
2633
* Output is the `config` half of the embedder pattern `{ config, composition }`.
2734
* Pair with {@link createIsolatedContext} or {@link createServer} and an optional
2835
* {@link ServerContextComposition} for per-instance injectables.

src/alliance/setup.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { getDefaultServerContext, type ServerContext } from '../core/server/serv
44
import { resolveAllianceConfig } from './config.js';
55
import { setupCoreServer, type ServerHandle, type SetupCoreServerOptions } from '../core/setup.js';
66
import { registerBuiltinUrlGenerators } from './url-builtins.js';
7-
import { registerGuidedQueryTool } from './tools/guided-query-tool.js';
87
import { registerSuggestQueryParamsTool } from './tools/suggest-query-params-tool.js';
98

109
/**
@@ -56,7 +55,7 @@ function normalizeSetupAllianceArgs(
5655

5756
/**
5857
* Create and configure the MCP server with the full Alliance tool surface:
59-
* all core tools plus `suggest_query_params`, `guided_query`, and built-in URL generators.
58+
* all core tools (including `guided_query`) plus `suggest_query_params` and built-in URL generators.
6059
*
6160
* When `config` is omitted, resolves env via {@link resolveAllianceConfig} (Alliance index/rerank defaults when unset).
6261
*/
@@ -88,6 +87,5 @@ export async function setupAllianceServer(
8887

8988
registerBuiltinUrlGenerators(resolvedCtx);
9089
registerSuggestQueryParamsTool(server, resolvedCtx);
91-
registerGuidedQueryTool(server, resolvedCtx);
9290
return server;
9391
}

0 commit comments

Comments
 (0)