fix(agiloft): repoint the block at the alrest surface and fix EWLogin - #6562
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
️✅ There are no secrets present in this pull request anymore.If these secrets were true positive and are still valid, we highly recommend you to revoke them. 🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request. |
PR SummaryHigh Risk Overview Record create/read/update/delete/search move to Adds List Tables, Upsert, Natural Language Search, Async Status, and a working Saved Search. Field-projected reads go through search to avoid ~184KB full records; search/select results are capped with a Reviewed by Cursor Bugbot for commit 0aba13d. Configure here. |
Greptile SummaryThe PR repairs Agiloft authentication and redirects compatible record operations to the token-authenticated alrest API while retaining inline credentials for legacy EW-only operations.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; both previously reported projected-read identity issues are fixed by numeric input validation and canonical numeric result matching.
|
| Filename | Overview |
|---|---|
| apps/sim/app/api/tools/agiloft/read_record/route.ts | Projected reads now reject non-numeric IDs, query through alrest search, and select results by numeric ID equivalence. |
| apps/sim/tools/agiloft/utils.server.ts | Centralizes pinned-IP Agiloft login, alrest envelope parsing, legacy request execution, and logout behavior. |
| apps/sim/tools/agiloft/utils.ts | Adds URL builders, optional-input normalization, error extraction, and shared Agiloft response utilities. |
| apps/sim/lib/api/contracts/tools/agiloft.ts | Updates Agiloft request and response contracts for nullable optional inputs and newly supported operations. |
| apps/sim/blocks/blocks/agiloft.ts | Repoints the native block at the updated Agiloft tool catalog and operation schemas. |
| apps/sim/app/api/tools/agiloft/create_record/route.test.ts | Adds broad coverage for login parameters, alrest envelopes, projections, result ceilings, and projected-read identity safeguards. |
Sequence Diagram
sequenceDiagram
participant Workflow
participant Sim as Agiloft Tool Route
participant Login as EWLogin
participant Alrest as alrest API
participant Legacy as EW Legacy API
Workflow->>Sim: Invoke Agiloft operation
alt alrest-compatible operation
Sim->>Login: POST form credentials and required context
Login-->>Sim: Token and authentication scheme
Sim->>Alrest: Request with authorization token
Alrest-->>Sim: success/result or success:false/errors
Sim-->>Workflow: Normalized tool result
else EW-only operation
Sim->>Legacy: Request with inline credentials
Legacy-->>Sim: EWREST or operation-specific response
Sim-->>Workflow: Parsed tool result
end
Reviews (7): Last reviewed commit: "fix(agiloft): stop retrying refusals, an..." | Re-trigger Greptile
a6f0e38 to
88935c0
Compare
|
@cursor review |
|
@cursor review |
|
@cursor review |
2a60bca to
852b01c
Compare
|
@cursor review |
…tation
The native Agiloft block could not authenticate against any instance. A
customer reported it; production traces for their workspace confirm every
failure mode verbatim. Fixing that exposed a second, larger problem, and a
per-endpoint audit against the full published documentation found the rest.
Authentication
- EWLogin sent only $KB/$login/$password as query parameters. A live instance
answers `400 EWWrongDataException ... One has to specify $table, $KB, $lang
parameters`. $table is required even though only $KB/$login/$password/$lang
are documented. Parameters now travel in a form-encoded body, which the docs
permit and which keeps the password out of URLs and access logs.
- The authentication scheme is read from the login response and trimmed;
Agiloft returns it as "Bearer " with a trailing space.
- EWLogout was missing $lang.
Surfaces
- Record create, read, update, search and saved-search now use the endpoints
that accept the token EWLogin issues; the legacy operations authenticate from
inline credentials, which is what that surface expects. Nothing sends both
forms at once — the documented 400 for doing so is what the original report
had run into.
- EWSelect passes credentials in a POST body, one of the five operations
documented to support it.
- Attachment retrieval uses the documented EWRetrieve endpoint, with
filePosition rather than position, and no longer needs a login/logout pair.
Defects found in the audit
- remove_attachment reported zero on every call: its body is the EWREST
assignment form but the route ran JSON.parse then Number(), yielding NaN.
- The EWREST parser could not read EWActionButton's documented response, which
puts both assignments on one line.
- EWLock treated any 200 as success, including the documented
{error, error_description} envelope, and invented an 'UNKNOWN' status.
- EWTable discarded the linked-field details, required flag and text field type
it had asked for, making includeLinkedInfo inert.
- select_records had no result ceiling at all; both it and search now cap and
report a truncated flag rather than reporting a capped length as a total.
- Optional string inputs rejected null, so a blank Page field failed validation
before any request was made.
- Upsert treated the documented 202 async acknowledgement as a missing-ID
failure, and returned no callback ID for the caller to poll.
- Every response contract required an output that the 401 and 500 paths never
return.
Coverage added
- Table and field discovery (EWTable), upsert (EWUpsert), async status
(EWAsyncStatus), natural language search (EWNLPSearch), action buttons
(EWActionButton), the REPLACE_WITH_ANOTHER delete rule with its substitute
records, $async on upsert, and <fieldName>$overwrite on attach.
- Reads with a named field list go through the search projection; an unfiltered
contract record runs to roughly 184KB and swamps downstream agent context.
- Errors are readable: Agiloft wraps failures in HTML around a typed exception
and an internal task id, and the JSON endpoints now request real status codes
rather than a 200 the caller has to interpret.
Not implemented: $searchSQL and $operationHints=NOLOCK are EWRead/EWUpdate
parameters and those operations do not run on that surface here; EWQuestion,
EWHotlinks, EWOData, EWBroadcast and webhook registration have no documentation
beyond their names.
Verified against the published documentation, not against a live instance.
check:canvas-sentences failed: the nlp_search card resolved to nothing on an untouched canvas, so it painted empty. Its only basic-mode field was the long-input query, and the field list is advanced, so every segment dropped. The sentence now leads with the knowledge base, matching the shape List Tables already uses — both operations are knowledge-base scoped rather than table-scoped, so it also reads more accurately.
8734173 to
be5d283
Compare
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
1 issue from previous review remains unresolved.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit be5d283. Configure here.
…operations return Five findings from review that had gone unanswered. An Agiloft refusal was surfacing as HTTP 500. readAlrestJson throws when the envelope reports success:false, the route catch mapped that to 500, and the tool runner retries 500s — so a create the server had already rejected could be retried and duplicate the record. Refusals now return a settled failure with the message intact; genuine faults still 500. list_tables could not run in its primary mode. EWTable is knowledge-base scoped, but some instances reject EWLogin without a $table, so whole-knowledge-base discovery failed at login with nothing to fall back to. It now says what the caller can do about it rather than surfacing the raw login error. Upsert corrupted structured values. Every field went through String(), so a multi-value field collapsed into one joined string instead of the documented repeated key/value pairs, and an object silently wrote "[object Object]" into the record. Arrays now encode as repeated pairs and objects are refused, since Agiloft documents no encoding for them. Two outputs were invisible in the editor. `records` was conditioned on search_records alone, so natural language search results could not be chained, and `callbackId` on run_action_button alone, so a queued upsert's callback could not be wired into Async Status even though both values exist at runtime.
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 0aba13d. Configure here.
Transcribed Agiloft REST docs committed by accident in #6562 alongside the alrest repointing. Nothing imports or links it, it sits in a dot-directory at the repo root rather than anywhere docs live, and the integration it informed has shipped. Contents are the vendor's own public examples — placeholder credentials and localhost hosts only, so nothing sensitive was exposed while it was public.

Summary
Customer report: the native Agiloft block cannot authenticate against any instance. Production traces for their workspace confirm every failure mode verbatim, so this is fixed against real evidence rather than inference.
$KB/$login/$passwordas query params; the live server answers400 EWWrongDataException ... One has to specify $table, $KB, $lang parameters.$tableis required even though only$KB/$login/$password/$langare documented. Parameters now go in a form-encoded body — Agiloft's docs allow it, and it keeps the password out of URLs and access logs./ewws/EW*authenticates from inline$login/$passwordand rejects a bearer token;/ewws/alrest/{KB}accepts it. Create, read, update, delete, search, and attachment retrieval now go through alrest.success: falseon HTTP 200. alrest reports failures with a 200 and{"success": false, "errors":[...]}.readAlrestJsonis now the only sanctioned reader; checkingresponse.okalone turned refusals into successful empty results."authentication_scheme": "Bearer ". It's read from the response and trimmed rather than hardcoded or concatenated blind.nulland failed validation withexpected string, received nullbefore any HTTP call. Optional string params now accept null.fieldarray.Operations with no documented alrest equivalent (select, attachment info/attach/remove, lock, choice-line-id, action button) stay on
/ewws/EW*but now authenticate inline instead of sending a token that surface rejects.Type of Change
Testing
39 unit tests. Each fix was reverted once to confirm its assertions go red.
type-check,lint,tool-metadata:check,integration-catalog:check,check:api-validationall pass.Evidence base: production trace spans for the reporting workspace contain both the verbatim login refusal and a working customer-built tool using the alrest recipe, which is what the alrest paths and envelope handling are modelled on.
Not verified against a live instance. The EW*-only operations listed above are the weakest part — inline-credential auth there is documented but untested, and their alrest equivalents are unknown. Worth a smoke test against a real KB before relying on them.
Checklist