@dipertq/dsh-openviking-status 0.2.2 → 0.3.1

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/lib/index.js CHANGED
@@ -899,9 +899,63 @@ function getCandidateSessionIds(sessionId) {
899
899
  }
900
900
  return Array.from(new Set(candidates));
901
901
  }
902
+ var TASKS_LIMIT_CAP = 200;
903
+ var SESSION_COMMIT_TASK_TYPE = "session_commit";
904
+ function clampLimit(raw, fallback = TASKS_LIMIT_CAP) {
905
+ const n = typeof raw === "string" ? Number.parseInt(raw, 10) : Number(raw);
906
+ if (!Number.isFinite(n) || n <= 0) return fallback;
907
+ return Math.min(TASKS_LIMIT_CAP, Math.max(1, Math.floor(n)));
908
+ }
909
+ function extractTaskId(body) {
910
+ if (!body || typeof body !== "object") return null;
911
+ const containers = [
912
+ body,
913
+ body.result,
914
+ body.data
915
+ ];
916
+ for (const c of containers) {
917
+ if (!c || typeof c !== "object") continue;
918
+ const id = c.task_id ?? c.id;
919
+ if (typeof id === "string" && id.trim()) return id.trim();
920
+ }
921
+ return null;
922
+ }
923
+ function extractTaskItems(data) {
924
+ if (!data || typeof data !== "object") return [];
925
+ if (Array.isArray(data)) return data;
926
+ const obj = data;
927
+ if (Array.isArray(obj.result)) return obj.result;
928
+ if (Array.isArray(obj.items)) return obj.items;
929
+ if (Array.isArray(obj.tasks)) return obj.tasks;
930
+ if (obj.result && typeof obj.result === "object") {
931
+ const res = obj.result;
932
+ if (Array.isArray(res.items)) return res.items;
933
+ if (Array.isArray(res.tasks)) return res.tasks;
934
+ }
935
+ return [];
936
+ }
937
+ async function resolveResourceId(endpoint, headers, sessionId, cache) {
938
+ const key = sessionId.trim();
939
+ const cached = cache?.get(key);
940
+ if (cached) return cached;
941
+ for (const candidateId of getCandidateSessionIds(sessionId)) {
942
+ const daemonRes = await fetch(
943
+ `${endpoint}/api/v1/sessions/${encodeURIComponent(candidateId)}`,
944
+ { method: "GET", headers }
945
+ ).catch(() => null);
946
+ if (!daemonRes) continue;
947
+ if (daemonRes.status === 404) continue;
948
+ if (daemonRes.ok) {
949
+ cache?.set(key, candidateId);
950
+ return candidateId;
951
+ }
952
+ }
953
+ return null;
954
+ }
902
955
  function apply(ctx, config) {
903
956
  let currentSettings = () => config ?? {};
904
957
  let settingsService = null;
958
+ const resourceIdCache = /* @__PURE__ */ new Map();
905
959
  ctx.inject?.(["settings"], (settingsCtx) => {
906
960
  settingsService = settingsCtx.settings;
907
961
  settingsCtx.settings?.installSection(
@@ -1176,7 +1230,13 @@ function apply(ctx, config) {
1176
1230
  sendJson(res, 200, { ok: false, error: String(errorMsg) });
1177
1231
  return;
1178
1232
  }
1179
- sendJson(res, 200, { ok: true });
1233
+ const okBody = await daemonRes.json().catch(() => null);
1234
+ const taskId = extractTaskId(okBody);
1235
+ sendJson(res, 200, {
1236
+ ok: true,
1237
+ ...taskId ? { task_id: taskId } : {},
1238
+ resource_id: candidateId
1239
+ });
1180
1240
  return;
1181
1241
  }
1182
1242
  sendJson(res, 200, {
@@ -1189,6 +1249,118 @@ function apply(ctx, config) {
1189
1249
  }
1190
1250
  });
1191
1251
  }, "openviking-status: session commit proxy route");
1252
+ ctx.effect?.(() => {
1253
+ return ctx.webServer?.register({
1254
+ kind: "exact",
1255
+ path: `${API_PREFIX}/tasks`,
1256
+ handler: async (req, res) => {
1257
+ try {
1258
+ const url = new URL(req.url || "/", "http://localhost");
1259
+ const sessionId = url.searchParams.get("session");
1260
+ if (!sessionId || !sessionId.trim()) {
1261
+ sendJson(res, 400, { status: "missing", error: "Missing session" });
1262
+ return;
1263
+ }
1264
+ const effective = resolveEffective();
1265
+ const headers = getHeaders(effective.apiKey);
1266
+ const resourceId = await resolveResourceId(
1267
+ effective.endpoint,
1268
+ headers,
1269
+ sessionId.trim(),
1270
+ resourceIdCache
1271
+ );
1272
+ if (!resourceId) {
1273
+ sendJson(res, 200, { status: "missing", tasks: [] });
1274
+ return;
1275
+ }
1276
+ const limit = clampLimit(url.searchParams.get("limit"));
1277
+ const query = new URLSearchParams({
1278
+ resource_id: resourceId,
1279
+ task_type: SESSION_COMMIT_TASK_TYPE,
1280
+ limit: String(limit)
1281
+ });
1282
+ const daemonRes = await fetch(
1283
+ `${effective.endpoint}/api/v1/tasks?${query.toString()}`,
1284
+ { method: "GET", headers }
1285
+ ).catch(() => null);
1286
+ if (!daemonRes) {
1287
+ sendJson(res, 200, { status: "unreachable", tasks: [] });
1288
+ return;
1289
+ }
1290
+ if (daemonRes.status === 401 || daemonRes.status === 403) {
1291
+ sendJson(res, 200, { status: "unauthorized", tasks: [] });
1292
+ return;
1293
+ }
1294
+ if (!daemonRes.ok) {
1295
+ sendJson(res, 200, {
1296
+ status: "error",
1297
+ detail: `HTTP ${daemonRes.status}`,
1298
+ tasks: []
1299
+ });
1300
+ return;
1301
+ }
1302
+ const data = await daemonRes.json().catch(() => ({}));
1303
+ const items = extractTaskItems(data);
1304
+ sendJson(res, 200, {
1305
+ status: "ok",
1306
+ resource_id: resourceId,
1307
+ tasks: items
1308
+ });
1309
+ } catch (err) {
1310
+ sendJson(res, 200, { status: "unreachable", detail: String(err) });
1311
+ }
1312
+ }
1313
+ });
1314
+ }, "openviking-status: tasks proxy route");
1315
+ ctx.effect?.(() => {
1316
+ return ctx.webServer?.register({
1317
+ kind: "exact",
1318
+ path: `${API_PREFIX}/task`,
1319
+ handler: async (req, res) => {
1320
+ try {
1321
+ const url = new URL(req.url || "/", "http://localhost");
1322
+ const taskId = url.searchParams.get("id");
1323
+ if (!taskId || !taskId.trim()) {
1324
+ sendJson(res, 400, { status: "missing", error: "Missing id" });
1325
+ return;
1326
+ }
1327
+ const withEvents = url.searchParams.get("events") === "1" || url.searchParams.get("events") === "true";
1328
+ const effective = resolveEffective();
1329
+ const query = withEvents ? "?include_events=true" : "";
1330
+ const daemonRes = await fetch(
1331
+ `${effective.endpoint}/api/v1/tasks/${encodeURIComponent(
1332
+ taskId.trim()
1333
+ )}${query}`,
1334
+ { method: "GET", headers: getHeaders(effective.apiKey) }
1335
+ ).catch(() => null);
1336
+ if (!daemonRes) {
1337
+ sendJson(res, 200, { status: "unreachable" });
1338
+ return;
1339
+ }
1340
+ if (daemonRes.status === 404) {
1341
+ sendJson(res, 200, { status: "missing" });
1342
+ return;
1343
+ }
1344
+ if (daemonRes.status === 401 || daemonRes.status === 403) {
1345
+ sendJson(res, 200, { status: "unauthorized" });
1346
+ return;
1347
+ }
1348
+ if (!daemonRes.ok) {
1349
+ sendJson(res, 200, {
1350
+ status: "error",
1351
+ detail: `HTTP ${daemonRes.status}`
1352
+ });
1353
+ return;
1354
+ }
1355
+ const data = await daemonRes.json().catch(() => ({}));
1356
+ const task = data?.result ?? data?.data ?? data;
1357
+ sendJson(res, 200, { status: "ok", task });
1358
+ } catch (err) {
1359
+ sendJson(res, 200, { status: "unreachable", detail: String(err) });
1360
+ }
1361
+ }
1362
+ });
1363
+ }, "openviking-status: task detail proxy route");
1192
1364
  }
1193
1365
  export {
1194
1366
  Config,