@altimateai/altimate-code 0.7.2 → 0.7.3
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/CHANGELOG.md +47 -0
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,53 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.7.3] - 2026-05-24
|
|
9
|
+
|
|
10
|
+
A telemetry-driven hardening release. Five P0 fixes merged from a `telemetry-analysis-2026-05-21` pass — every one tied to a measured failure number from the App Insights pipeline. The headline wins are user-visible: `finops_*` tools now work without an explicit `warehouse=` parameter (auto-pick the first compatible connection); `project_scan` no longer crashes on hosts where `git` isn't in PATH (the silent 437-user regression was masked by the PII filter collapsing the binary name to `?` in error messages); and `webfetch` caches 404/410/451 responses for up to 30 minutes so the agent stops re-asking dead URLs. Two telemetry-only fixes (build-agent name normalization, Anthropic token-count semantics) clean up dashboard mis-bucketing without changing user-visible behavior.
|
|
11
|
+
|
|
12
|
+
A five-persona pre-release review drove a second hardening pass: HTTPS basic-auth credentials are now stripped from `git remote get-url origin` output before it reaches LLM-visible metadata or session transcripts; raw `git` stderr is routed through `Telemetry.maskString` to redact embedded emails and bearer tokens; `normalizeAgentName` gained C0 control-char stripping + NFKC normalization + a 64-char cap to neutralize log-injection and homoglyph-bucket attacks via custom agent configs; the webfetch failure cache now also drops auth-bearing query params (`token`, `api_key`, `signature`, `x-amz-signature`, etc.) from the cache key so presigned-URL secrets can't sit in an in-memory `Map` for 30 minutes; cache-hit error messages are prefixed with `(cached failure, Nm ago)` so an agent debugging a fast failure can tell cache vs. live network apart; and 34 adversarial tests pin every one of these regression classes plus the `warehouse_filter` / `warehouse` parameter disambiguation that caused LLM confusion.
|
|
13
|
+
|
|
14
|
+
### Dashboard query change
|
|
15
|
+
|
|
16
|
+
`tokens_input_total` is now **always** emitted on `generation` telemetry events (previously omitted when zero/null). Dashboards reading `tokens_input` to compute volume will under-report on Anthropic-cache-hit sessions — switch any "total input tokens consumed" queries to `tokens_input_total`. The old `tokens_input` field is preserved and reports uncached input tokens (clamped at zero so inconsistent provider counts can't produce negative cost). The two fields satisfy the invariant `tokens_input + tokens_cache_read + tokens_cache_write === tokens_input_total`.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **`finops_*` tools auto-pick a warehouse when omitted.** All six finops tools (`finops_analyze_credits`, `finops_expensive_queries`, `finops_query_history`, `finops_role_*`, `finops_unused_resources`, `finops_warehouse_advice`) previously required an explicit `warehouse=<connection-name>` argument. Telemetry showed them at a 100% error rate because the LLM consistently guessed unconfigured warehouse names and got dead-end "Credit analysis is not available for unknown warehouses" errors with no enumeration of what *was* configured. The new `resolveFinopsWarehouse` helper centralizes resolution: if no warehouse is requested, it auto-picks the first configured connection whose driver type supports the operation (`snowflake` / `bigquery` / `databricks` for credit/sizing/usage tools; broader for query history; Snowflake-only for role-hierarchy). Errors now enumerate configured warehouse names and point at `warehouse_add` when nothing is configured. Trim is applied on the requested name (LLM whitespace edge cases) and type matching is case-insensitive (`"Snowflake"` / `"snowflake"` / `"SNOWFLAKE"` resolve identically). (#828, closes #827)
|
|
21
|
+
- **`project_scan` no longer crashes when `git` is missing from PATH.** Telemetry showed a 32% failure rate across 437 users with the masked error `"Executable not found in $PATH: ?"` — the binary name was being collapsed to `?` by the PII filter, hiding the real cause for two months. `Bun.spawnSync` *throws* when a binary isn't found (not just non-zero exit), and `project_scan` was running the throw unguarded. The new `safeSpawnSync` wrapper catches it cleanly and returns `null`, and `detectGit` distinguishes three states via `GitInfo.gitAvailable` + `gitError`: `git missing` (binary not in PATH — surface install hint), `git present but degraded` (non-128 exit code — corrupted `.git`, permission denied; surfaces exit code + masked stderr), and `git present, not a repo` (clean exit 128 — render "Not a git repository"). The `metadata.degraded` array always emits even when empty, sorted and deduplicated, so dashboard queries never have to null-coalesce. (#831, closes #830)
|
|
22
|
+
- **Build agent telemetry no longer reports 0% completion.** A rename from `"build"` → `"builder"` in the agent registry left three writer sites still emitting the legacy name: the TUI sent `agent: "build"` on session start, the plan-exit synthetic message wrote `lastUser.agent = "build"`, and the `agent_outcome` event read from that. The agent execution alias at `Agent.get()` masked the issue at runtime, but every dashboard saw a phantom `"build"` bucket with 0% completion alongside the real `"builder"` bucket. The new `normalizeAgentName` helper is the single source of truth — used by both `session_start` and `agent_outcome` emits so they can never drift, case-insensitive against the legacy name, plus C0-control-char strip + NFKC + 64-char cap so a malicious or hand-edited config can't inject newlines into App Insights or create a cardinality bomb. The TUI and plan tool now write `"builder"` directly. (#833, closes #832)
|
|
23
|
+
- **Anthropic `tokens_input` is no longer always 0 in telemetry.** `Session.getUsage` previously assumed OpenAI-style accounting (where `inputTokens` is the inclusive total including cached) — but Anthropic returns `inputTokens` exclusive of cached, so the subtraction `inputTokens - cacheRead - cacheWrite` produced 0 (or negative) on every cache-hit session. The new branch tests `metadata.anthropic || metadata.bedrock` and skips the subtraction for those providers. `tokens_input_total` is now always emitted as the inclusive total (so dashboards have a clean denominator), and `tokens.input` is clamped at zero — inconsistent provider counts (e.g. `inputTokens=1000, cachedInputTokens=2000`) can no longer leak negative cost into App Insights or session totals. Venice metadata path (`metadata.venice.usage.cacheCreationInputTokens`) is now covered with the same treatment as Anthropic/Bedrock. (#837, closes #836)
|
|
24
|
+
- **`webfetch` failure cache now persists known-bad URLs for 30 minutes (5 min for 451) and collapses LLM-generated URL variations.** Telemetry showed 486 residual webfetch 404 retries across the 14-day window (down from March's 2,222 but still meaningful) — the LLM kept fetching the same dead URL with different tracking parameters, fragments, and case variations and getting fresh 404s each time. The cache key is now the *normalized* URL: tracking params (`utm_*`, `fbclid`, `gclid`, `mc_*`, `_ga`, `_gl`, `igshid`, `mibextid`, HubSpot `_hsenc`/`_hsmi`, Marketo `mkt_tok`, Adobe `s_cid`/`s_kwcid`, Piwik/Matomo `pk_*`/`piwik_*`, `__cf_chl_*`) are stripped, query params are sorted by (key, value), the host is lowercased, the fragment is dropped, and HTTPS basic-auth userinfo (`user:pass@`) is removed. The functional `ref` param is deliberately *preserved* (GitHub raw URLs and git APIs use it to select branches/tags). Auth-bearing query params (`token`, `access_token`, `api_key`, `apikey`, `signature`, `sig`, `x-amz-signature`, `x-amz-credential`, `x-amz-security-token`, `x-goog-signature`, `x-goog-credential`) are dropped from the **cache key only** — the actual `fetch()` still uses the raw URL — so an S3 presigned URL that 404s doesn't leak its signature into the in-memory `Map` for 30 minutes. 451 uses a shorter 5-min TTL because it's observer-conditional (VPN swap unblocks). Cache-hit errors now prefix with `(cached failure, Nm ago)` so an agent debugging a fast failure can tell cache vs. live network apart. LRU re-touch on repeated failures via `delete-then-set` so a frequently-failing URL doesn't sit at the head of the FIFO and get evicted first under pressure (cache size cap is 500). (#839, closes #838)
|
|
25
|
+
|
|
26
|
+
### Privacy & Security (pre-release hardening pass)
|
|
27
|
+
|
|
28
|
+
- **`git remote get-url origin` output is now credential-stripped before it reaches LLM-visible metadata or session transcripts.** Pre-fix, `metadata.git.remoteUrl` shipped the URL verbatim — including embedded HTTPS basic-auth like `https://x-access-token:ghp_xxx@github.com/...` or `https://user:pass@gitlab.internal/...` — which then flowed to the LLM provider on every `project_scan` call and was preserved in the session transcript. The new `stripGitRemoteCredentials` helper sets `username` and `password` to empty on parseable URLs, preserves SSH-form remotes (`git@github.com:owner/repo.git` has no userinfo concept), and drops unparseable URLs entirely rather than risk leaking embedded creds. Flagged by the v0.7.3 compliance/chaos review.
|
|
29
|
+
- **`gitError.stderr` is masked via `Telemetry.maskString` before persisting.** Git stderr on auth failures and bad-object errors contains embedded HTTPS remote URLs (with userinfo), commit emails, and `/Users/<realname>/` paths. The masker (already redacting `sk-`, `Bearer`, and `<email>` in error strings elsewhere) now runs before the stderr is sliced to 240 chars and assigned to `metadata.git.gitError.stderr`. Mask-before-slice order is pinned by adversarial test so a refactor can't reorder them and surface a half-redacted email.
|
|
30
|
+
- **`normalizeAgentName` hardens against adversarial input.** Strips C0 control characters (`\x00-\x1f` + DEL) — a custom-agent config with `name: "x\nfake_event=hello"` would have split App Insights into two events; NFKC-normalizes so fullwidth/homoglyph agent names (`"builder"`) don't create separate telemetry buckets; caps length at 64 chars because agent names are slugs and anything larger is a cardinality bomb. Three new pinning tests guarantee each invariant.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- **`warehouse_filter` parameter description disambiguated from `warehouse`.** With `warehouse` now optional, the previous description ("Filter to a specific Snowflake warehouse") was ambiguous next to the connection-name `warehouse` parameter. New description: "Filter result rows by an in-warehouse Snowflake compute name (NOT the connection name). Distinct from `warehouse`: `warehouse` picks which connection to query; `warehouse_filter` narrows which Snowflake virtual warehouse's queries are returned in the result set. Snowflake only." Applied to both `finops_analyze_credits` and `finops_query_history`. End-user persona flagged the LLM-confusion risk during pre-release review.
|
|
35
|
+
- **`DEFAULT_FINOPS_TYPES` is the canonical "supported by any cloud warehouse" type list.** Pre-fix, three handlers (`credit-analyzer`, `unused-resources`, `warehouse-advisor`) each declared the same `["snowflake", "bigquery", "databricks"]` literal as a local `const`. Now exported from `warehouse-resolver.ts`; adding a fourth driver (e.g. Redshift `account_usage`) is one edit, not three.
|
|
36
|
+
- **`docs/docs/data-engineering/tools/finops-tools.md` updated for the auto-pick behavior.** Pre-fix, the doc said `warehouse (required): Connection name` — directly contradicting the v0.7.3 code. Now lists `warehouse` as optional with the auto-pick semantics, includes a top-of-file `v0.7.3+` note about the change, and shows the bare (no-warehouse) invocation form in at least one example. PM persona flagged the doc/code drift as P0 pre-release.
|
|
37
|
+
|
|
38
|
+
### Testing
|
|
39
|
+
|
|
40
|
+
- **34 adversarial tests** in `release-v0.7.3-adversarial.test.ts` pin the regression classes:
|
|
41
|
+
- **finops auto-pick** — code/doc/tool-description alignment (no `warehouse (required)` left in docs; "Optional" appears in tool descriptions; `warehouse_filter` description disambiguates from `warehouse`; `DEFAULT_FINOPS_TYPES` is single source of truth; resolver trims whitespace; resolver auto-picks on empty/undefined/whitespace).
|
|
42
|
+
- **project_scan privacy** — `stripGitRemoteCredentials` present + sets `username`/`password` empty; `gitError.stderr` runs through `Telemetry.maskString`; mask-before-slice order; `safeSpawnSync` returns null on missing binary; `GitInfo.gitAvailable` + `gitError` distinguish three states; output line distinguishes "binary missing" from "not a repo".
|
|
43
|
+
- **normalizeAgentName** — single declaration site (single source of truth); case-folds before "build" compare; strips C0 control chars; NFKC-normalizes; length-caps at 64; both `session_start` and `agent_outcome` route through the helper.
|
|
44
|
+
- **webfetch cache key** — `AUTH_PARAMS_FOR_CACHE_KEY` enumerates `token`/`access_token`/`api_key`/`apikey`/`signature`/`sig`/`x-amz-signature`/`x-amz-credential`/`x-goog-signature`; presigned-S3 URLs with different signatures collapse; api_key/token variants all collapse; functional params (`page`, `q`) are NOT stripped; auth-param strip is case-insensitive; cache-hit error prefix wording is distinguishable; `isUrlCachedFailure` exposes `ageMs`; 451 has shorter TTL than 404/410.
|
|
45
|
+
- **URL normalization privacy invariants** — userinfo stripped from cache key; utm/fbclid/mc_ tracking collapses; normalization is idempotent; invalid URL passes through verbatim.
|
|
46
|
+
- **CHANGELOG presence** — release-skill backstop that catches a release commit without a 0.7.3 entry + all 5 merged PR numbers referenced.
|
|
47
|
+
|
|
48
|
+
### Deferred to follow-up issues
|
|
49
|
+
|
|
50
|
+
- [#840](https://github.com/AltimateAI/altimate-code/issues/840) Surface auto-picked warehouse name in `finops_*` tool output (currently `autoPicked: true` is computed but not rendered).
|
|
51
|
+
- [#841](https://github.com/AltimateAI/altimate-code/issues/841) Audit: webfetch failure cache crosses logical sessions in `altimate serve` daemon mode.
|
|
52
|
+
- [#842](https://github.com/AltimateAI/altimate-code/issues/842) Route the three compaction-summary `lastUser.agent` writes through `normalizeAgentName` (currently only the emit boundary is normalized; persisted state can still record legacy `"build"`).
|
|
53
|
+
- [#843](https://github.com/AltimateAI/altimate-code/issues/843) Audit: cost telemetry retention + re-identification policy (`tokens_input_total` + `cost` are now always emitted per generation event; document TTL and TOS alignment).
|
|
54
|
+
|
|
8
55
|
## [0.7.2] - 2026-05-21
|
|
9
56
|
|
|
10
57
|
A focused hotfix for v0.7.1's broken install endpoint plus a defensive pass on the upgrade fetch surface. v0.7.1 documented and embedded `https://altimate.ai/install` in the curl install path and in `altimate upgrade`'s in-place upgrader — that host is the marketing-site SPA and returns an HTML 404 for `/install`, so every curl install and every curl-installed user's `altimate upgrade` silently failed end-to-end. v0.7.2 swaps the host to `https://www.altimate.sh/install` (apex `altimate.sh` is still not routed to the Amplify Next.js app — tracked separately, drop the `www.` once apex DNS is fixed), wraps the upgrader fetch with a 15s bounded timeout, replaces the raw `AbortError: The operation was aborted` with an actionable error that names the URL, prints the manual re-install one-liner, and points at the GitHub releases fallback. Realigns the published GitHub Action (`github/action.yml`) with the v0.7.1 binary rename (`altimate-code` → `altimate`) and new install directory (`~/.altimate/bin`) — pre-fix, every Action consumer hit the broken URL on cache miss and then a missing binary even if the URL had worked. 30 adversarial tests pin the regression classes (URL eradication, cross-file host consistency, named-constant invariants, error-surface invariants, action.yml alignment, marker integrity, migration recovery surface, CHANGELOG presence).
|
package/package.json
CHANGED
|
@@ -7,20 +7,20 @@
|
|
|
7
7
|
"scripts": {
|
|
8
8
|
"postinstall": "bun ./postinstall.mjs || node ./postinstall.mjs"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.7.
|
|
10
|
+
"version": "0.7.3",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@altimateai/altimate-core": "0.3.1"
|
|
14
14
|
},
|
|
15
15
|
"optionalDependencies": {
|
|
16
|
-
"@altimateai/altimate-code-windows-x64": "0.7.
|
|
17
|
-
"@altimateai/altimate-code-linux-x64": "0.7.
|
|
18
|
-
"@altimateai/altimate-code-linux-arm64": "0.7.
|
|
19
|
-
"@altimateai/altimate-code-windows-x64-baseline": "0.7.
|
|
20
|
-
"@altimateai/altimate-code-darwin-arm64": "0.7.
|
|
21
|
-
"@altimateai/altimate-code-linux-x64-baseline": "0.7.
|
|
22
|
-
"@altimateai/altimate-code-darwin-x64": "0.7.
|
|
23
|
-
"@altimateai/altimate-code-darwin-x64-baseline": "0.7.
|
|
16
|
+
"@altimateai/altimate-code-windows-x64": "0.7.3",
|
|
17
|
+
"@altimateai/altimate-code-linux-x64": "0.7.3",
|
|
18
|
+
"@altimateai/altimate-code-linux-arm64": "0.7.3",
|
|
19
|
+
"@altimateai/altimate-code-windows-x64-baseline": "0.7.3",
|
|
20
|
+
"@altimateai/altimate-code-darwin-arm64": "0.7.3",
|
|
21
|
+
"@altimateai/altimate-code-linux-x64-baseline": "0.7.3",
|
|
22
|
+
"@altimateai/altimate-code-darwin-x64": "0.7.3",
|
|
23
|
+
"@altimateai/altimate-code-darwin-x64-baseline": "0.7.3"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"pg": ">=8",
|