Repository navigation
feat(skills,cli): benchmark-driven agent efficiency (batch, compact, --pin) #638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
ce4b36a
a95cba1
ba79345
0d83569
1d6ad7e
ef34abf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -91,6 +91,10 @@ export class N8nApiClient { | |||||||||||||||||
|
|
||||||||||||||||||
| this.client = axios.create({ | ||||||||||||||||||
| baseURL: host, | ||||||||||||||||||
| // Fail-closed default: no API call may hang indefinitely on a | ||||||||||||||||||
| // stalled network (setup, push, verify). Calls that need longer | ||||||||||||||||||
| // pass their own explicit timeout, which takes precedence. | ||||||||||||||||||
| timeout: 30_000, | ||||||||||||||||||
| headers: { | ||||||||||||||||||
| 'X-N8N-API-KEY': this.apiKey, | ||||||||||||||||||
| 'Content-Type': 'application/json', | ||||||||||||||||||
|
|
@@ -272,6 +276,35 @@ export class N8nApiClient { | |||||||||||||||||
| * | ||||||||||||||||||
| * @returns Array of IProject | ||||||||||||||||||
| */ | ||||||||||||||||||
| /** | ||||||||||||||||||
| * One authenticated request, reported honestly. | ||||||||||||||||||
| * | ||||||||||||||||||
| * Every other read method here swallows failures and falls back to a placeholder, | ||||||||||||||||||
| * which is right for a caller that wants data and wrong for a caller that wants to | ||||||||||||||||||
| * know whether the credentials work at all. Only a 2xx proves the n8n public API | ||||||||||||||||||
| * accepted the key: 401/403 means it rejected it, and anything else — a 404 from a | ||||||||||||||||||
| * non-n8n host, a 5xx, an HTML error page — is not a working API no matter what | ||||||||||||||||||
| * answered. | ||||||||||||||||||
| * | ||||||||||||||||||
| * `timeoutMs` must actually bound the process, not just the caller's patience: a | ||||||||||||||||||
| * request that only loses a `Promise.race` keeps the axios socket (and the event | ||||||||||||||||||
| * loop) alive until the instance-level timeout fires. | ||||||||||||||||||
| */ | ||||||||||||||||||
| async verifyAccess(timeoutMs?: number): Promise<{ ok: boolean; reason?: 'unauthorized' | 'unreachable' | 'api-unavailable'; status?: number }> { | ||||||||||||||||||
| try { | ||||||||||||||||||
| await this.client.get('/api/v1/projects', { | ||||||||||||||||||
| params: { limit: 1 }, | ||||||||||||||||||
| ...(timeoutMs ? { timeout: timeoutMs, signal: AbortSignal.timeout(timeoutMs) } : {}), | ||||||||||||||||||
| }); | ||||||||||||||||||
|
Comment on lines
+295
to
+298
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Use
📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| return { ok: true }; | ||||||||||||||||||
| } catch (error: any) { | ||||||||||||||||||
| const status = error?.response?.status; | ||||||||||||||||||
| if (status === 401 || status === 403) return { ok: false, reason: 'unauthorized', status }; | ||||||||||||||||||
| if (status) return { ok: false, reason: 'api-unavailable', status }; | ||||||||||||||||||
| return { ok: false, reason: 'unreachable' }; | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| async getProjects(): Promise<IProject[]> { | ||||||||||||||||||
| try { | ||||||||||||||||||
| const projects: IProject[] = []; | ||||||||||||||||||
|
|
||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
The API-key guidance no longer fits a
.envworkspace.The widened gate lets a workspace that only has a
.envreach the constructor. If that.envsetsN8N_HOSTbut noN8N_API_KEY, the resolved environment has a host and no key, andsourceKindisexternal-instance. Execution then reaches the message at Line 133, which tells the user to runn8nac env auth set default --api-key-stdin. That command resolves the environment throughensureV4WorkspaceConfig(), so it fails withUnknown workspace environment: defaultfor a.env-derived environment, which persists nothing.Add the
.envcase to that message. Detect it fromresolvedEnvironment.environmentId === 'env-file'or fromapiKeySource, and tell the user to setN8N_API_KEYin the workspace.env.🤖 Prompt for AI Agents