@workser/cli 0.6.18 → 0.6.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3663,6 +3663,88 @@ var import_picocolors2 = __toESM(require_picocolors(), 1);
3663
3663
 
3664
3664
  // src/help-content.ts
3665
3665
  var HELP_TOPICS = [
3666
+ {
3667
+ topic: "agent-cloud-media",
3668
+ title: "Pictures, voice, video \u2014 and calling a model without an agent",
3669
+ summary: "What an Agent Cloud agent can make and read, plus one-shot model calls from the app's own code.",
3670
+ commands: ["agent-cloud"],
3671
+ source: "skills/workser/reference/agent-cloud-media.md",
3672
+ body: `# Pictures, voice, video \u2014 and calling a model without an agent
3673
+
3674
+ ### Models that are not chat models
3675
+
3676
+ \`models\` used to list chat models and nothing else \u2014 not by choice, but
3677
+ because the catalogue threw every other kind away before anyone could ask for
3678
+ one. It no longer does:
3679
+
3680
+ \`\`\`
3681
+ workser agent-cloud models --kind image # models that draw
3682
+ workser agent-cloud models --kind video
3683
+ workser agent-cloud models --kind speech # text in, a voice out
3684
+ workser agent-cloud models --kind transcription # a voice in, text out
3685
+ workser agent-cloud models --kind embedding # for search by meaning
3686
+ workser agent-cloud models --accepts image # chat models that see photos
3687
+ \`\`\`
3688
+
3689
+ Prices are shown in the unit the model is SOLD in \u2014 \`4.6 credits each\` for a
3690
+ picture, \`credits/1M\` for words. A picture quoted per million would be out by
3691
+ six orders of magnitude.
3692
+
3693
+ \`default_model\` must stay a **chat model**. It is what the agent thinks with;
3694
+ setting it to an image model publishes an agent that never answers anybody.
3695
+ The other kinds are reached through abilities, below.
3696
+
3697
+ ## What the agent can make, and what it can read
3698
+
3699
+ These are abilities on the agent, not models you set:
3700
+
3701
+ | Ability | The agent gains |
3702
+ | --- | --- |
3703
+ | \`media_generation.image\` | \`generate_image\` \u2014 answer with a picture, art for a post |
3704
+ | \`media_generation.audio.speech\` | \`generate_speech\` \u2014 reply in voice |
3705
+ | \`media_generation.audio.sound_effects\` | \`generate_sound_effect\` |
3706
+ | \`media_generation.audio.music\` | \`generate_music\` \u2014 a background track |
3707
+ | \`media_generation.video\` | \`generate_video\` \u2014 short clips |
3708
+ | \`perception.image\` | \`describe_image\` \u2014 read a photo a customer sent |
3709
+ | \`perception.video\` | \`describe_video\` |
3710
+ | \`perception.audio\` | \`transcribe_audio\` \u2014 a voice note becomes text |
3711
+
3712
+ Turn on only what the job needs. **Video costs an order of magnitude more than
3713
+ everything else here**, and it is refused outright on a deployment where an
3714
+ operator has not priced it \u2014 that refusal is a configuration fact, not the
3715
+ user's mistake, so relay it rather than retrying.
3716
+
3717
+ Everything these produce comes back as a **URL in the project's storage**, so
3718
+ it can go straight into a reply, a post, or the next tool.
3719
+
3720
+ ## When the app itself needs a model, not an agent
3721
+
3722
+ An agent is a sandbox, a tool loop, and minutes of metered runtime. Most of
3723
+ what an app needs a model for is one call that takes a second: a product
3724
+ description, a thumbnail, a spoken confirmation, search that understands
3725
+ meaning. Starting an agent for those is the wrong shape and the wrong price.
3726
+
3727
+ Use \`@workser/app\` in the app's own code:
3728
+
3729
+ \`\`\`ts
3730
+ import { workser } from '@workser/app';
3731
+
3732
+ const blurb = await workser.ai.text('Write a 40-word description of ' + name);
3733
+ const art = await workser.ai.image('product photo of ' + name);
3734
+ const audio = await workser.ai.speech('Your order is confirmed.');
3735
+ const vector = await workser.ai.embed(descriptions); // many in one call
3736
+ for await (const word of workser.ai.stream(question)) process.stdout.write(word);
3737
+ \`\`\`
3738
+
3739
+ Nobody holds a provider key: Workser's own credential is used and the
3740
+ organisation's credit ledger is charged, the same wallet an agent run draws on.
3741
+ It needs no setup in a Workser-deployed app \u2014 the two environment variables are
3742
+ injected at provisioning.
3743
+
3744
+ **The rule:** one answer goes to \`workser.ai\`; work that takes minutes and uses
3745
+ tools goes to an agent.
3746
+ `
3747
+ },
3666
3748
  {
3667
3749
  topic: "agent-cloud",
3668
3750
  title: "Ship an agent inside the app",
@@ -3743,6 +3825,11 @@ workser agent-cloud machines # video, data analysis, design, ...
3743
3825
  A model marked "needs your own key" will make \`publish\` FAIL unless a matching
3744
3826
  secret is stored first. Add the key with \`add <id> secret\` before setting it.
3745
3827
 
3828
+ \`default_model\` must stay a **chat model** \u2014 setting it to an image model
3829
+ publishes an agent that never answers anybody. Pictures, video, voice and
3830
+ transcription are abilities, not models you set, and one call from the app's
3831
+ own code needs no agent at all: \`workser help agent-cloud-media\`.
3832
+
3746
3833
  ## Agents need a paid plan \u2014 the trial does not include them
3747
3834
 
3748
3835
  \`create\` and \`run\` both refuse with **402** on a free or trialling
@@ -3750,9 +3837,9 @@ organisation. That is a rule, not a fault: every run buys model tokens and
3750
3837
  holds a machine, so it costs real money the moment it happens.
3751
3838
 
3752
3839
  **When you hit it, hand the plan over \u2014 do not just describe it.** Workser
3753
- files the refusal on the conversation as a step and an artifact the user can
3754
- click, so the person you are helping gets something actionable rather than a
3755
- paragraph. Say plainly what you were doing, that agents need a plan, and stop.
3840
+ files the refusal on the conversation as a clickable step and artifact, so the
3841
+ person gets something actionable. Say what you were doing, that agents need a
3842
+ plan, and stop.
3756
3843
 
3757
3844
  Do NOT:
3758
3845
 
@@ -7898,21 +7985,37 @@ function registerAgentCloud(program3) {
7898
7985
  });
7899
7986
  })
7900
7987
  );
7901
- cloud.command("models").description("Models this organisation can run an agent on, cheapest first").option("--all", "Include models that need your own provider key").action(
7988
+ cloud.command("models").description("Models this organisation can run an agent on, cheapest first").option("--all", "Include models that need your own provider key").option(
7989
+ "--kind <kind>",
7990
+ "text | image | video | speech | transcription | embedding (comma-separated)"
7991
+ ).option("--accepts <inputs>", "Only models that can read this: image, audio, video, file").action(
7902
7992
  action(async ({ ctx, opts }) => {
7903
- const res = await api(ctx, "/v1/agent-cloud/catalog/models/live");
7993
+ const q = new URLSearchParams();
7994
+ if (opts.kind) q.set("kind", String(opts.kind));
7995
+ if (opts.accepts) q.set("accepts", String(opts.accepts));
7996
+ if (opts.kind && !String(opts.kind).split(",").includes("text")) {
7997
+ q.set("tools_only", "false");
7998
+ }
7999
+ const suffix = q.toString() ? `?${q.toString()}` : "";
8000
+ const res = await api(
8001
+ ctx,
8002
+ `/v1/agent-cloud/catalog/models/gateways${suffix}`
8003
+ );
7904
8004
  const models = (res?.models ?? []).filter(
7905
8005
  (m) => opts.all || m.credit_tier === "PLATFORM_CREDITS"
7906
8006
  );
7907
8007
  ok(res, () => {
7908
8008
  if (!models.length) {
7909
- warn("The live model list could not be read.");
8009
+ warn(
8010
+ opts.kind ? `No ${opts.kind} models are available on your credits. Try --all.` : "The live model list could not be read."
8011
+ );
7910
8012
  return;
7911
8013
  }
7912
8014
  for (const m of models.slice(0, 40)) {
7913
- const price = typeof m.input_price_per_million_usd === "number" ? `$${m.input_price_per_million_usd.toFixed(2)}/M in` : "price unknown";
8015
+ const price = m.price_unit === "each" ? typeof m.credits_each === "number" ? `${m.credits_each} credits each` : "price unknown" : typeof m.input_price_per_million_usd === "number" ? `$${m.input_price_per_million_usd.toFixed(2)}/M in` : "price unknown";
7914
8016
  const byok = m.credit_tier === "PLATFORM_CREDITS" ? "" : import_picocolors17.default.yellow(" needs your own key");
7915
- line(`${import_picocolors17.default.bold(m.id)} ${import_picocolors17.default.dim(price)}${byok}`);
8017
+ const kind = m.kind && m.kind !== "text" ? import_picocolors17.default.dim(` [${m.kind}]`) : "";
8018
+ line(`${import_picocolors17.default.bold(m.model ?? m.id)}${kind} ${import_picocolors17.default.dim(price)}${byok}`);
7916
8019
  }
7917
8020
  });
7918
8021
  })
@@ -11846,7 +11949,7 @@ function colour(d) {
11846
11949
 
11847
11950
  // src/index.ts
11848
11951
  var pkg = {
11849
- version: true ? "0.6.18" : "0.0.0-dev"
11952
+ version: true ? "0.6.19" : "0.0.0-dev"
11850
11953
  };
11851
11954
  var program2 = new Command();
11852
11955
  program2.name("workser").description(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workser/cli",
3
- "version": "0.6.18",
3
+ "version": "0.6.19",
4
4
  "description": "Workser CLI — give your local AI agent native DevOps & infrastructure on Workser. The agent runs `workser …` to provision, deploy, and manage real apps.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -0,0 +1,81 @@
1
+ ---
2
+ topic: agent-cloud-media
3
+ title: Pictures, voice, video — and calling a model without an agent
4
+ summary: What an Agent Cloud agent can make and read, plus one-shot model calls from the app's own code.
5
+ commands: [agent-cloud]
6
+ ---
7
+
8
+ # Pictures, voice, video — and calling a model without an agent
9
+
10
+ ### Models that are not chat models
11
+
12
+ `models` used to list chat models and nothing else — not by choice, but
13
+ because the catalogue threw every other kind away before anyone could ask for
14
+ one. It no longer does:
15
+
16
+ ```
17
+ workser agent-cloud models --kind image # models that draw
18
+ workser agent-cloud models --kind video
19
+ workser agent-cloud models --kind speech # text in, a voice out
20
+ workser agent-cloud models --kind transcription # a voice in, text out
21
+ workser agent-cloud models --kind embedding # for search by meaning
22
+ workser agent-cloud models --accepts image # chat models that see photos
23
+ ```
24
+
25
+ Prices are shown in the unit the model is SOLD in — `4.6 credits each` for a
26
+ picture, `credits/1M` for words. A picture quoted per million would be out by
27
+ six orders of magnitude.
28
+
29
+ `default_model` must stay a **chat model**. It is what the agent thinks with;
30
+ setting it to an image model publishes an agent that never answers anybody.
31
+ The other kinds are reached through abilities, below.
32
+
33
+ ## What the agent can make, and what it can read
34
+
35
+ These are abilities on the agent, not models you set:
36
+
37
+ | Ability | The agent gains |
38
+ | --- | --- |
39
+ | `media_generation.image` | `generate_image` — answer with a picture, art for a post |
40
+ | `media_generation.audio.speech` | `generate_speech` — reply in voice |
41
+ | `media_generation.audio.sound_effects` | `generate_sound_effect` |
42
+ | `media_generation.audio.music` | `generate_music` — a background track |
43
+ | `media_generation.video` | `generate_video` — short clips |
44
+ | `perception.image` | `describe_image` — read a photo a customer sent |
45
+ | `perception.video` | `describe_video` |
46
+ | `perception.audio` | `transcribe_audio` — a voice note becomes text |
47
+
48
+ Turn on only what the job needs. **Video costs an order of magnitude more than
49
+ everything else here**, and it is refused outright on a deployment where an
50
+ operator has not priced it — that refusal is a configuration fact, not the
51
+ user's mistake, so relay it rather than retrying.
52
+
53
+ Everything these produce comes back as a **URL in the project's storage**, so
54
+ it can go straight into a reply, a post, or the next tool.
55
+
56
+ ## When the app itself needs a model, not an agent
57
+
58
+ An agent is a sandbox, a tool loop, and minutes of metered runtime. Most of
59
+ what an app needs a model for is one call that takes a second: a product
60
+ description, a thumbnail, a spoken confirmation, search that understands
61
+ meaning. Starting an agent for those is the wrong shape and the wrong price.
62
+
63
+ Use `@workser/app` in the app's own code:
64
+
65
+ ```ts
66
+ import { workser } from '@workser/app';
67
+
68
+ const blurb = await workser.ai.text('Write a 40-word description of ' + name);
69
+ const art = await workser.ai.image('product photo of ' + name);
70
+ const audio = await workser.ai.speech('Your order is confirmed.');
71
+ const vector = await workser.ai.embed(descriptions); // many in one call
72
+ for await (const word of workser.ai.stream(question)) process.stdout.write(word);
73
+ ```
74
+
75
+ Nobody holds a provider key: Workser's own credential is used and the
76
+ organisation's credit ledger is charged, the same wallet an agent run draws on.
77
+ It needs no setup in a Workser-deployed app — the two environment variables are
78
+ injected at provisioning.
79
+
80
+ **The rule:** one answer goes to `workser.ai`; work that takes minutes and uses
81
+ tools goes to an agent.
@@ -79,6 +79,11 @@ workser agent-cloud machines # video, data analysis, design, ...
79
79
  A model marked "needs your own key" will make `publish` FAIL unless a matching
80
80
  secret is stored first. Add the key with `add <id> secret` before setting it.
81
81
 
82
+ `default_model` must stay a **chat model** — setting it to an image model
83
+ publishes an agent that never answers anybody. Pictures, video, voice and
84
+ transcription are abilities, not models you set, and one call from the app's
85
+ own code needs no agent at all: `workser help agent-cloud-media`.
86
+
82
87
  ## Agents need a paid plan — the trial does not include them
83
88
 
84
89
  `create` and `run` both refuse with **402** on a free or trialling
@@ -86,9 +91,9 @@ organisation. That is a rule, not a fault: every run buys model tokens and
86
91
  holds a machine, so it costs real money the moment it happens.
87
92
 
88
93
  **When you hit it, hand the plan over — do not just describe it.** Workser
89
- files the refusal on the conversation as a step and an artifact the user can
90
- click, so the person you are helping gets something actionable rather than a
91
- paragraph. Say plainly what you were doing, that agents need a plan, and stop.
94
+ files the refusal on the conversation as a clickable step and artifact, so the
95
+ person gets something actionable. Say what you were doing, that agents need a
96
+ plan, and stop.
92
97
 
93
98
  Do NOT:
94
99