@aion0/forge 0.10.3 → 0.10.5

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/RELEASE_NOTES.md CHANGED
@@ -1,11 +1,11 @@
1
- # Forge v0.10.3
1
+ # Forge v0.10.5
2
2
 
3
3
  Released: 2026-05-30
4
4
 
5
- ## Changes since v0.10.2
5
+ ## Changes since v0.10.4
6
6
 
7
7
  ### Other
8
- - fix(settings): unmask apiProfiles.*.apiKey on POST (regression in v0.10.0)
8
+ - fix(chat/anthropic): normalize baseURL to include /v1 (fix Not Found regression)
9
9
 
10
10
 
11
- **Full Changelog**: https://github.com/aiwatching/forge/compare/v0.10.2...v0.10.3
11
+ **Full Changelog**: https://github.com/aiwatching/forge/compare/v0.10.4...v0.10.5
@@ -24,9 +24,8 @@
24
24
  * no-op (returns false, no save).
25
25
  */
26
26
 
27
- import { writeFileSync } from 'node:fs';
27
+ import { copyFileSync, existsSync } from 'node:fs';
28
28
  import { join } from 'node:path';
29
- import YAML from 'yaml';
30
29
  import { getDataDir } from '../dirs';
31
30
  import type { Settings } from '../settings';
32
31
 
@@ -130,23 +129,17 @@ function detectsLegacyShape(settings: Settings): boolean {
130
129
  return false;
131
130
  }
132
131
 
133
- function writeBackup(settings: Settings): void {
132
+ function writeBackup(_settings: Settings): void {
133
+ // Raw byte copy of settings.yaml — never re-serialize the decrypted
134
+ // in-memory form. v0.10.x shipped a YAML.stringify(settings) backup
135
+ // that leaked plaintext API tokens + ANTHROPIC_AUTH_TOKEN into the
136
+ // data dir. Fixed in v0.10.4+.
134
137
  try {
138
+ const src = join(getDataDir(), 'settings.yaml');
139
+ if (!existsSync(src)) return;
135
140
  const ts = Date.now();
136
141
  const backupPath = join(getDataDir(), `settings.backup.agents-${ts}.yaml`);
137
- const slice = {
138
- _backup_note: 'Pre-migration snapshot of agent-related settings. Safe to delete after verifying migration worked.',
139
- _backup_ts: new Date(ts).toISOString(),
140
- agents: settings.agents,
141
- defaultAgent: settings.defaultAgent,
142
- chatAgent: settings.chatAgent,
143
- telegramAgent: settings.telegramAgent,
144
- docsAgent: settings.docsAgent,
145
- telegramModel: settings.telegramModel,
146
- taskModel: settings.taskModel,
147
- pipelineModel: settings.pipelineModel,
148
- };
149
- writeFileSync(backupPath, YAML.stringify(slice), 'utf-8');
142
+ copyFileSync(src, backupPath);
150
143
  console.log(`[migrate-agents] backup → ${backupPath}`);
151
144
  } catch (err) {
152
145
  console.warn('[migrate-agents] backup write failed (continuing anyway):', err instanceof Error ? err.message : err);
@@ -50,9 +50,16 @@ function decodeToolName(name: string): string { return name.replace(/__/g, '.');
50
50
 
51
51
  function makeClient(apiKey: string, baseUrl: string) {
52
52
  const oauth = isOauthToken(apiKey);
53
+ // @ai-sdk/anthropic appends `/messages` directly onto the baseURL (unlike
54
+ // @anthropic-ai/sdk which inserts `/v1/`). If the URL doesn't end in /v1,
55
+ // the request goes to `${host}/messages` and 404s. Forge's defaultBaseUrl
56
+ // returns the host without /v1 to match the other SDK — normalize here.
57
+ const normalized = baseUrl
58
+ ? baseUrl.replace(/\/+$/, '') + (/\/v\d+$/.test(baseUrl.replace(/\/+$/, '')) ? '' : '/v1')
59
+ : undefined;
53
60
  return createAnthropic({
54
61
  apiKey: oauth ? '' : apiKey,
55
- baseURL: baseUrl || undefined,
62
+ baseURL: normalized,
56
63
  headers: oauth
57
64
  ? {
58
65
  authorization: `Bearer ${apiKey}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.10.3",
3
+ "version": "0.10.5",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {