@agentage/extension 0.2.0 → 0.2.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.
Files changed (69) hide show
  1. package/dist/agcid/scope.d.ts +0 -1
  2. package/dist/agcid/scope.js +0 -1
  3. package/dist/auth/route-access.d.ts +2 -0
  4. package/dist/auth/route-access.js +21 -0
  5. package/dist/auth/token-check.d.ts +10 -0
  6. package/dist/auth/token-check.js +18 -0
  7. package/dist/command/check-cli.js +2 -7
  8. package/dist/command/run-command.d.ts +1 -0
  9. package/dist/command/run-command.js +5 -15
  10. package/dist/context/test-context.js +20 -17
  11. package/dist/discovery/discovery.schema.d.ts +5 -0
  12. package/dist/discovery/discovery.schema.js +1 -1
  13. package/dist/manifest/entry.d.ts +5 -0
  14. package/dist/manifest/entry.js +29 -0
  15. package/dist/manifest/parts.d.ts +1 -0
  16. package/dist/manifest/parts.js +1 -0
  17. package/dist/mcp/mcp-app.js +27 -7
  18. package/dist/mcp/server.js +3 -1
  19. package/dist/mcp/tools.d.ts +2 -0
  20. package/dist/mcp/tools.js +4 -0
  21. package/dist/runtime/part-runners.d.ts +5 -5
  22. package/dist/runtime/part-runners.js +19 -24
  23. package/dist/runtime/run-part.d.ts +4 -2
  24. package/dist/runtime/run-part.js +43 -27
  25. package/dist/server/app.d.ts +2 -0
  26. package/dist/server/app.js +12 -1
  27. package/dist/store/migrate.js +7 -3
  28. package/dist/store/migrations.d.ts +2 -0
  29. package/dist/store/migrations.js +32 -6
  30. package/dist/store/store.d.ts +7 -1
  31. package/dist/store/store.js +37 -7
  32. package/dist/tool/build.d.ts +0 -2
  33. package/dist/tool/build.js +5 -3
  34. package/dist/tool/check.d.ts +16 -0
  35. package/dist/tool/check.js +30 -0
  36. package/dist/tool/docker.js +3 -2
  37. package/dist/tool/exec.d.ts +1 -0
  38. package/dist/tool/exec.js +43 -16
  39. package/dist/tool/main.js +23 -24
  40. package/dist/tool/record-extras.js +7 -11
  41. package/dist/tool/stage.d.ts +1 -0
  42. package/dist/tool/stage.js +8 -10
  43. package/dist/tool/timeouts.d.ts +10 -0
  44. package/dist/tool/timeouts.js +19 -0
  45. package/dist/tool/up/compose-run.d.ts +2 -1
  46. package/dist/tool/up/compose-run.js +3 -2
  47. package/dist/tool/up/compose.d.ts +2 -1
  48. package/dist/tool/up/compose.js +13 -10
  49. package/dist/tool/up/dev-issuer.js +2 -1
  50. package/dist/tool/up/down.d.ts +1 -0
  51. package/dist/tool/up/down.js +39 -30
  52. package/dist/tool/up/gateway.d.ts +9 -0
  53. package/dist/tool/up/gateway.js +11 -17
  54. package/dist/tool/up/lines.js +1 -1
  55. package/dist/tool/up/ports.d.ts +2 -0
  56. package/dist/tool/up/ports.js +22 -0
  57. package/dist/tool/up/project.d.ts +4 -0
  58. package/dist/tool/up/project.js +20 -0
  59. package/dist/tool/up/store-line.d.ts +11 -0
  60. package/dist/tool/up/store-line.js +36 -0
  61. package/dist/tool/up/token.js +9 -2
  62. package/dist/tool/up/up.d.ts +3 -6
  63. package/dist/tool/up/up.js +49 -46
  64. package/dist/tool/up/wait.js +4 -2
  65. package/dist/ui/ui-app.d.ts +2 -0
  66. package/dist/ui/ui-app.js +18 -5
  67. package/dist/worker/runs.js +11 -11
  68. package/dist/worker/scheduler.js +14 -5
  69. package/package.json +1 -1
package/dist/ui/ui-app.js CHANGED
@@ -1,23 +1,36 @@
1
1
  import cors from 'cors';
2
2
  import express, {} from 'express';
3
3
  import { createPartApp, PUBLIC_CORS } from '../server/app.js';
4
- // Widgets reach their own /mcp and /api only; the dev issuer of `up` is the one other origin.
5
- const CSP = {
4
+ const LOOPBACK = new Set(['localhost', '127.0.0.1']);
5
+ // AGENTAGE_DEV_ISSUER, when set, must be a loopback http origin: anything else stops the start.
6
+ export const devIssuerOrigin = (value) => {
7
+ if (!value)
8
+ return undefined;
9
+ const url = URL.canParse(value) ? new URL(value) : undefined;
10
+ if (url?.protocol !== 'http:' || !LOOPBACK.has(url.hostname))
11
+ throw new Error(`AGENTAGE_DEV_ISSUER ${value} is not a loopback http origin`);
12
+ return url.origin;
13
+ };
14
+ // Widgets reach their own /mcp and /api only; under `up` also the dev issuer.
15
+ const cspFor = (devIssuer) => ({
6
16
  directives: {
7
17
  defaultSrc: ["'self'"],
8
18
  scriptSrc: ["'self'"],
9
19
  styleSrc: ["'self'", "'unsafe-inline'"],
10
- connectSrc: ["'self'", 'http://localhost:4281', 'http://127.0.0.1:4281'],
20
+ connectSrc: devIssuer ? ["'self'", devIssuer] : ["'self'"],
11
21
  imgSrc: ["'self'", 'data:'],
12
22
  upgradeInsecureRequests: null,
13
23
  },
14
- };
24
+ });
15
25
  const IMMUTABLE = 'public, max-age=31536000, immutable';
16
26
  // /ui/{version}/: static widget modules, anonymous, cached forever (a version never changes).
17
27
  export const createUiApp = (options) => createPartApp({
18
28
  ...options,
19
29
  part: 'ui',
20
- helmet: { contentSecurityPolicy: CSP, crossOriginResourcePolicy: { policy: 'cross-origin' } },
30
+ helmet: {
31
+ contentSecurityPolicy: cspFor(devIssuerOrigin(options.devIssuer)),
32
+ crossOriginResourcePolicy: { policy: 'cross-origin' },
33
+ },
21
34
  mount: (app) => void app.use(`/ui/${options.pkg.version}`, cors(PUBLIC_CORS), express.static(options.dir, {
22
35
  index: false,
23
36
  fallthrough: true,
@@ -21,6 +21,15 @@ const fromRow = (row) => ({
21
21
  log: row.log,
22
22
  ...(row.timeout_ms === null ? {} : { timeoutMs: row.timeout_ms }),
23
23
  });
24
+ const LAST = 'select * from agentage_job_runs where job = $1 order by id desc limit 1';
25
+ const valuesOf = (run) => [
26
+ run.job,
27
+ run.startedAt,
28
+ run.endedAt,
29
+ run.status,
30
+ run.log,
31
+ run.timeoutMs ?? null,
32
+ ];
24
33
  // Runs live in the extension's own store, in a table the kit owns; the last 50 per job are kept.
25
34
  export const storeRuns = (store) => {
26
35
  let table;
@@ -28,21 +37,12 @@ export const storeRuns = (store) => {
28
37
  return {
29
38
  save: async (run) => {
30
39
  await ready();
31
- const values = [
32
- run.job,
33
- run.startedAt,
34
- run.endedAt,
35
- run.status,
36
- run.log,
37
- run.timeoutMs ?? null,
38
- ];
39
- await store.query(INSERT, values);
40
+ await store.query(INSERT, valuesOf(run));
40
41
  await store.query(PRUNE, [run.job]);
41
42
  },
42
43
  last: async (job) => {
43
44
  await ready();
44
- const sql = 'select * from agentage_job_runs where job = $1 order by id desc limit 1';
45
- const { rows } = await store.query(sql, [job]);
45
+ const { rows } = await store.query(LAST, [job]);
46
46
  return rows[0] ? fromRow(rows[0]) : undefined;
47
47
  },
48
48
  };
@@ -20,6 +20,7 @@ const fire = async (s, entry) => {
20
20
  arm(s, entry);
21
21
  if (!entry.running)
22
22
  return execute(s, entry);
23
+ entry.overran = true;
23
24
  s.deps.log.warn('job skipped: its previous run is still running', { job: entry.name });
24
25
  return undefined;
25
26
  };
@@ -27,7 +28,8 @@ const newEntry = (name, cron, job, options, at) => {
27
28
  JobNameSchema.parse(name);
28
29
  const parsed = parseCron(cron);
29
30
  const timeout = JobOptionsSchema.parse(options)?.timeout;
30
- const entry = { name, cron: parsed, job, nextAt: nextRun(parsed, at), running: false };
31
+ const nextAt = nextRun(parsed, at);
32
+ const entry = { name, cron: parsed, job, nextAt, running: false, overran: false };
31
33
  if (timeout !== undefined)
32
34
  entry.timeoutMs = toMs(timeout);
33
35
  return entry;
@@ -44,9 +46,9 @@ const runJob = async (entry, log, buffer) => {
44
46
  };
45
47
  // Never twice at once; every run saved with its log, a failed save is logged and the job goes on.
46
48
  const execute = async (s, entry) => {
47
- entry.running = true;
48
- const buffer = { text: '', truncated: false };
49
49
  const startedAt = s.now();
50
+ Object.assign(entry, { running: true, runningSince: startedAt, overran: false });
51
+ const buffer = { text: '', truncated: false };
50
52
  const status = await runJob(entry, s.deps.log, buffer);
51
53
  entry.running = false;
52
54
  entry.last = status;
@@ -56,10 +58,17 @@ const execute = async (s, entry) => {
56
58
  await s.deps.runs.save(run).catch((err) => s.deps.log.error(err, { job: entry.name }));
57
59
  return run;
58
60
  };
59
- // ok: the last run ok and the timer on time; a failed or late job is degraded, never a restart.
61
+ // A run still going past its declared timeout, or one that made the job skip a tick.
62
+ const overrunning = (s, entry) => {
63
+ if (!entry.running)
64
+ return false;
65
+ const ranMs = s.now().getTime() - (entry.runningSince?.getTime() ?? 0);
66
+ return entry.overran || (entry.timeoutMs !== undefined && ranMs > entry.timeoutMs);
67
+ };
68
+ // ok: the last run ok, the timer on time, no run overrunning; else degraded, never a restart.
60
69
  const check = (s, entry) => async () => {
61
70
  const late = s.now().getTime() - entry.nextAt.getTime() > LATE_MS;
62
- return entry.last === 'failed' || late ? 'degraded' : 'ok';
71
+ return entry.last === 'failed' || late || overrunning(s, entry) ? 'degraded' : 'ok';
63
72
  };
64
73
  const scheduleOn = (s) => (name, cron, job, options) => {
65
74
  const entry = newEntry(name, cron, job, options, s.now());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentage/extension",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "The agentage extension kit: create(ctx) per part (pages, ui, api, mcp, worker, cli), the store, /health, discovery, the envelope, and the build tool with up and token",
5
5
  "type": "module",
6
6
  "license": "MIT",