@manyoars/oars 0.2.0 → 0.4.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.
Files changed (320) hide show
  1. package/README.md +147 -28
  2. package/dist/api.js +1 -1
  3. package/dist/bin.js +6 -29
  4. package/dist/cli.d.ts +10 -4
  5. package/dist/cli.js +440 -91
  6. package/dist/commands/keys.d.ts +31 -0
  7. package/dist/commands/keys.js +65 -0
  8. package/dist/commands/login.d.ts +1 -1
  9. package/dist/commands/login.js +3 -3
  10. package/dist/errors.d.ts +13 -13
  11. package/dist/errors.js +28 -11
  12. package/dist/gate/checks.d.ts +68 -0
  13. package/dist/gate/checks.js +584 -0
  14. package/dist/gate/command.d.ts +14 -0
  15. package/dist/gate/command.js +61 -0
  16. package/dist/gate/hook-fill-main.d.ts +1 -0
  17. package/dist/gate/hook-fill-main.js +16 -0
  18. package/dist/gate/hook-fill.d.ts +38 -0
  19. package/dist/gate/hook-fill.js +94 -0
  20. package/dist/gate/hook-main.d.ts +1 -0
  21. package/dist/gate/hook-main.js +47 -0
  22. package/dist/gate/hook-process.d.ts +24 -0
  23. package/dist/gate/hook-process.js +112 -0
  24. package/dist/gate/hook-record.d.ts +3 -0
  25. package/dist/gate/hook-record.js +8 -0
  26. package/dist/gate/hook.d.ts +48 -0
  27. package/dist/gate/hook.js +259 -0
  28. package/dist/gate/install.d.ts +25 -0
  29. package/dist/gate/install.js +126 -0
  30. package/dist/gate/local-bin.d.ts +8 -0
  31. package/dist/gate/local-bin.js +36 -0
  32. package/dist/gate/notes.d.ts +19 -0
  33. package/dist/gate/notes.js +27 -0
  34. package/dist/gate/novelty.d.ts +35 -0
  35. package/dist/gate/novelty.js +99 -0
  36. package/dist/gate/policy.d.ts +25 -0
  37. package/dist/gate/policy.js +73 -0
  38. package/dist/gate/record.d.ts +120 -0
  39. package/dist/gate/record.js +125 -0
  40. package/dist/gate/registry-state.d.ts +10 -0
  41. package/dist/gate/registry-state.js +30 -0
  42. package/dist/gate/registry.d.ts +56 -0
  43. package/dist/gate/registry.js +94 -0
  44. package/dist/gate/replay.d.ts +20 -0
  45. package/dist/gate/replay.js +254 -0
  46. package/dist/gate/report.d.ts +50 -0
  47. package/dist/gate/report.js +89 -0
  48. package/dist/gate/scope.d.ts +7 -0
  49. package/dist/gate/scope.js +27 -0
  50. package/dist/gate/transcripts.d.ts +68 -0
  51. package/dist/gate/transcripts.js +232 -0
  52. package/dist/hook-bin.d.ts +1 -0
  53. package/dist/hook-bin.js +50 -0
  54. package/dist/issuer.d.ts +10 -6
  55. package/dist/issuer.js +19 -24
  56. package/dist/main.d.ts +1 -0
  57. package/dist/main.js +67 -0
  58. package/dist/oidc.js +1 -1
  59. package/dist/sessions/actions.d.ts +35 -0
  60. package/dist/sessions/actions.js +429 -0
  61. package/dist/sessions/allow.d.ts +23 -0
  62. package/dist/sessions/allow.js +71 -0
  63. package/dist/sessions/archive.d.ts +11 -0
  64. package/dist/sessions/archive.js +38 -0
  65. package/dist/sessions/audit.d.ts +42 -0
  66. package/dist/sessions/audit.js +104 -0
  67. package/dist/sessions/baseline.d.ts +62 -0
  68. package/dist/sessions/baseline.js +190 -0
  69. package/dist/sessions/call-shape.d.ts +19 -0
  70. package/dist/sessions/call-shape.js +85 -0
  71. package/dist/sessions/capture-runtime.d.ts +10 -0
  72. package/dist/sessions/capture-runtime.js +12 -0
  73. package/dist/sessions/cell-increments.d.ts +47 -0
  74. package/dist/sessions/cell-increments.js +243 -0
  75. package/dist/sessions/cells.d.ts +109 -0
  76. package/dist/sessions/cells.js +261 -0
  77. package/dist/sessions/codex.d.ts +53 -0
  78. package/dist/sessions/codex.js +745 -0
  79. package/dist/sessions/command.d.ts +127 -0
  80. package/dist/sessions/command.js +419 -0
  81. package/dist/sessions/copilot.d.ts +40 -0
  82. package/dist/sessions/copilot.js +432 -0
  83. package/dist/sessions/coverage.d.ts +19 -0
  84. package/dist/sessions/coverage.js +56 -0
  85. package/dist/sessions/cursor.d.ts +24 -0
  86. package/dist/sessions/cursor.js +324 -0
  87. package/dist/sessions/derive.d.ts +57 -0
  88. package/dist/sessions/derive.js +386 -0
  89. package/dist/sessions/exclusion.d.ts +87 -0
  90. package/dist/sessions/exclusion.js +361 -0
  91. package/dist/sessions/extract.d.ts +181 -0
  92. package/dist/sessions/extract.js +1806 -0
  93. package/dist/sessions/fold.d.ts +17 -0
  94. package/dist/sessions/fold.js +71 -0
  95. package/dist/sessions/frame.d.ts +24 -0
  96. package/dist/sessions/frame.js +95 -0
  97. package/dist/sessions/gemini.d.ts +37 -0
  98. package/dist/sessions/gemini.js +613 -0
  99. package/dist/sessions/gold-arms.d.ts +67 -0
  100. package/dist/sessions/gold-arms.js +172 -0
  101. package/dist/sessions/gold.d.ts +197 -0
  102. package/dist/sessions/gold.js +463 -0
  103. package/dist/sessions/graph.d.ts +12 -0
  104. package/dist/sessions/graph.js +34 -0
  105. package/dist/sessions/grok.d.ts +36 -0
  106. package/dist/sessions/grok.js +421 -0
  107. package/dist/sessions/hook-calls.d.ts +3 -0
  108. package/dist/sessions/hook-calls.js +47 -0
  109. package/dist/sessions/hook-index.d.ts +66 -0
  110. package/dist/sessions/hook-index.js +164 -0
  111. package/dist/sessions/hooks.d.ts +17 -0
  112. package/dist/sessions/hooks.js +281 -0
  113. package/dist/sessions/identity.d.ts +27 -0
  114. package/dist/sessions/identity.js +131 -0
  115. package/dist/sessions/install.d.ts +70 -0
  116. package/dist/sessions/install.js +246 -0
  117. package/dist/sessions/lineage.d.ts +19 -0
  118. package/dist/sessions/lineage.js +118 -0
  119. package/dist/sessions/mcp.d.ts +7 -0
  120. package/dist/sessions/mcp.js +157 -0
  121. package/dist/sessions/merkle.d.ts +7 -0
  122. package/dist/sessions/merkle.js +28 -0
  123. package/dist/sessions/motif.d.ts +44 -0
  124. package/dist/sessions/motif.js +59 -0
  125. package/dist/sessions/opencode.d.ts +33 -0
  126. package/dist/sessions/opencode.js +319 -0
  127. package/dist/sessions/otel.d.ts +60 -0
  128. package/dist/sessions/otel.js +494 -0
  129. package/dist/sessions/package-books.d.ts +48 -0
  130. package/dist/sessions/package-books.js +120 -0
  131. package/dist/sessions/package-resolve.d.ts +32 -0
  132. package/dist/sessions/package-resolve.js +185 -0
  133. package/dist/sessions/pending.d.ts +34 -0
  134. package/dist/sessions/pending.js +142 -0
  135. package/dist/sessions/pi.d.ts +36 -0
  136. package/dist/sessions/pi.js +353 -0
  137. package/dist/sessions/pool-books.d.ts +21 -0
  138. package/dist/sessions/pool-books.js +75 -0
  139. package/dist/sessions/pool-choices.d.ts +5 -0
  140. package/dist/sessions/pool-choices.js +11 -0
  141. package/dist/sessions/pool-command.d.ts +115 -0
  142. package/dist/sessions/pool-command.js +669 -0
  143. package/dist/sessions/pool-delta.d.ts +54 -0
  144. package/dist/sessions/pool-delta.js +190 -0
  145. package/dist/sessions/pool-nightly-deps.d.ts +3 -0
  146. package/dist/sessions/pool-nightly-deps.js +11 -0
  147. package/dist/sessions/pool-nightly.d.ts +10 -0
  148. package/dist/sessions/pool-nightly.js +85 -0
  149. package/dist/sessions/pool-outbox.d.ts +76 -0
  150. package/dist/sessions/pool-outbox.js +313 -0
  151. package/dist/sessions/pool-print.d.ts +26 -0
  152. package/dist/sessions/pool-print.js +68 -0
  153. package/dist/sessions/pool-raw.d.ts +27 -0
  154. package/dist/sessions/pool-raw.js +68 -0
  155. package/dist/sessions/pool-replica.d.ts +35 -0
  156. package/dist/sessions/pool-replica.js +91 -0
  157. package/dist/sessions/pool-send-lock.d.ts +20 -0
  158. package/dist/sessions/pool-send-lock.js +87 -0
  159. package/dist/sessions/pool-sent.d.ts +4 -0
  160. package/dist/sessions/pool-sent.js +26 -0
  161. package/dist/sessions/pool-totals.d.ts +10 -0
  162. package/dist/sessions/pool-totals.js +21 -0
  163. package/dist/sessions/pool-wire.d.ts +435 -0
  164. package/dist/sessions/pool-wire.js +1100 -0
  165. package/dist/sessions/pool.d.ts +32 -0
  166. package/dist/sessions/pool.js +164 -0
  167. package/dist/sessions/projection.d.ts +75 -0
  168. package/dist/sessions/projection.js +165 -0
  169. package/dist/sessions/public-vocabulary.d.ts +72 -0
  170. package/dist/sessions/public-vocabulary.js +295 -0
  171. package/dist/sessions/query.d.ts +123 -0
  172. package/dist/sessions/query.js +268 -0
  173. package/dist/sessions/read-adoption.d.ts +2 -0
  174. package/dist/sessions/read-adoption.js +27 -0
  175. package/dist/sessions/read-call-shape.d.ts +2 -0
  176. package/dist/sessions/read-call-shape.js +25 -0
  177. package/dist/sessions/read-change.d.ts +2 -0
  178. package/dist/sessions/read-change.js +30 -0
  179. package/dist/sessions/read-cost.d.ts +4 -0
  180. package/dist/sessions/read-cost.js +48 -0
  181. package/dist/sessions/read-day-move.d.ts +3 -0
  182. package/dist/sessions/read-day-move.js +65 -0
  183. package/dist/sessions/read-fit.d.ts +7 -0
  184. package/dist/sessions/read-fit.js +41 -0
  185. package/dist/sessions/read-interaction.d.ts +5 -0
  186. package/dist/sessions/read-interaction.js +62 -0
  187. package/dist/sessions/read-lead-lag.d.ts +15 -0
  188. package/dist/sessions/read-lead-lag.js +81 -0
  189. package/dist/sessions/read-live.d.ts +6 -0
  190. package/dist/sessions/read-live.js +38 -0
  191. package/dist/sessions/read-method.d.ts +2 -0
  192. package/dist/sessions/read-method.js +29 -0
  193. package/dist/sessions/read-next-step.d.ts +2 -0
  194. package/dist/sessions/read-next-step.js +35 -0
  195. package/dist/sessions/read-order.d.ts +54 -0
  196. package/dist/sessions/read-order.js +62 -0
  197. package/dist/sessions/read-readable.d.ts +8 -0
  198. package/dist/sessions/read-readable.js +24 -0
  199. package/dist/sessions/read-recovery-edge.d.ts +2 -0
  200. package/dist/sessions/read-recovery-edge.js +26 -0
  201. package/dist/sessions/read-recovery.d.ts +20 -0
  202. package/dist/sessions/read-recovery.js +97 -0
  203. package/dist/sessions/read-rows.d.ts +13 -0
  204. package/dist/sessions/read-rows.js +47 -0
  205. package/dist/sessions/read-substitution.d.ts +5 -0
  206. package/dist/sessions/read-substitution.js +51 -0
  207. package/dist/sessions/read-support.d.ts +48 -0
  208. package/dist/sessions/read-support.js +73 -0
  209. package/dist/sessions/read-tool-day.d.ts +2 -0
  210. package/dist/sessions/read-tool-day.js +26 -0
  211. package/dist/sessions/read-version-boundary.d.ts +31 -0
  212. package/dist/sessions/read-version-boundary.js +95 -0
  213. package/dist/sessions/read.d.ts +86 -0
  214. package/dist/sessions/read.js +87 -0
  215. package/dist/sessions/recall-bundle.d.ts +12 -0
  216. package/dist/sessions/recall-bundle.js +33 -0
  217. package/dist/sessions/recall-consequence.d.ts +45 -0
  218. package/dist/sessions/recall-consequence.js +179 -0
  219. package/dist/sessions/recall-frames.d.ts +18 -0
  220. package/dist/sessions/recall-frames.js +44 -0
  221. package/dist/sessions/recall-next.d.ts +145 -0
  222. package/dist/sessions/recall-next.js +241 -0
  223. package/dist/sessions/recall-object.d.ts +139 -0
  224. package/dist/sessions/recall-object.js +78 -0
  225. package/dist/sessions/recall-pool.d.ts +19 -0
  226. package/dist/sessions/recall-pool.js +96 -0
  227. package/dist/sessions/recall-push.d.ts +26 -0
  228. package/dist/sessions/recall-push.js +47 -0
  229. package/dist/sessions/recall-reads.d.ts +124 -0
  230. package/dist/sessions/recall-reads.js +417 -0
  231. package/dist/sessions/recall-render.d.ts +19 -0
  232. package/dist/sessions/recall-render.js +168 -0
  233. package/dist/sessions/recovery-calls.d.ts +21 -0
  234. package/dist/sessions/recovery-calls.js +25 -0
  235. package/dist/sessions/redact.d.ts +17 -0
  236. package/dist/sessions/redact.js +113 -0
  237. package/dist/sessions/repo-root.d.ts +10 -0
  238. package/dist/sessions/repo-root.js +101 -0
  239. package/dist/sessions/schema.d.ts +694 -0
  240. package/dist/sessions/schema.js +167 -0
  241. package/dist/sessions/session-shape.d.ts +76 -0
  242. package/dist/sessions/session-shape.js +355 -0
  243. package/dist/sessions/sources.d.ts +50 -0
  244. package/dist/sessions/sources.js +233 -0
  245. package/dist/sessions/steps.d.ts +105 -0
  246. package/dist/sessions/steps.js +250 -0
  247. package/dist/sessions/store.d.ts +309 -0
  248. package/dist/sessions/store.js +1498 -0
  249. package/dist/sessions/strata.d.ts +26 -0
  250. package/dist/sessions/strata.js +77 -0
  251. package/dist/sessions/survival.d.ts +27 -0
  252. package/dist/sessions/survival.js +230 -0
  253. package/dist/sessions/transcript-tail.d.ts +14 -0
  254. package/dist/sessions/transcript-tail.js +64 -0
  255. package/dist/sessions/verify.d.ts +53 -0
  256. package/dist/sessions/verify.js +286 -0
  257. package/dist/sessions/vocab-load.d.ts +26 -0
  258. package/dist/sessions/vocab-load.js +61 -0
  259. package/dist/sessions/vscode-copilot.d.ts +38 -0
  260. package/dist/sessions/vscode-copilot.js +494 -0
  261. package/dist/telemetry/command.d.ts +8 -0
  262. package/dist/telemetry/command.js +85 -0
  263. package/dist/telemetry/consent.d.ts +17 -0
  264. package/dist/telemetry/consent.js +63 -0
  265. package/dist/telemetry/crash.d.ts +8 -0
  266. package/dist/telemetry/crash.js +52 -0
  267. package/dist/telemetry/emit.d.ts +31 -0
  268. package/dist/telemetry/emit.js +42 -0
  269. package/dist/telemetry/fields.d.ts +16 -0
  270. package/dist/telemetry/fields.js +26 -0
  271. package/dist/telemetry/health.d.ts +21 -0
  272. package/dist/telemetry/health.js +108 -0
  273. package/dist/telemetry/hook-emit.d.ts +4 -0
  274. package/dist/telemetry/hook-emit.js +18 -0
  275. package/dist/telemetry/measures.d.ts +32 -0
  276. package/dist/telemetry/measures.js +128 -0
  277. package/dist/telemetry/observe.d.ts +13 -0
  278. package/dist/telemetry/observe.js +51 -0
  279. package/dist/telemetry/read-events.d.ts +9 -0
  280. package/dist/telemetry/read-events.js +17 -0
  281. package/dist/telemetry/record.d.ts +17 -0
  282. package/dist/telemetry/record.js +26 -0
  283. package/dist/telemetry/report.d.ts +77 -0
  284. package/dist/telemetry/report.js +188 -0
  285. package/dist/telemetry/schema.d.ts +40 -0
  286. package/dist/telemetry/schema.js +187 -0
  287. package/dist/telemetry/send-main.d.ts +1 -0
  288. package/dist/telemetry/send-main.js +11 -0
  289. package/dist/telemetry/send.d.ts +36 -0
  290. package/dist/telemetry/send.js +172 -0
  291. package/dist/telemetry/spool.d.ts +17 -0
  292. package/dist/telemetry/spool.js +70 -0
  293. package/dist/telemetry/wire.d.ts +25 -0
  294. package/dist/telemetry/wire.js +76 -0
  295. package/package.json +4 -5
  296. package/vocab/crates.json +1 -0
  297. package/vocab/go.json +1 -0
  298. package/vocab/harness.json +1 -0
  299. package/vocab/homebrew.json +1 -0
  300. package/vocab/manifest.json +1 -0
  301. package/vocab/maven.json +1 -0
  302. package/vocab/models.json +1 -0
  303. package/vocab/npm.json +1 -0
  304. package/vocab/programs.json +1 -0
  305. package/vocab/pypi.json +1 -0
  306. package/vocab/rubygems.json +1 -0
  307. package/dist/commands/deploy-input.d.ts +0 -38
  308. package/dist/commands/deploy-input.js +0 -150
  309. package/dist/commands/deploy.d.ts +0 -22
  310. package/dist/commands/deploy.js +0 -124
  311. package/dist/commands/status.d.ts +0 -7
  312. package/dist/commands/status.js +0 -18
  313. package/dist/commands/templates.d.ts +0 -11
  314. package/dist/commands/templates.js +0 -32
  315. package/dist/commands/test-charge.d.ts +0 -11
  316. package/dist/commands/test-charge.js +0 -34
  317. package/dist/journal.d.ts +0 -26
  318. package/dist/journal.js +0 -58
  319. package/parity/deploy-plans/paid-api.json +0 -34
  320. package/parity/deploy-plans/per-task-agent.json +0 -34
@@ -1,38 +0,0 @@
1
- import type { components } from '@manyoars/oars-client';
2
- import type { AgentTemplate } from './templates.js';
3
- type RegisterWorkloadRequest = components['schemas']['RegisterWorkloadRequest'];
4
- type CreatePriceInput = components['schemas']['CreatePriceInput'];
5
- /** What `oars deploy` is told to deploy, as the flags give it. A flag the developer did not pass is undefined. */
6
- export interface DeployFlags {
7
- template?: string;
8
- image?: string;
9
- manifestFile?: string;
10
- name?: string;
11
- port?: number;
12
- public?: boolean;
13
- cpuMillicores?: number;
14
- memoryMib?: number;
15
- alwaysOn?: boolean;
16
- /** `--price`: starter prices to pick from a template (all of them by default). */
17
- prices: string[];
18
- /** `--no-prices`. */
19
- noPrices: boolean;
20
- priceFile?: string;
21
- /** `NAME=value` entries. */
22
- secrets: string[];
23
- /** Names of environment variables to read. */
24
- secretsFromEnv: string[];
25
- }
26
- /** The register body and the prices to create, validated and ready to send. */
27
- export interface DeployInput {
28
- request: RegisterWorkloadRequest;
29
- prices: CreatePriceInput[];
30
- }
31
- /** Reads the catalog once, when a `--template` deploy has passed every check that needs no network. */
32
- export type TemplateLookup = () => Promise<AgentTemplate[]>;
33
- /**
34
- * Turns the flags into the calls' bodies. Exactly one of `--template`, `--image`, `--manifest`. Every mistake the flags alone can
35
- * show is found before any request; only `--template` then reads the catalog (`catalog`), so a typo there costs one GET.
36
- */
37
- export declare const loadDeployInput: (flags: DeployFlags, env: NodeJS.ProcessEnv, catalog: TemplateLookup) => Promise<DeployInput>;
38
- export {};
@@ -1,150 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { CliError, ExitCode } from '../errors.js';
3
- const usage = (message) => new CliError(message, ExitCode.USAGE, 'usage');
4
- const DIGEST = /@sha256:[0-9a-f]{64}$/;
5
- const PRICE_KINDS = ['ONE_TIME', 'RECURRING_MONTHLY', 'CREDIT_PACK'];
6
- const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
7
- const has = (value, key, type) => typeof Reflect.get(value, key) === type;
8
- const isService = (value) => isObject(value) && has(value, 'name', 'string') && has(value, 'image', 'string') && has(value, 'cpuMillicores', 'number') && has(value, 'memoryMib', 'number');
9
- const isRegisterRequest = (value) => {
10
- if (!isObject(value) || !has(value, 'name', 'string'))
11
- return false;
12
- const services = Reflect.get(value, 'services');
13
- return Array.isArray(services) && services.length > 0 && services.every(isService);
14
- };
15
- const isPriceKind = (value) => PRICE_KINDS.some((kind) => kind === value);
16
- const isPrice = (value) => isObject(value) && has(value, 'priceRef', 'string') && has(value, 'displayName', 'string') && has(value, 'amountUsd', 'string') && isPriceKind(Reflect.get(value, 'kind'));
17
- const isPrices = (value) => Array.isArray(value) && value.every(isPrice);
18
- /** A JSON file's parsed content; a file that cannot be read or parsed is exit 2 naming it. */
19
- const readJson = async (path) => {
20
- let text;
21
- try {
22
- text = await readFile(path, 'utf8');
23
- }
24
- catch (error) {
25
- throw usage(`Cannot read ${path}: ${error instanceof Error ? error.message : String(error)}`);
26
- }
27
- try {
28
- return JSON.parse(text);
29
- }
30
- catch (error) {
31
- throw usage(`${path} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
32
- }
33
- };
34
- /** The platform deploys what a digest names; a tag can move, so a service without one is refused before any request. */
35
- const requireDigest = (image) => {
36
- if (!DIGEST.test(image)) {
37
- throw usage(`${image} is not pinned by digest. Print one with: docker buildx imagetools inspect ${image}\nthen deploy <name>@sha256:<64 hex digits>.`);
38
- }
39
- };
40
- const secretsFrom = (flags, env) => [
41
- ...flags.secrets.map((entry) => {
42
- const at = entry.indexOf('=');
43
- // The entry may be the secret itself, so the message does not echo it.
44
- if (at < 1)
45
- throw usage('--secret takes NAME=value; use --secret-from-env NAME to read the value from the environment.');
46
- return { name: entry.slice(0, at), value: entry.slice(at + 1) };
47
- }),
48
- ...flags.secretsFromEnv.map((name) => {
49
- const value = env[name];
50
- if (value === undefined || value === '')
51
- throw usage(`--secret-from-env ${name}: the environment variable ${name} is not set.`);
52
- return { name, value };
53
- }),
54
- ];
55
- const requestFromFlags = (flags, image) => {
56
- if (flags.name === undefined)
57
- throw usage('--image needs --name <name>.');
58
- requireDigest(image);
59
- return {
60
- name: flags.name,
61
- ...(flags.alwaysOn === true ? { alwaysOn: true } : {}),
62
- services: [{ name: 'app', image, port: flags.port ?? 8080, public: flags.public ?? false, cpuMillicores: flags.cpuMillicores ?? 250, memoryMib: flags.memoryMib ?? 256 }],
63
- };
64
- };
65
- /** The register body of an --image or --manifest deploy. */
66
- const imageOrFileRequest = async (flags) => {
67
- if (flags.image !== undefined)
68
- return requestFromFlags(flags, flags.image);
69
- if (flags.manifestFile !== undefined)
70
- return requestFromFile(flags, flags.manifestFile);
71
- throw usage('Pass exactly one of --template, --image, or --manifest.');
72
- };
73
- /** The flags that describe an --image deploy; a template or a manifest file holds its own. */
74
- const refuseImageFlags = (flags, source) => {
75
- const given = ['name', 'port', 'public', 'cpuMillicores', 'memoryMib'].filter((key) => flags[key] !== undefined);
76
- if (given.length > 0)
77
- throw usage(`--name, --port, --public, --cpu-millicores, and --memory-mib describe an --image deploy; ${source} holds its own.`);
78
- };
79
- const requestFromFile = async (flags, path) => {
80
- refuseImageFlags(flags, 'a --manifest file');
81
- const parsed = await readJson(path);
82
- if (!isRegisterRequest(parsed)) {
83
- throw usage(`${path} is not a workload manifest: it needs a name and services, each with name, image, cpuMillicores and memoryMib.`);
84
- }
85
- for (const service of parsed.services)
86
- requireDigest(service.image);
87
- return flags.alwaysOn === true ? { ...parsed, alwaysOn: true } : parsed;
88
- };
89
- const pricesFromFile = async (path) => {
90
- const parsed = await readJson(path);
91
- if (!isPrices(parsed)) {
92
- throw usage(`${path} must be a JSON array of prices, each with priceRef, displayName, amountUsd (a decimal string) and kind (ONE_TIME, RECURRING_MONTHLY or CREDIT_PACK).`);
93
- }
94
- return parsed;
95
- };
96
- /** A starter price as the create call takes it. `credits` is left out of a price that has none (the wire may carry null). */
97
- const priceFromTemplate = (price) => ({
98
- priceRef: price.priceRef,
99
- displayName: price.displayName,
100
- amountUsd: price.amountUsd,
101
- kind: price.kind,
102
- ...(typeof price.credits === 'number' ? { credits: price.credits } : {}),
103
- });
104
- /** `--template`: the entry's manifest, and the starter prices `--price` picked (every one without it, none for `--no-prices`). */
105
- const fromTemplate = (flags, template) => {
106
- const wanted = flags.noPrices ? [] : flags.prices;
107
- const unknown = wanted.filter((ref) => !template.starterPrices.some((price) => price.priceRef === ref));
108
- if (unknown.length > 0) {
109
- throw usage(`Template ${template.templateId} has no starter price ${unknown.join(', ')}; its prices are ${template.starterPrices.map((price) => price.priceRef).join(', ')}.`);
110
- }
111
- const chosen = flags.noPrices || flags.prices.length > 0 ? template.starterPrices.filter((price) => wanted.includes(price.priceRef)) : template.starterPrices;
112
- return { request: flags.alwaysOn === true ? { ...template.manifest, alwaysOn: true } : template.manifest, prices: chosen.map(priceFromTemplate) };
113
- };
114
- /** A catalog entry's id is what the platform serves, so an id it does not list is exit 2 naming the ids it does. */
115
- const findTemplate = async (id, resolve) => {
116
- const catalog = await resolve();
117
- const found = catalog.find((template) => template.templateId === id);
118
- if (found === undefined) {
119
- throw usage(`No template ${id}. ${catalog.length === 0 ? 'The catalog is empty.' : `Available: ${catalog.map((template) => template.templateId).join(', ')}.`} List them with: oars templates`);
120
- }
121
- return found;
122
- };
123
- /** The checks on a `--template` deploy's flags, then its catalog entry; the flags are all read before the one GET. */
124
- const templateInput = async (flags, id, catalog) => {
125
- refuseImageFlags(flags, 'the template');
126
- if (flags.priceFile !== undefined)
127
- throw usage('--price-file adds prices to an --image or --manifest deploy; a template brings its own: choose among them with --price, or skip them with --no-prices.');
128
- if (flags.noPrices && flags.prices.length > 0)
129
- throw usage('--price and --no-prices contradict each other.');
130
- return fromTemplate(flags, await findTemplate(id, catalog));
131
- };
132
- /**
133
- * Turns the flags into the calls' bodies. Exactly one of `--template`, `--image`, `--manifest`. Every mistake the flags alone can
134
- * show is found before any request; only `--template` then reads the catalog (`catalog`), so a typo there costs one GET.
135
- */
136
- export const loadDeployInput = async (flags, env, catalog) => {
137
- if ([flags.template, flags.image, flags.manifestFile].filter((source) => source !== undefined).length !== 1) {
138
- throw usage('Pass exactly one of --template, --image, or --manifest.');
139
- }
140
- const picked = flags.template === undefined ? undefined : await templateInput(flags, flags.template, catalog);
141
- if (picked === undefined && (flags.prices.length > 0 || flags.noPrices)) {
142
- throw usage("--price and --no-prices choose among a template's starter prices; use --price-file with --image or --manifest.");
143
- }
144
- const base = picked?.request ?? (await imageOrFileRequest(flags));
145
- const secrets = [...(base.secrets ?? []), ...secretsFrom(flags, env)];
146
- return {
147
- request: secrets.length === 0 ? base : { ...base, secrets },
148
- prices: picked?.prices ?? (flags.priceFile === undefined ? [] : await pricesFromFile(flags.priceFile)),
149
- };
150
- };
@@ -1,22 +0,0 @@
1
- import { type DeployFlags } from './deploy-input.js';
2
- import type { Outcome, RunDeps } from '../cli.js';
3
- export interface DeployOptions extends DeployFlags {
4
- apiUrl: string;
5
- /** The command line as typed (without the node and script entries), for the rerun line. */
6
- argv: string[];
7
- /** False for `--no-start`: register and price, but make no deploy call. */
8
- start: boolean;
9
- /** `--idempotency-key`: the base of every step's key. A fresh UUID when absent. */
10
- idempotencyKey?: string;
11
- }
12
- /**
13
- * The command that resumes a failed deploy: the same arguments plus `--idempotency-key <base>`. Secret values are never
14
- * printed, so `--secret NAME=value` becomes `--secret-from-env NAME` (the developer exports NAME before the rerun).
15
- */
16
- export declare const rerunCommand: (argv: string[], base: string) => string;
17
- /**
18
- * The web deploy page's order: register, each price, deploy (design §3.1). Each call carries its own idempotency key
19
- * (`stepKey(base, step)`), so a rerun with the same base replays what finished and carries on. The first failed step stops
20
- * the sequence (exit 9) with the workload id, the rerun line, and the SDK key when this run minted it.
21
- */
22
- export declare const deploy: (deps: RunDeps, options: DeployOptions) => Promise<Outcome>;
@@ -1,124 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { apiClient, unwrap } from '../api.js';
3
- import { CliError, ExitCode } from '../errors.js';
4
- import { stepKey } from '../journal.js';
5
- import { resolveAuthToken } from '../session.js';
6
- import { loadDeployInput } from './deploy-input.js';
7
- import { listTemplates, STEP as TEMPLATES_STEP } from './templates.js';
8
- const SHELL_SAFE = /^[A-Za-z0-9_@%+=:,./-]+$/;
9
- const quote = (token) => (SHELL_SAFE.test(token) ? token : `'${token.replaceAll("'", "'\\''")}'`);
10
- /**
11
- * The command that resumes a failed deploy: the same arguments plus `--idempotency-key <base>`. Secret values are never
12
- * printed, so `--secret NAME=value` becomes `--secret-from-env NAME` (the developer exports NAME before the rerun).
13
- */
14
- export const rerunCommand = (argv, base) => {
15
- const secretName = (entry) => entry.split('=')[0] ?? '';
16
- const tokens = [];
17
- for (let at = 0; at < argv.length; at += 1) {
18
- const arg = argv[at] ?? '';
19
- if (arg === '--idempotency-key') {
20
- at += 1;
21
- }
22
- else if (arg === '--secret') {
23
- at += 1;
24
- tokens.push('--secret-from-env', secretName(argv[at] ?? ''));
25
- }
26
- else if (arg.startsWith('--secret=')) {
27
- tokens.push('--secret-from-env', secretName(arg.slice('--secret='.length)));
28
- }
29
- else if (!arg.startsWith('--idempotency-key=')) {
30
- tokens.push(arg);
31
- }
32
- }
33
- return ['oars', ...tokens, '--idempotency-key', base].map(quote).join(' ');
34
- };
35
- /** A failure after register is exit 9 whatever its own code: the workload exists, so the developer's next move is the rerun. */
36
- const partialFailure = (error, step, partial) => {
37
- const cause = error instanceof CliError ? error : new CliError(`Unexpected error: ${error instanceof Error ? error.message : String(error)}`, ExitCode.UNEXPECTED, step);
38
- return new CliError(cause.message, ExitCode.PARTIAL, step, cause.problem, partial);
39
- };
40
- /**
41
- * The web deploy page's order: register, each price, deploy (design §3.1). Each call carries its own idempotency key
42
- * (`stepKey(base, step)`), so a rerun with the same base replays what finished and carries on. The first failed step stops
43
- * the sequence (exit 9) with the workload id, the rerun line, and the SDK key when this run minted it.
44
- */
45
- export const deploy = async (deps, options) => {
46
- // Resolved once, and only when a step needs it: a deploy with a mistake in its flags fails before it asks for a login.
47
- let pending;
48
- const authToken = () => (pending ??= resolveAuthToken(deps, options.apiUrl));
49
- const input = await loadDeployInput(options, deps.env, async () => listTemplates(apiClient(deps, { apiUrl: options.apiUrl, step: TEMPLATES_STEP, token: await authToken() })));
50
- const token = await authToken();
51
- const base = options.idempotencyKey ?? randomUUID();
52
- const clientFor = (step) => apiClient(deps, { apiUrl: options.apiUrl, step, token });
53
- const prior = await deps.journal.read(base).catch(() => undefined);
54
- const progress = { base, steps: prior?.steps ?? [] };
55
- if (prior !== undefined) {
56
- deps.io.stderr(`Resuming deploy ${base}: ${prior.steps.map((entry) => entry.step).join(', ') || 'nothing finished yet'} already done.\n`);
57
- }
58
- // The journal only tells the developer where the last run got to; the platform's replay is what makes the rerun correct, so
59
- // a journal that cannot be written must not lose the one-time SDK key.
60
- const note = async (step, status) => {
61
- progress.steps = [...progress.steps.filter((entry) => entry.step !== step), { step, status }];
62
- await deps.journal.write(progress).catch((error) => {
63
- deps.io.stderr(`Could not record progress in the journal: ${error instanceof Error ? error.message : String(error)}\n`);
64
- });
65
- };
66
- const registerResult = await clientFor('register').POST('/agents/workloads', {
67
- params: { header: { 'Idempotency-Key': stepKey(base, 'register') } },
68
- body: input.request,
69
- });
70
- const workload = unwrap('register', registerResult);
71
- await note('register', registerResult.response.status);
72
- // A replayed registration carries no key: only the run that created the workload can show it.
73
- const partial = { workloadId: workload.id, ...(workload.sdkKey === undefined ? {} : { sdkKey: workload.sdkKey }), rerun: rerunCommand(options.argv, base) };
74
- const path = { workloadId: workload.id };
75
- const stages = [
76
- ...input.prices.map((price) => {
77
- const step = `price:${price.priceRef}`;
78
- return {
79
- step,
80
- send: async () => {
81
- const result = await clientFor(step).POST('/billing/agents/{workloadId}/prices', { params: { path }, headers: { 'Idempotency-Key': stepKey(base, step) }, body: price });
82
- unwrap(step, result);
83
- return result.response.status;
84
- },
85
- };
86
- }),
87
- ...(options.start
88
- ? [
89
- {
90
- step: 'deploy',
91
- send: async () => {
92
- const result = await clientFor('deploy').POST('/agents/workloads/{workloadId}/deploy', { params: { path }, headers: { 'Idempotency-Key': stepKey(base, 'deploy') } });
93
- unwrap('deploy', result);
94
- return result.response.status;
95
- },
96
- },
97
- ]
98
- : []),
99
- ];
100
- for (const stage of stages) {
101
- let status;
102
- try {
103
- status = await stage.send();
104
- }
105
- catch (error) {
106
- throw partialFailure(error, stage.step, partial);
107
- }
108
- await note(stage.step, status);
109
- }
110
- await deps.journal.delete(base).catch(() => undefined);
111
- const prices = input.prices.map((price) => price.priceRef);
112
- const nextSteps = [`oars status ${workload.id}`, `oars test-charge ${workload.id}${prices[0] === undefined ? '' : ` --price ${prices[0]}`}`];
113
- const lines = [
114
- `${options.start ? 'Deployed' : 'Registered'} ${workload.name} (workload ${workload.id})`,
115
- ...(workload.sdkKey === undefined ? [] : [`SDK key (shown once; save it now): ${workload.sdkKey}`]),
116
- ...(prices.length === 0 ? [] : [`Prices: ${prices.join(', ')}`]),
117
- 'Next:',
118
- ...nextSteps.map((step) => ` ${step}`),
119
- ];
120
- return {
121
- document: { ok: true, workloadId: workload.id, ...(workload.sdkKey === undefined ? {} : { sdkKey: workload.sdkKey }), prices, started: options.start, nextSteps },
122
- text: lines.join('\n'),
123
- };
124
- };
@@ -1,7 +0,0 @@
1
- import type { Outcome, RunDeps } from '../cli.js';
2
- export interface StatusOptions {
3
- apiUrl: string;
4
- workloadId: string;
5
- }
6
- /** The workload (`GET /agents/workloads/{id}`) and its billing mode (`GET /billing/agents/{id}/mode`, TEST until the creator goes live). */
7
- export declare const status: (deps: RunDeps, options: StatusOptions) => Promise<Outcome>;
@@ -1,18 +0,0 @@
1
- import { apiClient, unwrap } from '../api.js';
2
- import { resolveAuthToken } from '../session.js';
3
- const STEP = 'status';
4
- /** The workload (`GET /agents/workloads/{id}`) and its billing mode (`GET /billing/agents/{id}/mode`, TEST until the creator goes live). */
5
- export const status = async (deps, options) => {
6
- const client = apiClient(deps, { apiUrl: options.apiUrl, step: STEP, token: await resolveAuthToken(deps, options.apiUrl) });
7
- const params = { path: { workloadId: options.workloadId } };
8
- const workload = unwrap(STEP, await client.GET('/agents/workloads/{workloadId}', { params }));
9
- const { billingMode } = unwrap(STEP, await client.GET('/billing/agents/{workloadId}/mode', { params }));
10
- const { deployment } = workload;
11
- const lines = [
12
- `${workload.name} (${workload.id})`,
13
- `Workload: ${workload.status}${workload.suspended ? ' (suspended)' : ''}`,
14
- `Deployment: ${deployment.status} (${deployment.health}), desired ${deployment.desiredState}`,
15
- `Billing mode: ${billingMode}`,
16
- ];
17
- return { document: { ok: true, workload, billingMode }, text: lines.join('\n') };
18
- };
@@ -1,11 +0,0 @@
1
- import type { components, OarsClient } from '@manyoars/oars-client';
2
- import type { Outcome, RunDeps } from '../cli.js';
3
- export type AgentTemplate = components['schemas']['AgentTemplateResponse'];
4
- export interface TemplatesOptions {
5
- apiUrl: string;
6
- }
7
- export declare const STEP = "templates";
8
- /** Every entry of `GET /agents/templates`, following the pages until the last one. */
9
- export declare const listTemplates: (client: OarsClient) => Promise<AgentTemplate[]>;
10
- /** `oars templates`: the platform's starter-template catalog, the ids `oars deploy --template` takes. */
11
- export declare const templates: (deps: RunDeps, options: TemplatesOptions) => Promise<Outcome>;
@@ -1,32 +0,0 @@
1
- import { apiClient, unwrap } from '../api.js';
2
- import { resolveAuthToken } from '../session.js';
3
- export const STEP = 'templates';
4
- // The catalog holds a handful of entries; a page this large is the whole of it, and the loop below only covers a catalog that outgrows it.
5
- const PAGE_SIZE = 100;
6
- /** Every entry of `GET /agents/templates`, following the pages until the last one. */
7
- export const listTemplates = async (client) => {
8
- const templates = [];
9
- for (let page = 0;; page += 1) {
10
- const result = unwrap(STEP, await client.GET('/agents/templates', { params: { query: { page, size: PAGE_SIZE } } }));
11
- templates.push(...result.content);
12
- if (result.last)
13
- return templates;
14
- }
15
- };
16
- const describePrice = (price) => `${price.priceRef} ($${price.amountUsd}${typeof price.credits === 'number' ? `, ${String(price.credits)} credits` : ''})`;
17
- /** `oars templates`: the platform's starter-template catalog, the ids `oars deploy --template` takes. */
18
- export const templates = async (deps, options) => {
19
- const client = apiClient(deps, { apiUrl: options.apiUrl, step: STEP, token: await resolveAuthToken(deps, options.apiUrl) });
20
- const catalog = await listTemplates(client);
21
- const lines = catalog.length === 0
22
- ? ['No starter templates are available.']
23
- : [
24
- ...catalog.flatMap((template) => [
25
- `${template.templateId}: ${template.name}`,
26
- ` ${template.description}`,
27
- ...(template.starterPrices.length === 0 ? [] : [` Prices: ${template.starterPrices.map(describePrice).join(', ')}`]),
28
- ]),
29
- 'Deploy one with: oars deploy --template <id>',
30
- ];
31
- return { document: { ok: true, templates: catalog }, text: lines.join('\n') };
32
- };
@@ -1,11 +0,0 @@
1
- import type { Outcome, RunDeps } from '../cli.js';
2
- export interface TestChargeOptions {
3
- apiUrl: string;
4
- workloadId: string;
5
- /** `--price`; absent means the workload's one active price. */
6
- priceRef?: string;
7
- /** The base of the step key, so a retry of this command replays the charge instead of making a second one. */
8
- idempotencyKey: string;
9
- }
10
- /** `POST /billing/agents/{id}/test-charges`: a TEST-mode charge against one of the workload's prices (no money moves). */
11
- export declare const testCharge: (deps: RunDeps, options: TestChargeOptions) => Promise<Outcome>;
@@ -1,34 +0,0 @@
1
- import { apiClient, unwrap } from '../api.js';
2
- import { CliError, ExitCode } from '../errors.js';
3
- import { stepKey } from '../journal.js';
4
- import { resolveAuthToken } from '../session.js';
5
- const STEP = 'test-charge';
6
- /** The price a charge without `--price` uses: the workload's only active one, else exit 2 saying which to pick from. */
7
- const onlyActivePrice = async (client, workloadId) => {
8
- const page = unwrap(STEP, await client.GET('/billing/agents/{workloadId}/prices', { params: { path: { workloadId }, query: { size: 100 } } }));
9
- const active = page.content.filter((price) => price.active).map((price) => price.priceRef);
10
- if (!page.last) {
11
- throw new CliError(`${workloadId} has more prices than one request lists; pass --price <priceRef>.`, ExitCode.USAGE, 'usage');
12
- }
13
- const [only, ...others] = active;
14
- if (only === undefined) {
15
- throw new CliError(`${workloadId} has no active price; create one, or pass --price <priceRef>.`, ExitCode.USAGE, 'usage');
16
- }
17
- if (others.length > 0) {
18
- throw new CliError(`${workloadId} has several active prices (${active.join(', ')}); pass --price <priceRef>.`, ExitCode.USAGE, 'usage');
19
- }
20
- return only;
21
- };
22
- /** `POST /billing/agents/{id}/test-charges`: a TEST-mode charge against one of the workload's prices (no money moves). */
23
- export const testCharge = async (deps, options) => {
24
- const client = apiClient(deps, { apiUrl: options.apiUrl, step: STEP, token: await resolveAuthToken(deps, options.apiUrl) });
25
- const priceRef = options.priceRef ?? (await onlyActivePrice(client, options.workloadId));
26
- const charge = unwrap(STEP, await client.POST('/billing/agents/{workloadId}/test-charges', {
27
- params: { path: { workloadId: options.workloadId }, header: { 'Idempotency-Key': stepKey(options.idempotencyKey, STEP) } },
28
- body: { priceRef },
29
- }));
30
- return {
31
- document: { ok: true, chargeId: charge.chargeId, status: charge.status },
32
- text: `Test charge ${charge.chargeId} for ${priceRef}: ${charge.status}`,
33
- };
34
- };
package/dist/journal.d.ts DELETED
@@ -1,26 +0,0 @@
1
- /**
2
- * Where a command got to, for the rerun that follows a failure (design §3.2). It holds step names and the HTTP status each
3
- * answered with, never a secret: the SDK key is shown once and the platform replays every finished step by its idempotency key.
4
- */
5
- export interface JournalRecord {
6
- /** The human base key (`--idempotency-key` or the UUID the first run made). */
7
- base: string;
8
- steps: Array<{
9
- step: string;
10
- status: number;
11
- }>;
12
- }
13
- export interface JournalStore {
14
- /** Undefined when no run with this base key has left a record, including when the file is unreadable as one. */
15
- read: (base: string) => Promise<JournalRecord | undefined>;
16
- write: (record: JournalRecord) => Promise<void>;
17
- delete: (base: string) => Promise<void>;
18
- }
19
- /** One step's `Idempotency-Key`: the lowercase SHA-256 hex of `<base>:<step>`, the 64-hex form every aor-common interceptor accepts. */
20
- export declare const stepKey: (base: string, step: string) => string;
21
- /**
22
- * Keeps one file per base key in `<dir>/oars/journal/`, named by the key's hash because the key is whatever the developer typed.
23
- * A write goes to a sibling file and is renamed over the old one; a torn file reads as no record, and the platform's replay
24
- * makes the rerun correct either way.
25
- */
26
- export declare const fileJournalStore: (dir: string) => JournalStore;
package/dist/journal.js DELETED
@@ -1,58 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
3
- import { join } from 'node:path';
4
- /** One step's `Idempotency-Key`: the lowercase SHA-256 hex of `<base>:<step>`, the 64-hex form every aor-common interceptor accepts. */
5
- export const stepKey = (base, step) => createHash('sha256').update(`${base}:${step}`).digest('hex');
6
- const isRecord = (value) => {
7
- if (typeof value !== 'object' || value === null)
8
- return false;
9
- const base = Reflect.get(value, 'base');
10
- const steps = Reflect.get(value, 'steps');
11
- return (typeof base === 'string' &&
12
- Array.isArray(steps) &&
13
- steps.every((entry) => typeof entry === 'object' && entry !== null && typeof Reflect.get(entry, 'step') === 'string' && typeof Reflect.get(entry, 'status') === 'number'));
14
- };
15
- const isMissing = (error) => error instanceof Error && 'code' in error && error.code === 'ENOENT';
16
- /**
17
- * Keeps one file per base key in `<dir>/oars/journal/`, named by the key's hash because the key is whatever the developer typed.
18
- * A write goes to a sibling file and is renamed over the old one; a torn file reads as no record, and the platform's replay
19
- * makes the rerun correct either way.
20
- */
21
- export const fileJournalStore = (dir) => {
22
- const folder = join(dir, 'oars', 'journal');
23
- const fileFor = (base) => join(folder, `${createHash('sha256').update(base).digest('hex')}.json`);
24
- return {
25
- read: async (base) => {
26
- let text;
27
- try {
28
- text = await readFile(fileFor(base), 'utf8');
29
- }
30
- catch (error) {
31
- if (isMissing(error))
32
- return undefined;
33
- throw error;
34
- }
35
- try {
36
- const parsed = JSON.parse(text);
37
- return isRecord(parsed) && parsed.base === base ? parsed : undefined;
38
- }
39
- catch {
40
- return undefined;
41
- }
42
- },
43
- write: async (record) => {
44
- await mkdir(folder, { recursive: true, mode: 0o700 });
45
- const file = fileFor(record.base);
46
- const temp = `${file}.tmp`;
47
- try {
48
- await writeFile(temp, `${JSON.stringify(record, null, 2)}\n`, { mode: 0o600 });
49
- await rename(temp, file);
50
- }
51
- catch (error) {
52
- await rm(temp, { force: true });
53
- throw error;
54
- }
55
- },
56
- delete: (base) => rm(fileFor(base), { force: true }),
57
- };
58
- };
@@ -1,34 +0,0 @@
1
- [
2
- {
3
- "method": "POST",
4
- "path": "/agents/workloads",
5
- "body": {
6
- "name": "Paid API",
7
- "services": [
8
- {
9
- "name": "api",
10
- "image": "ghcr.io/manyoars/paid-api@sha256:c24de301f3b29f912c6235046b1f964a213b8437e496ba4b9f9de362e094b13f",
11
- "port": 8080,
12
- "public": true,
13
- "cpuMillicores": 250,
14
- "memoryMib": 256
15
- }
16
- ]
17
- }
18
- },
19
- {
20
- "method": "POST",
21
- "path": "/billing/agents/{workloadId}/prices",
22
- "body": { "priceRef": "calls-100", "displayName": "100 calls", "amountUsd": "5.00", "kind": "CREDIT_PACK", "credits": 100 }
23
- },
24
- {
25
- "method": "POST",
26
- "path": "/billing/agents/{workloadId}/prices",
27
- "body": { "priceRef": "calls-1000", "displayName": "1,000 calls", "amountUsd": "40.00", "kind": "CREDIT_PACK", "credits": 1000 }
28
- },
29
- {
30
- "method": "POST",
31
- "path": "/agents/workloads/{workloadId}/deploy",
32
- "body": null
33
- }
34
- ]
@@ -1,34 +0,0 @@
1
- [
2
- {
3
- "method": "POST",
4
- "path": "/agents/workloads",
5
- "body": {
6
- "name": "Per-task agent",
7
- "services": [
8
- {
9
- "name": "agent",
10
- "image": "ghcr.io/manyoars/per-task-agent@sha256:3dfe58ccacfcf8bf136e487e0dd6152092d26e6349f9671a2c46f78a097c07b3",
11
- "port": 8080,
12
- "public": true,
13
- "cpuMillicores": 500,
14
- "memoryMib": 512
15
- }
16
- ]
17
- }
18
- },
19
- {
20
- "method": "POST",
21
- "path": "/billing/agents/{workloadId}/prices",
22
- "body": { "priceRef": "task-1", "displayName": "1 task", "amountUsd": "9.00", "kind": "CREDIT_PACK", "credits": 1 }
23
- },
24
- {
25
- "method": "POST",
26
- "path": "/billing/agents/{workloadId}/prices",
27
- "body": { "priceRef": "tasks-5", "displayName": "5 tasks", "amountUsd": "40.00", "kind": "CREDIT_PACK", "credits": 5 }
28
- },
29
- {
30
- "method": "POST",
31
- "path": "/agents/workloads/{workloadId}/deploy",
32
- "body": null
33
- }
34
- ]