web-task-api 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 (121) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +284 -0
  3. package/dist/scripts/demo.d.ts +1 -0
  4. package/dist/scripts/demo.js +32 -0
  5. package/dist/scripts/demo.js.map +1 -0
  6. package/dist/scripts/profile-login.d.ts +1 -0
  7. package/dist/scripts/profile-login.js +38 -0
  8. package/dist/scripts/profile-login.js.map +1 -0
  9. package/dist/src/agents/auto-agent.d.ts +22 -0
  10. package/dist/src/agents/auto-agent.js +54 -0
  11. package/dist/src/agents/auto-agent.js.map +1 -0
  12. package/dist/src/agents/cliproxy-agent.d.ts +18 -0
  13. package/dist/src/agents/cliproxy-agent.js +137 -0
  14. package/dist/src/agents/cliproxy-agent.js.map +1 -0
  15. package/dist/src/agents/index.d.ts +2 -0
  16. package/dist/src/agents/index.js +17 -0
  17. package/dist/src/agents/index.js.map +1 -0
  18. package/dist/src/agents/mock-agent.d.ts +15 -0
  19. package/dist/src/agents/mock-agent.js +132 -0
  20. package/dist/src/agents/mock-agent.js.map +1 -0
  21. package/dist/src/agents/opencode-agent.d.ts +20 -0
  22. package/dist/src/agents/opencode-agent.js +122 -0
  23. package/dist/src/agents/opencode-agent.js.map +1 -0
  24. package/dist/src/agents/planner-prompt.d.ts +6 -0
  25. package/dist/src/agents/planner-prompt.js +116 -0
  26. package/dist/src/agents/planner-prompt.js.map +1 -0
  27. package/dist/src/browser/session.d.ts +41 -0
  28. package/dist/src/browser/session.js +267 -0
  29. package/dist/src/browser/session.js.map +1 -0
  30. package/dist/src/client.d.ts +44 -0
  31. package/dist/src/client.js +59 -0
  32. package/dist/src/client.js.map +1 -0
  33. package/dist/src/config.d.ts +16 -0
  34. package/dist/src/config.js +18 -0
  35. package/dist/src/config.js.map +1 -0
  36. package/dist/src/index.d.ts +2 -0
  37. package/dist/src/index.js +15 -0
  38. package/dist/src/index.js.map +1 -0
  39. package/dist/src/lib.d.ts +6 -0
  40. package/dist/src/lib.js +5 -0
  41. package/dist/src/lib.js.map +1 -0
  42. package/dist/src/mcp-server.d.ts +3 -0
  43. package/dist/src/mcp-server.js +191 -0
  44. package/dist/src/mcp-server.js.map +1 -0
  45. package/dist/src/mcp.d.ts +2 -0
  46. package/dist/src/mcp.js +14 -0
  47. package/dist/src/mcp.js.map +1 -0
  48. package/dist/src/recipes/registry.d.ts +21 -0
  49. package/dist/src/recipes/registry.js +38 -0
  50. package/dist/src/recipes/registry.js.map +1 -0
  51. package/dist/src/server/app.d.ts +5 -0
  52. package/dist/src/server/app.js +89 -0
  53. package/dist/src/server/app.js.map +1 -0
  54. package/dist/src/sessions/store.d.ts +48 -0
  55. package/dist/src/sessions/store.js +84 -0
  56. package/dist/src/sessions/store.js.map +1 -0
  57. package/dist/src/storage/run-store.d.ts +12 -0
  58. package/dist/src/storage/run-store.js +30 -0
  59. package/dist/src/storage/run-store.js.map +1 -0
  60. package/dist/src/tasks/errors.d.ts +5 -0
  61. package/dist/src/tasks/errors.js +11 -0
  62. package/dist/src/tasks/errors.js.map +1 -0
  63. package/dist/src/tasks/output-validator.d.ts +1 -0
  64. package/dist/src/tasks/output-validator.js +21 -0
  65. package/dist/src/tasks/output-validator.js.map +1 -0
  66. package/dist/src/tasks/runner.d.ts +38 -0
  67. package/dist/src/tasks/runner.js +236 -0
  68. package/dist/src/tasks/runner.js.map +1 -0
  69. package/dist/src/tasks/schemas.d.ts +266 -0
  70. package/dist/src/tasks/schemas.js +67 -0
  71. package/dist/src/tasks/schemas.js.map +1 -0
  72. package/dist/tests/agent-adapters.test.d.ts +1 -0
  73. package/dist/tests/agent-adapters.test.js +87 -0
  74. package/dist/tests/agent-adapters.test.js.map +1 -0
  75. package/dist/tests/agent-selection.test.d.ts +1 -0
  76. package/dist/tests/agent-selection.test.js +26 -0
  77. package/dist/tests/agent-selection.test.js.map +1 -0
  78. package/dist/tests/auto-agent.test.d.ts +1 -0
  79. package/dist/tests/auto-agent.test.js +86 -0
  80. package/dist/tests/auto-agent.test.js.map +1 -0
  81. package/dist/tests/browser-session.test.d.ts +1 -0
  82. package/dist/tests/browser-session.test.js +41 -0
  83. package/dist/tests/browser-session.test.js.map +1 -0
  84. package/dist/tests/client.test.d.ts +1 -0
  85. package/dist/tests/client.test.js +35 -0
  86. package/dist/tests/client.test.js.map +1 -0
  87. package/dist/tests/fixture-site.d.ts +6 -0
  88. package/dist/tests/fixture-site.js +93 -0
  89. package/dist/tests/fixture-site.js.map +1 -0
  90. package/dist/tests/mcp.test.d.ts +1 -0
  91. package/dist/tests/mcp.test.js +186 -0
  92. package/dist/tests/mcp.test.js.map +1 -0
  93. package/dist/tests/output-validator.test.d.ts +1 -0
  94. package/dist/tests/output-validator.test.js +27 -0
  95. package/dist/tests/output-validator.test.js.map +1 -0
  96. package/dist/tests/request-validation.test.d.ts +1 -0
  97. package/dist/tests/request-validation.test.js +25 -0
  98. package/dist/tests/request-validation.test.js.map +1 -0
  99. package/dist/tests/runner-options.test.d.ts +1 -0
  100. package/dist/tests/runner-options.test.js +44 -0
  101. package/dist/tests/runner-options.test.js.map +1 -0
  102. package/dist/tests/session-api.test.d.ts +1 -0
  103. package/dist/tests/session-api.test.js +244 -0
  104. package/dist/tests/session-api.test.js.map +1 -0
  105. package/dist/tests/session-client.test.d.ts +1 -0
  106. package/dist/tests/session-client.test.js +28 -0
  107. package/dist/tests/session-client.test.js.map +1 -0
  108. package/dist/tests/task-api-failure.test.d.ts +1 -0
  109. package/dist/tests/task-api-failure.test.js +39 -0
  110. package/dist/tests/task-api-failure.test.js.map +1 -0
  111. package/dist/tests/task-api.test.d.ts +1 -0
  112. package/dist/tests/task-api.test.js +50 -0
  113. package/dist/tests/task-api.test.js.map +1 -0
  114. package/docs/design.md +513 -0
  115. package/docs/releasing.md +62 -0
  116. package/package.json +78 -0
  117. package/recipes/dexscreener-token-read.json +19 -0
  118. package/recipes/fixture-catalog.json +14 -0
  119. package/recipes/generic-search.json +14 -0
  120. package/recipes/gmgn-token-read.json +19 -0
  121. package/server.json +79 -0
@@ -0,0 +1,27 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { validateOutput } from "../src/tasks/output-validator.js";
4
+ test("rejects additionalProperties when schema forbids them", () => {
5
+ assert.throws(() => validateOutput({
6
+ type: "object",
7
+ additionalProperties: false,
8
+ properties: { ok: { type: "string" } },
9
+ required: ["ok"],
10
+ }, { ok: "yes", extra: true }));
11
+ });
12
+ test("rejects enum mismatch", () => {
13
+ assert.throws(() => validateOutput({
14
+ type: "object",
15
+ properties: { status: { type: "string", enum: ["confirmed"] } },
16
+ required: ["status"],
17
+ }, { status: "pending" }));
18
+ });
19
+ test("accepts valid object matching schema", () => {
20
+ assert.doesNotThrow(() => validateOutput({
21
+ type: "object",
22
+ additionalProperties: false,
23
+ properties: { status: { type: "string", enum: ["confirmed"] } },
24
+ required: ["status"],
25
+ }, { status: "confirmed" }));
26
+ });
27
+ //# sourceMappingURL=output-validator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-validator.test.js","sourceRoot":"","sources":["../../tests/output-validator.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAElE,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;IACjE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CACjB,cAAc,CACZ;QACE,IAAI,EAAE,QAAQ;QACd,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QACtC,QAAQ,EAAE,CAAC,IAAI,CAAC;KACjB,EACD,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAC3B,CACF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACjC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CACjB,cAAc,CACZ;QACE,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE;QAC/D,QAAQ,EAAE,CAAC,QAAQ,CAAC;KACrB,EACD,EAAE,MAAM,EAAE,SAAS,EAAE,CACtB,CACF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;IAChD,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CACvB,cAAc,CACZ;QACE,IAAI,EAAE,QAAQ;QACd,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE;QAC/D,QAAQ,EAAE,CAAC,QAAQ,CAAC;KACrB,EACD,EAAE,MAAM,EAAE,WAAW,EAAE,CACxB,CACF,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { createApp } from "../src/server/app.js";
4
+ test("rejects profile path traversal in task request", async () => {
5
+ const app = createApp();
6
+ try {
7
+ const response = await app.inject({
8
+ method: "POST",
9
+ url: "/v1/tasks/run",
10
+ payload: {
11
+ goal: "Inspect page",
12
+ mode: "read",
13
+ profile: "../chrome-profile",
14
+ input: {},
15
+ agent: { kind: "mock" },
16
+ },
17
+ });
18
+ assert.equal(response.statusCode, 400);
19
+ assert.match(response.body, /profile must use only letters, numbers, underscore, or hyphen/);
20
+ }
21
+ finally {
22
+ await app.close();
23
+ }
24
+ });
25
+ //# sourceMappingURL=request-validation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-validation.test.js","sourceRoot":"","sources":["../../tests/request-validation.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,IAAI,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;IAChE,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAChC,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,eAAe;YACpB,OAAO,EAAE;gBACP,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,mBAAmB;gBAC5B,KAAK,EAAE,EAAE;gBACT,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;aACxB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,+DAA+D,CAAC,CAAC;IAC/F,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { resolveBrowserLaunchOptions } from "../src/tasks/runner.js";
4
+ test("protected-site recipe prefers headful Chrome launch by default", () => {
5
+ const request = {
6
+ goal: "Inspect site",
7
+ mode: "read",
8
+ input: {},
9
+ profile: "gmgn",
10
+ agent: { kind: "mock" },
11
+ limits: {},
12
+ };
13
+ const launch = resolveBrowserLaunchOptions(request, {
14
+ id: "gmgn-token-read",
15
+ name: "GMGN",
16
+ description: "starter",
17
+ browserHints: {
18
+ preferChrome: true,
19
+ preferHeadful: true,
20
+ preferPersistentProfile: true,
21
+ },
22
+ }, "/tmp/shots");
23
+ assert.equal(launch.headless, false);
24
+ assert.equal(launch.preferChrome, true);
25
+ assert.equal(launch.protectedSiteMode, true);
26
+ });
27
+ test("protected-site recipe requires persistent profile source", () => {
28
+ const request = {
29
+ goal: "Inspect site",
30
+ mode: "read",
31
+ input: {},
32
+ agent: { kind: "mock" },
33
+ limits: {},
34
+ };
35
+ assert.throws(() => resolveBrowserLaunchOptions(request, {
36
+ id: "gmgn-token-read",
37
+ name: "GMGN",
38
+ description: "starter",
39
+ browserHints: {
40
+ preferPersistentProfile: true,
41
+ },
42
+ }, "/tmp/shots"));
43
+ });
44
+ //# sourceMappingURL=runner-options.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-options.test.js","sourceRoot":"","sources":["../../tests/runner-options.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAGrE,IAAI,CAAC,gEAAgE,EAAE,GAAG,EAAE;IAC1E,MAAM,OAAO,GAAgB;QAC3B,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,MAAM;QACf,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QACvB,MAAM,EAAE,EAAE;KACX,CAAC;IAEF,MAAM,MAAM,GAAG,2BAA2B,CACxC,OAAO,EACP;QACE,EAAE,EAAE,iBAAiB;QACrB,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,SAAS;QACtB,YAAY,EAAE;YACZ,YAAY,EAAE,IAAI;YAClB,aAAa,EAAE,IAAI;YACnB,uBAAuB,EAAE,IAAI;SAC9B;KACF,EACD,YAAY,CACb,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0DAA0D,EAAE,GAAG,EAAE;IACpE,MAAM,OAAO,GAAgB;QAC3B,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,EAAE;QACT,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QACvB,MAAM,EAAE,EAAE;KACX,CAAC;IAEF,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CACjB,2BAA2B,CACzB,OAAO,EACP;QACE,EAAE,EAAE,iBAAiB;QACrB,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,SAAS;QACtB,YAAY,EAAE;YACZ,uBAAuB,EAAE,IAAI;SAC9B;KACF,EACD,YAAY,CACb,CACF,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,244 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { createApp } from "../src/server/app.js";
4
+ import { startFixtureSite } from "./fixture-site.js";
5
+ test("creates session and reuses session defaults across tasks", async () => {
6
+ const fixture = await startFixtureSite();
7
+ const app = createApp();
8
+ try {
9
+ const created = await app.inject({
10
+ method: "POST",
11
+ url: "/v1/sessions",
12
+ payload: {
13
+ name: "gmgn guest scout",
14
+ mode: "guest",
15
+ startUrl: fixture.url,
16
+ notes: "Use this session for repeated token lookup tasks.",
17
+ },
18
+ });
19
+ assert.equal(created.statusCode, 201, created.body);
20
+ const session = created.json();
21
+ assert.equal(session.name, "gmgn guest scout");
22
+ const run = await app.inject({
23
+ method: "POST",
24
+ url: "/v1/tasks/run",
25
+ payload: {
26
+ sessionId: session.id,
27
+ goal: "Search for banana and return product, price, and stock.",
28
+ recipeId: "fixture-catalog",
29
+ input: { query: "banana" },
30
+ outputSchema: {
31
+ type: "object",
32
+ required: ["product", "price", "stock"],
33
+ properties: {
34
+ product: { type: "string" },
35
+ price: { type: "string" },
36
+ stock: { type: "string" },
37
+ },
38
+ },
39
+ agent: { kind: "mock" },
40
+ },
41
+ });
42
+ assert.equal(run.statusCode, 200, run.body);
43
+ const task = run.json();
44
+ assert.equal(task.sessionId, session.id);
45
+ assert.equal(task.result.product, "Banana");
46
+ const fetched = await app.inject({
47
+ method: "GET",
48
+ url: `/v1/sessions/${session.id}`,
49
+ });
50
+ assert.equal(fetched.statusCode, 200);
51
+ const updatedSession = fetched.json();
52
+ assert.equal(updatedSession.taskCount, 1);
53
+ assert.equal(updatedSession.history.length, 1);
54
+ assert.equal(updatedSession.history[0].taskId, task.taskId);
55
+ assert.match(updatedSession.history[0].resultSummary, /Banana/);
56
+ }
57
+ finally {
58
+ await app.close();
59
+ await fixture.close();
60
+ }
61
+ });
62
+ test("preserves guest browser state across tasks when using the same session", async () => {
63
+ const fixture = await startFixtureSite();
64
+ const app = createApp();
65
+ try {
66
+ const created = await app.inject({
67
+ method: "POST",
68
+ url: "/v1/sessions",
69
+ payload: {
70
+ name: "gmgn guest continuity",
71
+ mode: "guest",
72
+ notes: "Keep guest session warm between tasks.",
73
+ },
74
+ });
75
+ const session = created.json();
76
+ const seedRun = await app.inject({
77
+ method: "POST",
78
+ url: "/v1/tasks/run",
79
+ payload: {
80
+ sessionId: session.id,
81
+ goal: "Read the seeded page and confirm session setup.",
82
+ startUrl: `${fixture.url}/seed-session`,
83
+ outputSchema: {
84
+ type: "object",
85
+ required: ["product", "price", "stock"],
86
+ properties: {
87
+ product: { type: "string" },
88
+ price: { type: "string" },
89
+ stock: { type: "string" },
90
+ },
91
+ },
92
+ agent: { kind: "mock" },
93
+ },
94
+ });
95
+ assert.equal(seedRun.statusCode, 200, seedRun.body);
96
+ const checkRun = await app.inject({
97
+ method: "POST",
98
+ url: "/v1/tasks/run",
99
+ payload: {
100
+ sessionId: session.id,
101
+ goal: "Check whether the guest session is still present.",
102
+ startUrl: `${fixture.url}/check-session`,
103
+ outputSchema: {
104
+ type: "object",
105
+ required: ["product", "price", "stock"],
106
+ properties: {
107
+ product: { type: "string" },
108
+ price: { type: "string" },
109
+ stock: { type: "string" },
110
+ },
111
+ },
112
+ agent: { kind: "mock" },
113
+ },
114
+ });
115
+ assert.equal(checkRun.statusCode, 200, checkRun.body);
116
+ const payload = checkRun.json();
117
+ assert.equal(payload.result.product, "Session Preserved");
118
+ assert.equal(payload.sessionId, session.id);
119
+ }
120
+ finally {
121
+ await app.close();
122
+ await fixture.close();
123
+ }
124
+ });
125
+ test("returns 404 for missing session on task run", async () => {
126
+ const app = createApp();
127
+ try {
128
+ const response = await app.inject({
129
+ method: "POST",
130
+ url: "/v1/tasks/run",
131
+ payload: {
132
+ sessionId: "00000000-0000-0000-0000-000000000000",
133
+ goal: "Inspect page",
134
+ mode: "read",
135
+ input: {},
136
+ agent: { kind: "mock" },
137
+ },
138
+ });
139
+ assert.equal(response.statusCode, 404);
140
+ assert.match(response.body, /session_not_found/);
141
+ }
142
+ finally {
143
+ await app.close();
144
+ }
145
+ });
146
+ test("requires profile when creating profile-mode session", async () => {
147
+ const app = createApp();
148
+ try {
149
+ const response = await app.inject({
150
+ method: "POST",
151
+ url: "/v1/sessions",
152
+ payload: {
153
+ name: "axiom",
154
+ mode: "profile",
155
+ },
156
+ });
157
+ assert.equal(response.statusCode, 400);
158
+ assert.match(response.body, /profile mode requires a bound profile/);
159
+ }
160
+ finally {
161
+ await app.close();
162
+ }
163
+ });
164
+ test("rejects guest-mode session bound to named profile", async () => {
165
+ const app = createApp();
166
+ try {
167
+ const response = await app.inject({
168
+ method: "POST",
169
+ url: "/v1/sessions",
170
+ payload: {
171
+ name: "bad guest",
172
+ mode: "guest",
173
+ profile: "axiom",
174
+ },
175
+ });
176
+ assert.equal(response.statusCode, 400);
177
+ assert.match(response.body, /guest mode cannot bind a named profile/);
178
+ }
179
+ finally {
180
+ await app.close();
181
+ }
182
+ });
183
+ test("rejects rebinding a guest session to a named profile via update", async () => {
184
+ const app = createApp();
185
+ try {
186
+ const created = await app.inject({
187
+ method: "POST",
188
+ url: "/v1/sessions",
189
+ payload: {
190
+ name: "guest scout",
191
+ mode: "guest",
192
+ },
193
+ });
194
+ const session = created.json();
195
+ const response = await app.inject({
196
+ method: "PATCH",
197
+ url: `/v1/sessions/${session.id}`,
198
+ payload: {
199
+ profile: "axiom",
200
+ },
201
+ });
202
+ assert.equal(response.statusCode, 409);
203
+ assert.match(response.body, /guest_session_cannot_bind_profile/);
204
+ }
205
+ finally {
206
+ await app.close();
207
+ }
208
+ });
209
+ test("rejects protected-site task on a fresh guest session without warmed state", async () => {
210
+ const fixture = await startFixtureSite();
211
+ const app = createApp();
212
+ try {
213
+ const created = await app.inject({
214
+ method: "POST",
215
+ url: "/v1/sessions",
216
+ payload: {
217
+ name: "fresh guest",
218
+ mode: "guest",
219
+ startUrl: fixture.url,
220
+ },
221
+ });
222
+ const session = created.json();
223
+ const response = await app.inject({
224
+ method: "POST",
225
+ url: "/v1/tasks/run",
226
+ payload: {
227
+ sessionId: session.id,
228
+ goal: "Inspect protected-site recipe",
229
+ startUrl: fixture.url,
230
+ recipeId: "gmgn-token-read",
231
+ mode: "read",
232
+ input: {},
233
+ agent: { kind: "mock" },
234
+ },
235
+ });
236
+ assert.equal(response.statusCode, 409);
237
+ assert.match(response.body, /session_not_warmed_for_protected_recipe/);
238
+ }
239
+ finally {
240
+ await app.close();
241
+ await fixture.close();
242
+ }
243
+ });
244
+ //# sourceMappingURL=session-api.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-api.test.js","sourceRoot":"","sources":["../../tests/session-api.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,IAAI,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;IAC1E,MAAM,OAAO,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IAExB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC/B,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,cAAc;YACnB,OAAO,EAAE;gBACP,IAAI,EAAE,kBAAkB;gBACxB,IAAI,EAAE,OAAO;gBACb,QAAQ,EAAE,OAAO,CAAC,GAAG;gBACrB,KAAK,EAAE,mDAAmD;aAC3D;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;QAE/C,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC3B,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,eAAe;YACpB,OAAO,EAAE;gBACP,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,IAAI,EAAE,yDAAyD;gBAC/D,QAAQ,EAAE,iBAAiB;gBAC3B,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE;gBAC1B,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC;oBACvC,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC3B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBAC1B;iBACF;gBACD,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;aACxB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAE5C,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC/B,MAAM,EAAE,KAAK;YACb,GAAG,EAAE,gBAAgB,OAAO,CAAC,EAAE,EAAE;SAClC,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACtC,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5D,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;IACxF,MAAM,OAAO,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IAExB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC/B,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,cAAc;YACnB,OAAO,EAAE;gBACP,IAAI,EAAE,uBAAuB;gBAC7B,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,wCAAwC;aAChD;SACF,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAE/B,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC/B,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,eAAe;YACpB,OAAO,EAAE;gBACP,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,IAAI,EAAE,iDAAiD;gBACvD,QAAQ,EAAE,GAAG,OAAO,CAAC,GAAG,eAAe;gBACvC,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC;oBACvC,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC3B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBAC1B;iBACF;gBACD,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;aACxB;SACF,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAEpD,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAChC,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,eAAe;YACpB,OAAO,EAAE;gBACP,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,IAAI,EAAE,mDAAmD;gBACzD,QAAQ,EAAE,GAAG,OAAO,CAAC,GAAG,gBAAgB;gBACxC,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC;oBACvC,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC3B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBAC1B;iBACF;gBACD,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;aACxB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;IAC7D,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAChC,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,eAAe;YACpB,OAAO,EAAE;gBACP,SAAS,EAAE,sCAAsC;gBACjD,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,EAAE;gBACT,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;aACxB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;IACnD,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;IACrE,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAChC,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,cAAc;YACnB,OAAO,EAAE;gBACP,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,SAAS;aAChB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,uCAAuC,CAAC,CAAC;IACvE,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;IACnE,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAChC,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,cAAc;YACnB,OAAO,EAAE;gBACP,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,OAAO;aACjB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,wCAAwC,CAAC,CAAC;IACxE,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;IACjF,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC/B,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,cAAc;YACnB,OAAO,EAAE;gBACP,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,OAAO;aACd;SACF,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAE/B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAChC,MAAM,EAAE,OAAO;YACf,GAAG,EAAE,gBAAgB,OAAO,CAAC,EAAE,EAAE;YACjC,OAAO,EAAE;gBACP,OAAO,EAAE,OAAO;aACjB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,mCAAmC,CAAC,CAAC;IACnE,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;IAC3F,MAAM,OAAO,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC/B,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,cAAc;YACnB,OAAO,EAAE;gBACP,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,OAAO;gBACb,QAAQ,EAAE,OAAO,CAAC,GAAG;aACtB;SACF,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAE/B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAChC,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,eAAe;YACpB,OAAO,EAAE;gBACP,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,IAAI,EAAE,+BAA+B;gBACrC,QAAQ,EAAE,OAAO,CAAC,GAAG;gBACrB,QAAQ,EAAE,iBAAiB;gBAC3B,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,EAAE;gBACT,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;aACxB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,yCAAyC,CAAC,CAAC;IACzE,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { WebTaskApiClient } from "../src/client.js";
4
+ test("WebTaskApiClient creates sessions", async () => {
5
+ let seenUrl = "";
6
+ let seenBody = "";
7
+ const client = new WebTaskApiClient({
8
+ baseUrl: "http://127.0.0.1:9999",
9
+ fetch: (async (url, init) => {
10
+ seenUrl = String(url);
11
+ seenBody = String(init?.body ?? "");
12
+ return new Response(JSON.stringify({
13
+ id: "s1",
14
+ name: "guest scout",
15
+ mode: "guest",
16
+ createdAt: new Date().toISOString(),
17
+ updatedAt: new Date().toISOString(),
18
+ taskCount: 0,
19
+ history: [],
20
+ }), { status: 201, headers: { "content-type": "application/json" } });
21
+ }),
22
+ });
23
+ const result = await client.createSession({ name: "guest scout", mode: "guest" });
24
+ assert.equal(seenUrl, "http://127.0.0.1:9999/v1/sessions");
25
+ assert.match(seenBody, /guest scout/);
26
+ assert.equal(result.id, "s1");
27
+ });
28
+ //# sourceMappingURL=session-client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-client.test.js","sourceRoot":"","sources":["../../tests/session-client.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,IAAI,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;IACnD,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,QAAQ,GAAG,EAAE,CAAC;IAElB,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC;QAClC,OAAO,EAAE,uBAAuB;QAChC,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YAC1B,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YACtB,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;YACpC,OAAO,IAAI,QAAQ,CACjB,IAAI,CAAC,SAAS,CAAC;gBACb,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,SAAS,EAAE,CAAC;gBACZ,OAAO,EAAE,EAAE;aACZ,CAAC,EACF,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,CACjE,CAAC;QACJ,CAAC,CAAiB;KACnB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAClF,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,mCAAmC,CAAC,CAAC;IAC3D,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACtC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,39 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { createApp } from "../src/server/app.js";
4
+ import { startFixtureSite } from "./fixture-site.js";
5
+ test("fails when output schema rejects the agent result", async () => {
6
+ const fixture = await startFixtureSite();
7
+ const app = createApp();
8
+ try {
9
+ const response = await app.inject({
10
+ method: "POST",
11
+ url: "/v1/tasks/run",
12
+ payload: {
13
+ goal: "Search for banana and return product, price, and stock.",
14
+ startUrl: fixture.url,
15
+ recipeId: "fixture-catalog",
16
+ input: { query: "banana" },
17
+ outputSchema: {
18
+ type: "object",
19
+ additionalProperties: false,
20
+ required: ["product", "status"],
21
+ properties: {
22
+ product: { type: "string" },
23
+ status: { type: "string", enum: ["confirmed"] },
24
+ },
25
+ },
26
+ agent: { kind: "mock" },
27
+ },
28
+ });
29
+ assert.equal(response.statusCode, 500);
30
+ const payload = response.json();
31
+ assert.equal(payload.status, "failed");
32
+ assert.match(payload.error, /Output schema validation failed/);
33
+ }
34
+ finally {
35
+ await app.close();
36
+ await fixture.close();
37
+ }
38
+ });
39
+ //# sourceMappingURL=task-api-failure.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-api-failure.test.js","sourceRoot":"","sources":["../../tests/task-api-failure.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,IAAI,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;IACnE,MAAM,OAAO,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IAExB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAChC,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,eAAe;YACpB,OAAO,EAAE;gBACP,IAAI,EAAE,yDAAyD;gBAC/D,QAAQ,EAAE,OAAO,CAAC,GAAG;gBACrB,QAAQ,EAAE,iBAAiB;gBAC3B,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE;gBAC1B,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,oBAAoB,EAAE,KAAK;oBAC3B,QAAQ,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC;oBAC/B,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC3B,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC,EAAE;qBAChD;iBACF;gBACD,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;aACxB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,iCAAiC,CAAC,CAAC;IACjE,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { createApp } from "../src/server/app.js";
4
+ import { startFixtureSite } from "./fixture-site.js";
5
+ test("runs the local fixture task end-to-end through HTTP API", async () => {
6
+ const fixture = await startFixtureSite();
7
+ const app = createApp();
8
+ try {
9
+ const response = await app.inject({
10
+ method: "POST",
11
+ url: "/v1/tasks/run",
12
+ payload: {
13
+ goal: "Search for banana and return product, price, and stock.",
14
+ startUrl: fixture.url,
15
+ recipeId: "fixture-catalog",
16
+ input: { query: "banana" },
17
+ outputSchema: {
18
+ type: "object",
19
+ required: ["product", "price", "stock"],
20
+ properties: {
21
+ product: { type: "string" },
22
+ price: { type: "string" },
23
+ stock: { type: "string" },
24
+ },
25
+ },
26
+ agent: { kind: "mock" },
27
+ },
28
+ });
29
+ assert.equal(response.statusCode, 200, response.body);
30
+ const payload = response.json();
31
+ assert.equal(payload.status, "completed");
32
+ assert.equal(payload.result.product, "Banana");
33
+ assert.equal(payload.result.price, "$1.29");
34
+ assert.equal(payload.result.stock, "In stock");
35
+ const stored = await app.inject({
36
+ method: "GET",
37
+ url: `/v1/tasks/${payload.taskId}`,
38
+ });
39
+ assert.equal(stored.statusCode, 200);
40
+ const storedPayload = stored.json();
41
+ assert.equal(storedPayload.taskId, payload.taskId);
42
+ assert.ok(Array.isArray(storedPayload.steps));
43
+ assert.ok(storedPayload.steps.length >= 3);
44
+ }
45
+ finally {
46
+ await app.close();
47
+ await fixture.close();
48
+ }
49
+ });
50
+ //# sourceMappingURL=task-api.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-api.test.js","sourceRoot":"","sources":["../../tests/task-api.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,IAAI,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;IACzE,MAAM,OAAO,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IAExB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAChC,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,eAAe;YACpB,OAAO,EAAE;gBACP,IAAI,EAAE,yDAAyD;gBAC/D,QAAQ,EAAE,OAAO,CAAC,GAAG;gBACrB,QAAQ,EAAE,iBAAiB;gBAC3B,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE;gBAC1B,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC;oBACvC,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC3B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBAC1B;iBACF;gBACD,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;aACxB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAE/C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC9B,MAAM,EAAE,KAAK;YACb,GAAG,EAAE,aAAa,OAAO,CAAC,MAAM,EAAE;SACnC,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACrC,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC,CAAC,CAAC"}