autopreso 0.1.5 → 0.1.6
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 +7 -2
- package/assets/autopreso.png +0 -0
- package/package.json +2 -1
- package/public/app.js +20 -5
- package/src/agent-provider.js +9 -2
- package/src/cli.js +1 -0
- package/src/settings-store.js +5 -2
package/README.md
CHANGED
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
|
|
12
12
|
<h3 align="center">Let the whiteboard whiteboard itself.</h3>
|
|
13
13
|
|
|
14
|
+
<p align="center">
|
|
15
|
+
<img src="https://raw.githubusercontent.com/kunchenguid/autopreso/main/assets/autopreso.png" alt="autopreso whiteboard hero screenshot" width="960" />
|
|
16
|
+
</p>
|
|
17
|
+
|
|
14
18
|
> [!WARNING]
|
|
15
19
|
> autopreso is in **alpha** and under active development. Expect rough edges, breaking changes, and the occasional weird drawing. Bug reports welcome.
|
|
16
20
|
|
|
@@ -112,8 +116,8 @@ When no settings file exists, autopreso picks providers based on what it finds i
|
|
|
112
116
|
| ------------------------------------------ | ------------------------------ | -------------------------- |
|
|
113
117
|
| Nothing | OpenAI `gpt-5.5` (needs a key) | Moonshine `medium` (macOS) |
|
|
114
118
|
| `OPENAI_API_KEY` in env | OpenAI `gpt-5.5` | OpenAI Realtime |
|
|
115
|
-
| Codex CLI signed in (`~/.codex/auth.json`) | Codex `gpt-5.5`
|
|
116
|
-
| Codex CLI signed in + `OPENAI_API_KEY` | Codex `gpt-5.5`
|
|
119
|
+
| Codex CLI signed in (`~/.codex/auth.json`) | Codex `gpt-5.5-fast` | Moonshine `medium` |
|
|
120
|
+
| Codex CLI signed in + `OPENAI_API_KEY` | Codex `gpt-5.5-fast` | OpenAI Realtime |
|
|
117
121
|
| `OLLAMA_MODEL` set | Ollama (your model) | Moonshine `medium` |
|
|
118
122
|
|
|
119
123
|
Auto-detection precedence: **Codex CLI auth wins over `OLLAMA_MODEL` wins over `OPENAI_API_KEY`** for the agent. Transcription flips to OpenAI Realtime any time an OpenAI key is present, otherwise Moonshine. After first run, this auto-detection no longer applies - change providers from the in-app status panel.
|
|
@@ -127,6 +131,7 @@ Provider variables only seed `settings.json` on first run. Once the file exists,
|
|
|
127
131
|
| `PORT` | Port to listen on. Default: `3210`. |
|
|
128
132
|
| `OPENAI_API_KEY` | Seeds the OpenAI key for both agent and Realtime STT. |
|
|
129
133
|
| `OPENAI_MODEL` | Seeds the OpenAI agent model. |
|
|
134
|
+
| `OPENAI_BASE_URL` | Seeds the OpenAI agent API base URL. |
|
|
130
135
|
| `CODEX_MODEL` | Seeds the Codex model. |
|
|
131
136
|
| `OLLAMA_MODEL` | Seeds the Ollama model. |
|
|
132
137
|
| `AUTOPRESO_CACHE_LOG` | Cache usage log path. Default: `~/.config/autopreso/logs/cache.log`. |
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autopreso",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Realtime speech to presentation. Let the whiteboard whiteboard itself.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Kun Chen <kun@kunchenguid.com>",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"autopreso": "src/cli.js"
|
|
33
33
|
},
|
|
34
34
|
"files": [
|
|
35
|
+
"assets/",
|
|
35
36
|
"LICENSE",
|
|
36
37
|
"public/",
|
|
37
38
|
"src/"
|
package/public/app.js
CHANGED
|
@@ -11,7 +11,7 @@ import { STARTER_ELEMENTS } from "./starter-elements.js";
|
|
|
11
11
|
const SAMPLE_RATE = 24000;
|
|
12
12
|
const REASONING_EFFORTS = ["none", "low", "medium", "high", "xhigh"];
|
|
13
13
|
const OPENAI_AGENT_MODELS = ["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"];
|
|
14
|
-
const CODEX_AGENT_MODELS = ["gpt-5.5", "gpt-5.5
|
|
14
|
+
const CODEX_AGENT_MODELS = ["gpt-5.5-fast", "gpt-5.5", "gpt-5.4"];
|
|
15
15
|
const OPENAI_TRANSCRIPTION_MODELS = [
|
|
16
16
|
"gpt-realtime-whisper",
|
|
17
17
|
"gpt-4o-transcribe",
|
|
@@ -1331,6 +1331,9 @@ function AgentEditor({ settings, onSave, onCancel }) {
|
|
|
1331
1331
|
const [reasoningEffort, setReasoningEffort] = React.useState(
|
|
1332
1332
|
settings.agent.openai.reasoningEffort,
|
|
1333
1333
|
);
|
|
1334
|
+
const [openaiBaseURL, setOpenaiBaseURL] = React.useState(
|
|
1335
|
+
settings.agent.openai.baseURL,
|
|
1336
|
+
);
|
|
1334
1337
|
const [codexModel, setCodexModel] = React.useState(
|
|
1335
1338
|
settings.agent.codex.model,
|
|
1336
1339
|
);
|
|
@@ -1354,6 +1357,7 @@ function AgentEditor({ settings, onSave, onCancel }) {
|
|
|
1354
1357
|
if (provider === "openai") {
|
|
1355
1358
|
patch.agent.openai.model = openaiModel;
|
|
1356
1359
|
patch.agent.openai.reasoningEffort = reasoningEffort;
|
|
1360
|
+
patch.agent.openai.baseURL = openaiBaseURL;
|
|
1357
1361
|
} else if (provider === "codex") {
|
|
1358
1362
|
patch.agent.codex.model = codexModel;
|
|
1359
1363
|
} else {
|
|
@@ -1429,7 +1433,7 @@ function AgentEditor({ settings, onSave, onCancel }) {
|
|
|
1429
1433
|
: null,
|
|
1430
1434
|
needsOpenAIKey
|
|
1431
1435
|
? field(
|
|
1432
|
-
"
|
|
1436
|
+
"API key",
|
|
1433
1437
|
React.createElement("input", {
|
|
1434
1438
|
type: "password",
|
|
1435
1439
|
value: openaiKey,
|
|
@@ -1441,7 +1445,7 @@ function AgentEditor({ settings, onSave, onCancel }) {
|
|
|
1441
1445
|
: null,
|
|
1442
1446
|
provider === "openai" && settings.hasOpenAIKey
|
|
1443
1447
|
? field(
|
|
1444
|
-
"
|
|
1448
|
+
"API key",
|
|
1445
1449
|
React.createElement("input", {
|
|
1446
1450
|
type: "password",
|
|
1447
1451
|
value: openaiKey,
|
|
@@ -1451,6 +1455,17 @@ function AgentEditor({ settings, onSave, onCancel }) {
|
|
|
1451
1455
|
}),
|
|
1452
1456
|
)
|
|
1453
1457
|
: null,
|
|
1458
|
+
provider === "openai"
|
|
1459
|
+
? field(
|
|
1460
|
+
"Base URL",
|
|
1461
|
+
React.createElement("input", {
|
|
1462
|
+
type: "text",
|
|
1463
|
+
value: openaiBaseURL,
|
|
1464
|
+
onChange: (e) => setOpenaiBaseURL(e.target.value),
|
|
1465
|
+
disabled: busy,
|
|
1466
|
+
}),
|
|
1467
|
+
)
|
|
1468
|
+
: null,
|
|
1454
1469
|
errorText
|
|
1455
1470
|
? React.createElement("div", { className: "editor-error" }, errorText)
|
|
1456
1471
|
: null,
|
|
@@ -1543,7 +1558,7 @@ function TranscriptionEditor({ settings, onSave, onCancel }) {
|
|
|
1543
1558
|
: null,
|
|
1544
1559
|
needsOpenAIKey
|
|
1545
1560
|
? field(
|
|
1546
|
-
"
|
|
1561
|
+
"API key",
|
|
1547
1562
|
React.createElement("input", {
|
|
1548
1563
|
type: "password",
|
|
1549
1564
|
value: openaiKey,
|
|
@@ -1555,7 +1570,7 @@ function TranscriptionEditor({ settings, onSave, onCancel }) {
|
|
|
1555
1570
|
: null,
|
|
1556
1571
|
provider === "openai" && settings.hasOpenAIKey
|
|
1557
1572
|
? field(
|
|
1558
|
-
"
|
|
1573
|
+
"API key",
|
|
1559
1574
|
React.createElement("input", {
|
|
1560
1575
|
type: "password",
|
|
1561
1576
|
value: openaiKey,
|
package/src/agent-provider.js
CHANGED
|
@@ -3,7 +3,9 @@ import { createOpenAI } from "@ai-sdk/openai";
|
|
|
3
3
|
import { DEFAULT_CODEX_BASE_URL, createCodexFetch, readCodexCliAuthSync } from "./codex-auth.js";
|
|
4
4
|
|
|
5
5
|
const DEFAULT_OPENAI_AGENT_MODEL = "gpt-5.5";
|
|
6
|
+
const DEFAULT_CODEX_AGENT_MODEL = "gpt-5.5-fast";
|
|
6
7
|
const DEFAULT_OPENAI_REASONING_EFFORT = "low";
|
|
8
|
+
const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
|
|
7
9
|
const DEFAULT_OLLAMA_BASE_URL = "http://localhost:11434/v1";
|
|
8
10
|
const OPENAI_REASONING_EFFORTS = new Set(["none", "low", "medium", "high", "xhigh"]);
|
|
9
11
|
|
|
@@ -12,6 +14,7 @@ export function defaultWhiteboardAgentProvider(options = {}) {
|
|
|
12
14
|
provider: "openai",
|
|
13
15
|
model: DEFAULT_OPENAI_AGENT_MODEL,
|
|
14
16
|
apiKey: options.openaiApiKey,
|
|
17
|
+
baseURL: DEFAULT_OPENAI_BASE_URL,
|
|
15
18
|
reasoningEffort: DEFAULT_OPENAI_REASONING_EFFORT,
|
|
16
19
|
};
|
|
17
20
|
}
|
|
@@ -33,7 +36,7 @@ export function resolveAgentProviderFromSettings({ settings, env = process.env }
|
|
|
33
36
|
if (provider === "codex") {
|
|
34
37
|
const codexAuth = readCodexCliAuthSync(env);
|
|
35
38
|
if (!codexAuth) throw new Error("Codex CLI auth not found. Run `codex` and sign in with ChatGPT.");
|
|
36
|
-
const codexModel = resolveCodexModel(settings.agent.codex.model ||
|
|
39
|
+
const codexModel = resolveCodexModel(settings.agent.codex.model || DEFAULT_CODEX_AGENT_MODEL);
|
|
37
40
|
return {
|
|
38
41
|
provider: "codex",
|
|
39
42
|
...codexModel,
|
|
@@ -50,6 +53,7 @@ export function resolveAgentProviderFromSettings({ settings, env = process.env }
|
|
|
50
53
|
model: settings.agent.openai.model || DEFAULT_OPENAI_AGENT_MODEL,
|
|
51
54
|
apiKey,
|
|
52
55
|
reasoningEffort: validateReasoningEffort(settings.agent.openai.reasoningEffort),
|
|
56
|
+
baseURL: withoutTrailingSlash(cleanEnvValue(settings.agent.openai.baseURL) ?? DEFAULT_OPENAI_BASE_URL),
|
|
53
57
|
};
|
|
54
58
|
}
|
|
55
59
|
|
|
@@ -81,7 +85,10 @@ export function createWhiteboardAgentModel(agentProvider) {
|
|
|
81
85
|
return codex.responses(agentProvider.model);
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
const openai = createOpenAI({
|
|
88
|
+
const openai = createOpenAI({
|
|
89
|
+
apiKey: agentProvider.apiKey,
|
|
90
|
+
baseURL: agentProvider.baseURL,
|
|
91
|
+
});
|
|
85
92
|
return openai(agentProvider.model);
|
|
86
93
|
}
|
|
87
94
|
|
package/src/cli.js
CHANGED
|
@@ -76,6 +76,7 @@ Environment:
|
|
|
76
76
|
PORT Port to listen on. Default: 3210
|
|
77
77
|
OPENAI_API_KEY Seeds the OpenAI key on first run if no settings file exists
|
|
78
78
|
OPENAI_MODEL Seeds the OpenAI agent model on first run
|
|
79
|
+
OPENAI_BASE_URL Seeds the OpenAI agent API base URL on first run
|
|
79
80
|
OPENAI_REASONING_EFFORT Seeds reasoning effort on first run (none, low, medium, high, xhigh)
|
|
80
81
|
CODEX_HOME Codex CLI home directory. Default: ~/.codex
|
|
81
82
|
CODEX_MODEL Seeds the Codex model on first run
|
package/src/settings-store.js
CHANGED
|
@@ -8,8 +8,8 @@ export const MAX_AGENT_INSTRUCTIONS_CHARS = 100_000;
|
|
|
8
8
|
export const DEFAULT_SETTINGS = Object.freeze({
|
|
9
9
|
agent: {
|
|
10
10
|
provider: "openai",
|
|
11
|
-
openai: { model: "gpt-5.5", reasoningEffort: "low" },
|
|
12
|
-
codex: { model: "gpt-5.5", baseURL: "https://chatgpt.com/backend-api/codex" },
|
|
11
|
+
openai: { model: "gpt-5.5", reasoningEffort: "low", baseURL: "https://api.openai.com/v1" },
|
|
12
|
+
codex: { model: "gpt-5.5-fast", baseURL: "https://chatgpt.com/backend-api/codex" },
|
|
13
13
|
ollama: { model: "", baseURL: "http://localhost:11434/v1" },
|
|
14
14
|
},
|
|
15
15
|
transcription: {
|
|
@@ -102,6 +102,9 @@ function seedFromEnv(settings, env, readCodexAuth) {
|
|
|
102
102
|
const openaiModel = trimOrEmpty(env.OPENAI_MODEL);
|
|
103
103
|
if (openaiModel) next.agent.openai.model = openaiModel;
|
|
104
104
|
|
|
105
|
+
const openaiBaseURL = trimOrEmpty(env.OPENAI_BASE_URL);
|
|
106
|
+
if (openaiBaseURL) next.agent.openai.baseURL = openaiBaseURL;
|
|
107
|
+
|
|
105
108
|
const reasoningEffort = trimOrEmpty(env.OPENAI_REASONING_EFFORT);
|
|
106
109
|
if (reasoningEffort) next.agent.openai.reasoningEffort = reasoningEffort;
|
|
107
110
|
|