Repository navigation
Conversation
…variables pipeline [PLT-104204] (#626) * feat(cases): add getVariables to CaseInstances [PLT-104204] Adds getVariables (service-level + bound method) to CaseInstances, reusing the wire-identical PIMS instances variables endpoint. Shared BPMN variable parsing/enrichment extracted from ProcessInstancesService into src/services/maestro/instance-variables.ts (insights.ts precedent); shared types moved to instance-variables.types.ts with ProcessInstance*/CaseInstance* aliases kept for API compatibility. Also fixes pre-existing double telemetry (GetVariables no longer fires GetBpmn) and hoists parsing regexes to module level. Co-Authored-By: Claude Fable 5 <[email protected]> * fix(cases): address review feedback [PLT-104204] - Replace any with unknown in shared instance-variables types - Inline {@link} in getVariables @returns; drop misleading optional chaining from the JSDoc example Co-Authored-By: Claude Fable 5 <[email protected]> * docs(cases): correct bound getVariables @returns wording [PLT-104204] Co-Authored-By: Claude Fable 5 <[email protected]> * docs(cases): correct getVariables OAuth scope to PIMS OR.Execution.Read [PLT-104204] PIMS alone fails the folder-permission check on the variables endpoint (verified manually); PIMS + OR.Execution.Read is the combination proven working in E2E and stated in the ticket. Applies to both ProcessInstances and CaseInstances rows since they share the endpoint. Co-Authored-By: Claude Fable 5 <[email protected]> * fix(maestro): handle any BPMN attribute order when resolving variable source [PLT-104204] The element-name regex required id to precede name; XML does not guarantee attribute ordering, so name-first elements silently lost their human-readable source. Extract attributes independently, mirroring parseBpmnVariables. Adds a reverse-order regression test. Co-Authored-By: Claude Fable 5 <[email protected]> * test(cases): drop duplicated BPMN-failure test from getVariables suite [PLT-104204] Shared-helper degradation behavior is covered in the process-instances suite; the case-side suite keeps its own wiring, enrichment, attribute-order, parentElementId, and error tests — matching how Cases/MaestroProcesses test shared insights methods per service. Co-Authored-By: Claude Fable 5 <[email protected]> * fix(maestro): fetch BPMN and variables in parallel in getVariables [PLT-104204] The two calls are independent; Promise.allSettled preserves the existing failure contract — BPMN stays best-effort (warn + unenriched globals) while a variables failure propagates to the caller. Requested in PR review. Co-Authored-By: Claude Fable 5 <[email protected]> * refactor(maestro): replace PaginationServiceAccess with AuthenticatedGet [PLT-104204] Neither endpoint paginates — the accessor was only a bridge to BaseService's protected get() from the module-level shared helper. A purpose-named AuthenticatedGet capability declares exactly what the helper needs; each service passes an arrow closing over its this.get(). Co-Authored-By: Claude Fable 5 <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]>
* ci(publish): attach packed sdk tarball to GitHub release Pack the SDK in the same publish run (so the tarball matches the npm artifact bit-for-bit, telemetry version included) and attach it to the GitHub release for the version tag — creating the release if it doesn't exist yet. Gives air-gapped consumers a downloadable install artifact instead of only the auto-generated source archives. Co-Authored-By: Claude Fable 5 <[email protected]> * fix: address convention review comments Pin gh release create to the built commit via --target GITHUB_SHA and retry the attach step (it is the only fallible step after npm publish; a full re-run would fail on the already-published version). Co-Authored-By: Claude Fable 5 <[email protected]> * ci(publish): attach air-gapped bundle to GitHub release Every SDK publish now also builds and attaches a zip containing the exact published tarballs for @uipath/uipath-typescript (the version just published) and @uipath/coded-action-app (latest) plus their full transitive dependency closure, resolved via lockfile walk — nothing hand-listed. Offline install recipe (npm cache add + npm install --offline) verified against an unreachable registry. Co-Authored-By: Claude Fable 5 <[email protected]> * refactor: simplify airgap bundle script Same behavior, ~40% smaller: drop redundant guards (execFileSync already fails loudly; the manifest wipe-guard subsumes the path checks), inline the single-use functions, and tighten the README. Co-Authored-By: Claude Fable 5 <[email protected]> * ci: adopt UiPath/cli export-airgapped pattern for the SDK bundle Move the bundle out of publish-sdk into a dedicated workflow mirroring UiPath/cli's export-airgapped.yml: build -> verify -> attach. The verify job publishes every bundle tarball into a throwaway no-uplink Verdaccio and installs both SDKs from it alone, so an incomplete bundle can never reach a release. Triggered by release publication (covers manually created releases) and dispatched explicitly from publish.yml, whose GITHUB_TOKEN-created releases cannot fire the release event. Co-Authored-By: Claude Fable 5 <[email protected]> * fix: address review comments Skip the retry sleep after the final attach attempt and fail loudly if a root package is missing from the resolved closure. Co-Authored-By: Claude Fable 5 <[email protected]> * ci: attach assets on release publication, leave publish.yml untouched Releases stay human-created (draft notes published manually) — publishing the draft fires this workflow, which attaches both the registry-fetched SDK tarball and the verified bundle ZIP. Reverts all publish.yml changes (no release creation, no dispatch, no extra permissions) and gates the attach job behind the production environment per review feedback. Co-Authored-By: Claude Fable 5 <[email protected]> * ci: make airgap bundle workflow release-triggered only Publishing the draft release is the human approval, so the environment gate and the manual dispatch path are removed. The workflow publishes nothing to any registry (verify's npm publish targets a throwaway localhost Verdaccio); its only side effect is attaching assets to the release that fired it. Backfill for older releases = run the bundle script locally + gh release upload. Co-Authored-By: Claude Fable 5 <[email protected]> * ci: attach only the bundle zip, matching the cli approach The standalone SDK tarball was a carryover from this PR's first iteration — it is not independently installable offline and the same file ships inside the bundle. One asset, like UiPath/cli. Co-Authored-By: Claude Fable 5 <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]>
* chore: bump version to 1.5.6 Co-Authored-By: Claude Fable 5 <[email protected]> * chore(release-metadata): regenerate for 1.5.6 * chore: bump version to 1.6.0 1.5.6 -> 1.6.0: PR #619 renamed public input/response fields on the Data Fabric entity schema APIs (fieldName -> name, isInsightsEnabled -> isAnalyticsEnabled), which is a breaking change and warrants a minor. Co-Authored-By: Claude Fable 5 <[email protected]> * chore(release-metadata): regenerate for 1.6.0 --------- Co-authored-by: Claude Fable 5 <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…PLT-106037] (#614) * feat(functions): add Functions service for invoking coded functions [PLT-106037] Adds a modular `@uipath/uipath-typescript/functions` service that discovers and invokes JS/Python coded functions, masking the underlying process + HTTP trigger plumbing. - getAll(options?): folder-scoped, paginated listing over /odata/HttpTriggers - invoke(name, input?, options?): resolves the function by name, resolves the folder key, and calls the function's HTTP trigger; returns typed output - bound invoke() on each getAll item Folder context accepted as folderId / folderKey / folderPath (or SDK-init folder context). Verified end-to-end against a live tenant. Co-Authored-By: Claude Fable 5 <[email protected]> * feat(functions): long-running invoke support and parent-job attribution [PLT-106037] - invoke() now follows the gateway's 303 status long-poll chain for functions exceeding the ~25s response window: explicit redirect handling, fresh auth token per poll leg, bounded by a new maxWaitSeconds option (default 300) with a clear timeout error. Browsers fall back to the engine's automatic redirect handling (manual redirects are not readable there). - New jobKey option on invoke: sent as X-UIPATH-JobKey so the run is recorded with the parent job's key (parentJobKey) and inherits its context and licensing transaction. Applied to the invocation leg only. - ApiClient: RequestSpec.redirect passthrough and a raw response type so the invoke leg can observe the 303 chain. Co-Authored-By: Claude Fable 5 <[email protected]> * refactor(functions): single invoke path, package filtering, better lookup errors [PLT-106037] Coded functions over HTTP are request/response only, so the long-running handling is removed: no platform branch, no manual 303 loop, no job polling. invoke() issues one request and returns the output, letting the engine follow any redirect. Drops the maxWaitSeconds option. Also: - filter on processName / processSlug now maps to the Release navigation path, so functions can be narrowed to one package server-side - a name lookup miss lists the folder's function names, since the usual cause is passing a package name - ApiClient no longer sends Content-Type on GET/HEAD, which Orchestrator rejects for GET function invocations Co-Authored-By: Claude <[email protected]> * refactor(functions): remove dead code from the Functions PR [PLT-106037] Drops machinery left behind by the abandoned 303 long-poll invoke approach and tightens the surface the PR adds, so the diff reflects only what the feature needs. Shared core (reverts unused additions to the HTTP layer): - RESPONSE_TYPES.RAW, the 'raw' member of ResponseType, and the RAW passthrough branch in ApiClient — nothing ever set responseType 'raw'. The platform long-polls the job server-side and returns the output as the response body, so no caller drives a redirect chain. - RequestSpec.redirect and its `redirect: options.redirect` fetch passthrough — no call site ever set it. Functions service: - release.id in RawFunctionTrigger: declared but never read, contradicting the type's own "only the fields consumed" contract. - fn.method.toUpperCase() at the invoke call site: BaseService.request() already uppercases the verb. - Private helpers took `options?` and defended with `options ?? {}` / `options?.x` while their only call site always passes a defined object; narrowed to a required FolderScopedOptions. - The "and N more" suffix on the name-lookup error could only ever render "and 1 more" ($top caps the response one row past the limit), so it now says "and more". - resourceType label 'Function.getByName' named a method the service does not expose; now 'Functions.invoke', matching the convention used elsewhere. - The subpath barrel exported the class under both Functions and FunctionService; only the public alias is exported now, matching Notifications and Governance. The unit test imports the class from the implementation file instead. Docs: - Every FunctionServiceModel @example called methods on `fns`, a variable no example declares (the Usage block declares `functions`). Examples now use `functions` throughout, with the getAll result renamed to `deployed` where it would otherwise shadow it. - The module @example used a literal folderId; now the <folderId> placeholder. Tests: - Deleted functions.browser.test.ts. Its only distinguishing assertion was `expect.not.objectContaining({ redirect: 'manual' })` against the now-removed field, and the service has no platform branch, so the rest duplicated functions.test.ts. - Removed the unused ERROR_FUNCTION_NOT_FOUND test constant. Also drops an unrelated "AI App Builders" mkdocs nav section that leaked into this branch; it points at pages that live on the docs/ai-app-builders branch and would have published five dead nav entries. Co-Authored-By: Claude Opus 4.8 <[email protected]> * refactor(functions): test hygiene, mock types and doc comments [PLT-106037] - functions.test.ts called vi.unstubAllGlobals() in afterEach while stubbing no globals at all — the repo's only unpaired instance (jobs and conversational-agent each pair one unstub with 4-8 stubs). - RawFunctionTrigger.folderName's "(null on list responses)" qualifier could not discriminate anything: the service only ever reads the HttpTriggers collection, so every response it sees is a list response. - Dropped an orphaned {@link} line TypeDoc would render as stray text. - createMockRawFunctionTrigger typed as Record<string, unknown> instead of any. - Added the missing afterEach teardown to the model test. - FunctionMap's comment claimed it mapped responses; it is only used by transformOptions for OData query rewriting. Co-Authored-By: Claude <[email protected]> * refactor(functions): address review feedback on docs and types [PLT-106037] - Drop folderName: HttpTriggers is folder-scoped (400s without a folder header), so OrganizationUnitFullyQualifiedName is always null — confirmed on the list query, with $select, and on HttpTriggers({id}). The mock asserted a value the API never returns. - Remove the execution-limit note from invoke(); the platform has not settled on a duration yet. - Bound-method guards throw ValidationError instead of a generic Error. - jobKey doc is one line and no longer names the internal header. - Note that inputArguments carries sample values, not a schema. - Link the OR.Default scope docs. Co-Authored-By: Claude <[email protected]> * refactor(functions): wrap invoke identifier in a FunctionRef object [PLT-106037] Take a FunctionRef ({ name }) instead of a bare name string so the identifier can be extended (e.g. to accept id) without breaking the signature. Generated with Claude Code Co-Authored-By: Claude <[email protected]> * refactor(functions): drop `any` from function test types [PLT-106037] - Type createMockTransformedFunctionCollection's return as NonPaginatedResponse<FunctionGetResponse> (the base shape callers spread pagination fields onto). - Type mockApiClient as ReturnType<typeof createMockApiClient>. Generated with Claude Code Co-Authored-By: Claude <[email protected]> * chore(functions): wire CI secrets and address convention feedback [PLT-106037] CI: - Add UIPATH_FUNCTIONS_TEST_FOLDER_ID(_DEV) and UIPATH_FUNCTIONS_TEST_FUNCTION_NAME(_DEV) to the Set/Create Integration Test Configuration steps so tests/.env.integration exposes FUNCTIONS_TEST_FOLDER_ID / FUNCTIONS_TEST_FUNCTION_NAME. Without this, the functions integration test's beforeAll throws in CI. The corresponding secrets and a deployed coded function must be provisioned separately. Convention: - Drop functions.types / functions.models from the orchestrator top-level barrel. New services must be modularized only — @uipath/uipath-typescript/functions remains the sole public surface. - Replace \`as any\` on the PaginationHelpers.getAll return with the typed \`as Promise<...>\` pattern used by agents.ts. Generated with Claude Code Co-Authored-By: Claude <[email protected]> * fix(api-client): preserve caller-set Content-Type on bodyless requests [PLT-106037] Previously the default json Content-Type was always added by getDefaultHeaders() and then unconditionally deleted for GET / HEAD / FormData. The delete also stripped any Content-Type coming from clientConfig.headers, so a caller that configured a custom Content-Type lost it on any bodyless call. Only per-request options.headers survived because they were spread after the delete. Flip the logic: only inject the default Content-Type when the request has a JSON body. No delete anywhere. clientConfig.headers and options.headers overrides now both survive regardless of the request method. Add ApiClient unit tests covering the new precedence: - GET omits Content-Type by default - POST with a JSON body sends application/json - POST with a FormData body omits Content-Type (browser sets boundary) - clientConfig.headers['Content-Type'] survives on GET - options.headers['Content-Type'] overrides the default on GET - clientConfig.headers['Content-Type'] overrides the default on POST Generated with Claude Code Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]>
#608) The SDK appended acr_values (tenant:/tenantName:) to the authorize URL, which routes auth directly to the org's SAML IdP. That blocked Basic Auth users in mixed-auth orgs ("account not found"). setMultiLogin() existed only to skip acr_values as a workaround. Alpha testing confirms Identity now resolves the target org from client_id alone, so acr_values is never needed and all auth types work without it. Make no-acr the permanent default and remove the now-redundant setMultiLogin() (it was @internal and became a no-op). BREAKING CHANGE: removes the @internal setMultiLogin() from UiPath and IUiPath. No-acr behavior is now automatic, so callers should delete setMultiLogin() calls. Generated with Claude Code Co-authored-by: Claude <[email protected]>
…08-03) (#634) Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Adds a github_packages_only boolean input to the Publish SDK package workflow. When checked, the npm publish step is skipped in all three publish jobs (ts-sdk, coded-action-app-sdk, telemetry), and the deploy-docs and trigger-cf-worker jobs are skipped, so prerelease builds can be published to GitHub Packages without touching the public npm registry. Co-authored-by: Claude Fable 5 <[email protected]>
…version (#638) * ci: tag GitHub Packages-only publishes as dev and require prerelease version Addresses review comments from #628 that were missed before merge: - publish with --tag dev when github_packages_only is true so prerelease builds don't take over the latest tag in GitHub Packages - fail the workflow when github_packages_only is true but package.json does not contain a prerelease version Co-Authored-By: Claude Fable 5 <[email protected]> * ci: validate version in both publish modes and pass inputs via env Review follow-ups: block publishing a prerelease version to public npm when github_packages_only is false (mirror of the original guard), and pass workflow inputs to run scripts via env vars per Actions hardening guidance, matching the existing Generate Summary pattern. Co-Authored-By: Claude Fable 5 <[email protected]> * ci: scope version guard to github_packages_only mode only Drop the inverse guard (blocking prerelease versions from npm publishes) to keep this PR limited to the review comments from #628. Co-Authored-By: Claude Fable 5 <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]>
…640) The production environment requires reviewer approval on every run, which blocks github_packages_only prerelease publishes behind an admin gate even though they never touch the public npm registry. Route runs with github_packages_only=true to a separate github-packages-dev environment (no required reviewers) so prereleases publish without approval, while official npm releases keep the production gate. Co-authored-by: Claude Fable 5 <[email protected]>
* docs(samples): add preview GIFs for the five coded action apps Converted from each app's README demo video (1600px wide, 15fps, 256-color palette, static loading stretches collapsed) and wired into the Template Gallery, which previously showed generated posters for these apps. Co-Authored-By: Claude Fable 5 <[email protected]> * docs(samples): add Preview sections to action app READMEs Satisfies the check-samples readme-preview rule: each README now embeds its screenshots/preview.gif under a Preview heading, in addition to the original demo video at the end. Co-Authored-By: Claude Fable 5 <[email protected]> * docs(samples): drop demo video links superseded by preview GIFs Co-Authored-By: Claude Fable 5 <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]>
…#630) * docs(samples): refresh data-fabric-app preview GIF in HD Co-Authored-By: Claude Fable 5 <[email protected]> * docs(samples): refresh data-fabric-app-angular preview GIF in HD Co-Authored-By: Claude Fable 5 <[email protected]> * docs(samples): refresh process-app-v1 preview GIF in HD Co-Authored-By: Claude Fable 5 <[email protected]> * docs(samples): refresh process-app-v0 preview GIF in HD Co-Authored-By: Claude Fable 5 <[email protected]> * fix(samples): add missing Traces.Api scope and gitignore uipath.json - process-app-v0/v1 call getExecutionHistory(), which requires the Traces.Api scope per docs/oauth-scopes.md — without it the execution history call fails with 401. Add it to uipath.json.example and READMEs. - conversational-agent-app, process-app-v0 and process-app-v1 did not gitignore uipath.json, risking accidental commits of real org config. Co-Authored-By: Claude Fable 5 <[email protected]> * docs(samples): refresh document-validation-app preview GIF in HD Co-Authored-By: Claude Fable 5 <[email protected]> * docs(samples): refresh conversational-agent-app preview GIF in HD Co-Authored-By: Claude Fable 5 <[email protected]> * revert(samples): allow committing uipath.json in samples Client IDs for non-confidential PKCE apps are not secrets; keeping uipath.json pushable per team decision. Co-Authored-By: Claude Fable 5 <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]>
…OL-3062] (#612) The DataFabricRoleService and DataFabricDirectoryService classes were exported from the /entities subpath, but their option/response types and enums (e.g. DataFabricDirectoryEntityTypeInput) were not re-exported, forcing consumers like the CLI to derive them via Parameters<> from method signatures. Re-export roles/directory types and ServiceModel interfaces through the entities subpath and main barrels. All symbols keep their @internal JSDoc tags, so the generated docs are unchanged. Follow-up to review comments on UiPath/cli#2891. Co-authored-by: Claude Fable 5 <[email protected]>
…k data/tags/metadata (#632) Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
…652) The generic SaveTaskData endpoint rejects Form and App tasks (backend AllowedTaskTypes). Route saveData by task type: Form and App go to their own save endpoints, everything else keeps the generic one. Bound task.saveData() auto-injects the task's own type. Follow-up to #632. Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
* chore: change to centralized managed GitHub pool 11 workflow file(s) modified, 31 action(s) pinned Runners migrated: ubuntu-latest ubuntu-24.04 ubuntu-22.04 ubuntu-24.04-arm ubuntu-22.04-arm ubuntu-slim ubuntu-18.04 ubuntu-20.04 windows-latest * fix(ci): raise Node heap for builds on managed runners The uipath-ubuntu-* runners have less RAM than ubuntu-latest, so Node auto-sizes its heap to ~2 GB and the rollup build aborts with an out-of-memory error (exit 134). Co-Authored-By: Claude Opus 5 <[email protected]> --------- Co-authored-by: Claude Opus 5 <[email protected]>
* feat: make client side tools public and available with examples * chore: remove internal flag from executingToolCall event
#629) * feat(identity): add Identity Settings service (GET + PUT api/Setting) Adds a new modular `IdentitySettings` service exposing the two Identity Setting endpoints available to external apps: - `getAll()` — GET api/Setting, bulk read of the organization's settings (scope `PM.Setting` or `PM.Setting.Read`) - `updateSettings()` — PUT api/Setting, bulk create/update of settings (scope `PM.Setting` or `PM.Setting.Write`) Both accept an optional `partitionGlobalId`; when omitted the API falls back to the partition the calling token is scoped to. The Identity API routes at the organization level (no tenant segment), so `IDENTITY_API_BASE` uses the documented `../` URL-normalization pattern to collapse the tenant segment ApiClient inserts — mirroring NOTIFICATION_BASE. Exposed via the `@uipath/uipath-typescript/identity-settings` subpath, with unit tests, integration tests, JSDoc on the ServiceModel, and OAuth scope + mkdocs nav entries. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * refactor(identity): rename module to Identity and align with real API shape Renames the service from `IdentitySettings` to `Identity`, exposed via the `@uipath/uipath-typescript/identity` subpath: - `IdentitySettingService` -> `IdentityService`, exported as `Identity` - files moved to identity.ts / identity.types.ts / identity.models.ts, mirroring the single-service layout used by Governance - `getAll()` -> `getSettings()`, so the method still names what it returns now that the service is named after the domain rather than the resource Also corrects the request and response shapes against a captured live response: - adds the `key` query param (repeated per key) and makes `keys` a required argument — the endpoint is a bulk get-by-key - adds the `userId` scope param; settings are per-user within a partition - `IdentitySetting` now carries the fields the API actually returns: `id`, `key`, `value`, `partitionGlobalId`, `userId` - `value` is always a string (JSON-valued settings arrive as a JSON string); keys with nothing stored are omitted from the response rather than returned with an empty value - splits the write shape into `IdentitySettingUpsert` (`key` + `value` only) The integration suite now snapshots a configured existing key, overwrites it, and restores the snapshot, replacing the previous throwaway-key approach. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * fix(identity): correct updateSettings request and response shape Validated against the first-party Identity settings client. Two real defects in the write path: - the PUT body is an object, not a bare array: `{ settings, partitionGlobalId, userId? }`. Scope travels in the body on writes, in the query string on reads. - the PUT responds with the stored rows, so `updateSettings` now returns `IdentitySetting[]` (including each generated `id`) instead of an `OperationResponse` echoing the submitted payload. `partitionGlobalId` is now a required argument on `updateSettings` — the write payload types it as required, and unlike a read the partition cannot be inferred. Callers that lack it can read any setting first; every `IdentitySetting` carries its own `partitionGlobalId`. The read path needed no change: `IdentitySetting` already matched the client's `ISetting` field-for-field. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * feat(identity): restrict setting keys to the IdentitySettingKey enum Adds `IdentitySettingKey` and types both operations against it, so only the supported keys can be read or written: UserLanguage, UserLanguageDate, UserTheme, UserAccessibility, UserAlert, UserCaseAppOrder, UserCasePinnedInstancesByTenant, UserCaseInstancesTableFiltersByTenant `getSettings(keys)` and `IdentitySettingUpsert.key` now take the enum rather than a raw string, and `IdentitySetting.key` is typed as the enum so callers can compare response keys without casting. A unit test pins the members and their wire values, since adding or renaming one is a public API change. The integration suite no longer needs a configured key: it reads every supported key and round-trips whichever one has a stored value, so the IDENTITY_TEST_SETTING_KEY env var is removed again. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * feat(identity): make all settings operations user-scoped The settings store distinguishes organization-scoped from user-scoped rows by whether `userId` is present in the request — omitting it targets the partition-wide row rather than falling back to the calling user. The SDK now only exposes the user-scoped path: - `userId` is a required argument on both operations and is always sent - on writes it goes in the body alongside `settings` and `partitionGlobalId` - on reads it goes in the query string - both throw ValidationError when it is missing, so no call can silently become organization-scoped Signatures are now `getSettings(keys, userId, options?)` and `updateSettings(settings, userId, partitionGlobalId)`, dropping the options bag from the write path since `userId` was its only member. This also settles the response typing: `IdentitySetting.userId` stays a non-null string because only user-scoped rows are ever read. Corrects JSDoc that described omitted `userId` as defaulting to the calling user, and a stale module comment calling the settings organization-level. Integration tests take the user GUID from IDENTITY_TEST_USER_ID; the SDK cannot derive it from a PAT. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * refactor(identity): expose the organization GUID as organizationId The Identity API calls the organization a "partition", but every other service in this package names that GUID `organizationId` (see the traces types, where it is documented as the organization/account GUID). `partitionGlobalId` was leaking an Identity-internal abstraction into the public surface. The wire contract is unchanged — `partitionGlobalId` is still what goes over HTTP — but it is now confined to the request boundary: - adds `IdentitySettingMap` and applies `transformData` to both read and write responses, renaming the field on the way out - adds `RawIdentitySetting` in identity.internal-types.ts for the wire shape, not re-exported from the barrel - `IdentitySetting.organizationId` replaces `partitionGlobalId`, and the option/argument are renamed to match - mock factories now return the raw wire shape, with tests asserting the renamed field is present and the wire field is gone on both operations `IdentitySettingMap` is deliberately not exported from the models barrel, matching AssetMap/QueueMap which are not part of the public API either. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * test(identity): close coverage gaps and import via the subpath barrel Line coverage was already 100%, but several API behaviours were unexercised: - the unit suite imported the service from its deep path, so the subpath barrel consumers actually use was never loaded. It now imports `Identity` and `IdentitySettingKey` from `src/services/identity`, with an assertion that both survive as runtime values — the failure mode an `export type *` regression would cause. - adds a read that passes all eight enum members in one request, so every key's plumbing is covered rather than the three that happened to be used - adds empty-response cases for both operations - adds a multi-setting write asserting each submitted row comes back, and the same bulk path to the integration suite, writing existing values back so the call is a no-op against the shared environment - fixes a misleading assertion in the bulk write test, where the mocked response carried fewer rows than the batch and the length was hardcoded to the mock factory's size rather than the batch's Also confirms the remaining field names already match the rest of the package: `userId: string` as in the notification and conversational-agent user types, and `id: number` as in jobs/buckets/queues/assets. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * ci(identity): wire IDENTITY_TEST_USER_ID and drop an unused test constant The Identity integration suite throws when IDENTITY_TEST_USER_ID is absent, so the coverage job needs the variable plumbed through like every other integration secret. Adds it to the config step and the generated tests/.env.integration, reading UIPATH_IDENTITY_TEST_USER_ID_DEV with a fallback to UIPATH_IDENTITY_TEST_USER_ID. The secret itself still has to be created for the job to go green — until then the suite reports honestly that it is not being exercised rather than passing without running. Also removes ERROR_SETTING_NOT_FOUND, which was defined but never referenced (flagged in review). Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * test(identity): default the integration user GUID instead of requiring config The user GUID is an identifier, not a credential, so the Identity suite now falls back to the dev test user rather than throwing when IDENTITY_TEST_USER_ID is unset. The env var still takes precedence, since settings are scoped to (organization, user) and a GUID from one organization returns no rows in another. The "nothing stored" guard now names the user and points at the likely cause, so a wrong-organization run reports that rather than looking like a user who simply has no settings. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * test(identity): skip the integration suite until the CI app is authorized The coverage job's only failure is the Identity suite: the first getSettings call returns 403 Forbidden, so the request is rejected before it reaches the resource. No user GUID or configuration value changes that — the CI external application is not authorized for identity settings. Skips the suite with the reason recorded, matching the existing precedent for the Data Fabric access tests, which are skipped until the CI app has the required scopes. The body is left intact so it runs unchanged once the `PM.Setting` scope is granted. The Data Fabric importRecordsById timeout in the previous run was flaky and passed this time, so this was the last thing keeping the job red. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * refactor(identity): singularise the options type name Renames IdentitySettingsGetOptions to IdentitySettingGetOptions. Every options type in the package uses the singular entity name (AssetGetByIdOptions, AgentGetSummaryOptions, AgentMemoryGetTimelineOptions), and every other type in this module already does too — IdentitySetting, IdentitySettingUpsert, IdentitySettingKey, IdentitySettingMap, RawIdentitySetting. This was the one outlier. Raised in review. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * Revert "test(identity): skip the integration suite until the CI app is authorized" The skip's stated reason was wrong. Three consecutive coverage runs each 403'd in a different, unrelated suite: 05:08 Identity getSettings 05:31 Data Fabric EntityService.getAll 05:58 Agent Feedback deleteCategory, submit Data Fabric passed in the third run. A 403 that roams between services on every run is environment-level authorization trouble, not a missing `PM.Setting` scope on the Identity endpoint — so Identity is in the same position as every other suite, none of which are skipped. Restores the suite with its beforeAll guard, which is what review asked for. The guard deliberately does not wrap the call in try/catch, since rules.md requires integration test API calls to let errors propagate. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * docs(identity): inline the @returns type links main added a convention while this branch was open: a `{@link}` on a standalone line after `@returns` renders as stray text in TypeDoc rather than a link, so it belongs inline in the sentence. Both Identity methods had the standalone form. Also drops an orphaned comment fragment left in test-config.ts by the rebase conflict resolution. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * test(identity): require IDENTITY_TEST_USER_ID instead of a hardcoded fallback The secret already exists in the repository, so the fallback GUID was both unnecessary and actively harmful: it pointed at a user in a different organization than the CI PAT authenticates against, and identity settings are scoped to (organization, user). That may well be the cause of the 403 this suite has been reporting — a userId outside the caller's organization is plausibly rejected rather than returned empty, which is the assumption I had been reasoning from. The suite now throws when the variable is absent, so a misconfigured environment says so instead of silently querying a foreign user. Raised in review by @Sarath1018. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * docs(identity): add the missing import to the bulk-update example The second `updateSettings` @example referenced IdentitySettingKey without opening with its import, so it was not copy-pasteable on its own. The other three example blocks already carried it. Raised in review. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * test(identity): send the organization GUID on reads Reads were relying on the API to infer the organization, which it does not do: omitting the parameter falls back to the *host* partition, not the caller's own organization, and an external application is not authorized for that — hence the 403 this suite has been reporting. Confirmed by a reviewer who ran the suite locally with both values supplied and had all 8 tests pass. - adds `UIPATH_ORGANIZATION_ID` to the integration config and plumbs it through coverage.yml from the existing secret, alongside IDENTITY_TEST_USER_ID - every read in the suite now names the organization explicitly, and beforeAll requires both values - corrects the JSDoc, which claimed the fallback was the caller's organization. That would have walked SDK consumers into the same 403, so `getSettings` examples now pass `organizationId` too This also retracts the scope request in my earlier comments: `PM.Setting` was not the problem. Raised in review by @Sarath1018. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * refactor(platform)!: rename the Identity settings service to Platform "Identity" is the internal service name, which the SDK conventions rule out for developer-facing paths and classes. Platform Management expects further surface (organization settings, licensing, tenants) to land in the same namespace, so the module is named for it. Renames across the public surface: - subpath `./identity` -> `./platform` (package.json, rollup.config.js) - `IdentityService as Identity` -> `PlatformService as Platform` - `IdentityServiceModel`, `IdentitySetting`, `IdentitySettingKey`, `IdentitySettingUpsert`, `IdentitySettingGetOptions`, `IdentitySettingMap`, `RawIdentitySetting` -> `Platform*` - `@track('Identity.*')` -> `@track('Platform.*')` - `src/{models,services}/identity/` -> `.../platform/`, files renamed to match - `docs/oauth-scopes.md` section and `mkdocs.yml` nav entry `PLATFORM_SETTING_ENDPOINTS` moves to a new endpoints/platform.ts, leaving endpoints/identity.ts to the OAuth `connect/*` endpoints it already held. `IDENTITY_BASE` / `IDENTITY_API_BASE` and the `identity_/api/Setting` URL are unchanged: they name the wire reality, not the SDK surface. Test plumbing keeps the `IDENTITY_TEST_USER_ID` env var and its `identityTestUserId` config field, which track the already-provisioned `UIPATH_IDENTITY_TEST_USER_ID` repository secret and are not developer-facing. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * refactor(platform)!: name the settings methods getUserSettings/updateUserSettings Both operations are user-scoped by construction: userId is a required argument and always sent, so neither call can act on an organization-wide row. Under the Platform namespace, where organization settings, licensing and tenants are expected to land, getSettings/updateSettings would not say which scope they act on. Renames the methods, their @track names (Platform.GetUserSettings, Platform.UpdateUserSettings), the ValidationError messages, and the oauth-scopes table. The Conversational Agent user service keeps its own getSettings/updateSettings — different service, unchanged. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * refactor(platform): transform setting rows with transformData directly transformData already accepts T | T[] and maps element-wise, so the per-item toPlatformSetting helper was redundant. Calling it on the array matches the existing idiom (see FeedbackService.getById). Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 * fix(platform): harden setting argument validation and fix the module example - Guard keys/settings with `!x?.length` so untyped JS callers passing null/undefined get a ValidationError instead of a TypeError. - Reject an explicitly empty organizationId on reads instead of dropping it. Dropping it made the request target the host partition, so the caller got an opaque 403 rather than being told what was wrong. Omitting the option entirely is still allowed. - The module @example called getUserSettings without organizationId, which would 403 for the same reason — it now passes one. Adds 6 unit tests; each was confirmed to fail with its guard reverted. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_013Q3NWsanguD7ZWnYjFSEf6 --------- Co-authored-by: Claude <[email protected]>
The release-metadata-gen workflow runs `npm run build` on the managed uipath-ubuntu-* runners introduced in #648, but was missed when that PR raised the Node heap on the other build workflows (coverage.yml, publish.yml). Node auto-sizes its heap to ~2 GB there, so the rollup build aborts with an out-of-memory error (exit 134) and the metadata is never regenerated/committed onto version-bump PRs. Add the same NODE_OPTIONS=--max-old-space-size=6144 the sibling workflows already use. Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Adds attachments.create() to upload a file, plus jobs.getAttachments() and jobs.linkAttachment() to work with a job's attachments. Refs APPS-35700 Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
* chore: bump version to 1.6.1 Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * chore(release-metadata): regenerate for 1.6.1 * fix(release-metadata): correct CaseInstances.getVariables since to 1.6.0 It shipped in 1.6.0 (#626) but was never recorded in the 1.6.0 metadata — that bump regenerated against an earlier (1.5.6) branch state before #626 landed, then only the sdkVersion string was updated. The current regen therefore stamped it 1.6.1; correct it to 1.6.0. The generator carries this value forward on future regens. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * chore(release-metadata): regenerate for 1.6.1 --------- Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* docs(functions): mark the coded Functions service as preview Marks the entire Functions (coded functions) surface as experimental, following the governance/agent-memory pattern (@experimental + a Preview warning admonition). Applied to the service-level JSDoc, both FunctionServiceModel methods (getAll, invoke), and the bound FunctionMethods.invoke. Functions is modular-only (no UiPath-class wrapper, not a TypeDoc entry point), so the service class needs no tag — same as GovernanceService. @experimental does not affect release-metadata (only @internal is excluded), so coded functions still ships as a public, documented API. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * fix(functions): export function models from the orchestrator barrel The orchestrator models barrel omitted functions, so FunctionServiceModel never reached TypeDoc's entry point (src/index.ts) and its docs page was never generated — the mkdocs nav link (added in #614) 404'd. Re-export functions.types and functions.models like the sibling orchestrator services, so the Functions API reference page renders. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * docs(functions): mark the FunctionMethods interface as preview FunctionMethods renders as its own TypeDoc page; without @experimental on the interface declaration the page showed no preview warning even though its method was tagged. Tag the interface declaration to match FunctionServiceModel (both interface and method levels). Addresses review comment on #659. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
#647) * feat(data-fabric): add havingFilter to entity record queries Post-aggregation filter (SQL HAVING) on grouped aggregate results: conditions reference declared aggregate aliases (aggregates-only server contract, DS-9077/DS-9078). Requires aggregates + groupBy - enforced client-side with an actionable ValidationError. havingFilter is registered in excludeFromPrefix so the key reaches the wire un-prefixed; without this the pagination helper would send it as $havingFilter and the server would never see it. Server-side: native (LDO) entities only, gated by the enable-having-on-query feature flag (400 otherwise). Co-Authored-By: Claude Fable 5 <[email protected]> * refactor(data-fabric): use an enum for having operators, document havingFilter Review follow-ups: enum matching the QueryFilterOperator convention (drop the redundant <> - the server normalizes !=), tests on enum members, and havingFilter added to both query methods @PARAM lists with HAVING examples. Co-Authored-By: Claude Fable 5 <[email protected]> * test(data-fabric): add havingFilter integration coverage Data-independent HAVING assertions on the fixture entity: a satisfiable threshold (cnt >= 1) must return every group and an unsatisfiable one must return none - a backend that ignores havingFilter returns every group there, which is the failing signal. Requires the enable-having-on-query tenant flag; without it the server 400s naming the flag, failing loud as requested. Co-Authored-By: Claude Fable 5 <[email protected]> * test(data-fabric): decouple having test from join fixture, jsdoc nits Group by Id (always present) instead of the join fixture field, drop the unexplained LDO acronym from the JSDoc, and use unknown over any in the integration assertion. Co-Authored-By: Claude Fable 5 <[email protected]> * test(data-fabric): use toHaveLength for the empty-groups assertion Sonar S5906: toHaveLength reports the actual array contents on failure. Co-Authored-By: Claude Fable 5 <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]>
* feat: cas add personal connections support * test: add tests for cas connections feat * feat: update per conventions * refactor: update expiresAt prop * test: update test for transform * test: remove unused import * docs: remove jsdoc * docs: update jsdoc for model returns * chore: feedback from comments * docs: update scope reqs * test: add integration tests * chore: update config for cas integration
* fix(telemetry): declare the forceFlush LogRecordExporter requires `ApplicationInsightsEventExporter implements LogRecordExporter` but never declared `forceFlush`, which that interface requires at the pinned `@opentelemetry/sdk-logs`. `npm run typecheck` fails on main today with TS2420 and TS2345 because of it. Implemented as a no-op, matching the existing `shutdown`: records are posted fire-and-forget in `sendAsCustomEvent`, so there is no queue of in-flight requests here to await. Making it flush for real would mean tracking those promises, which is a behaviour change and not this commit's business. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HwgxkTUnqbWRN3xUwr6B46 * feat(telemetry): let a consumer supply its own connection string `TelemetryClientInitOptions` had no way to name an Application Insights resource, so every consumer was pinned to the one `sed`-patched into this package at publish time. That is a gap in a package whose design is "each consumer builds its own client": a consumer could set its own `cloudRoleName`, `serviceName` and context, but not its own destination. The Coded Action App SDK telemetry doc already described this as supported — "custom connection string: passed to provider constructor" — and it is true internally, since `setupTelemetryProvider` takes it as a parameter. It was simply never exposed on the public `initialize()`. Add an optional `connectionString`, defaulting to the packaged value, so the SDK and coded-action-app are unaffected. An empty string disables telemetry rather than falling back, so a consumer whose own value is unset emits nothing instead of silently reporting to the shared resource. Requested and approved in #feat-codedapps. No version bump — that is a separate PR per the release workflow. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HwgxkTUnqbWRN3xUwr6B46 * test(telemetry): assert getLogger too in the placeholder no-op test Matches the sibling no-op tests, which all assert both. Logically redundant — `getLogger` lives on the provider — but the inconsistency was the point. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HwgxkTUnqbWRN3xUwr6B46 --------- Co-authored-by: Claude <[email protected]>
Bumps the pip group with 1 update in the /docs directory: [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions). Updates `pymdown-extensions` from 10.21.3 to 11.0.1 - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](facelessuser/pymdown-extensions@10.21.3...11.0.1) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-version: 11.0.1 dependency-type: direct:production dependency-group: pip ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
#650 bumped pymdown-extensions to 11.0.1, but mkdocs-material 9.6.18 declares pymdown-extensions~=10.2 (>=10.2,<11), so pip cannot satisfy both and every docs build dies at install with ResolutionImpossible. 9.7.0 is the first mkdocs-material release to relax that to >=10.2. Bumping to 9.7.7 keeps the 11.0.1 upgrade instead of reverting it. Co-authored-by: Claude Opus 5 <[email protected]>
…ers, updateTopicGroups) (#518) Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
* docs: update claude docs from PR review analysis (2026-08-03 to 2026-08-10) Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix: address convention review comments * docs: trim and compact PR-review convention insights - Drop the endpoint-specific RetentionAction sentinel war-story from the read-modify-write rule, keeping only its generalizable kernel - Lead the nested-payload rule with the open-map type discriminator so an agent can actually detect "user-defined" - Remove restatements and info already covered elsewhere (pipeline step 1, transform-completeness bullet, DF exception) Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * docs: drop clauses already covered elsewhere in the conventions - Remove the untracked-helper/double-telemetry note from read-modify-write (already stated as the @track delegation anti-pattern) - Cross-reference the read-path header-destructuring rule from write-body hygiene instead of re-explaining the leak Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * docs: apply write-body hygiene in the read-modify-write example Strip query/header-only fields before merging into the PUT body so the example doesn't contradict the Write request body hygiene section. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * docs: update claude docs from PR review analysis (2026-08-10 to 2026-08-17) Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <[email protected]> Co-authored-by: shreyash0502 <[email protected]>
* fix(auth): refresh access tokens ahead of expiry [APPS-37340] External apps can now be configured with a shortened access token lifetime (300-3600s). At 300s the SDK refreshes 12x more often than at the 3600s default, so a request signed in a token's final moments can be rejected server-side once network latency and clock skew are added — and the resulting 401 is not retried. Treat a token as expired 60s before its actual expiry so it is renewed before it can expire in flight. The buffer is applied only where a refresh is actually possible; validity checks and stored-token loading keep using the true expiry, so a page reload late in a token's life still restores the session instead of forcing a re-login. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> * refactor(auth): extract getExpiryMs so the expiry parse is explicit Both expiry checks built a Date unconditionally, which cloned an already-correct Date on every request and left the string handling implicit. Move it behind a named helper that branches on the type, so the accepted shapes are stated in one signature rather than implied by a constructor call in two places. Behaviour is unchanged: a Date returns its own timestamp, an ISO string parses to the same value, and an unparseable value still yields NaN and so leaves the token treated as not expired. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> * fix(auth): apply the expiry buffer on the OAuth path only [APPS-37340] Action Center and embedded hosts return their cached token until it actually expires, so a buffer on those paths cannot renew anything early. Restore those files to main and keep the buffer in TokenManager. getExpiryMs now returns the epoch for an unreadable expiry, so the token reads as expired instead of never expiring. Docs trimmed to the renewal behaviour only. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
* feat(du-validation): add validation start and result poll service * feat(du-validation): add tests and module wiring * feat(du-validation): wire document-understanding-validation entry * feat(du-validation): wire document-understanding-validation build entry * test(du-validation): address review JSDoc, types, and integration coverage * fix(du-validation): transform PascalCase API responses to camelCase * fix(du-validation): keep oauth and endpoint exports off main conflict hunks * fix(du-validation): rename operation timestamps to *Time Map createdAt and lastUpdatedAt to createdTime and lastModifiedTime after PascalCase conversion, and drop the double cast in the unit test. Co-authored-by: Bogdan Nikolov <[email protected]> * fix(du-validation): shallow-case only validation envelopes Recursive case conversion rewrote framework leaves inside result, so DocumentId was undefined at runtime while the type still required it. Convert the operation, error, and result envelopes and leave generated payloads unchanged. * refactor(du): apply Naren review on scopes and DocumentUnderstanding Rename DuValidationService to DocumentUnderstanding and drop the DuValidation public alias. Use a Document Understanding scopes heading and point the API reference at the overview. * refactor(du): rename service class to DocumentUnderstanding Drop the DuValidation and DuValidationService public names so later methods can live on the same class. * docs(oauth): use Document Understanding heading Point the framework API reference at the Document Understanding API overview so later methods can share this section. * fix(du-validation): use DocumentUnderstanding prefix for start telemetry Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * fix(du-validation): use DocumentUnderstanding prefix for result telemetry Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * fix(du-validation): cover all validation guards and add docs nav entry - Unit tests for missing tag/documentTypeId (start) and projectId/tag/documentTypeId (result) - Export validation types/models from the root barrel so TypeDoc renders DuValidationServiceModel - Add Document Understanding entry to mkdocs.yml nav Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> --------- Co-authored-by: Cursor Agent <[email protected]> Co-authored-by: Naren <[email protected]> Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
* feat(agenthub): add chat completions via LLM gateway * feat(agenthub): wire agenthub endpoints, headers, and models * feat(agenthub): wire agenthub entry * feat(agenthub): wire agenthub build entry * fix(agenthub): restore trailing newlines in src/index.ts * fix(agenthub): apply review convention fixes * test(agenthub): assert ValidationError class and add integration coverage * fix(agenthub): map snake_case chat completion wire fields Send maxTokens as max_tokens and map finish_reason to finishReason so the OpenAI-compatible gateway fields round-trip through the SDK types. Entire-Checkpoint: 70406c9e3c32 * fix(agenthub): add snake_case key transforms for chat completions Entire-Checkpoint: 70406c9e3c32 * fix(agenthub): add snakeToCamelCaseKeys and camelToSnakeCaseKeys Entire-Checkpoint: 70406c9e3c32 * chore(release-metadata): regenerate for 1.7.1 * fix(agenthub): address chat completion review comments Use enums for message roles and tool types, type the POST response as the snake_case wire shape, and split the method examples into a minimal call and one with generation parameters. Co-authored-by: Bogdan Nikolov <[email protected]> * fix(agenthub): keep chat completions internal and out of public docs - Mark createChatCompletion @internal, following the Notification service pattern - Drop root barrel export, mkdocs nav entry and OAuth scope doc (LLMGateway is an internal scope) - Revert release-metadata.json changes for already-released 1.7.1/1.7.2 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * fix(agenthub): type tool calls and usage, take model and messages positionally - createChatCompletion(model, messages, options?) replaces the request object; generation params, tools, toolChoice and signal move into the options bag, and the model is sent in the gateway header only - response now carries object, model, createdTime and usage; choice messages expose toolCalls with nullable content, mapped by hand so tool-call argument keys are never rewritten - request messages accept toolCalls and toolCallId; tool results are sent in the normalized { result, call_id } content shape - drop @experimental and the bare AgentHubService export to match the Notification internal-service pattern - integration test covers usage, transform completeness and a forced tool-call round trip Co-Authored-By: Claude Fable 5.1 <[email protected]> * revert(agenthub): drop tool-call typing and response expansion Reverting the batch of changes to keep #754 focused; the positional signature and tag cleanup are re-applied separately in the next commit. This reverts commit a56a09b. Co-Authored-By: Claude Fable 5.1 <[email protected]> * fix(agenthub): take model and messages positionally, drop experimental tag - createChatCompletion(model, messages, options?) replaces the request object; maxTokens, temperature and tools join signal in the options bag - remove the @experimental banners: the method is @internal, so it is not part of the documented surface and the preview warning has nothing to attach to Co-Authored-By: Claude Fable 5.1 <[email protected]> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Cursor Agent <[email protected]> Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]> Co-authored-by: Sarath1018 <[email protected]>
* docs: update claude docs from PR review analysis (2026-08-31 to 2026-09-07) Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix: address convention review comments on claude docs update Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * fix: clarify ref resolution ?? order and regex sharing framing Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * docs: update claude docs from PR review analysis (2026-09-07 to 2026-09-14) Co-Authored-By: Claude Sonnet 4.6 <[email protected]> * docs: update Claude docs from PR review analysis (2026-09-21 to 2026-09-28) Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <[email protected]>
…#769) The four videos are now published on the UiPath Product channel, so the embeds use those ids instead of the originals. Co-authored-by: Claude Opus 5 <[email protected]>
… [APPS-37257] (#722) * fix(core): reject a config carrying both auth methods at construction [APPS-37257] `#mergeConfigSources` elects an auth method only when the caller names exactly one of them. When the caller names a secret *and* at least one OAuth field, the election XOR is false, nothing is dropped, and the merged config carries both methods — so `isCompleteConfig`'s XOR fails and the constructor silently stores `#partialConfig` without registering internals. The caller first hears about it from an unrelated service constructor ("Invalid SDK instance"), or from `initialize()` reporting a configuration that was never "not found". The method's own comment claimed the case was "left intact for validateConfig() to reject". It was not: `validateConfig`'s only call site sits inside `#initializeWithConfig`, which runs only once `isCompleteConfig` has returned true — precisely what a both-methods config makes false. The function was unreachable dead code and is removed. - Guard the merge, after the existing drop block, so PR #675's cross-source resolution is preserved: a pure secret over injected OAuth meta tags still works. Only a caller contradicting themselves throws. - `conflictingAuthMessage` names every auth field and the layer that supplied it (constructor argument / `<meta name="uipath:...">` / env var), and states which fields to remove. It never interpolates a field value — `secret` is a bearer token and this string reaches browser consoles. - `missingConfigMessage` now describes a config that was found but is short, instead of claiming none was found. - Export `PartialUiPathConfig`, `BaseConfig` and `OAuthFields` from `/core`. The constructor's declared parameter type was unreachable from that entry point, which is what pushed callers to `as unknown as ConstructorParameters<...>[0]`. - Drop `scope` from the secret-auth JSDoc example: pasted into a coded app it inherits the other two OAuth fields from the meta tags and hits the new guard. Every input that now throws already failed — later, and somewhere else. Verified: typecheck, oxlint, 2760/2760 unit tests, build; and end to end against the built dist with the dev plugin's meta tags faked — the reporter's scenario, their explicit-undefined workaround, and `new UiPath()` with no config all still construct and register. Co-Authored-By: Claude Opus 5 <[email protected]> * docs(core): tighten the precedence note and correct a test description Review feedback on #722: - The precedence admonition in docs/authentication.md said the same thing three ways over thirteen lines. Four lines, same facts. - `falls back to generic guidance when no layer named an OAuth field` was wrong: the test's own `metaConfig` names all three OAuth fields. The condition is that the *constructor argument* named none — `namedOAuth` filters `sources.config` only — so a failure would have read as if no layer had OAuth at all. Co-Authored-By: Claude Opus 5 <[email protected]> * refactor(core): hoist the config field lists to module constants Review feedback on #722: describeGaps built ['clientId', 'redirectUri', 'scope'] inline twice and ['baseUrl', 'orgName', 'tenantName'] once, which agent_docs/conventions.md forbids — static lookup tables belong at module scope. BASE_FIELDS and OAUTH_FIELDS now sit beside AUTH_FIELDS, and AUTH_FIELDS derives from OAUTH_FIELDS so the OAuth triple is declared once. The spread keeps the literal tuple, so AuthField is still "secret" | "clientId" | "redirectUri" | "scope" and AUTH_FIELD_SOURCES' Record stays exhaustive. No behaviour change: every message string is byte-identical, pinned by the existing tests. Co-Authored-By: Claude Opus 5 <[email protected]> --------- Co-authored-by: Claude Opus 5 <[email protected]>
* feat(folders): add getByKey lookup on odata/Folders * feat(folders): wire folders endpoints and models * feat(folders): wire folders entry * feat(folders): wire folders build entry * docs(folders): align getByKey JSDoc with SDK conventions * docs(folders): use SDK names in folder JSDoc and tests * fix(folders): export Folders only from the folders subpath Drop the legacy dual export of FolderService. Callers import Folders. * docs(folders): split getByKey JSDoc into bare and select examples First example is a bare call; the second passes select. * test(folders): move unit constants to FOLDER_TEST_CONSTANTS Share folder test data from tests/utils/constants/folders.ts. Entire-Checkpoint: 6cf46c9463ed * fix(folders): address getByKey review comments Remove the internal action name from the class JSDoc, cover empty and whitespace key validation, and drop isPersonal. GetByKey does not return that field, so the integration assertion failed. Co-authored-by: Bogdan Nikolov <[email protected]> * test(folders): type the unit mock client Use ReturnType<typeof createMockApiClient> so the mock methods are typed, and cast the mock once as ApiClient in mockImplementation. * fix(folders): type isActive/fullyQualifiedNameOrderable and drop unsupported expand - Add isActive and fullyQualifiedNameOrderable to FolderGetResponse (returned by GetByKey) - FolderGetByKeyOptions now accepts select only; every expand value returns 400 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * fix(folders): strip @odata.context and share integration preconditions - Drop @odata.context from the getByKey response, matching the attachments service - Move the folders service and folder key checks into a single beforeAll Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> --------- Co-authored-by: Cursor Agent <[email protected]> Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
…ts, execution-history fixture) (#745) * test(maestro): give the Insights SLA tests a 90s budget getSlaSummary / getStagesSlaSummary hit insightsrtm_, whose SLA aggregations routinely run 15-30s+ server-side (measured 16s, 23s, >30s, >30s across the last four coverage runs). They run only under the user token and were failing on the 30s default while the endpoint was still working. Same treatment as the Data Fabric schema DDL tests: a budget for a slow-but-succeeding server. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(maestro): read execution history from a settled process instance The suite's shared instance is whatever processInstances.getAll() returns first. The list is newest-first, so under concurrent CI legs that is routinely an instance another suite cancelled before it executed a single element, and its history is empty - the transform test then throws its own precondition (seen on #736 run 35093134016). Pick a settled instance that has actually run something instead of depending on list position. Co-Authored-By: Claude Fable 5.1 <[email protected]> --------- Co-authored-by: Claude Fable 5.1 <[email protected]>
…quential group (#747) Entity create/delete in the tenant makes concurrent bulk inserts on other entities fail server-side with "Insert bulk failed due to a schema change of the target table". Over the last 30h of CI every one of these 500s (7 of 88 bulk writes, 8%) landed while our own schema suite was creating sdk_* entities; bulk writes with no DDL in flight failed 0 of 27 times. Split the integration config into two vitest projects: everything except entities-schema in group 0, the schema suite alone in group 1, so the DDL never overlaps the record-writing suites. One invocation, one coverage report; file and name filters keep working. Co-authored-by: Claude Fable 5.1 <[email protected]>
…xed-limit assertions (#768) * test(data-fabric): share one fixture entity across sqlType default/fixed-limit assertions Seven read-only tests in the `sqlType constraint defaults` block each created and deleted their own entity to verify one field's default or fixed lengthLimit. Consolidated into a single beforeAll fixture entity carrying all seven field types; each `it` now asserts against the shared entity. Cuts seven `CreateEntity` + `SoftDeleteEntity` DDL cycles down to one per PR run per credential cell, easing pressure on the shared alpha entity SQL elastic pool during CI (currently hitting its max_workers=100 ceiling under integration load). Custom-constraint tests (user-provided lengthLimit / decimalPrecision) and mutation tests (update STRING lengthLimit / DECIMAL constraints) keep their own entities — they mutate schema, so they can't share. Verified locally: all 12 `sqlType constraint defaults` tests pass; the 8 shared assertions run sub-1ms each after the beforeAll create. Co-Authored-By: Claude Opus 4.7 <[email protected]> * test(data-fabric): drop dual-credential run — DF suites run PAT-only Every DF integration suite was declared with describeIntegration(..., 'both', ...), which runs the suite twice per PR — once under PAT, once under the Minter user token — against the same shared alpha entity SQL elastic pool. DF endpoints accept PAT fine and the backend has no branching on token type (verified: no PersonalAccessToken/client_id/token_type conditionals in WebAppCommon/EntityServiceRuntime middleware), so the second run exercises no unique code path yet doubles the load on the pool. Flip access, attachment, choicesets, entities-query, entities-records, entities-schema to 'pat' — halves DF requests per PR run per the arithmetic of credential-cell count. Ceiling errors were 186 in one 32-min CI window on the shared pool (max_workers=100); this is the biggest single lever we can pull SDK-side without scaling infra. Revert to 'both' once the pool is either scaled or the CI tenant DB is isolated from production tenants. Co-Authored-By: Claude Opus 4.7 <[email protected]> * test(data-fabric): scope PAT-only narrowing back to entities-schema; drop redundant strDefaultField assertion Per review feedback: 1. Revert 'both' → 'pat' on attachment, choicesets, entities-query, entities-records. Narrowing to PAT for shared-pool relief violated the convention that 'pat' is reserved for services specific to the external-application identity. Keep 'pat' only on entities-schema, where the beforeAll-fixture consolidation is the primary lever this PR delivers. 2. Drop `strDefaultField` from the shared fixture entity. It duplicated `strField` (both STRING with no lengthLimit) and the corresponding 'confirmed via GET' assertion added no independent verification — the shared beforeAll already calls getById. Verified locally: the sqlType constraint defaults block runs 11 tests, all pass; the 7 shared-fixture assertions run sub-1ms after beforeAll. Co-Authored-By: Claude Opus 4.7 <[email protected]> * test(data-fabric): revert PAT-only narrowing on access and entities-schema Per the same review rule that reverted the other four DF suites: 'pat' is reserved for services specific to the external-application identity. Neither access (whose comment describes a scope-related 403, not an identity-model distinction) nor entities-schema (kept previously on a performance argument) satisfies that criterion. Every DF suite now runs 'both' again. The net effective change on this PR is the beforeAll fixture consolidation in entities-schema — the DDL lever the reviewer accepted — and the drop of the redundant strDefaultField assertion. Co-Authored-By: Claude Opus 4.7 <[email protected]> --------- Co-authored-by: Claude Opus 4.7 <[email protected]>
* feat(ci): build changed sample apps on pull requests * fix: build changed sample apps in check-samples --------- Co-authored-by: swati354 <[email protected]>
* feat(core): add trace() markers and the @trace method decorator trace(label, values?) records a point in code, and @trace records every call of a class method. When tracing is available, both are added to the trace; otherwise they are printed with console.debug. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * fix(core): address review feedback A host may record a span asynchronously. trace() and @trace ignored what recordSpan returned, so a rejected promise escaped the try/catch as an unhandled rejection and crashed the process. Markers and traced calls now record through one helper that catches a throw or a rejection and warns the same way. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
…RL origin [SW-31977] (#782) A coded function passes its handler context to `new UiPath(ctx)`; four gaps closed for that path: - `ctx.platform.folderKey` becomes the default folder for calls that need one and name none, the way the `uipath:folder-key` meta tag already does for coded apps (the context wins over the tag). Orchestrator name lookups and the other calls that threw "requires folder context" run against it, and a by-name lookup that finds nothing there names the folder in its NotFoundError. Integration Service calls are left out and keep falling back to the meta tag alone: Integration Service rejects a connection outside the folder named in X-UIPATH-FolderKey (403 CNS1045 on getById, 404 on execute), and a function's connection often lives in another folder. - The context's `baseUrl` is reduced to its http(s) origin: the organization and tenant are appended to it, so a host handing over a longer URL would address a tenant one level too deep. A value that is not an http(s) URL is left out of the configuration, like a blank coordinate, so the environment can fill it and the error can name it; a context with a token but no platform contributes the token alone. Configuration passed directly is not inspected. - When a handler context was passed and the merged configuration is still incomplete, the error opens with "UiPath SDK configuration is incomplete:" and names the missing coordinate (`ctx.platform is null`, `ctx.robot.accessToken is null`, ...) and the variable that could fill it, instead of advising to pass the context. The reason is recorded in the internals registry through a `Symbol.for` global, so a service constructed from another bundle reports it too; coded functions never call `initialize()`, so that is the path they see. - `HttpMethod`, `Headers`, `QueryParams` and `ResponseType` are exported from `/core`, beside the `HttpRequestInit` and `RetryOptions` that reference them (already public from the root entry). Verify: `npm run typecheck`, `npm run lint`, `npm run test:unit` (3164 tests), `npm run build`, `npm run docs:validate`. Co-authored-by: Claude Fable 5.1 <[email protected]>
…7918] (#775) * ci: run only the integration suites a pull request can affect PR coverage runs used to execute every integration suite for every change, so a docs- or packages-only PR spent ~17 minutes per leg creating Data Fabric entities and Maestro instances it could not influence, and every platform hiccup in ~3,000 requests failed the PR. A new `scope` job classifies the files changed against the base branch (scripts/integration-scope.mjs). Suites are the folders under tests/integration/shared; a change under src/services/<name>, src/models/<name> or tests/integration/shared/<name> runs that suite, docs, samples, packages and unit tests run nothing, and anything else (core, utils, the harness, config, workflows, a domain with no suite folder) runs everything. The cross-cutting smoke, http and auth-errors suites run whenever any suite runs. The `integration` job receives the resulting vitest path filters and is skipped only when the resolver explicitly says nothing is affected; a missing output still runs. The `ci:full-integration` label forces a full run; weekly-coverage.yml keeps running everything. Co-Authored-By: Claude Fable 5.1 <[email protected]> * ci: address review on the integration-test scoping - Rename the `scope` job to `integration-scope`, matching the script. - Treat all three always-on entries alike: a change to the smoke test, `shared/http/` or `auth-errors` runs only the always-on suites. Other loose test files still run everything. - Make the full-run reason name the missing suite folder for a domain that has none, instead of calling the path "outside the per-domain folders". - Move the full-run label check into the script (`--labels`); the workflow passes the PR's labels through and `FULL_RUN_LABEL` is the only place the name lives. - Document the scoping in tests/integration/README.md ("Which suites run on a pull request") instead of an agent_docs/rules.md bullet; keep only the suite-folder naming clause there. - Unit tests for the always-on paths, both reason messages, a version-bump change set and the label path. Co-Authored-By: Claude Fable 5.1 <[email protected]> * docs: leave agent_docs/rules.md untouched The integration-test scoping is documented in tests/integration/README.md only; the suite-folder naming clause goes too. Co-Authored-By: Claude Fable 5.1 <[email protected]> * ci: run nothing for a service that has no integration suite A change under src/services/<name> or src/models/<name> where the service folder exists but tests/integration/shared/<name> does not (integration-service today) has no suite to run, so it no longer falls back to the full run. Only real service folders qualify; src/models folders that are not a service (common, document-understanding) are shared code and still run everything. The former safety net for a mis-named suite folder — fall back to the full run — is replaced by a unit test asserting every suite folder is named after a src/services folder. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test: cover the git diff failure path of the scope resolver A base ref git does not know must fall back to the full run, never throw or exit. Also covers the --base success path and --files parsing. Co-Authored-By: Claude Fable 5.1 <[email protected]> --------- Co-authored-by: Claude Fable 5.1 <[email protected]>
…ateExternalConnection (#783) Follow-on to #642. Adds federated source and join deltas to EntityUpdateByIdOptions (all @experimental). They are applied inside the existing full re-upsert (buildFederatedUpsertParts): - addExternalSources / removeExternalSources - addExternalFields / removeExternalFields (fieldNames are the entity's column names) - addSourceJoins: connect a source added in the same call - updateSourceJoin: change only the join fields of an existing join - replaceSourceJoins: set the complete join set. This is how the primary source changes, because the backend derives the primary from the joins (the source every join starts from). A join can't be removed on its own, so there is no removeSourceJoins. It can't be combined with addSourceJoins or updateSourceJoin. - updateExternalConnection: point a connector source at another connection, keeping its object, fields and joins and re-pointing the joins at the new connection id. Native sources are rejected. Every delta that names an existing source identifies it by BOTH sourceObjectName and sourceConnectionId (a connector connectionId, or the entityId for a native source), because an entity can have two sources with the same object name on different connections. Shared FederatedSourceRef type. The SDK does not repeat validation the backend already does (join graph, duplicate sources, empty sources, duplicate field names). Also fixes the join cascade on removeExternalFields: joins refer to external field names, so the removed columns are mapped to their external names before joins are dropped. JSDoc on every option explains what it does and how the deltas fit together. Adds unit tests for each delta and integration tests (gated on the DF_FED_* env vars) for adding a native source with its join, changing the primary, cascading a source removal and swapping a connection. Also fixes the by-name updateRecord/updateRecords integration tests: they updated writableFields[0] with generateFieldValue, which has no choiceset case and falls back to a string; when the shared entity's first writable field resolves to an integer choiceset the backend rejects it. p_GetFieldsByEntityId has no ORDER BY, so field order is query-plan-dependent — a plan flip on alpha (Sep 26-28) made the choiceset field first on every branch. Mirror the choiceset-skip the by-id update tests apply. Co-authored-by: Claude Opus 4.8 <[email protected]>
…quest CI (#802) * refactor(endpoints): one folder per service domain, scoped by pull-request CI The endpoint-constant files did not match the service folders the integration-test scoping (#775) is keyed on: Action Center's endpoints lived in orchestrator.ts, platform's in identity.ts and authorization.ts, agents' in feedback.ts and memory.ts, observability's in traces.ts and agent-traces.ts. Every endpoint change therefore ran the full suite. - src/utils/constants/endpoints/<domain>/..., one folder per src/services/ domain, files keeping their names. orchestrator.ts is split: the task constants move to action-center/tasks.ts. identity.ts moves whole into platform/. base.ts stays loose as the shared prefixes. The top-level barrel lists the files; no per-folder barrels. - scripts/integration-scope.mjs: endpoints/<name>/** is scoped like src/services/<name>/**; the barrel is ignored; base.ts runs everything. - Guard tests: every endpoint folder is named after a src/services folder; a folder's exports are used only by that domain's code (or src/core); loose files are not used by services. - Accepted: platform/identity.ts is also imported by core's organization resolver; a change there runs the platform suite only. - Docs: tests/integration/README.md, agent_docs/conventions.md, agent_docs/architecture.md. Co-Authored-By: Claude Fable 5.1 <[email protected]> * ci: ignore endpoints/base.ts in the integration-test scoping Every new service adds a base path there, and its own endpoint folder and suite already trigger its run; running the whole suite for the shared file would make every onboarding PR a full run again. Editing an existing base path is therefore not covered by a pull-request run. Co-Authored-By: Claude Fable 5.1 <[email protected]> * refactor(endpoints): import endpoint constants through the barrel The eight deep imports (data-fabric/data-fabric, platform/identity) were carried over from the flat layout; every other service already imports from src/utils/constants/endpoints. Co-Authored-By: Claude Fable 5.1 <[email protected]> --------- Co-authored-by: Claude Fable 5.1 <[email protected]>
) * ci: scope new-service pull requests to their own integration suite A new-service PR still ran every suite because three files outside the domain folders change on each one: - package.json (exports, scripts, version) is ignored. A dependency change or version bump still runs everything through package-lock.json. - tests/utils/constants/<name>.ts is scoped like src/services/<name>/ when <name> is a suite domain; common.ts and entity-named files still run everything. - tests/integration/config/unified-setup.ts, where services are registered, runs only the always-on suites when the change only adds lines (learned from `git diff --numstat`); any other edit runs everything. The always-on suites load the file. A drift guard fails when a domain-named constants file is used by another suite. It found the observability agent-traces suite using agent fixtures from agents.ts; those now live in common.ts as TEST_AGENT, which AGENT_TEST_CONSTANTS references so the unit tests are unchanged. Verified against #664 (feat/platform-groups): scope=platform. Co-Authored-By: Claude Fable 5.1 <[email protected]> * ci: ignore scripts/ in the integration-test scoping Everything under scripts/ is CI and release tooling (API-surface check, sample builds, docs, release metadata, the scoping resolver itself); nothing there takes part in an integration run, and each script has its own unit tests. A broken resolver fails the fail-closed integration-scope job rather than skipping anything silently. Co-Authored-By: Claude Fable 5.1 <[email protected]> * ci: ignore tests/utils as a whole in the integration-test scoping tests/unit was already ignored; tests/utils holds unit-test fixtures and helpers. Four fixture files under tests/utils/constants are read by the agents, http and observability suites, so a fixture-only edit is knowingly uncovered until the weekly run or the next change to that suite. This supersedes the by-name rule for tests/utils/constants/<name>.ts and its drift guard, and reverts the TEST_AGENT fixture move they required. Co-Authored-By: Claude Fable 5.1 <[email protected]> --------- Co-authored-by: Claude Fable 5.1 <[email protected]>
…[APPS-37218] (#664) * feat(platform): add Groups service for organization group management Adds PlatformGroupService (exported as Groups) to the /platform subpath: - getAll(organizationId) — all local and built-in groups - getById(groupId, organizationId) - create(name, organizationId, options?) — the API requires a client-generated group GUID, so the SDK generates it; initial members via memberUserIds - updateById(groupId, organizationId, name, options?) — the API requires the name on every update (409 without it, live-verified), so it is a required positional; membership edits via memberUserIdsToAdd/ memberUserIdsToRemove; the bound group.update() auto-fills the current name - deleteById(groupId, organizationId) - getMembers(groupId, organizationId, options?) — paged member references with fetch-all default Groups are enriched with organizationId (not on the wire) so bound update/delete/getMembers capture full context. Numeric GroupType codes mapped to enums; members/mappedRole/scope dropped from the public shape (members is always empty on the wire — membership is served by getMembers). Verified against the live API: 2389 unit tests passing, integration 8/8 (full CRUD, membership round-trips from both group and user side, pagination), runtime E2E through packed dist bundles. Co-Authored-By: Claude Fable 5 <[email protected]> * fix(platform): address review comments on the Groups module doc and bound-method tests - Say which /platform operations are user-scoped vs organization-scoped in the module JSDoc - Cover the missing organization id guard for the bound delete() and getMembers() Co-Authored-By: Claude Fable 5.1 <[email protected]> * refactor(platform): resolve the organization id inside Groups; drop it from every method Groups now uses the shared organization id resolver like Users: no method takes organizationId, and the response no longer carries the SDK-added organizationId field. Bound methods only guard the group id. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(platform): declare the Groups suite with describeIntegration Co-Authored-By: Claude Fable 5.1 <[email protected]> * fix(platform): address review comments on Groups — /groups subpath, update options, member paging - Expose Groups on its own /groups subpath like Users and Roles - updateById(groupId, update: PlatformGroupUpdateOptions) reads the current name when the caller omits it, so membership edits no longer require passing the name - getMembers fetch-all mirrors Users: dedupe by id, short page terminal, advance by page size - Docs call the service Groups, matching the SDK Co-Authored-By: Claude Fable 5.1 <[email protected]> * refactor(platform): fold the Groups write renames into the single PlatformGroupMap One map per service, as Users does: transformData() applies it to responses and transformRequest() reverses it for the create/update bodies. Co-Authored-By: Claude Fable 5.1 <[email protected]> * fix(platform): reject an explicitly empty group name on update; document the read-before-write Drop the dead !update guard (the parameter is required), distinguish an omitted name from an empty one the API rejects, and note in the JSDoc that a membership-only update reads the current name first. Co-Authored-By: Claude Fable 5.1 <[email protected]> * docs(platform): mirror the read-before-write note on the bound group.update() Co-Authored-By: Claude Fable 5.1 <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]>
…suites (#791) * ci(pr-checks): run one PR Checks run per pull request A new push to a pull request now cancels the run already in flight for that PR. Without a concurrency group every push ran a full integration pass, and two legs of the same branch shared the dev tenant: runs 35974091102 and 35974404828 (pushes 28 s apart) renamed the same fixture user under each other and failed the users suite. weekly-coverage.yml keeps its own group. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(integration): budget the insightsrtm_ suites and the smoke Data Fabric call Agents, Agent Traces, Maestro Processes and Maestro Cases call insightsrtm_, whose aggregations take 15-30 s server-side on the CI tenant (agents.getAll p90 17 s, getTopRunCount tail up to 29.6 s), so vitest's 30 s default fails healthy responses in 38 of the last 99 failed user legs. Each suite gets the 120 s budget the Action Center suite already uses. The smoke Data Fabric connectivity call goes from 15 s to 60 s; it queues behind schema DDL from concurrent runs. No retries, no assertion changes. Same treatment #745 gives the SLA tests in case-instances. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(integration): budget the Agent Memory and Governance suites too Both sit on insightsrtm_ (memory.ts and governance.ts build on INSIGHTS_RTM_BASE) and timed out at 30 s in 7 of the last 99 failed user legs. Same 120 s suite budget as the other insightsrtm_ suites. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(maestro): keep concurrent runs off each other's case-instance fixtures The suite scavenges tenant-wide state that every concurrent leg sees: the newest Completed timer instance for reopen, and any Running instance of the fixture process for pause/close. Two legs on the tenant at once pick the same instance; one reopens and closes it, the other polls it for 180 s ("did not complete within 180s", 21 of the last 100 runs) or has its pause rejected ("Canceling->Pausing is not a valid state transition"). Observed live on the #745 user leg against the #746 leg, Sep 16 15:54-16:12. - reopen claims a shared orphan by calling reopen as soon as it reads Completed; if the orphan is no longer Completed or the reopen is rejected, it starts an instance of its own and waits for that one. A reopen failure on our own instance still propagates. Own instances that end Cancelled or Faulted fail immediately instead of after 180 s. - seedRunningInstance reuses a Running orphan only when it is older than an hour, so it cannot belong to a leg still in flight. - getVariables' beforeAll gets a 60 s hook budget (ten enriched lookups). Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(maestro): budget the Process Instances suite A pageSize: 1 getAll timed out at 30 s on the #791 pat leg with no other run on the tenant; PIMS list and lookup calls stall under load. Same 120 s suite budget as the other Maestro suites. No retries, no assertion changes. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(integration): retry Data Fabric record suites once on failure On the #791 user leg, with no other run on the tenant, Data Fabric answered 503 to getAll, 504 to deleteAttachment, and the entities-query cleanup hook overran 60 s. The record and attachment suites move into their own vitest project (same group order as `integration`, so scheduling is unchanged) carrying retry: 1, so one re-run separates a service fault from a regression; repeated assertion failures still fail and hooks are not retried. The entities-query cleanup hook gets 120 s like the other Data Fabric cleanups. Collection is unchanged: 1198 tests, same set, no file in two projects. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(integration): budget the Agent Feedback suite, give the reopen wait the test budget On the #791 user leg (run 36837133226, alone on the tenant) three llmopstenant_ feedback calls that take under a second on the pat leg timed out at 30 s, the getVariables hook overran 60 s, and the [v1] reopen cell started an instance of its own that the engine had not completed after 180 s. Feedback gets the 120 s suite budget, the getVariables hook 120 s, and the reopen wait 240 s inside a 300 s test. The reopen poll now logs which fixture path it took and warns when getById fails instead of swallowing it, so the next failure names the cause. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(integration): skip the stages SLA tests at the gateway ceiling, retry Insights suites once getStagesSlaSummary now takes 43-60 s server-side on the CI tenant (12 calls measured on 2026-10-01; p50 was 26 s a week earlier) and the gateway answers 504 at 60 s, so the two tests fail on roughly every other call and no client budget can change that. They are it.skip with the reason, next to the getSlaSummary test already skipped in the same block, until Insights RTM brings the aggregation back under the gateway limit. The read-only insightsrtm_/llmopstenant_ suites (agents, feedback, memory, governance, traces/agent, maestro processes and cases) move into an integration-insights project with retry: 1, matching the Data Fabric one: getTopRunCount answered in 0.4-10 s all day and then 504'd once after 60 s. case-instances stays out of it because its pause/resume/reopen tests mutate state. Collection is unchanged: 1194 tests, same set as main, no file in two projects. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(integration): drop the retry projects, settle the slow-suite budgets at 90 s Across four PR Checks runs with retry: 1 active, no test passed on a second attempt; the one case it was meant for (a Data Fabric 504) failed twice because a 504 means the server took over 60 s and a retry asks it again. Both projects go, and vitest.integration.config.ts returns to the #747 layout. The suite budgets stay but at 90 s: a single request cannot succeed past the 60 s gateway limit, so 90 s covers one slow call plus a follow-up and nothing above that is reachable. The getVariables and entities-query cleanup hooks use the same value. The reopen wait returns to 180 s / 240 s; the atomic claim, the orphan age filter and the diagnostics stay. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(integration): skip choice-set fields in generated records, wait 120 s for seeded instances Two failures that kept recurring after #745/#747/#768/#775 landed: - The shared fixture entity carries a choice-set field. getWritableFields let it through and generateFieldValue wrote a random string into it, which the server rejects ("Single choiceset value Test_x is not integer"): 23 legs in September, 2 more on Oct 4. Choice-set fields are now excluded, like relationship and file fields already are. - The process-instances cancel test polled 20 x 2 s for its own instance to reach Running and gave up at ~60 s; PIMS took longer four times since Oct 2. The poll now runs against a 120 s deadline inside a 180 s test. Co-Authored-By: Claude Fable 5.1 <[email protected]> * test(maestro): wait on a deadline for the resumed case instance to run The pause/resume test polled 30 x 2 s after resume and asserted on the last reading; on the #791 pat leg the instance was still Resuming when the polls ran out while another PR's run shared the tenant. The wait is now a 120 s deadline, matching the cancel test, inside a 240 s test. Co-Authored-By: Claude Fable 5.1 <[email protected]> * fix(tests): import the data-fabric endpoint constant from the endpoints barrel #802 moved src/utils/constants/endpoints/data-fabric.ts into endpoints/data-fabric/data-fabric.ts without an index, so the bare folder import in entities-schema.integration.test.ts no longer resolves and every integration leg on main has failed at import since 09:58 UTC on Oct 5 (ERR_MODULE_NOT_FOUND, seen on #791 and feat/platform-groups). Import from the endpoints barrel like the other tests do. Co-Authored-By: Claude Fable 5.1 <[email protected]> --------- Co-authored-by: Claude Fable 5.1 <[email protected]>
) * refactor(platform)!: source the organization from the SDK instance Platform settings are scoped to an (organization, user) pair, but the organization was passed in per call — as an option on getUserSettings and a required positional argument on updateUserSettings. The SDK already knows which organization it was initialized against, so both methods now read it from the instance and callers only supply the user. BREAKING CHANGE: updateUserSettings() no longer takes an organizationId argument and getUserSettings() no longer takes an options argument. PlatformSettingGetOptions is removed. Both shipped in 1.6.1. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> * fix: address convention review comments Remove the integration-test organizationId config, orphaned when the Platform suite stopped needing it; drop the stale README row; stop the module @example deriving userId from a read result that may omit the key. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> * docs(platform): keep the existing JSDoc wording Restore the service class comment and drop the per-method scoping notes, so the module, service class, and ServiceModel comments all read as they did before. The signature change alone drives the remaining JSDoc edits. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> * refactor(platform): drop the partitionGlobalId query param The organization is already on the request path — ApiClient builds {baseUrl}/{orgName}/identity_/api/Setting — so sending it again as partitionGlobalId on the read and in the body on the write is redundant. Reverts the BaseService.config.orgName accessor added earlier on this branch: Platform was its only consumer, and nothing reads it now. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> * fix(platform): send the resolved organization GUID as partitionGlobalId Identity scopes settings by partition GUID, not by the org name in the URL: without partitionGlobalId a read answers "User is not host admin" (401) and the API gateway rejects it (403). Feed the param from the shared organization id resolver, so callers still never pass an organization, and drop the unused UIPATH_ORGANIZATION_ID wiring from the coverage workflow. Co-Authored-By: Claude Fable 5.1 <[email protected]> * refactor(platform)!: rename the Platform service to Settings on its own /settings subpath Mirrors the Users, Groups, and Roles layout: PlatformSettingService is exported as Settings from @uipath/uipath-typescript/settings, the model interface is PlatformSettingServiceModel, and the platform.* model files become settings.*. The /platform subpath is removed. The stale header example that still passed the removed options argument is fixed. Co-Authored-By: Claude Fable 5.1 <[email protected]> * ci: do not run the integration suites for coverage.yml or tests/integration/config changes Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5 (1M context) <[email protected]> Co-authored-by: Sarath1018 <[email protected]>
Minor bump: #691 removes the /platform subpath and moves user settings to /settings. release-metadata.json regenerated from a fresh build. Co-authored-by: Claude Opus 5.5 <[email protected]>
… ExternalReference (#787) * fix(functions): resolve process-prefixed trigger names and invoke via ExternalReference Functions.invoke() looked triggers up by exact name, but Orchestrator stores triggers created since July 2026 as `<process name>_<name>`, so the lookup missed. It also built the URL from Release.Slug, which is null on tenants without release slugs, producing `/t/<key>/<process>/null` and a 404. The lookup now accepts the declared or the full stored name, with an optional `processName` to pick between processes that declare the same name. The invoke route and folder key come from the trigger's ExternalReference, falling back to the slugs only when it is absent. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(functions): keep processSlug typed as string The route now comes from ExternalReference, so the fix no longer needs the public type change. buildInvokeRoute still accepts a null process slug, which the API returns on tenants without release slugs. Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(functions): warn when listing function names for a not-found error fails Co-Authored-By: Claude Opus 5.5 <[email protected]> * fix(functions): match the ExternalReference route as non-space characters Co-Authored-By: Claude Opus 5.5 <[email protected]> * ci: scope a loose service file to the domains that import it src/services/base.ts and src/services/folder-scoped.ts sit beside the domain folders, so any change to them ran the full integration suite. The resolver now follows src/ imports (through the services barrel) and takes the union of the importers' classifications: folder-scoped.ts runs action-center and orchestrator, base.ts still runs everything because core imports it. #787 would have run two suites instead of all of them. The resolver also emits `projects`, the vitest projects the scope needs, so the workflow can skip the Data Fabric schema leg when Data Fabric is not in scope. Co-Authored-By: Claude Fable 5.1 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>
…tion (#774) A coded function's robot token alone always got 204 from StartTransaction: Orchestrator only hands out an item when RobotIdentifier names the robot. new UiPath(ctx) now keeps ctx.robot.key and startTransaction sends it. Co-authored-by: Claude Opus 5.5 <[email protected]>
The rollup .d.ts bundling has outgrown the 4 GB heap SETUP.md grants: npm run build has aborted with a JavaScript heap OOM on every Agentic Inner Loop run since 24 Sep, even on a 32 GB agent, because the cap is the explicit --max-old-space-size, not the machine. The repo's CI already builds with 6144 (coverage.yml, publish.yml); match it. Co-authored-by: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LM6VtZJcXXfPgooJz9CkdA Co-authored-by: Claude <[email protected]>
…28] (#665) * feat(platform): add Directory service for principal lookups Adds PlatformDirectoryService (exported as Directory) to the /platform subpath — the read-only lookup layer over an organization's principals: - search(organizationId, options?) — find users, groups, and applications by name prefix, entity type, and source - getGroupMembership(userId, groupIds, organizationId) — returns the subset of the given groups the user belongs to; the membership check behind RBAC gating ("is this user in the Administrators group?") Transforms: identifier→id and identityName→name renames, redundant objectType dropped, numeric entity-type codes mapped to enums (live API sends codes despite the spec declaring strings). Read-only service — no bound methods, per convention. Also hardens the Users integration suite against parallel-file races: sibling suites mutate the shared test user's group memberships, so the replace-semantics assertion now checks membership survival across the update call instead of exact snapshot equality. Verified against the live API: 2403 unit tests passing, all four platform integration suites green in a parallel run (31/31). Co-Authored-By: Claude Fable 5 <[email protected]> * fix(platform): address review comments on Directory; resolve the organization id internally - Declare the suite with describeIntegration and throw when the Everyone group is missing - Self-contained getGroupMembership example - Directory resolves the organization GUID like Users, Groups, and Roles: search(options?) and getGroupMembership(userId, groupIds) no longer take organizationId Co-Authored-By: Claude Fable 5.1 <[email protected]> * fix(platform): address review comments on Directory — /directory subpath, required search term - Expose Directory on its own /directory subpath like Users, Groups, and Roles; the /platform module is settings-only again - search(startsWith, options?): the API rejects a search without a term and returns every match unpaged, so the prefix is a required positional argument and the JSDoc says so - Throw a clear error when the live search returns nothing instead of dereferencing results[0]; drop the Users suite change that belongs with #663; collapse double blank lines; call the service Directory in docs and suite titles Co-Authored-By: Claude Fable 5.1 <[email protected]> * fix(platform): reject a whitespace-only directory search term The API answers 400 for it just as for an empty string, so the guard trims before checking. The value itself is still sent as given — the API does not trim, and a padded prefix simply matches nothing. Co-Authored-By: Claude Fable 5.1 <[email protected]> * fix: integration test --------- Co-authored-by: Claude Fable 5 <[email protected]>
Raina451
force-pushed
the
fix/pca-sdk-public-runtime
branch
from
October 7, 2026 08:00
80993d1 to
4a6189a
Compare
Raina451
force-pushed
the
fix/pca-sdk-public-runtime
branch
from
October 7, 2026 08:35
4a6189a to
c89f87f
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
This PR lets a public coded app use the SDK without a sign-in. When the page carries
uipath:app-key, the SDK switches to public mode and sends supported calls to the Apps service with the visitor's session cookie. It renews the session on a 401.Supported in public mode:
processes.startandjobs.getOutputentities.insertRecord,getRecordByNameandgetRecordsByName(withpageSize/jumpToPage/cursor)buckets.uploadFile: the service picks the stored path, which comes back aspathResources are named by their binding (
name, plusfolderPathwhen the binding is folder-scoped), the same waybindings_v2.jsonkeys them. The service applies Solutions overrides, so a page's override table is ignored here. Ids and keys are rejected. Any other call throws aValidationErrorbefore reaching the network.Why
Public apps have no user token, so these calls have to go through the Apps service endpoints that act as the app (business-apps-jamjam
/integrations/codedapp/*).Docs:
docs/coded-apps/public-apps.md.Generated with Claude Code