@aion0/forge 0.8.3 → 0.8.4

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,12 +1,12 @@
1
- # Forge v0.8.3
1
+ # Forge v0.8.4
2
2
 
3
3
  Released: 2026-05-20
4
4
 
5
- ## Changes since v0.8.2
5
+ ## Changes since v0.8.3
6
6
 
7
7
  ### Other
8
- - feat(jobs): add 'manual' schedule kind Fire-button-only
9
- - feat(jobs): one-shot + cron schedule kinds alongside period
8
+ - fix(http-protocol): apply manifest parameter defaults before template expansion
9
+ - fix(http-protocol): drop unsubstituted {args.*} query params
10
10
 
11
11
 
12
- **Full Changelog**: https://github.com/aiwatching/forge/compare/v0.8.2...v0.8.3
12
+ **Full Changelog**: https://github.com/aiwatching/forge/compare/v0.8.3...v0.8.4
@@ -51,6 +51,10 @@ function buildUrl(spec: HttpRequestSpec, settings: Record<string, any>, args: Re
51
51
  const url = new URL(base);
52
52
  for (const [k, raw] of Object.entries(spec.query)) {
53
53
  const v = expandAllTokens(String(raw), settings, args);
54
+ // Drop query params whose value didn't substitute (caller didn't pass
55
+ // that optional arg). Leaving `{args.foo}` in the URL would send it
56
+ // verbatim and many APIs return 400 on unknown values.
57
+ if (/\{(args|settings)\./.test(v) || v === '') continue;
54
58
  url.searchParams.append(k, v);
55
59
  }
56
60
  return url.toString();
@@ -90,9 +94,22 @@ export async function runHttp({ tool, settings, args }: HttpProtocolArgs): Promi
90
94
  const method = (spec.method || 'GET').toUpperCase();
91
95
  const timeoutMs = Math.min(MAX_TIMEOUT_MS, Math.max(1, Number(tool.timeout_ms || DEFAULT_TIMEOUT_MS)));
92
96
 
93
- const url = buildUrl(spec, settings, args);
94
- const headers = buildHeaders(spec, settings, args);
95
- const { body, contentType } = buildBody(spec, settings, args);
97
+ // Apply parameter defaults from the manifest so templates like
98
+ // {args.per_page} can resolve when the LLM omits the field. LLMs are
99
+ // inconsistent about including defaults in tool calls; merging them
100
+ // here is closer to how users expect a schema `default:` to behave.
101
+ const argsWithDefaults: Record<string, any> = { ...args };
102
+ if (tool.parameters) {
103
+ for (const [name, schema] of Object.entries(tool.parameters)) {
104
+ if (argsWithDefaults[name] === undefined && schema && (schema as any).default !== undefined) {
105
+ argsWithDefaults[name] = (schema as any).default;
106
+ }
107
+ }
108
+ }
109
+
110
+ const url = buildUrl(spec, settings, argsWithDefaults);
111
+ const headers = buildHeaders(spec, settings, argsWithDefaults);
112
+ const { body, contentType } = buildBody(spec, settings, argsWithDefaults);
96
113
  if (body != null && contentType && !headers.has('content-type')) headers.set('content-type', contentType);
97
114
 
98
115
  const controller = new AbortController();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.8.3",
3
+ "version": "0.8.4",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {