@oka-core/reason 0.2.13 → 0.2.15
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/dist/auth.d.ts +15 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +77 -0
- package/dist/client.d.ts +22 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +82 -59
- package/dist/tools/auth.d.ts.map +1 -1
- package/dist/tools/auth.js +8 -7
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +2 -2
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +44 -2
- package/package.json +1 -1
package/dist/auth.d.ts
CHANGED
|
@@ -39,6 +39,21 @@ export declare function resolveApiKey(): string;
|
|
|
39
39
|
* Async version that tries token refresh before giving up.
|
|
40
40
|
*/
|
|
41
41
|
export declare function resolveApiKeyWithRefresh(): Promise<string>;
|
|
42
|
+
export declare class McpTokenManager {
|
|
43
|
+
private refreshTimer;
|
|
44
|
+
/**
|
|
45
|
+
* Get a valid token, refreshing proactively if needed.
|
|
46
|
+
* This is the single entry point for auth — replaces resolveApiKey().
|
|
47
|
+
*/
|
|
48
|
+
getValidToken(): Promise<string>;
|
|
49
|
+
/**
|
|
50
|
+
* Schedule a background refresh REFRESH_BEFORE_EXPIRY_S before token expires.
|
|
51
|
+
*/
|
|
52
|
+
private scheduleRefresh;
|
|
53
|
+
private backgroundRefresh;
|
|
54
|
+
private clearTimer;
|
|
55
|
+
destroy(): void;
|
|
56
|
+
}
|
|
42
57
|
export interface LoginResult {
|
|
43
58
|
success: boolean;
|
|
44
59
|
message: string;
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAWD,wBAAgB,qBAAqB,IAAI,iBAAiB,GAAG,IAAI,CAOhE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAa/D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW1D;AAID,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CA0B7C;AAOD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOnD;AAID;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAuBtC;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAwBhE;AAuGD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,aAAa,CAAC,EAAE,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC,CAsCtB"}
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAWD,wBAAgB,qBAAqB,IAAI,iBAAiB,GAAG,IAAI,CAOhE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAa/D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW1D;AAID,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CA0B7C;AAOD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOnD;AAID;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAuBtC;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAwBhE;AASD,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAA8C;IAElE;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAsCtC;;OAEG;IACH,OAAO,CAAC,eAAe;YAeT,iBAAiB;IAQ/B,OAAO,CAAC,UAAU;IAOlB,OAAO,IAAI,IAAI;CAGhB;AAuGD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,aAAa,CAAC,EAAE,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC,CAsCtB"}
|
package/dist/auth.js
CHANGED
|
@@ -191,6 +191,83 @@ export async function resolveApiKeyWithRefresh() {
|
|
|
191
191
|
}
|
|
192
192
|
return "";
|
|
193
193
|
}
|
|
194
|
+
// ─── MCP Token Manager ──────────────────────────────────────────
|
|
195
|
+
// Proactive token refresh adapted for Node.js file-based credentials.
|
|
196
|
+
// Same pattern as @oka/auth-sdk TokenManager but reads ~/.oka/credentials.json
|
|
197
|
+
// instead of window.localStorage.
|
|
198
|
+
const REFRESH_BEFORE_EXPIRY_S = 300; // 5 minutes
|
|
199
|
+
export class McpTokenManager {
|
|
200
|
+
refreshTimer = null;
|
|
201
|
+
/**
|
|
202
|
+
* Get a valid token, refreshing proactively if needed.
|
|
203
|
+
* This is the single entry point for auth — replaces resolveApiKey().
|
|
204
|
+
*/
|
|
205
|
+
async getValidToken() {
|
|
206
|
+
// 1. Environment variable always wins
|
|
207
|
+
const envKey = process.env["OKA_API_KEY"];
|
|
208
|
+
if (envKey)
|
|
209
|
+
return envKey;
|
|
210
|
+
// 2. Check stored credentials
|
|
211
|
+
const stored = loadStoredCredentials();
|
|
212
|
+
if (stored?.api_key)
|
|
213
|
+
return stored.api_key;
|
|
214
|
+
if (stored?.access_token) {
|
|
215
|
+
const now = Date.now() / 1000;
|
|
216
|
+
const exp = extractJwtExp(stored.access_token) ?? stored.expires_at ?? 0;
|
|
217
|
+
const expiringSoon = exp - now < REFRESH_BEFORE_EXPIRY_S;
|
|
218
|
+
if (!expiringSoon) {
|
|
219
|
+
this.scheduleRefresh(exp);
|
|
220
|
+
return stored.access_token;
|
|
221
|
+
}
|
|
222
|
+
// Token expired or expiring soon — refresh now
|
|
223
|
+
if (stored.refresh_token) {
|
|
224
|
+
const newToken = await tryRefresh();
|
|
225
|
+
if (newToken) {
|
|
226
|
+
const newExp = extractJwtExp(newToken) ?? 0;
|
|
227
|
+
this.scheduleRefresh(newExp);
|
|
228
|
+
return newToken;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Refresh failed but token might still be technically valid
|
|
232
|
+
if (exp > now) {
|
|
233
|
+
return stored.access_token;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return "";
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Schedule a background refresh REFRESH_BEFORE_EXPIRY_S before token expires.
|
|
240
|
+
*/
|
|
241
|
+
scheduleRefresh(expiresAtSec) {
|
|
242
|
+
this.clearTimer();
|
|
243
|
+
const delayMs = (expiresAtSec - REFRESH_BEFORE_EXPIRY_S - Date.now() / 1000) * 1000;
|
|
244
|
+
if (delayMs <= 0)
|
|
245
|
+
return; // Already in refresh window, handled by getValidToken
|
|
246
|
+
this.refreshTimer = setTimeout(() => {
|
|
247
|
+
void this.backgroundRefresh();
|
|
248
|
+
}, delayMs);
|
|
249
|
+
// Don't let the timer prevent Node.js from exiting
|
|
250
|
+
if (this.refreshTimer && typeof this.refreshTimer === "object") {
|
|
251
|
+
this.refreshTimer.unref();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async backgroundRefresh() {
|
|
255
|
+
const newToken = await tryRefresh();
|
|
256
|
+
if (newToken) {
|
|
257
|
+
const exp = extractJwtExp(newToken) ?? 0;
|
|
258
|
+
this.scheduleRefresh(exp);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
clearTimer() {
|
|
262
|
+
if (this.refreshTimer) {
|
|
263
|
+
clearTimeout(this.refreshTimer);
|
|
264
|
+
this.refreshTimer = null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
destroy() {
|
|
268
|
+
this.clearTimer();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
194
271
|
const DEFAULT_AUTH_SERVER = "https://id.oka.so";
|
|
195
272
|
const DEFAULT_CLIENT_ID = "oka-reason-mcp";
|
|
196
273
|
async function requestDeviceCode(authServerUrl, clientId) {
|
package/dist/client.d.ts
CHANGED
|
@@ -154,6 +154,7 @@ export interface HybridPipelineMeta {
|
|
|
154
154
|
after_dedup: number;
|
|
155
155
|
pipeline_stages: string[];
|
|
156
156
|
elapsed_ms: number;
|
|
157
|
+
feedback_id?: string;
|
|
157
158
|
}
|
|
158
159
|
export interface HybridSearchResponse {
|
|
159
160
|
query: string;
|
|
@@ -182,6 +183,11 @@ export declare class OkaClient {
|
|
|
182
183
|
private readonly agentId;
|
|
183
184
|
private readonly sessionId;
|
|
184
185
|
private readonly timeout;
|
|
186
|
+
private readonly tokenManager;
|
|
187
|
+
/** Maps learning_id → feedback_id for LTR attribution across tool calls. */
|
|
188
|
+
private readonly searchContext;
|
|
189
|
+
/** Reverse map: short ID prefix → full UUID */
|
|
190
|
+
private readonly idLookup;
|
|
185
191
|
constructor(config?: OkaClientConfig);
|
|
186
192
|
updateApiKey(key: string): void;
|
|
187
193
|
ingest(event: IngestEvent): Promise<void>;
|
|
@@ -217,18 +223,29 @@ export declare class OkaClient {
|
|
|
217
223
|
* GET /api/learnings/query/:input
|
|
218
224
|
*/
|
|
219
225
|
hybridSearch(query: string, options?: HybridSearchOptions): Promise<HybridSearchResponse>;
|
|
226
|
+
/**
|
|
227
|
+
* Submit explicit feedback on a learning (useful/not useful).
|
|
228
|
+
*/
|
|
229
|
+
submitFeedback(params: {
|
|
230
|
+
learning_id?: string;
|
|
231
|
+
useful?: boolean;
|
|
232
|
+
reason?: string;
|
|
233
|
+
used_ids?: string[];
|
|
234
|
+
query_feedback_id?: string;
|
|
235
|
+
}): Promise<void>;
|
|
236
|
+
/**
|
|
237
|
+
* Report which learnings were actually used (implicit feedback).
|
|
238
|
+
* Groups by feedback_id from searchContext for correct attribution.
|
|
239
|
+
*/
|
|
240
|
+
reportUsedLearnings(usedIds: string[]): void;
|
|
220
241
|
/**
|
|
221
242
|
* Trigger a consolidation run.
|
|
222
243
|
* POST /api/reasoning/consolidate
|
|
223
244
|
*/
|
|
224
245
|
triggerConsolidation(req: ConsolidateRequest): Promise<ConsolidateResponse>;
|
|
225
246
|
private authHeaders;
|
|
247
|
+
private buildHeaders;
|
|
226
248
|
private get;
|
|
227
249
|
private post;
|
|
228
|
-
/**
|
|
229
|
-
* On 401, attempt to refresh the token and retry the request once.
|
|
230
|
-
* Returns the parsed JSON response on success, or null if refresh failed.
|
|
231
|
-
*/
|
|
232
|
-
private retryWithRefresh;
|
|
233
250
|
}
|
|
234
251
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventBuffer } from "./buffer.js";
|
|
2
|
-
import {
|
|
2
|
+
import { McpTokenManager } from "./auth.js";
|
|
3
3
|
/**
|
|
4
4
|
* Unified HTTP client for Oka Reason API.
|
|
5
5
|
*
|
|
@@ -21,6 +21,11 @@ export class OkaClient {
|
|
|
21
21
|
agentId;
|
|
22
22
|
sessionId;
|
|
23
23
|
timeout;
|
|
24
|
+
tokenManager;
|
|
25
|
+
/** Maps learning_id → feedback_id for LTR attribution across tool calls. */
|
|
26
|
+
searchContext = new Map();
|
|
27
|
+
/** Reverse map: short ID prefix → full UUID */
|
|
28
|
+
idLookup = new Map();
|
|
24
29
|
constructor(config) {
|
|
25
30
|
this.apiUrl = (config?.apiUrl ||
|
|
26
31
|
process.env["OKA_API_URL"] ||
|
|
@@ -31,6 +36,7 @@ export class OkaClient {
|
|
|
31
36
|
this.sessionId = process.env["SESSION_ID"] || `session-${Date.now()}`;
|
|
32
37
|
this.buffer = new EventBuffer(100);
|
|
33
38
|
this.timeout = 15_000;
|
|
39
|
+
this.tokenManager = new McpTokenManager();
|
|
34
40
|
}
|
|
35
41
|
updateApiKey(key) {
|
|
36
42
|
this.apiKey = key;
|
|
@@ -52,12 +58,10 @@ export class OkaClient {
|
|
|
52
58
|
if (events.length === 0)
|
|
53
59
|
return;
|
|
54
60
|
try {
|
|
61
|
+
const headers = await this.authHeaders();
|
|
55
62
|
await fetch(`${this.apiUrl}/api/reasoning/ingest`, {
|
|
56
63
|
method: "POST",
|
|
57
|
-
headers
|
|
58
|
-
"Content-Type": "application/json",
|
|
59
|
-
...this.authHeaders(),
|
|
60
|
-
},
|
|
64
|
+
headers,
|
|
61
65
|
body: JSON.stringify({ events }),
|
|
62
66
|
signal: AbortSignal.timeout(5_000),
|
|
63
67
|
});
|
|
@@ -96,8 +100,9 @@ export class OkaClient {
|
|
|
96
100
|
if (v)
|
|
97
101
|
url.searchParams.set(k, v);
|
|
98
102
|
}
|
|
103
|
+
const headers = await this.authHeaders();
|
|
99
104
|
const res = await fetch(url.toString(), {
|
|
100
|
-
headers
|
|
105
|
+
headers,
|
|
101
106
|
signal: AbortSignal.timeout(10_000),
|
|
102
107
|
});
|
|
103
108
|
if (!res.ok)
|
|
@@ -214,7 +219,7 @@ export class OkaClient {
|
|
|
214
219
|
params.set("rerank", "true");
|
|
215
220
|
if (options?.mode)
|
|
216
221
|
params.set("mode", options.mode);
|
|
217
|
-
|
|
222
|
+
const data = await this.get(`/api/learnings/query/${encodeURIComponent(query)}?${params}`).catch(() => ({
|
|
218
223
|
query,
|
|
219
224
|
results: [],
|
|
220
225
|
total_candidates: 0,
|
|
@@ -227,6 +232,60 @@ export class OkaClient {
|
|
|
227
232
|
elapsed_ms: 0,
|
|
228
233
|
},
|
|
229
234
|
}));
|
|
235
|
+
// Track learning → feedback_id for LTR attribution.
|
|
236
|
+
// Index by both full UUID and 8-char prefix (agents see short IDs).
|
|
237
|
+
if (data.pipeline.feedback_id) {
|
|
238
|
+
const fbId = data.pipeline.feedback_id;
|
|
239
|
+
this.idLookup.set(fbId.slice(0, 8), fbId);
|
|
240
|
+
for (const r of data.results) {
|
|
241
|
+
this.searchContext.set(r.id, fbId);
|
|
242
|
+
this.searchContext.set(r.id.slice(0, 8), fbId);
|
|
243
|
+
this.idLookup.set(r.id.slice(0, 8), r.id);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return data;
|
|
247
|
+
}
|
|
248
|
+
// ─── Feedback (LTR training data) ────────────────────────────────
|
|
249
|
+
/**
|
|
250
|
+
* Submit explicit feedback on a learning (useful/not useful).
|
|
251
|
+
*/
|
|
252
|
+
async submitFeedback(params) {
|
|
253
|
+
// Resolve short 8-char IDs to full UUIDs for the API
|
|
254
|
+
const resolved = {
|
|
255
|
+
...params,
|
|
256
|
+
learning_id: params.learning_id
|
|
257
|
+
? (this.idLookup.get(params.learning_id) ?? params.learning_id)
|
|
258
|
+
: undefined,
|
|
259
|
+
query_feedback_id: params.query_feedback_id
|
|
260
|
+
? (this.idLookup.get(params.query_feedback_id) ??
|
|
261
|
+
params.query_feedback_id)
|
|
262
|
+
: undefined,
|
|
263
|
+
};
|
|
264
|
+
await this.post("/api/reasoning/feedback", resolved).catch(() => { });
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Report which learnings were actually used (implicit feedback).
|
|
268
|
+
* Groups by feedback_id from searchContext for correct attribution.
|
|
269
|
+
*/
|
|
270
|
+
reportUsedLearnings(usedIds) {
|
|
271
|
+
// Group used IDs by their feedback_id, resolving short IDs to full UUIDs
|
|
272
|
+
const byFeedback = new Map();
|
|
273
|
+
for (const id of usedIds) {
|
|
274
|
+
const fullId = this.idLookup.get(id) ?? id;
|
|
275
|
+
const fbId = this.searchContext.get(id) ?? this.searchContext.get(fullId);
|
|
276
|
+
if (fbId) {
|
|
277
|
+
const list = byFeedback.get(fbId) ?? [];
|
|
278
|
+
list.push(fullId);
|
|
279
|
+
byFeedback.set(fbId, list);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// Fire-and-forget one request per feedback_id
|
|
283
|
+
for (const [feedbackId, ids] of byFeedback) {
|
|
284
|
+
this.submitFeedback({
|
|
285
|
+
query_feedback_id: feedbackId,
|
|
286
|
+
used_ids: ids,
|
|
287
|
+
}).catch(() => { });
|
|
288
|
+
}
|
|
230
289
|
}
|
|
231
290
|
// ─── Consolidation ──────────────────────────────────────────────
|
|
232
291
|
/**
|
|
@@ -238,17 +297,16 @@ export class OkaClient {
|
|
|
238
297
|
return this.post("/api/reasoning/consolidate", body, 120_000);
|
|
239
298
|
}
|
|
240
299
|
// ─── HTTP helpers ───────────────────────────────────────────────
|
|
241
|
-
authHeaders() {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
300
|
+
async authHeaders() {
|
|
301
|
+
const key = this.apiKey || (await this.tokenManager.getValidToken());
|
|
302
|
+
return this.buildHeaders(key);
|
|
303
|
+
}
|
|
304
|
+
buildHeaders(key) {
|
|
245
305
|
const headers = {
|
|
246
306
|
"Content-Type": "application/json",
|
|
247
307
|
};
|
|
248
308
|
if (key) {
|
|
249
309
|
// JWTs have dots (header.payload.signature); API keys don't.
|
|
250
|
-
// Sending both headers causes the server to try Bearer first and fail
|
|
251
|
-
// when the value is an API key, never falling back to X-Api-Key.
|
|
252
310
|
const isJwt = key.includes(".");
|
|
253
311
|
if (isJwt) {
|
|
254
312
|
headers["Authorization"] = `Bearer ${key}`;
|
|
@@ -260,22 +318,20 @@ export class OkaClient {
|
|
|
260
318
|
return headers;
|
|
261
319
|
}
|
|
262
320
|
async get(path) {
|
|
321
|
+
const headers = await this.authHeaders();
|
|
263
322
|
const controller = new AbortController();
|
|
264
323
|
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
265
324
|
try {
|
|
266
325
|
const response = await fetch(`${this.apiUrl}${path}`, {
|
|
267
326
|
method: "GET",
|
|
268
|
-
headers
|
|
327
|
+
headers,
|
|
269
328
|
signal: controller.signal,
|
|
270
329
|
});
|
|
271
|
-
if (response.
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
throw new Error("HTTP 401: authentication failed — run mcp__oka__login to re-authenticate");
|
|
330
|
+
if (!response.ok) {
|
|
331
|
+
throw new Error(response.status === 401
|
|
332
|
+
? "HTTP 401: authentication failed — run mcp__oka__login to re-authenticate"
|
|
333
|
+
: `HTTP ${response.status}`);
|
|
276
334
|
}
|
|
277
|
-
if (!response.ok)
|
|
278
|
-
throw new Error(`HTTP ${response.status}`);
|
|
279
335
|
return response.json();
|
|
280
336
|
}
|
|
281
337
|
finally {
|
|
@@ -283,22 +339,20 @@ export class OkaClient {
|
|
|
283
339
|
}
|
|
284
340
|
}
|
|
285
341
|
async post(path, body, timeout) {
|
|
342
|
+
const headers = await this.authHeaders();
|
|
286
343
|
const controller = new AbortController();
|
|
287
344
|
const timer = setTimeout(() => controller.abort(), timeout ?? this.timeout);
|
|
288
345
|
try {
|
|
289
346
|
const response = await fetch(`${this.apiUrl}${path}`, {
|
|
290
347
|
method: "POST",
|
|
291
|
-
headers
|
|
348
|
+
headers,
|
|
292
349
|
body: JSON.stringify(body),
|
|
293
350
|
signal: controller.signal,
|
|
294
351
|
});
|
|
295
|
-
if (response.status === 401) {
|
|
296
|
-
const retried = await this.retryWithRefresh("POST", path, body);
|
|
297
|
-
if (retried !== null)
|
|
298
|
-
return retried;
|
|
299
|
-
throw new Error("HTTP 401: authentication failed — run mcp__oka__login to re-authenticate");
|
|
300
|
-
}
|
|
301
352
|
if (!response.ok) {
|
|
353
|
+
if (response.status === 401) {
|
|
354
|
+
throw new Error("HTTP 401: authentication failed — run mcp__oka__login to re-authenticate");
|
|
355
|
+
}
|
|
302
356
|
const text = await response.text().catch(() => "");
|
|
303
357
|
throw new Error(`HTTP ${response.status}: ${text}`);
|
|
304
358
|
}
|
|
@@ -308,35 +362,4 @@ export class OkaClient {
|
|
|
308
362
|
clearTimeout(timer);
|
|
309
363
|
}
|
|
310
364
|
}
|
|
311
|
-
/**
|
|
312
|
-
* On 401, attempt to refresh the token and retry the request once.
|
|
313
|
-
* Returns the parsed JSON response on success, or null if refresh failed.
|
|
314
|
-
*/
|
|
315
|
-
async retryWithRefresh(method, path, body) {
|
|
316
|
-
const newKey = await resolveApiKeyWithRefresh();
|
|
317
|
-
if (!newKey)
|
|
318
|
-
return null;
|
|
319
|
-
const headers = {
|
|
320
|
-
"Content-Type": "application/json",
|
|
321
|
-
};
|
|
322
|
-
const isJwt = newKey.includes(".");
|
|
323
|
-
if (isJwt) {
|
|
324
|
-
headers["Authorization"] = `Bearer ${newKey}`;
|
|
325
|
-
}
|
|
326
|
-
else {
|
|
327
|
-
headers["X-Api-Key"] = newKey;
|
|
328
|
-
}
|
|
329
|
-
const opts = {
|
|
330
|
-
method,
|
|
331
|
-
headers,
|
|
332
|
-
signal: AbortSignal.timeout(this.timeout),
|
|
333
|
-
};
|
|
334
|
-
if (body !== undefined) {
|
|
335
|
-
opts.body = JSON.stringify(body);
|
|
336
|
-
}
|
|
337
|
-
const retryResponse = await fetch(`${this.apiUrl}${path}`, opts);
|
|
338
|
-
if (!retryResponse.ok)
|
|
339
|
-
return null;
|
|
340
|
-
return retryResponse.json();
|
|
341
|
-
}
|
|
342
365
|
}
|
package/dist/tools/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/tools/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/tools/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAU9C;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CA8I5E"}
|
package/dist/tools/auth.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { deviceAuthLogin, loadStoredCredentials, resolveApiKey,
|
|
2
|
+
import { McpTokenManager, deviceAuthLogin, loadStoredCredentials, resolveApiKey, } from "../auth.js";
|
|
3
|
+
const tokenManager = new McpTokenManager();
|
|
3
4
|
/**
|
|
4
5
|
* Register auth tools on the MCP server.
|
|
5
6
|
*/
|
|
@@ -29,10 +30,10 @@ export function registerAuthTools(server, client) {
|
|
|
29
30
|
],
|
|
30
31
|
};
|
|
31
32
|
}
|
|
32
|
-
// Token might be expired — try refresh before opening browser
|
|
33
|
+
// Token might be expired — try proactive refresh before opening browser
|
|
33
34
|
const stored = loadStoredCredentials();
|
|
34
35
|
if (stored?.refresh_token) {
|
|
35
|
-
const refreshed = await
|
|
36
|
+
const refreshed = await tokenManager.getValidToken();
|
|
36
37
|
if (refreshed) {
|
|
37
38
|
client.updateApiKey(refreshed);
|
|
38
39
|
return {
|
|
@@ -83,11 +84,11 @@ export function registerAuthTools(server, client) {
|
|
|
83
84
|
}
|
|
84
85
|
});
|
|
85
86
|
server.tool("whoami", "Check current authentication status — whether the MCP server has valid credentials.", {}, async () => {
|
|
86
|
-
//
|
|
87
|
-
let key =
|
|
88
|
-
// If
|
|
87
|
+
// Try token manager (proactive refresh)
|
|
88
|
+
let key = await tokenManager.getValidToken();
|
|
89
|
+
// If token manager returned empty, key might still be in sync path
|
|
89
90
|
if (!key) {
|
|
90
|
-
key =
|
|
91
|
+
key = resolveApiKey();
|
|
91
92
|
if (key) {
|
|
92
93
|
return {
|
|
93
94
|
content: [
|
package/dist/tools/read.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EACV,SAAS,EAKV,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EACV,SAAS,EAKV,MAAM,cAAc,CAAC;AAiItB;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CAopB5E"}
|
package/dist/tools/read.js
CHANGED
|
@@ -49,7 +49,7 @@ function formatHybridResults(query, results, totalCandidates, pipeline) {
|
|
|
49
49
|
const lines = [
|
|
50
50
|
`## Knowledge: ${query}`,
|
|
51
51
|
``,
|
|
52
|
-
`> ${totalCandidates} candidate(s), showing top ${results.length} | Pipeline: ${pipeline.pipeline_stages.join(" → ")} (${pipeline.elapsed_ms}ms)`,
|
|
52
|
+
`> ${totalCandidates} candidate(s), showing top ${results.length} | Pipeline: ${pipeline.pipeline_stages.join(" → ")} (${pipeline.elapsed_ms}ms)${pipeline.feedback_id ? ` | ref: ${pipeline.feedback_id.slice(0, 8)}` : ""}`,
|
|
53
53
|
``,
|
|
54
54
|
];
|
|
55
55
|
for (const r of results) {
|
|
@@ -83,7 +83,7 @@ function formatHybridResults(query, results, totalCandidates, pipeline) {
|
|
|
83
83
|
if (r.tags?.length > 0) {
|
|
84
84
|
lines.push(`**Tags:** ${r.tags.join(", ")}`);
|
|
85
85
|
}
|
|
86
|
-
lines.push(`*Matched by: ${r.matching_strategies.join(" + ")}*`);
|
|
86
|
+
lines.push(`*ID: ${r.id.slice(0, 8)} | Matched by: ${r.matching_strategies.join(" + ")}*`);
|
|
87
87
|
lines.push("");
|
|
88
88
|
}
|
|
89
89
|
return lines.join("\n");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CAqN7E"}
|
package/dist/tools/write.js
CHANGED
|
@@ -61,7 +61,8 @@ export function registerWriteTools(server, client) {
|
|
|
61
61
|
],
|
|
62
62
|
};
|
|
63
63
|
});
|
|
64
|
-
server.tool("done", "Record task completion with outcome and quality signals"
|
|
64
|
+
server.tool("done", "Record task completion with outcome and quality signals. " +
|
|
65
|
+
"If you used Oka learnings during the task, include their IDs in used_learning_ids.", {
|
|
65
66
|
task_id: z.string().describe("Identifier for the completed task"),
|
|
66
67
|
outcome: z
|
|
67
68
|
.enum(["success", "partial", "failed"])
|
|
@@ -74,8 +75,20 @@ export function registerWriteTools(server, client) {
|
|
|
74
75
|
.record(z.string(), z.number())
|
|
75
76
|
.default({})
|
|
76
77
|
.describe("Quality metrics (e.g., test_coverage: 0.92)"),
|
|
78
|
+
used_learning_ids: z
|
|
79
|
+
.array(z.string())
|
|
80
|
+
.optional()
|
|
81
|
+
.describe("IDs of Oka learnings used during the task"),
|
|
77
82
|
}, async (params) => {
|
|
78
|
-
|
|
83
|
+
const { used_learning_ids, ...completionPayload } = params;
|
|
84
|
+
await client.ingest({
|
|
85
|
+
event_type: "completion",
|
|
86
|
+
payload: completionPayload,
|
|
87
|
+
});
|
|
88
|
+
// Report implicit feedback for LTR training
|
|
89
|
+
if (used_learning_ids?.length) {
|
|
90
|
+
client.reportUsedLearnings(used_learning_ids);
|
|
91
|
+
}
|
|
79
92
|
return {
|
|
80
93
|
content: [
|
|
81
94
|
{
|
|
@@ -137,4 +150,33 @@ export function registerWriteTools(server, client) {
|
|
|
137
150
|
],
|
|
138
151
|
};
|
|
139
152
|
});
|
|
153
|
+
// ─── feedback (LTR training signal) ──────────────────────────────
|
|
154
|
+
server.tool("feedback", "Report whether a learning from Oka was useful or not. " +
|
|
155
|
+
"Improves future search quality. Call after using context or semantic_search.", {
|
|
156
|
+
learning_id: z.string().describe("Learning ID from search results"),
|
|
157
|
+
useful: z.boolean().describe("Was this learning useful?"),
|
|
158
|
+
query_feedback_id: z
|
|
159
|
+
.string()
|
|
160
|
+
.optional()
|
|
161
|
+
.describe("The ref ID from the search that returned this learning"),
|
|
162
|
+
reason: z
|
|
163
|
+
.enum(["helpful", "outdated", "wrong", "irrelevant"])
|
|
164
|
+
.optional()
|
|
165
|
+
.describe("Why the learning was or wasn't useful"),
|
|
166
|
+
}, async (params) => {
|
|
167
|
+
await client.submitFeedback({
|
|
168
|
+
learning_id: params.learning_id,
|
|
169
|
+
useful: params.useful,
|
|
170
|
+
query_feedback_id: params.query_feedback_id,
|
|
171
|
+
reason: params.reason,
|
|
172
|
+
});
|
|
173
|
+
return {
|
|
174
|
+
content: [
|
|
175
|
+
{
|
|
176
|
+
type: "text",
|
|
177
|
+
text: `Feedback recorded: ${params.learning_id.slice(0, 8)} → ${params.useful ? "useful" : "not useful"}`,
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
};
|
|
181
|
+
});
|
|
140
182
|
}
|