@oka-core/reason 0.2.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/dist/auth.d.ts +51 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +252 -0
- package/dist/buffer.d.ts +15 -0
- package/dist/buffer.d.ts.map +1 -0
- package/dist/buffer.js +29 -0
- package/dist/client.d.ts +183 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +292 -0
- package/dist/client_ext.d.ts +13 -0
- package/dist/client_ext.d.ts.map +1 -0
- package/dist/client_ext.js +12 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/schemas.d.ts +225 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +106 -0
- package/dist/tools/auth.d.ts +7 -0
- package/dist/tools/auth.d.ts.map +1 -0
- package/dist/tools/auth.js +131 -0
- package/dist/tools/read.d.ts +17 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +578 -0
- package/dist/tools/read_enhanced.d.ts +4 -0
- package/dist/tools/read_enhanced.d.ts.map +1 -0
- package/dist/tools/read_enhanced.js +304 -0
- package/dist/tools/write.d.ts +8 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +120 -0
- package/package.json +65 -0
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface StoredCredentials {
|
|
2
|
+
api_key?: string;
|
|
3
|
+
access_token?: string;
|
|
4
|
+
refresh_token?: string;
|
|
5
|
+
expires_at?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function loadStoredCredentials(): StoredCredentials | null;
|
|
8
|
+
export declare function storeCredentials(creds: StoredCredentials): void;
|
|
9
|
+
export declare function loadEnvFile(dir: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* Refresh the access token using a stored refresh_token.
|
|
12
|
+
* Calls `POST ${authServer}/api/token?grant_type=refresh_token`.
|
|
13
|
+
* On success, updates ~/.oka/credentials.json and returns the new access token.
|
|
14
|
+
* On failure, returns null (caller should fall through to unauthenticated).
|
|
15
|
+
*/
|
|
16
|
+
export declare function refreshAccessToken(authServerUrl?: string): Promise<string | null>;
|
|
17
|
+
/**
|
|
18
|
+
* Attempt token refresh with deduplication.
|
|
19
|
+
* Multiple concurrent callers share the same in-flight request.
|
|
20
|
+
*/
|
|
21
|
+
export declare function tryRefresh(): Promise<string | null>;
|
|
22
|
+
/**
|
|
23
|
+
* Resolve API key using credential chain:
|
|
24
|
+
* 1. OKA_API_KEY environment variable
|
|
25
|
+
* 2. ~/.oka/credentials.json file (valid token)
|
|
26
|
+
* 3. Empty string (unauthenticated — will get 401 on protected endpoints)
|
|
27
|
+
*
|
|
28
|
+
* Note: This is synchronous and cannot perform async refresh.
|
|
29
|
+
* Use `resolveApiKeyWithRefresh()` for async-capable resolution.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveApiKey(): string;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve API key with automatic refresh on expiry.
|
|
34
|
+
* Async version that tries token refresh before giving up.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveApiKeyWithRefresh(): Promise<string>;
|
|
37
|
+
export interface LoginResult {
|
|
38
|
+
success: boolean;
|
|
39
|
+
message: string;
|
|
40
|
+
verification_uri?: string;
|
|
41
|
+
user_code?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Run the device authorization flow (RFC 8628):
|
|
45
|
+
* 1. Request device code from id.oka.so
|
|
46
|
+
* 2. Open browser for user to authorize
|
|
47
|
+
* 3. Poll until user approves
|
|
48
|
+
* 4. Store token to ~/.oka/credentials.json
|
|
49
|
+
*/
|
|
50
|
+
export declare function deviceAuthLogin(authServerUrl?: string, clientId?: string): Promise<LoginResult>;
|
|
51
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +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,CAK/D;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,CAgCxB;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOnD;AAID;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAkBtC;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAqBhE;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
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { exec } from "node:child_process";
|
|
5
|
+
import { platform } from "node:process";
|
|
6
|
+
const OKA_DIR = join(homedir(), ".oka");
|
|
7
|
+
const CREDENTIALS_PATH = join(OKA_DIR, "credentials.json");
|
|
8
|
+
function ensureOkaDir() {
|
|
9
|
+
if (!existsSync(OKA_DIR)) {
|
|
10
|
+
mkdirSync(OKA_DIR, { recursive: true });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function loadStoredCredentials() {
|
|
14
|
+
try {
|
|
15
|
+
const raw = readFileSync(CREDENTIALS_PATH, "utf-8");
|
|
16
|
+
return JSON.parse(raw);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function storeCredentials(creds) {
|
|
23
|
+
ensureOkaDir();
|
|
24
|
+
writeFileSync(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), {
|
|
25
|
+
mode: 0o600,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
// ─── .env file loading ──────────────────────────────────────────
|
|
29
|
+
export function loadEnvFile(dir) {
|
|
30
|
+
const envPath = join(dir, ".env");
|
|
31
|
+
try {
|
|
32
|
+
const raw = readFileSync(envPath, "utf-8");
|
|
33
|
+
for (const line of raw.split("\n")) {
|
|
34
|
+
const trimmed = line.trim();
|
|
35
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
36
|
+
continue;
|
|
37
|
+
const eqIdx = trimmed.indexOf("=");
|
|
38
|
+
if (eqIdx === -1)
|
|
39
|
+
continue;
|
|
40
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
41
|
+
let value = trimmed.slice(eqIdx + 1).trim();
|
|
42
|
+
// Strip surrounding quotes
|
|
43
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
44
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
45
|
+
value = value.slice(1, -1);
|
|
46
|
+
}
|
|
47
|
+
// Only set if not already in env (env takes precedence)
|
|
48
|
+
if (!(key in process.env)) {
|
|
49
|
+
process.env[key] = value;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// .env file is optional
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// ─── Token refresh ──────────────────────────────────────────────
|
|
58
|
+
/** Guard to prevent concurrent refresh attempts. */
|
|
59
|
+
let refreshInFlight = null;
|
|
60
|
+
/**
|
|
61
|
+
* Refresh the access token using a stored refresh_token.
|
|
62
|
+
* Calls `POST ${authServer}/api/token?grant_type=refresh_token`.
|
|
63
|
+
* On success, updates ~/.oka/credentials.json and returns the new access token.
|
|
64
|
+
* On failure, returns null (caller should fall through to unauthenticated).
|
|
65
|
+
*/
|
|
66
|
+
export async function refreshAccessToken(authServerUrl) {
|
|
67
|
+
const stored = loadStoredCredentials();
|
|
68
|
+
if (!stored?.refresh_token)
|
|
69
|
+
return null;
|
|
70
|
+
const server = authServerUrl ?? DEFAULT_AUTH_SERVER;
|
|
71
|
+
try {
|
|
72
|
+
const res = await fetch(`${server}/api/token?grant_type=refresh_token`, {
|
|
73
|
+
method: "POST",
|
|
74
|
+
headers: { "Content-Type": "application/json" },
|
|
75
|
+
body: JSON.stringify({ refresh_token: stored.refresh_token }),
|
|
76
|
+
signal: AbortSignal.timeout(10_000),
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok)
|
|
79
|
+
return null;
|
|
80
|
+
const data = (await res.json());
|
|
81
|
+
storeCredentials({
|
|
82
|
+
access_token: data.access_token,
|
|
83
|
+
refresh_token: data.refresh_token ?? stored.refresh_token,
|
|
84
|
+
expires_at: Math.floor(Date.now() / 1000) + data.expires_in,
|
|
85
|
+
});
|
|
86
|
+
return data.access_token;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Attempt token refresh with deduplication.
|
|
94
|
+
* Multiple concurrent callers share the same in-flight request.
|
|
95
|
+
*/
|
|
96
|
+
export function tryRefresh() {
|
|
97
|
+
if (!refreshInFlight) {
|
|
98
|
+
refreshInFlight = refreshAccessToken().finally(() => {
|
|
99
|
+
refreshInFlight = null;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return refreshInFlight;
|
|
103
|
+
}
|
|
104
|
+
// ─── Credential chain ───────────────────────────────────────────
|
|
105
|
+
/**
|
|
106
|
+
* Resolve API key using credential chain:
|
|
107
|
+
* 1. OKA_API_KEY environment variable
|
|
108
|
+
* 2. ~/.oka/credentials.json file (valid token)
|
|
109
|
+
* 3. Empty string (unauthenticated — will get 401 on protected endpoints)
|
|
110
|
+
*
|
|
111
|
+
* Note: This is synchronous and cannot perform async refresh.
|
|
112
|
+
* Use `resolveApiKeyWithRefresh()` for async-capable resolution.
|
|
113
|
+
*/
|
|
114
|
+
export function resolveApiKey() {
|
|
115
|
+
// 1. Environment variable (highest priority)
|
|
116
|
+
const envKey = process.env["OKA_API_KEY"];
|
|
117
|
+
if (envKey)
|
|
118
|
+
return envKey;
|
|
119
|
+
// 2. Stored credentials file
|
|
120
|
+
const stored = loadStoredCredentials();
|
|
121
|
+
if (stored?.api_key)
|
|
122
|
+
return stored.api_key;
|
|
123
|
+
if (stored?.access_token) {
|
|
124
|
+
if (stored.expires_at && Date.now() / 1000 > stored.expires_at) {
|
|
125
|
+
// Token expired — fall through (async refresh will handle it)
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
return stored.access_token;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// 3. No credentials found
|
|
132
|
+
return "";
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Resolve API key with automatic refresh on expiry.
|
|
136
|
+
* Async version that tries token refresh before giving up.
|
|
137
|
+
*/
|
|
138
|
+
export async function resolveApiKeyWithRefresh() {
|
|
139
|
+
// 1. Environment variable
|
|
140
|
+
const envKey = process.env["OKA_API_KEY"];
|
|
141
|
+
if (envKey)
|
|
142
|
+
return envKey;
|
|
143
|
+
// 2. Stored credentials
|
|
144
|
+
const stored = loadStoredCredentials();
|
|
145
|
+
if (stored?.api_key)
|
|
146
|
+
return stored.api_key;
|
|
147
|
+
if (stored?.access_token) {
|
|
148
|
+
const isExpired = stored.expires_at && Date.now() / 1000 > stored.expires_at;
|
|
149
|
+
if (!isExpired)
|
|
150
|
+
return stored.access_token;
|
|
151
|
+
// 3. Token expired — try refresh
|
|
152
|
+
if (stored.refresh_token) {
|
|
153
|
+
const newToken = await tryRefresh();
|
|
154
|
+
if (newToken)
|
|
155
|
+
return newToken;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return "";
|
|
159
|
+
}
|
|
160
|
+
const DEFAULT_AUTH_SERVER = "https://id.oka.so";
|
|
161
|
+
const DEFAULT_CLIENT_ID = "oka-reason-mcp";
|
|
162
|
+
async function requestDeviceCode(authServerUrl, clientId) {
|
|
163
|
+
const body = new URLSearchParams({
|
|
164
|
+
client_id: clientId,
|
|
165
|
+
scope: "openid profile email",
|
|
166
|
+
});
|
|
167
|
+
const res = await fetch(`${authServerUrl}/api/device/authorize`, {
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
170
|
+
body: body.toString(),
|
|
171
|
+
});
|
|
172
|
+
if (!res.ok) {
|
|
173
|
+
throw new Error(`Device code request failed: ${res.status} ${res.statusText}`);
|
|
174
|
+
}
|
|
175
|
+
return res.json();
|
|
176
|
+
}
|
|
177
|
+
async function pollForToken(authServerUrl, clientId, deviceCode, interval, expiresIn) {
|
|
178
|
+
const deadline = Date.now() + expiresIn * 1000;
|
|
179
|
+
let currentInterval = interval;
|
|
180
|
+
while (Date.now() < deadline) {
|
|
181
|
+
await new Promise((r) => setTimeout(r, currentInterval * 1000));
|
|
182
|
+
const body = new URLSearchParams({
|
|
183
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
184
|
+
client_id: clientId,
|
|
185
|
+
device_code: deviceCode,
|
|
186
|
+
});
|
|
187
|
+
const res = await fetch(`${authServerUrl}/api/device/token`, {
|
|
188
|
+
method: "POST",
|
|
189
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
190
|
+
body: body.toString(),
|
|
191
|
+
});
|
|
192
|
+
if (res.ok)
|
|
193
|
+
return res.json();
|
|
194
|
+
const err = (await res.json().catch(() => ({ error: "unknown" })));
|
|
195
|
+
switch (err.error) {
|
|
196
|
+
case "authorization_pending":
|
|
197
|
+
continue;
|
|
198
|
+
case "slow_down":
|
|
199
|
+
currentInterval += 5;
|
|
200
|
+
continue;
|
|
201
|
+
case "access_denied":
|
|
202
|
+
throw new Error("User denied the authorization request");
|
|
203
|
+
case "expired_token":
|
|
204
|
+
throw new Error("Device code has expired");
|
|
205
|
+
default:
|
|
206
|
+
throw new Error(`Unexpected device auth error: ${err.error}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
throw new Error("Polling deadline exceeded — device code expired");
|
|
210
|
+
}
|
|
211
|
+
function openBrowser(url) {
|
|
212
|
+
const cmd = platform === "darwin"
|
|
213
|
+
? `open "${url}"`
|
|
214
|
+
: platform === "win32"
|
|
215
|
+
? `start "${url}"`
|
|
216
|
+
: `xdg-open "${url}"`;
|
|
217
|
+
exec(cmd, () => { });
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Run the device authorization flow (RFC 8628):
|
|
221
|
+
* 1. Request device code from id.oka.so
|
|
222
|
+
* 2. Open browser for user to authorize
|
|
223
|
+
* 3. Poll until user approves
|
|
224
|
+
* 4. Store token to ~/.oka/credentials.json
|
|
225
|
+
*/
|
|
226
|
+
export async function deviceAuthLogin(authServerUrl, clientId) {
|
|
227
|
+
const server = authServerUrl ?? DEFAULT_AUTH_SERVER;
|
|
228
|
+
const cid = clientId ?? DEFAULT_CLIENT_ID;
|
|
229
|
+
const codeResponse = await requestDeviceCode(server, cid);
|
|
230
|
+
const verifyUrl = codeResponse.verification_uri_complete ?? codeResponse.verification_uri;
|
|
231
|
+
openBrowser(verifyUrl);
|
|
232
|
+
try {
|
|
233
|
+
const tokenResponse = await pollForToken(server, cid, codeResponse.device_code, codeResponse.interval, codeResponse.expires_in);
|
|
234
|
+
storeCredentials({
|
|
235
|
+
access_token: tokenResponse.access_token,
|
|
236
|
+
refresh_token: tokenResponse.refresh_token,
|
|
237
|
+
expires_at: Math.floor(Date.now() / 1000) + tokenResponse.expires_in,
|
|
238
|
+
});
|
|
239
|
+
return {
|
|
240
|
+
success: true,
|
|
241
|
+
message: "Logged in successfully. Token stored to ~/.oka/credentials.json",
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
return {
|
|
246
|
+
success: false,
|
|
247
|
+
message: `Login failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
248
|
+
verification_uri: codeResponse.verification_uri,
|
|
249
|
+
user_code: codeResponse.user_code,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
package/dist/buffer.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory event buffer for offline resilience.
|
|
3
|
+
* Holds events when the API is unreachable, flushes when connectivity returns.
|
|
4
|
+
* Drops oldest events when capacity is exceeded.
|
|
5
|
+
*/
|
|
6
|
+
export declare class EventBuffer<T = unknown> {
|
|
7
|
+
private events;
|
|
8
|
+
private readonly maxSize;
|
|
9
|
+
constructor(maxSize: number);
|
|
10
|
+
add(event: T): void;
|
|
11
|
+
drain(): T[];
|
|
12
|
+
get size(): number;
|
|
13
|
+
get isEmpty(): boolean;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffer.d.ts","sourceRoot":"","sources":["../src/buffer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,WAAW,CAAC,CAAC,GAAG,OAAO;IAClC,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,EAAE,MAAM;IAI3B,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAOnB,KAAK,IAAI,CAAC,EAAE;IAMZ,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;CACF"}
|
package/dist/buffer.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory event buffer for offline resilience.
|
|
3
|
+
* Holds events when the API is unreachable, flushes when connectivity returns.
|
|
4
|
+
* Drops oldest events when capacity is exceeded.
|
|
5
|
+
*/
|
|
6
|
+
export class EventBuffer {
|
|
7
|
+
events = [];
|
|
8
|
+
maxSize;
|
|
9
|
+
constructor(maxSize) {
|
|
10
|
+
this.maxSize = maxSize;
|
|
11
|
+
}
|
|
12
|
+
add(event) {
|
|
13
|
+
if (this.events.length >= this.maxSize) {
|
|
14
|
+
this.events.shift(); // drop oldest
|
|
15
|
+
}
|
|
16
|
+
this.events.push(event);
|
|
17
|
+
}
|
|
18
|
+
drain() {
|
|
19
|
+
const drained = [...this.events];
|
|
20
|
+
this.events = [];
|
|
21
|
+
return drained;
|
|
22
|
+
}
|
|
23
|
+
get size() {
|
|
24
|
+
return this.events.length;
|
|
25
|
+
}
|
|
26
|
+
get isEmpty() {
|
|
27
|
+
return this.events.length === 0;
|
|
28
|
+
}
|
|
29
|
+
}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
export interface OkaClientConfig {
|
|
2
|
+
apiUrl?: string;
|
|
3
|
+
apiKey?: string;
|
|
4
|
+
repo?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface IngestEvent {
|
|
7
|
+
event_type: string;
|
|
8
|
+
payload: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
export interface QueryResult<T = unknown> {
|
|
11
|
+
results: T[];
|
|
12
|
+
confidence: number;
|
|
13
|
+
source_count: number;
|
|
14
|
+
}
|
|
15
|
+
export interface ConsolidateRequest {
|
|
16
|
+
repo: string;
|
|
17
|
+
trigger?: string;
|
|
18
|
+
max_events?: number;
|
|
19
|
+
min_confidence_for_backlog?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface ConsolidateResponse {
|
|
22
|
+
run_id: string;
|
|
23
|
+
status: string;
|
|
24
|
+
events_processed: number;
|
|
25
|
+
new_learnings: number;
|
|
26
|
+
reinforced: number;
|
|
27
|
+
contradicted: number;
|
|
28
|
+
backlog_items_generated: number;
|
|
29
|
+
model_id?: string;
|
|
30
|
+
input_tokens?: number;
|
|
31
|
+
output_tokens?: number;
|
|
32
|
+
}
|
|
33
|
+
export interface ContextQueryOptions {
|
|
34
|
+
file_patterns?: string;
|
|
35
|
+
limit?: number;
|
|
36
|
+
min_confidence?: number;
|
|
37
|
+
include_events?: boolean;
|
|
38
|
+
/** Visibility scope: user_repo (default), account_wide, user_private */
|
|
39
|
+
visibility?: "user_repo" | "account_wide" | "user_private";
|
|
40
|
+
}
|
|
41
|
+
export interface ContextResponse {
|
|
42
|
+
topic: string;
|
|
43
|
+
learnings: ContextLearning[];
|
|
44
|
+
total_matched: number;
|
|
45
|
+
}
|
|
46
|
+
export interface ContextLearning {
|
|
47
|
+
id: string;
|
|
48
|
+
summary: string;
|
|
49
|
+
detailed_description?: string;
|
|
50
|
+
tags: string[];
|
|
51
|
+
file_patterns: string[];
|
|
52
|
+
category: string;
|
|
53
|
+
confidence: number;
|
|
54
|
+
evidence_count: number;
|
|
55
|
+
suggested_action?: string;
|
|
56
|
+
status: string;
|
|
57
|
+
relevance_score: number;
|
|
58
|
+
aggregate_confidence: number;
|
|
59
|
+
source_count: number;
|
|
60
|
+
metadata: {
|
|
61
|
+
matching_strategy: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export interface LearningStats {
|
|
65
|
+
total_learnings: number;
|
|
66
|
+
by_category: Record<string, number>;
|
|
67
|
+
by_status: Record<string, number>;
|
|
68
|
+
avg_confidence: number;
|
|
69
|
+
high_confidence_count: number;
|
|
70
|
+
source_type_distribution: Record<string, number>;
|
|
71
|
+
}
|
|
72
|
+
export interface BacklogParams {
|
|
73
|
+
repo?: string;
|
|
74
|
+
status?: string;
|
|
75
|
+
priority?: string;
|
|
76
|
+
tags?: string;
|
|
77
|
+
limit?: number;
|
|
78
|
+
}
|
|
79
|
+
export interface EnhancedLearningParams {
|
|
80
|
+
repo?: string;
|
|
81
|
+
area?: string;
|
|
82
|
+
category?: string;
|
|
83
|
+
min_confidence?: number;
|
|
84
|
+
max_confidence?: number;
|
|
85
|
+
status?: string;
|
|
86
|
+
tags?: string;
|
|
87
|
+
sort_by?: string;
|
|
88
|
+
sort_order?: string;
|
|
89
|
+
limit?: number;
|
|
90
|
+
offset?: number;
|
|
91
|
+
/** Visibility scope: user_repo (default), account_wide, user_private */
|
|
92
|
+
visibility?: "user_repo" | "account_wide" | "user_private";
|
|
93
|
+
}
|
|
94
|
+
export interface PaginatedLearnings {
|
|
95
|
+
learnings: any[];
|
|
96
|
+
total: number;
|
|
97
|
+
limit: number;
|
|
98
|
+
offset: number;
|
|
99
|
+
}
|
|
100
|
+
export interface SemanticSearchOptions {
|
|
101
|
+
repo?: string;
|
|
102
|
+
limit?: number;
|
|
103
|
+
min_similarity?: number;
|
|
104
|
+
min_confidence?: number;
|
|
105
|
+
/** Visibility scope: user_repo (default), account_wide, user_private */
|
|
106
|
+
visibility?: "user_repo" | "account_wide" | "user_private";
|
|
107
|
+
}
|
|
108
|
+
export interface SemanticSearchResult {
|
|
109
|
+
id: string;
|
|
110
|
+
summary: string;
|
|
111
|
+
similarity: number;
|
|
112
|
+
}
|
|
113
|
+
export interface SemanticSearchResponse {
|
|
114
|
+
query: string;
|
|
115
|
+
results: SemanticSearchResult[];
|
|
116
|
+
total: number;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Unified HTTP client for Oka Reason API.
|
|
120
|
+
*
|
|
121
|
+
* Merges the functionality of OkaClient + OkaContextClient + OkaClientExt
|
|
122
|
+
* into a single class with all capabilities:
|
|
123
|
+
* - ingest() — fire-and-forget event ingestion with buffering
|
|
124
|
+
* - getContext() — the flagship context query (ranked learnings by topic)
|
|
125
|
+
* - getLearnings() — enhanced learning queries
|
|
126
|
+
* - getLearningStats() — aggregate statistics
|
|
127
|
+
* - queryEvents() — raw event queries
|
|
128
|
+
* - getBacklog() — backlog item listing
|
|
129
|
+
* - triggerConsolidation() — manual consolidation trigger
|
|
130
|
+
*/
|
|
131
|
+
export declare class OkaClient {
|
|
132
|
+
private readonly apiUrl;
|
|
133
|
+
private apiKey;
|
|
134
|
+
private readonly repo;
|
|
135
|
+
private readonly buffer;
|
|
136
|
+
private readonly agentId;
|
|
137
|
+
private readonly sessionId;
|
|
138
|
+
private readonly timeout;
|
|
139
|
+
constructor(config?: OkaClientConfig);
|
|
140
|
+
updateApiKey(key: string): void;
|
|
141
|
+
ingest(event: IngestEvent): Promise<void>;
|
|
142
|
+
private flush;
|
|
143
|
+
/**
|
|
144
|
+
* Get ranked learnings relevant to a topic.
|
|
145
|
+
* Calls `GET /api/learnings/context/:topic`.
|
|
146
|
+
*/
|
|
147
|
+
getContext(topic: string, options?: ContextQueryOptions): Promise<ContextResponse>;
|
|
148
|
+
query(params: Record<string, string | undefined>): Promise<QueryResult>;
|
|
149
|
+
/**
|
|
150
|
+
* Query enhanced learnings with rich filtering.
|
|
151
|
+
* GET /api/reasoning/learnings/enhanced
|
|
152
|
+
*/
|
|
153
|
+
getLearnings(params?: EnhancedLearningParams): Promise<PaginatedLearnings>;
|
|
154
|
+
/**
|
|
155
|
+
* Get learning statistics.
|
|
156
|
+
* GET /api/reasoning/learnings/stats
|
|
157
|
+
*/
|
|
158
|
+
getLearningStats(repo?: string): Promise<LearningStats>;
|
|
159
|
+
/**
|
|
160
|
+
* Query backlog items.
|
|
161
|
+
* GET /api/reasoning/backlog
|
|
162
|
+
*/
|
|
163
|
+
getBacklog(params?: BacklogParams): Promise<any[]>;
|
|
164
|
+
/**
|
|
165
|
+
* Semantic search for learnings by natural language query.
|
|
166
|
+
* GET /api/learnings/semantic/:query
|
|
167
|
+
*/
|
|
168
|
+
semanticSearch(query: string, options?: SemanticSearchOptions): Promise<SemanticSearchResponse>;
|
|
169
|
+
/**
|
|
170
|
+
* Trigger a consolidation run.
|
|
171
|
+
* POST /api/reasoning/consolidate
|
|
172
|
+
*/
|
|
173
|
+
triggerConsolidation(req: ConsolidateRequest): Promise<ConsolidateResponse>;
|
|
174
|
+
private authHeaders;
|
|
175
|
+
private get;
|
|
176
|
+
private post;
|
|
177
|
+
/**
|
|
178
|
+
* On 401, attempt to refresh the token and retry the request once.
|
|
179
|
+
* Returns the parsed JSON response on success, or null if refresh failed.
|
|
180
|
+
*/
|
|
181
|
+
private retryWithRefresh;
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|