agent-afk 5.82.11 → 5.83.0
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/dist/agent/tools/handlers/web-scrape.d.ts +2 -0
- package/dist/agent/tools/skill-executor/fork-result.d.ts +5 -0
- package/dist/browser/playwright/launcher.d.ts +1 -0
- package/dist/browser/types.d.ts +1 -0
- package/dist/bundled-plugins/awa-bundled/skills/review/SKILL.md +19 -13
- package/dist/cli/commands/interactive/shared.d.ts +1 -1
- package/dist/cli/quota-footer.d.ts +6 -0
- package/dist/cli/quota-indicator.d.ts +20 -0
- package/dist/cli/status-line.d.ts +2 -1
- package/dist/cli.mjs +478 -478
- package/dist/config/env.d.ts +1 -0
- package/dist/index.mjs +166 -166
- package/dist/telegram.mjs +219 -219
- package/dist/web/egress-guard.d.ts +24 -0
- package/dist/web/index.d.ts +2 -0
- package/dist/web/scrape.d.ts +2 -0
- package/dist/web/types.d.ts +1 -0
- package/package.json +2 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { ToolHandler } from '../types.js';
|
|
2
|
+
import type { EgressGuardOptions as GuardOpts } from '../../../web/egress-guard.js';
|
|
2
3
|
import type { RenderFn } from '../../../web/types.js';
|
|
3
4
|
type FetchFn = typeof fetch;
|
|
4
5
|
interface WebScrapeOptions {
|
|
5
6
|
fetchFn?: FetchFn;
|
|
6
7
|
env?: Record<string, string | undefined>;
|
|
7
8
|
renderFn?: RenderFn;
|
|
9
|
+
lookupFn?: GuardOpts['lookupFn'];
|
|
8
10
|
}
|
|
9
11
|
export declare function createWebScrapeHandler(opts?: WebScrapeOptions): ToolHandler;
|
|
10
12
|
export declare const webScrapeHandler: ToolHandler;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SubagentResult } from '../../subagent/result.js';
|
|
2
|
+
import type { ToolResult } from '../types.js';
|
|
3
|
+
export declare const CANCELLED_PARTIAL_MARKER = "[skill cancelled mid-flight \u2014 partial output preserved below]";
|
|
4
|
+
export declare function failedPartialMarker(errorMessage: string): string;
|
|
5
|
+
export declare function renderForkOutcome(result: SubagentResult, noOutputError: string): ToolResult;
|
package/dist/browser/types.d.ts
CHANGED
|
@@ -44,16 +44,22 @@ Never fabricate intent. When none is available the value is the literal `(none s
|
|
|
44
44
|
|
|
45
45
|
**Triage (inline).** From the resolved diff extract: change type (hotfix | feature | refactor | dep-bump | new-service), files changed, total lines changed, summary. Classify regime: `light` if ≤300 lines or change type is hotfix/dep-bump; `full` otherwise.
|
|
46
46
|
|
|
47
|
+
**Concurrency floor — declared, conditional, and enforced.** *Through synthesis*, a full-regime review peaks at **2 concurrent sub-agent sessions** (Wave 1's two dimension agents) and dispatches **3 in total** (Wave 1 ×2, then Wave 2 ×1, sequential). Wave 1.5 runs inline in the orchestrator and dispatches nothing. **No wave nests a child**: the sub-agents are shell-less by design, and nothing in this skill requires them to run a command, so none of them needs to nest a `git-investigator` to comply. If you add a requirement here that needs a shell, you have silently doubled this floor — put that requirement in Wave 1.5 instead.
|
|
48
|
+
|
|
49
|
+
**The post-synthesis tail is the conditional half of that budget.** A review that surfaces a `critical`/`high` finding invokes `/shadow-verify` (see **Post-synthesis** below), which dispatches one verifier per claim in parallel — so the whole-run budget is **peak 3 concurrent, 5–6 total**, and it lands on exactly the high-stakes reviews most likely to hit a rate ceiling. Bound it: **at most 3 claims in a single round, no repeat rounds**, and hand the verifiers Wave 1.5's manifest so each re-derives the *claim* instead of re-locating evidence Wave 1.5 already pinned at the ref. Wave 1.5 verifies that a citation is real; shadow-verify re-derives whether the inference drawn from it holds — never substitute one for the other.
|
|
50
|
+
|
|
47
51
|
**Wave 1 — Full review (regime=full, 2 parallel agents, `subagent_type: "research-agent"`).** Dispatch:
|
|
48
52
|
- **security · api-compat** — contracts, auth, injection, breaking changes, secret exposure.
|
|
49
53
|
- **correctness · spec-compliance · test-coverage · perf-observability** — logic bugs, regressions, whether the change satisfies its **stated intent** (unmet requirement or unrequested scope creep), missing tests, hot-path perf, logging gaps.
|
|
50
54
|
|
|
51
55
|
Each agent receives: full diff + file tree + triage header + **reviewed ref (SHA)** + the **stated intent** (what the change is meant to accomplish, or `(none supplied)`), the severity rubric, and the finding schema.
|
|
52
56
|
|
|
53
|
-
**Citation requirement (enforced per agent)
|
|
54
|
-
1. State the ref it
|
|
55
|
-
2.
|
|
56
|
-
3. If the line
|
|
57
|
+
**Citation requirement (enforced per agent).** Wave 1 agents cite from the diff and from file reads available in their own session. They do **not** run git and do **not** re-read at the reviewed ref — that verification is centralized in Wave 1.5 below, which re-reads every `blocking`/`critical`/`high` citation **and every `file-state` citation at any severity** at the ref, then drops the fabricated ones. Each agent must:
|
|
58
|
+
1. State the reviewed ref it was given in each finding: `ref: <sha>`.
|
|
59
|
+
2. Classify every citation as `diff-context` (line visible in the diff hunk) or `file-state` (line in the post-merge file, not visible in the hunk). Tag every `file-state` citation `[UNVERIFIED: not re-read]` so Wave 1.5 knows to check it — a Wave 1 `Read` observes the **working tree**, which equals the reviewed ref only when that ref is the checked-out HEAD, so for a PR, branch, or commit target that is not checked out locally the tag is load-bearing, not decorative.
|
|
60
|
+
3. Never paraphrase or reconstruct a line from memory. If the line is not visible in the diff, cite it as `file-state` and let Wave 1.5 resolve it — do not invent the content.
|
|
61
|
+
|
|
62
|
+
**Invariant — why Wave 1 does not run git.** `research-agent` has no shell (`tools: Read, Grep, Glob, WebFetch, WebSearch, Agent(git-investigator)` — no `Bash`, and that single `Agent(...)` entry is the nesting path this rule closes), so a mandatory `git show` forces it to dispatch a nested `git-investigator` purely to run one command. That doubles the concurrent session count of *every* Wave 1 agent, and is the structural cause of the rate-limit cascade in #726. Ref-anchored verification is therefore performed once, centrally, by a shell-capable actor — never N times by shell-less ones. Do not reintroduce a per-agent re-read here.
|
|
57
63
|
|
|
58
64
|
Banned words: "ensure", "consider", "may", "could". No `file:line` citation → omit the finding.
|
|
59
65
|
|
|
@@ -62,14 +68,14 @@ Banned words: "ensure", "consider", "may", "could". No `file:line` citation →
|
|
|
62
68
|
- `stated-intent` is `(none supplied)` → do **not** assess spec-compliance and do **not** substitute the global constraints for the spec. Emit exactly one line: `unverified — spec-compliance not assessed: no stated intent supplied (pass --brief/--spec, or review a PR/commit)`. Silently treating the diff or the constraints as "the spec" is the precise failure this rule prevents.
|
|
63
69
|
|
|
64
70
|
**api-compat reachability pre-check (mandatory before surfacing any breaking-change finding).**
|
|
65
|
-
For every symbol flagged as a breaking change,
|
|
71
|
+
For every symbol flagged as a breaking change, search production source files with the `Grep` tool — which needs no shell, so this check never forces a nested dispatch — for imports or usages of that symbol, excluding `*.test.*`, `*.spec.*`, `__tests__/`, `__mocks__/`, `/test/`, `/tests/`. Decision table:
|
|
66
72
|
- Zero production importers → downgrade finding to `nit`, append `[UNVERIFIED: no production importers]`, set confidence `low`.
|
|
67
73
|
- One or more production importers → severity stands; include one importer path as evidence.
|
|
68
74
|
|
|
69
|
-
If
|
|
75
|
+
If the `Grep` tool is unavailable, tag the finding `[UNVERIFIED: reachability not checked]` and downgrade one severity tier.
|
|
70
76
|
|
|
71
|
-
**Absence-claim grounding (mandatory for any claim that something does not exist).** Before emitting a finding of the form "no test covers X", "no handler validates Y", "no caller invokes Z", "X is not tested":
|
|
72
|
-
- Zero matches → finding stands; cite the
|
|
77
|
+
**Absence-claim grounding (mandatory for any claim that something does not exist).** Before emitting a finding of the form "no test covers X", "no handler validates Y", "no caller invokes Z", "X is not tested": search the production tree with the `Grep` tool — which needs no shell, so this check never forces a nested dispatch — for plausible match strings. Decision table:
|
|
78
|
+
- Zero matches → finding stands; cite the search pattern in the evidence field.
|
|
73
79
|
- One or more matches → emit `unverified — absence claim refuted by <path>:<line>` instead of the finding.
|
|
74
80
|
- Grep tooling unavailable or claim cannot be reduced to a pattern → tag finding `[UNVERIFIED: absence not checked]` and downgrade one severity tier.
|
|
75
81
|
|
|
@@ -77,14 +83,14 @@ This is the agent's first-line self-check; **Wave 1.5 Check B** independently re
|
|
|
77
83
|
|
|
78
84
|
**Wave 1 — Light review (regime=light, 1 agent, `subagent_type: "research-agent"`).** Single agent covers all dimensions (including spec-compliance). Same `stated-intent` input, rubric, schema, and citation requirement.
|
|
79
85
|
|
|
80
|
-
**Wave 1.5 — Citation + absence-claim verification (
|
|
86
|
+
**Wave 1.5 — Citation + absence-claim verification (INLINE — run by the orchestrator, dispatches nothing).** Run after Wave 1 returns, before Wave 2 synthesis. The orchestrator already holds exactly the read-only shell this verification needs (`git show` / `git diff` / `gh pr diff` / `grep` / `rg` — see the shell grant above), so running it inline costs **zero** additional sessions and zero nesting. A shell-less sub-agent here would have to nest a `git-investigator` to run the very commands the orchestrator can already run. Two independent checks:
|
|
81
87
|
|
|
82
|
-
**Check A — Citation verification.** Extracts every `file:line` citation from any `blocking`, `critical`, or `high` finding across all Wave 1 results. For each citation, runs `git show <reviewed-ref>:<file>` (or equivalent) and checks whether the quoted evidence snippet actually appears at that line in the reviewed ref — not in main, not in diff context alone. Classifies each citation as:
|
|
88
|
+
**Check A — Citation verification.** Extracts (a) every `file:line` citation from any `blocking`, `critical`, or `high` finding, **and (b) every citation tagged `file-state` at any severity** — `medium`, `low`, and `nit` included — across all Wave 1 results. Both sets are checked, because Wave 1 never re-reads at the ref: an unverified `file-state` citation in a `low` finding is exactly as fabricable as one in a `high` finding, and quoting a line absent from the reviewed change is a defect at every tier. For each citation, runs `git show <reviewed-ref>:<file>` (or equivalent) and checks whether the quoted evidence snippet actually appears at that line in the reviewed ref — not in main, not in diff context alone. Classifies each citation as:
|
|
83
89
|
- `verified` — content matches what is actually at that line on the reviewed ref.
|
|
84
90
|
- `diff-only` — line appears in the diff hunk but no longer exists at the reviewed ref HEAD (e.g., deleted block). Finding must be downgraded: the issue may already be resolved.
|
|
85
91
|
- `fabricated` — line does not exist at the reviewed ref and was not in the diff hunk; the evidence snippet is unverifiable. Finding is **dropped** from the report.
|
|
86
92
|
|
|
87
|
-
**Check B — Absence-claim verification.** Extracts every **absence claim**
|
|
93
|
+
**Check B — Absence-claim verification.** Extracts every **absence claim** across all Wave 1 results **at any severity** — `medium`, `low`, and `nit` included, for the same reason Check A checks every `file-state` citation: Wave 1's absence grounding is a self-check by an agent that never re-read at the ref, so an unverified absence claim in a `low` finding is exactly as fabricable as one in a `high` finding. These are claims of the form "no test covers X", "no handler validates Y", "no caller invokes Z", "X is not tested", "Y has no validation". Citations are not required for absence claims, so Check A cannot catch them; they need their own gate. For each, identify the asserted-absent symbol, test name, or behavior, then run `git grep -n <pattern> <reviewed-ref>` (or `rg --no-heading -n <pattern>` if outside a git context) across the production tree (exclude the same paths as the api-compat reachability check: tests, mocks, fixtures, when the claim is about production code). Classify as:
|
|
88
94
|
- `confirmed-absent` — zero matches in the asserted scope; finding stands.
|
|
89
95
|
- `false-absent` — one or more matches in the asserted scope; finding is **dropped** (the asserted-absent entity exists at the reviewed ref). Name the matching path(s) in the dropped-findings manifest.
|
|
90
96
|
- `grep-unavailable` — tooling missing, symbol ambiguous, or absence claim cannot be reduced to a grep pattern; finding tagged `[UNVERIFIED: absence not checked]` and downgraded one severity tier.
|
|
@@ -106,12 +112,12 @@ Sort overall: critical → high → medium → low → nit; security first withi
|
|
|
106
112
|
|
|
107
113
|
Confidence `low` → auto-downgrade one tier + append `[low confidence — verify with runtime context]`.
|
|
108
114
|
|
|
109
|
-
**Output per dimension:** if you have read the file(s)
|
|
115
|
+
**Output per dimension:** if you have read the relevant file(s) and have either real findings or a confirmed clean read, emit findings or `no issues found — read <file>`. If evidence is insufficient — you could not read the file, the tool was unavailable, no production importers were found for the symbol, or no test file exists at the asserted path — emit `unverified — <reason>` naming the missing evidence rather than invent a finding to fill the slot. Banned words from the hedging list (`ensure`, `consider`, `may`, `could`) remain banned **inside findings**; the `unverified` channel is the sanctioned path for uncertainty.
|
|
110
116
|
|
|
111
117
|
**Finding schema:** `severity · confidence · dimension · file:line_range · ref:<sha> · citation-type:(diff-context|file-state) · finding (one concrete sentence naming the failure mode) · evidence (verbatim code ≤4 lines) · suggestion (one concrete fix)`.
|
|
112
118
|
|
|
113
119
|
**Epistemic scope disclosure (required in synthesis output).** The "What was not checked" section must include:
|
|
114
|
-
- Which ref
|
|
120
|
+
- Which ref citations were verified against in Wave 1.5 (list the SHA or `unknown` if patch-file input). Example: `Citations verified inline against branch HEAD abc1234.`
|
|
115
121
|
- If any citations could not be verified against a live ref (patch-file input): `Citation verification skipped — no live ref available; diff-context citations only.`
|
|
116
122
|
- Any topical gaps (e.g. 'did not review Telegram surface', 'did not run tests').
|
|
117
123
|
- Whether a **stated intent** was available and spec-compliance was assessed. Example: `Stated intent: PR #123 title+body — spec-compliance assessed.` or `Stated intent: (none supplied) — spec-compliance not assessed.`
|
|
@@ -111,7 +111,7 @@ export declare const REPL_SPINNER_OPTIONS: {
|
|
|
111
111
|
};
|
|
112
112
|
export declare function contextRatio(stats: SessionStats, sampler?: ContextSampler): number;
|
|
113
113
|
export declare function formatStatusFields(stats: SessionStats, sampler?: ContextSampler, gitSampler?: GitStatusSampler): {
|
|
114
|
-
|
|
114
|
+
quotaWindows?: import("../../quota-indicator.js").QuotaWindows | undefined;
|
|
115
115
|
pr?: number | undefined;
|
|
116
116
|
branch?: string | undefined;
|
|
117
117
|
cwd?: string | undefined;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type QuotaWindows } from './quota-indicator.js';
|
|
2
|
+
export type QuotaUsageTier = 'quiet' | 'caution' | 'near' | 'over';
|
|
3
|
+
export declare function formatQuotaUsage(windows: QuotaWindows | undefined, now?: Date): {
|
|
4
|
+
tier: QuotaUsageTier;
|
|
5
|
+
text: string | null;
|
|
6
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { QuotaSnapshot } from '../agent/quota-cache.js';
|
|
2
|
+
export interface QuotaWindowState {
|
|
3
|
+
readonly utilization: number;
|
|
4
|
+
readonly resetsAt?: Date;
|
|
5
|
+
}
|
|
6
|
+
export interface QuotaWindows {
|
|
7
|
+
readonly fiveHour?: QuotaWindowState;
|
|
8
|
+
readonly sevenDay?: QuotaWindowState;
|
|
9
|
+
readonly observedAt?: Date;
|
|
10
|
+
}
|
|
11
|
+
export declare function quotaWindowsFromSnapshot(snapshot: QuotaSnapshot | undefined): QuotaWindows | undefined;
|
|
12
|
+
export type QuotaSeverity = 'calm' | 'caution' | 'critical';
|
|
13
|
+
export interface QuotaIndicator {
|
|
14
|
+
readonly text: string;
|
|
15
|
+
readonly severity: QuotaSeverity;
|
|
16
|
+
readonly stale: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare const STALE_AFTER_MS: number;
|
|
19
|
+
export declare function formatResetCountdown(msRemaining: number): string;
|
|
20
|
+
export declare function formatQuotaIndicator(windows: QuotaWindows, now?: Date): QuotaIndicator | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PermissionMode } from '../agent/types/sdk-types.js';
|
|
2
|
+
import { type QuotaWindows } from './quota-indicator.js';
|
|
2
3
|
export interface StatusLineFields {
|
|
3
4
|
model: string;
|
|
4
5
|
cost?: number;
|
|
@@ -11,7 +12,7 @@ export interface StatusLineFields {
|
|
|
11
12
|
cwd?: string;
|
|
12
13
|
branch?: string;
|
|
13
14
|
pr?: number;
|
|
14
|
-
|
|
15
|
+
quotaWindows?: QuotaWindows;
|
|
15
16
|
}
|
|
16
17
|
interface StatusLineOpts {
|
|
17
18
|
stream?: NodeJS.WriteStream;
|