@lazyingart/agintiflow 0.16.1 → 0.16.2

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/README.md CHANGED
@@ -46,7 +46,7 @@ aginti --list-profiles
46
46
  aginti --sandbox-status
47
47
  ```
48
48
 
49
- On first interactive use, if no main model key is detected, `aginti` opens an auth wizard. Use Up/Down to choose DeepSeek, OpenAI, or Qwen, paste the key, and press Enter to save it to the project-local ignored file `.aginti/.env` with `0600` permissions. The wizard then offers the optional auxiliary image key; press Esc to skip. You can rerun it even when keys already exist:
49
+ On first interactive use, if no main model key is detected, `aginti` opens an auth wizard. Use Up/Down to choose DeepSeek, OpenAI, or Qwen, paste the key, and press Enter to save it to the project-local ignored file `.aginti/.env` with `0600` permissions. The wizard points to DeepSeek keys at `https://platform.deepseek.com/api_keys` and OpenAI keys at `https://platform.openai.com/api-keys`. It then offers the optional auxiliary image key; press Esc to skip. You can rerun it even when keys already exist:
50
50
 
51
51
  ```bash
52
52
  aginti auth
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyingart/agintiflow",
3
- "version": "0.16.1",
3
+ "version": "0.16.2",
4
4
  "type": "module",
5
5
  "description": "AgInTiFlow is a resumable Playwright website-control agent with OpenAI-compatible tool calling.",
6
6
  "license": "Apache-2.0",
package/public/app.js CHANGED
@@ -25,6 +25,9 @@ const translations = {
25
25
  "DeepSeek/OpenAI/Qwen keys are missing. Use mock mode, export an env var, or save a project-local model key.",
26
26
  setupEnvHelp:
27
27
  "Env vars: DEEPSEEK_API_KEY, OPENAI_API_KEY, QWEN_API_KEY, LLM_API_KEY, and optional GRSAI for image generation. Mock mode remains available for local tests.",
28
+ setupKeyLinksLabel: "Get keys:",
29
+ deepseekKeyLink: "DeepSeek API keys",
30
+ openaiKeyLink: "OpenAI API keys",
28
31
  setupProviderLabel: "Provider",
29
32
  setupKeyLabel: "API key",
30
33
  saveKeyButton: "Save local key",
package/public/index.html CHANGED
@@ -50,6 +50,12 @@
50
50
  <p class="subtle" data-i18n="setupEnvHelp">
51
51
  Env vars: DEEPSEEK_API_KEY, OPENAI_API_KEY, QWEN_API_KEY, or LLM_API_KEY. Mock mode remains available for local tests.
52
52
  </p>
53
+ <p class="subtle key-links">
54
+ <span data-i18n="setupKeyLinksLabel">Get keys:</span>
55
+ <a href="https://platform.deepseek.com/api_keys" target="_blank" rel="noreferrer" data-i18n="deepseekKeyLink">DeepSeek API keys</a>
56
+ <span aria-hidden="true">·</span>
57
+ <a href="https://platform.openai.com/api-keys" target="_blank" rel="noreferrer" data-i18n="openaiKeyLink">OpenAI API keys</a>
58
+ </p>
53
59
  </div>
54
60
  <div class="grid">
55
61
  <label>
package/public/styles.css CHANGED
@@ -137,6 +137,23 @@ h1 {
137
137
  overflow-wrap: anywhere;
138
138
  }
139
139
 
140
+ .setup-card .key-links {
141
+ display: flex;
142
+ flex-wrap: wrap;
143
+ gap: 6px;
144
+ align-items: center;
145
+ }
146
+
147
+ .setup-card .key-links a {
148
+ color: #075985;
149
+ font-weight: 750;
150
+ text-decoration: none;
151
+ }
152
+
153
+ .setup-card .key-links a:hover {
154
+ text-decoration: underline;
155
+ }
156
+
140
157
  .setup-card[hidden] {
141
158
  display: none;
142
159
  }
@@ -4,7 +4,7 @@ import fs from "node:fs/promises";
4
4
  import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
- import { normalizeAuthProvider } from "../src/auth-onboarding.js";
7
+ import { authProviderKeyHelp, authProviderKeyUrl, normalizeAuthProvider } from "../src/auth-onboarding.js";
8
8
  import { getProviderDefaults } from "../src/model-routing.js";
9
9
  import { providerKeyStatus, setProviderKey } from "../src/project.js";
10
10
 
@@ -53,6 +53,8 @@ async function runCli(args, stdin = "") {
53
53
  try {
54
54
  assert(normalizeAuthProvider("auxilliary") === "grsai", "auxilliary alias did not normalize to grsai");
55
55
  assert(normalizeAuthProvider("qwen") === "qwen", "qwen provider did not normalize");
56
+ assert(authProviderKeyUrl("deepseek") === "https://platform.deepseek.com/api_keys", "DeepSeek key URL is missing");
57
+ assert(authProviderKeyHelp("openai").includes("https://platform.openai.com/api-keys"), "OpenAI key help is missing");
56
58
  const qwenDefaults = getProviderDefaults("qwen");
57
59
  assert(qwenDefaults.provider === "qwen" && qwenDefaults.model, "qwen provider defaults are not available");
58
60
 
@@ -75,7 +77,7 @@ try {
75
77
  {
76
78
  ok: true,
77
79
  projectRoot: tempRoot,
78
- checks: ["normalize-auth-provider", "qwen-defaults", "qwen-key-status", "cli-key-status-redacted"],
80
+ checks: ["normalize-auth-provider", "provider-key-links", "qwen-defaults", "qwen-key-status", "cli-key-status-redacted"],
79
81
  },
80
82
  null,
81
83
  2
@@ -10,12 +10,14 @@ export const MAIN_AUTH_PROVIDERS = [
10
10
  label: "DeepSeek",
11
11
  keyName: "DEEPSEEK_API_KEY",
12
12
  description: "default fast/pro route",
13
+ keyUrl: "https://platform.deepseek.com/api_keys",
13
14
  },
14
15
  {
15
16
  id: "openai",
16
17
  label: "OpenAI",
17
18
  keyName: "OPENAI_API_KEY",
18
19
  description: "OpenAI-compatible fallback",
20
+ keyUrl: "https://platform.openai.com/api-keys",
19
21
  },
20
22
  {
21
23
  id: "qwen",
@@ -55,6 +57,19 @@ function providerLabel(provider = "") {
55
57
  return match?.label || provider;
56
58
  }
57
59
 
60
+ export function authProviderKeyUrl(provider = "") {
61
+ const normalized = normalizeAuthProvider(provider, "");
62
+ const match = [...MAIN_AUTH_PROVIDERS, AUXILIARY_AUTH_PROVIDER].find((item) => item.id === normalized);
63
+ return match?.keyUrl || "";
64
+ }
65
+
66
+ export function authProviderKeyHelp(provider = "") {
67
+ const normalized = normalizeAuthProvider(provider, "");
68
+ const label = providerLabel(normalized);
69
+ const url = authProviderKeyUrl(normalized);
70
+ return url ? `Get ${label} API key: ${url}` : "";
71
+ }
72
+
58
73
  class MutedWritable extends Writable {
59
74
  constructor(target) {
60
75
  super();
@@ -144,17 +159,21 @@ export async function promptHidden(promptText) {
144
159
  }
145
160
 
146
161
  function renderProviderPicker({ providers, selected, title, status }) {
162
+ const keyLinks = providers
163
+ .filter((provider) => provider.keyUrl)
164
+ .map((provider) => `${provider.label}: ${provider.keyUrl}`);
147
165
  const lines = [
148
166
  `\n${title}`,
149
167
  "Use Up/Down to choose, Enter to confirm, Esc to go back/skip.",
150
168
  `Current key status: ${status}`,
169
+ keyLinks.length ? `API key pages: ${keyLinks.join(" · ")}` : "",
151
170
  "",
152
171
  ...providers.map((provider, index) => {
153
172
  const cursor = index === selected ? ">" : " ";
154
173
  return `${cursor} ${provider.label.padEnd(10)} ${provider.keyName.padEnd(16)} ${provider.description}`;
155
174
  }),
156
175
  ];
157
- return lines.join("\n");
176
+ return lines.filter((line, index) => line || index > 2).join("\n");
158
177
  }
159
178
 
160
179
  export async function chooseAuthProvider({
@@ -295,7 +314,8 @@ export async function runAuthWizard(projectRoot = process.cwd(), options = {}) {
295
314
 
296
315
  if (mainProvider) {
297
316
  const current = status[mainProvider] ? "currently available; paste a new key to replace, or Esc to keep existing" : "missing";
298
- const prompt = `${providerLabel(mainProvider)} main API key (${current}) [hidden]: `;
317
+ const keyHelp = authProviderKeyHelp(mainProvider);
318
+ const prompt = `${keyHelp ? `${keyHelp}\n` : ""}${providerLabel(mainProvider)} main API key (${current}) [hidden]: `;
299
319
  const secret = await promptSecret(prompt, { allowEscape: true });
300
320
  if (secret.value) {
301
321
  const result = await setProviderKey(projectRoot, mainProvider, secret.value);