mirror of
https://github.com/hanzoai/insights.git
synced 2026-11-02 14:32:45 +00:00
`insights/mount.py` is explicit: `/v1/` is the mount and `/api/` is the older spelling, kept on the wire for released CLI builds and personal-API-key holders and rewritten once at the edge by `ApiRewriteMiddleware`. Our own frontend was still on the older spelling: the orval clients were generated two days before the mount moved and the move did not regenerate them, so 70 files and 2323 paths said `/api/`. That is not only a spelling. `prepareUrl` in `lib/api.ts` rewrites `/v1/*` to the selected region's host in OAuth mode and nothing else, because that is what the cloud CORS allowlist covers — so every generated call quietly stayed same-origin, and `getExportsContentRetrieveUrl` builds an `<img src>` that never reaches `lib/api.ts` at all. The clients are regenerated from a spec that needs postgres, the datastore and Django, so this is the path strings only, which is the whole of what the mount move changes in them: orval copies paths verbatim from the spec, and the spec takes them from the URLconf. Doc comments carried the same stale prefix and move with them; their Python docstrings already say `/v1/`. The two frozen OAuth client-metadata paths are identifiers rather than API surface and appear in none of these files. The Slack task prompt told the agent to POST to `$INSIGHTS_API_URL/api/projects/...`, which is a live request path, not prose.
1510 lines
65 KiB
TypeScript
Generated
1510 lines
65 KiB
TypeScript
Generated
import { apiMutator } from '../../../../frontend/src/lib/api-orval-mutator'
|
|
/**
|
|
* Auto-generated from the Django backend OpenAPI schema.
|
|
* To modify these types, update the Django serializers or views, then run:
|
|
* insightscli build:openapi
|
|
* Questions or issues? #team-devex on Slack
|
|
*
|
|
* Insights API - generated
|
|
* OpenAPI spec version: 1.0.0
|
|
*/
|
|
import type {
|
|
CommitDiffResponseApi,
|
|
EditReportRequestApi,
|
|
EditReportResponseApi,
|
|
EmitFindingRequestApi,
|
|
EmitFindingResponseApi,
|
|
EmitReportRequestApi,
|
|
EmitReportResponseApi,
|
|
FleetFindingsSummaryApi,
|
|
ForgetRequestApi,
|
|
ForgetResponseApi,
|
|
PaginatedPauseStateResponseListApi,
|
|
PaginatedSignalReportArtefactListApi,
|
|
PaginatedSignalReportListApi,
|
|
PaginatedSignalSourceConfigListApi,
|
|
PatchedPullRequestReviewCommentUpdateApi,
|
|
PatchedSignalReportArtefactLogUpdateApi,
|
|
PatchedSignalReportContentUpdateApi,
|
|
PatchedSignalScoutConfigUpdateApi,
|
|
PatchedSignalSourceConfigApi,
|
|
PauseResponseApi,
|
|
PauseUntilRequestApi,
|
|
ProjectProfileApi,
|
|
PullRequestChecksResponseApi,
|
|
PullRequestCommentsResponseApi,
|
|
PullRequestReviewCommentCreateApi,
|
|
PullRequestReviewCommentCreateResponseApi,
|
|
PullRequestReviewCommentReactionCreateApi,
|
|
PullRequestReviewCommentReactionCreateResponseApi,
|
|
RecordStructuredOutputRequestApi,
|
|
RecordStructuredOutputResponseApi,
|
|
RememberRequestApi,
|
|
ReportSignalsResponseApi,
|
|
ScoutEmissionReportLinkApi,
|
|
ScoutMemberApi,
|
|
ScoutMetadataApi,
|
|
ScoutNoteApi,
|
|
ScoutNoteCreateRequestApi,
|
|
ScoutRunIdsBatchRequestApi,
|
|
ScratchpadEntryApi,
|
|
SignalReportApi,
|
|
SignalReportArtefactApi,
|
|
SignalReportArtefactLogCreateApi,
|
|
SignalReportArtefactWriteResponseApi,
|
|
SignalReportBulkStateRequestApi,
|
|
SignalReportBulkStateResponseApi,
|
|
SignalReportFeedbackRequestApi,
|
|
SignalReportFeedbackResponseApi,
|
|
SignalReportRefundRequestApi,
|
|
SignalReportRefundResponseApi,
|
|
SignalReportRefundSummaryResponseApi,
|
|
SignalReportStateRequestApi,
|
|
SignalScoutConfigApi,
|
|
SignalScoutConfigCreateApi,
|
|
SignalScoutCreateApi,
|
|
SignalScoutCreateResponseApi,
|
|
SignalScoutEmissionApi,
|
|
SignalScoutManualRunApi,
|
|
SignalScoutRunDetailApi,
|
|
SignalScoutRunSummaryApi,
|
|
SignalSourceConfigApi,
|
|
SignalUserAutonomyConfigApi,
|
|
SignalsProcessingListParams,
|
|
SignalsReportArtefactsListParams,
|
|
SignalsReportsListParams,
|
|
SignalsScoutConfigListParams,
|
|
SignalsScoutMembersListParams,
|
|
SignalsScoutNotesListParams,
|
|
SignalsScoutProjectProfileGetParams,
|
|
SignalsScoutRunsFindingsSummaryParams,
|
|
SignalsScoutRunsListParams,
|
|
SignalsScoutRunsRecentEmissionsParams,
|
|
SignalsScoutScratchpadSearchParams,
|
|
SignalsSourceConfigsListParams,
|
|
} from './api.schemas'
|
|
|
|
// https://stackoverflow.com/questions/49579094/typescript-conditional-types-filter-out-readonly-properties-pick-only-requir/49579497#49579497
|
|
type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B
|
|
|
|
type WritableKeys<T> = {
|
|
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, P>
|
|
}[keyof T]
|
|
|
|
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never
|
|
type DistributeReadOnlyOverUnions<T> = T extends any ? NonReadonly<T> : never
|
|
|
|
type Writable<T> = Pick<T, WritableKeys<T>>
|
|
type NonReadonly<T> = [T] extends [UnionToIntersection<T>]
|
|
? {
|
|
[P in keyof Writable<T>]: T[P] extends object ? NonReadonly<NonNullable<T[P]>> : T[P]
|
|
}
|
|
: DistributeReadOnlyOverUnions<T>
|
|
|
|
export const getSignalsProcessingListUrl = (projectId: string, params?: SignalsProcessingListParams) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/processing/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/processing/`
|
|
}
|
|
|
|
/**
|
|
* Return current processing state including pause status.
|
|
*/
|
|
export const signalsProcessingList = async (
|
|
projectId: string,
|
|
params?: SignalsProcessingListParams,
|
|
options?: RequestInit
|
|
): Promise<PaginatedPauseStateResponseListApi> => {
|
|
return apiMutator<PaginatedPauseStateResponseListApi>(getSignalsProcessingListUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsProcessingPauseUpdateUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/processing/pause/`
|
|
}
|
|
|
|
/**
|
|
* View and control signal processing pipeline state for a team.
|
|
*/
|
|
export const signalsProcessingPauseUpdate = async (
|
|
projectId: string,
|
|
pauseUntilRequestApi: PauseUntilRequestApi,
|
|
options?: RequestInit
|
|
): Promise<PauseResponseApi> => {
|
|
return apiMutator<PauseResponseApi>(getSignalsProcessingPauseUpdateUrl(projectId), {
|
|
...options,
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(pauseUntilRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsProcessingPauseDestroyUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/processing/pause/`
|
|
}
|
|
|
|
/**
|
|
* View and control signal processing pipeline state for a team.
|
|
*/
|
|
export const signalsProcessingPauseDestroy = async (
|
|
projectId: string,
|
|
options?: RequestInit
|
|
): Promise<PauseResponseApi> => {
|
|
return apiMutator<PauseResponseApi>(getSignalsProcessingPauseDestroyUrl(projectId), {
|
|
...options,
|
|
method: 'DELETE',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportsListUrl = (projectId: string, params?: SignalsReportsListParams) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/reports/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/reports/`
|
|
}
|
|
|
|
export const signalsReportsList = async (
|
|
projectId: string,
|
|
params?: SignalsReportsListParams,
|
|
options?: RequestInit
|
|
): Promise<PaginatedSignalReportListApi> => {
|
|
return apiMutator<PaginatedSignalReportListApi>(getSignalsReportsListUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportsRetrieveUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/`
|
|
}
|
|
|
|
export const signalsReportsRetrieve = async (
|
|
projectId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<SignalReportApi> => {
|
|
return apiMutator<SignalReportApi>(getSignalsReportsRetrieveUrl(projectId, id), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportsPartialUpdateUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/`
|
|
}
|
|
|
|
/**
|
|
* Edit the human-facing title and/or summary (description) of a signal report, addressed by id. Both fields are optional — supply only the ones you want to change; at least one is required. Every other report field (status, weights, judgments) is managed by the signals pipeline and cannot be set here. Returns the full updated report.
|
|
* @summary Edit a report's title or summary
|
|
*/
|
|
export const signalsReportsPartialUpdate = async (
|
|
projectId: string,
|
|
id: string,
|
|
patchedSignalReportContentUpdateApi?: PatchedSignalReportContentUpdateApi,
|
|
options?: RequestInit
|
|
): Promise<SignalReportApi> => {
|
|
return apiMutator<SignalReportApi>(getSignalsReportsPartialUpdateUrl(projectId, id), {
|
|
...options,
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(patchedSignalReportContentUpdateApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportsFeedbackCreateUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/feedback/`
|
|
}
|
|
|
|
/**
|
|
* Record a note left with the thumbs rating at the end of a report. The rating itself is a product-analytics event; this endpoint exists to carry the note into the scout steering channel. For a report authored by a scout, the note is forwarded to that scout as a steering note it reads on its next run; for any other report there is nothing to steer and the call is a no-op success. The report's state is never changed.
|
|
* @summary Leave feedback on a report
|
|
*/
|
|
export const signalsReportsFeedbackCreate = async (
|
|
projectId: string,
|
|
id: string,
|
|
signalReportFeedbackRequestApi: SignalReportFeedbackRequestApi,
|
|
options?: RequestInit
|
|
): Promise<SignalReportFeedbackResponseApi> => {
|
|
return apiMutator<SignalReportFeedbackResponseApi>(getSignalsReportsFeedbackCreateUrl(projectId, id), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(signalReportFeedbackRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportPrChecksUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/pr_checks/`
|
|
}
|
|
|
|
/**
|
|
* Fetch the CI status (GitHub Actions check runs and legacy commit statuses) of the pull request the report's implementation task opened, via the team's GitHub integration.
|
|
* @summary Fetch CI checks for a report's implementation PR
|
|
*/
|
|
export const signalsReportPrChecks = async (
|
|
projectId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<PullRequestChecksResponseApi> => {
|
|
return apiMutator<PullRequestChecksResponseApi>(getSignalsReportPrChecksUrl(projectId, id), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportPrCommentsUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/pr_comments/`
|
|
}
|
|
|
|
/**
|
|
* Fetch the pull request's conversation comments and inline review comments, merged chronologically, via the team's GitHub integration.
|
|
* @summary Fetch comments for a report's implementation PR
|
|
*/
|
|
export const signalsReportPrComments = async (
|
|
projectId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<PullRequestCommentsResponseApi> => {
|
|
return apiMutator<PullRequestCommentsResponseApi>(getSignalsReportPrCommentsUrl(projectId, id), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportPrReviewCommentsCreateUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/pr_review_comments/`
|
|
}
|
|
|
|
/**
|
|
* Post an inline review comment on the report's implementation pull request, attributed to the requesting user's own GitHub identity via their personal GitHub connection. Either replies to an existing thread (`in_reply_to`) or starts a new thread on a diff line (`path` + `line`).
|
|
* @summary Post an inline review comment on a report's implementation PR
|
|
*/
|
|
export const signalsReportPrReviewCommentsCreate = async (
|
|
projectId: string,
|
|
id: string,
|
|
pullRequestReviewCommentCreateApi: PullRequestReviewCommentCreateApi,
|
|
options?: RequestInit
|
|
): Promise<PullRequestReviewCommentCreateResponseApi> => {
|
|
return apiMutator<PullRequestReviewCommentCreateResponseApi>(
|
|
getSignalsReportPrReviewCommentsCreateUrl(projectId, id),
|
|
{
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(pullRequestReviewCommentCreateApi),
|
|
}
|
|
)
|
|
}
|
|
|
|
export const getSignalsReportPrReviewCommentUpdateUrl = (projectId: string, id: string, commentId: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/pr_review_comments/${commentId}/`
|
|
}
|
|
|
|
/**
|
|
* @summary Edit one of the requesting user's own review comments
|
|
*/
|
|
export const signalsReportPrReviewCommentUpdate = async (
|
|
projectId: string,
|
|
id: string,
|
|
commentId: string,
|
|
patchedPullRequestReviewCommentUpdateApi?: PatchedPullRequestReviewCommentUpdateApi,
|
|
options?: RequestInit
|
|
): Promise<PullRequestReviewCommentCreateResponseApi> => {
|
|
return apiMutator<PullRequestReviewCommentCreateResponseApi>(
|
|
getSignalsReportPrReviewCommentUpdateUrl(projectId, id, commentId),
|
|
{
|
|
...options,
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(patchedPullRequestReviewCommentUpdateApi),
|
|
}
|
|
)
|
|
}
|
|
|
|
export const getSignalsReportPrReviewCommentDestroyUrl = (projectId: string, id: string, commentId: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/pr_review_comments/${commentId}/`
|
|
}
|
|
|
|
/**
|
|
* @summary Delete one of the requesting user's own review comments
|
|
*/
|
|
export const signalsReportPrReviewCommentDestroy = async (
|
|
projectId: string,
|
|
id: string,
|
|
commentId: string,
|
|
options?: RequestInit
|
|
): Promise<void> => {
|
|
return apiMutator<void>(getSignalsReportPrReviewCommentDestroyUrl(projectId, id, commentId), {
|
|
...options,
|
|
method: 'DELETE',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportPrReviewCommentReactionsCreateUrl = (projectId: string, id: string, commentId: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/pr_review_comments/${commentId}/reactions/`
|
|
}
|
|
|
|
/**
|
|
* @summary React to a review comment as the requesting user
|
|
*/
|
|
export const signalsReportPrReviewCommentReactionsCreate = async (
|
|
projectId: string,
|
|
id: string,
|
|
commentId: string,
|
|
pullRequestReviewCommentReactionCreateApi: PullRequestReviewCommentReactionCreateApi,
|
|
options?: RequestInit
|
|
): Promise<PullRequestReviewCommentReactionCreateResponseApi> => {
|
|
return apiMutator<PullRequestReviewCommentReactionCreateResponseApi>(
|
|
getSignalsReportPrReviewCommentReactionsCreateUrl(projectId, id, commentId),
|
|
{
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(pullRequestReviewCommentReactionCreateApi),
|
|
}
|
|
)
|
|
}
|
|
|
|
export const getSignalsReportPrReviewCommentReactionDestroyUrl = (
|
|
projectId: string,
|
|
id: string,
|
|
commentId: string,
|
|
reactionId: string
|
|
) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/pr_review_comments/${commentId}/reactions/${reactionId}/`
|
|
}
|
|
|
|
/**
|
|
* @summary Remove one of the requesting user's own reactions from a review comment
|
|
*/
|
|
export const signalsReportPrReviewCommentReactionDestroy = async (
|
|
projectId: string,
|
|
id: string,
|
|
commentId: string,
|
|
reactionId: string,
|
|
options?: RequestInit
|
|
): Promise<void> => {
|
|
return apiMutator<void>(getSignalsReportPrReviewCommentReactionDestroyUrl(projectId, id, commentId, reactionId), {
|
|
...options,
|
|
method: 'DELETE',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportsRefundCreateUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/refund/`
|
|
}
|
|
|
|
/**
|
|
* Refund the flat charge for this report's implementation PR and archive the report. Refunds auto-approve: the charge is either excluded from usage before it is ever reported to billing (refund on the same UTC day as the PR run) or returned as a Stripe customer-balance credit on the next invoice. A refunded PR does not count toward the free monthly PR allowance. One refund per report, ever — repeat calls return the existing refund with already_refunded=true. The report is archived as part of the refund (a resolved report stays resolved) and can't be restored afterwards.
|
|
* @summary Refund a report's implementation PR
|
|
*/
|
|
export const signalsReportsRefundCreate = async (
|
|
projectId: string,
|
|
id: string,
|
|
signalReportRefundRequestApi: SignalReportRefundRequestApi,
|
|
options?: RequestInit
|
|
): Promise<SignalReportRefundResponseApi> => {
|
|
return apiMutator<SignalReportRefundResponseApi>(getSignalsReportsRefundCreateUrl(projectId, id), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(signalReportRefundRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportsSignalsRetrieveUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/signals/`
|
|
}
|
|
|
|
/**
|
|
* Fetch all signals for a report from Datastore, including full metadata.
|
|
* @summary List a report's signals
|
|
*/
|
|
export const signalsReportsSignalsRetrieve = async (
|
|
projectId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<ReportSignalsResponseApi> => {
|
|
return apiMutator<ReportSignalsResponseApi>(getSignalsReportsSignalsRetrieveUrl(projectId, id), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportsStateCreateUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${id}/state/`
|
|
}
|
|
|
|
/**
|
|
* Transition a report to a new state. The model validates allowed transitions.
|
|
*
|
|
* The request body is validated by SignalReportStateRequestSerializer — only the
|
|
* fields it declares (state, dismissal_reason, dismissal_note, snooze_for) are read,
|
|
* and only snooze_for is ever forwarded to transition_to. Any other key is ignored,
|
|
* so internal transition_to kwargs (reset_weight, error, ...) can't be injected.
|
|
*
|
|
* Body: {
|
|
* "state": "suppressed" | "potential" | "resolved",
|
|
* # Optional dismissal feedback (honored when state == "suppressed", "potential", or "resolved"):
|
|
* "dismissal_reason": "<canonical reason code, see SIGNAL_REPORT_DISMISSAL_REASON_CHOICES>",
|
|
* "dismissal_note": "free-form text",
|
|
* # Optional, only honored for state == "potential":
|
|
* "snooze_for": <number of additional signals before re-promotion>,
|
|
* }
|
|
*/
|
|
export const signalsReportsStateCreate = async (
|
|
projectId: string,
|
|
id: string,
|
|
signalReportStateRequestApi: SignalReportStateRequestApi,
|
|
options?: RequestInit
|
|
): Promise<SignalReportApi> => {
|
|
return apiMutator<SignalReportApi>(getSignalsReportsStateCreateUrl(projectId, id), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(signalReportStateRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportArtefactsListUrl = (
|
|
projectId: string,
|
|
reportId: string,
|
|
params?: SignalsReportArtefactsListParams
|
|
) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/reports/${reportId}/artefacts/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/reports/${reportId}/artefacts/`
|
|
}
|
|
|
|
/**
|
|
* List every artefact on a report — the full work log: signal findings (the evidence behind the report), status judgments (safety / actionability / priority, repo selection, suggested reviewers — the newest row of each status type is canonical), and log entries (code references, commits, task runs, notes). `suggested_reviewers` content is enriched with Insights user info at read time.
|
|
* @summary List a report's artefacts
|
|
*/
|
|
export const signalsReportArtefactsList = async (
|
|
projectId: string,
|
|
reportId: string,
|
|
params?: SignalsReportArtefactsListParams,
|
|
options?: RequestInit
|
|
): Promise<PaginatedSignalReportArtefactListApi> => {
|
|
return apiMutator<PaginatedSignalReportArtefactListApi>(
|
|
getSignalsReportArtefactsListUrl(projectId, reportId, params),
|
|
{
|
|
...options,
|
|
method: 'GET',
|
|
}
|
|
)
|
|
}
|
|
|
|
export const getSignalsReportArtefactsCreateUrl = (projectId: string, reportId: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${reportId}/artefacts/`
|
|
}
|
|
|
|
/**
|
|
* Append an artefact to a report (see artefact_type for the writable types). Everything is append-only: log entries (code reference, commit, task run, note) accumulate, while status types (safety / actionability / priority judgments, repo selection, suggested reviewers) are latest-wins — appending a new version supersedes the previous one as the report's canonical status. Content is validated against the type's schema.
|
|
* @summary Append an artefact to a report
|
|
*/
|
|
export const signalsReportArtefactsCreate = async (
|
|
projectId: string,
|
|
reportId: string,
|
|
signalReportArtefactLogCreateApi: SignalReportArtefactLogCreateApi,
|
|
options?: RequestInit
|
|
): Promise<SignalReportArtefactWriteResponseApi> => {
|
|
return apiMutator<SignalReportArtefactWriteResponseApi>(getSignalsReportArtefactsCreateUrl(projectId, reportId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(signalReportArtefactLogCreateApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportArtefactsRetrieveUrl = (projectId: string, reportId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${reportId}/artefacts/${id}/`
|
|
}
|
|
|
|
/**
|
|
* Get one artefact by id, content parsed (and reviewers enriched) the same way as the list.
|
|
* @summary Get a single artefact
|
|
*/
|
|
export const signalsReportArtefactsRetrieve = async (
|
|
projectId: string,
|
|
reportId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<SignalReportArtefactApi> => {
|
|
return apiMutator<SignalReportArtefactApi>(getSignalsReportArtefactsRetrieveUrl(projectId, reportId, id), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportArtefactsPartialUpdateUrl = (projectId: string, reportId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${reportId}/artefacts/${id}/`
|
|
}
|
|
|
|
/**
|
|
* Replace the content of an existing artefact, addressed by id. The new content is validated against the artefact's type schema. Editing the latest row of a status type changes the report's canonical status (latest-wins); to re-assess while keeping history, append a new artefact instead. Attribution is creation-time only — edits don't reassign it.
|
|
* @summary Replace an artefact's content
|
|
*/
|
|
export const signalsReportArtefactsPartialUpdate = async (
|
|
projectId: string,
|
|
reportId: string,
|
|
id: string,
|
|
patchedSignalReportArtefactLogUpdateApi?: PatchedSignalReportArtefactLogUpdateApi,
|
|
options?: RequestInit
|
|
): Promise<SignalReportArtefactWriteResponseApi> => {
|
|
return apiMutator<SignalReportArtefactWriteResponseApi>(
|
|
getSignalsReportArtefactsPartialUpdateUrl(projectId, reportId, id),
|
|
{
|
|
...options,
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(patchedSignalReportArtefactLogUpdateApi),
|
|
}
|
|
)
|
|
}
|
|
|
|
export const getSignalsReportArtefactsDestroyUrl = (projectId: string, reportId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${reportId}/artefacts/${id}/`
|
|
}
|
|
|
|
/**
|
|
* Delete an artefact, addressed by id. Deleting the latest row of a status type reverts the report's canonical status to the previous version (latest-wins over what remains).
|
|
* @summary Delete an artefact
|
|
*/
|
|
export const signalsReportArtefactsDestroy = async (
|
|
projectId: string,
|
|
reportId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<void> => {
|
|
return apiMutator<void>(getSignalsReportArtefactsDestroyUrl(projectId, reportId, id), {
|
|
...options,
|
|
method: 'DELETE',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportArtefactsDiffUrl = (projectId: string, reportId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/${reportId}/artefacts/${id}/diff/`
|
|
}
|
|
|
|
/**
|
|
* Fetch the unified diff of a `commit` artefact's branch against the repository default branch via the team's GitHub integration — using the branch's current tip so the diff reflects the latest state of the work, not just the single recorded commit.
|
|
* @summary Fetch the diff for a commit artefact
|
|
*/
|
|
export const signalsReportArtefactsDiff = async (
|
|
projectId: string,
|
|
reportId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<CommitDiffResponseApi> => {
|
|
return apiMutator<CommitDiffResponseApi>(getSignalsReportArtefactsDiffUrl(projectId, reportId, id), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportsBulkStateCreateUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/bulk-state/`
|
|
}
|
|
|
|
/**
|
|
* Transition many reports to a new state in one call.
|
|
*
|
|
* Each id is processed independently: a report whose transition isn't allowed from its
|
|
* current status is reported as `skipped` (a 409 on the single-report endpoint) and the
|
|
* rest still go through. Returns one result per requested id (in request order, after
|
|
* de-duplication) plus per-outcome counts. The whole call is 200 even on partial failure —
|
|
* inspect `results` / the counts to see what happened.
|
|
*/
|
|
export const signalsReportsBulkStateCreate = async (
|
|
projectId: string,
|
|
signalReportBulkStateRequestApi: SignalReportBulkStateRequestApi,
|
|
options?: RequestInit
|
|
): Promise<SignalReportBulkStateResponseApi> => {
|
|
return apiMutator<SignalReportBulkStateResponseApi>(getSignalsReportsBulkStateCreateUrl(projectId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(signalReportBulkStateRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsReportsRefundSummaryRetrieveUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/reports/refund-summary/`
|
|
}
|
|
|
|
/**
|
|
* Aggregate credited-path refunds across the whole organization for the current billing period — counts only, no per-team detail. The billing usage widget needs this because billing usage is org-wide while reports (and their refunds) are team-scoped: subtract the refunded credits from billing usage to show the net PR count. Excluded-path refunds never reach billing usage, so no adjustment is needed for them. Also carries the org's live billable credits for the period (billing's recorded usage lags by up to a day), so the widget can count just-created PRs and react to same-day refunds.
|
|
* @summary Summarize credited PR refunds for the billing period
|
|
*/
|
|
export const signalsReportsRefundSummaryRetrieve = async (
|
|
projectId: string,
|
|
options?: RequestInit
|
|
): Promise<SignalReportRefundSummaryResponseApi> => {
|
|
return apiMutator<SignalReportRefundSummaryResponseApi>(getSignalsReportsRefundSummaryRetrieveUrl(projectId), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutCreateUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/`
|
|
}
|
|
|
|
/**
|
|
* Create a `signals-scout-*` skill and its runnable config atomically. The skill always receives the report-channel tools. The optional config controls schedule, enablement, dry-run posture, network access, and typed destinations such as Slack. Repeating the same definition is safe and applies any supplied config fields; reusing its name for a different definition returns 409.
|
|
* @summary Create a scout
|
|
*/
|
|
export const signalsScoutCreate = async (
|
|
projectId: string,
|
|
signalScoutCreateApi: SignalScoutCreateApi,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutCreateResponseApi> => {
|
|
return apiMutator<SignalScoutCreateResponseApi>(getSignalsScoutCreateUrl(projectId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(signalScoutCreateApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutConfigListUrl = (projectId: string, params?: SignalsScoutConfigListParams) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/scout/configs/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/scout/configs/`
|
|
}
|
|
|
|
/**
|
|
* List the per-(team, skill) scout configs for this project. Each row includes its schedule (rolling `run_interval_minutes`, or a project-local `run_cron_schedule` when set), `enabled`, `emit` posture, and `tags`. A freshly authored scout skill appears here once its config is registered, either explicitly via create or by the coordinator's next tick. Pass `tags` to narrow the fleet to the scouts carrying at least one of the given labels.
|
|
* @summary List scout configs
|
|
*/
|
|
export const signalsScoutConfigList = async (
|
|
projectId: string,
|
|
params?: SignalsScoutConfigListParams,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutConfigApi[]> => {
|
|
return apiMutator<SignalScoutConfigApi[]>(getSignalsScoutConfigListUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutConfigCreateUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/configs/`
|
|
}
|
|
|
|
/**
|
|
* Register the config for a `signals-scout-*` skill immediately, without waiting for the coordinator to auto-register it. The same call can optionally set `run_interval_minutes`, a cron `run_cron_schedule`, `enabled`, `emit`, `network_access`, and output destinations. The skill must already exist on this project. Upsert: if a config already exists for the skill, the provided fields are applied to it.
|
|
* @summary Create a scout config
|
|
*/
|
|
export const signalsScoutConfigCreate = async (
|
|
projectId: string,
|
|
signalScoutConfigCreateApi: SignalScoutConfigCreateApi,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutConfigApi> => {
|
|
return apiMutator<SignalScoutConfigApi>(getSignalsScoutConfigCreateUrl(projectId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(signalScoutConfigCreateApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutConfigUpdateUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/configs/${id}/`
|
|
}
|
|
|
|
/**
|
|
* Tune one scout: change its schedule (rolling `run_interval_minutes`, or a cron `run_cron_schedule` that takes precedence when set), `enabled`, `emit` (dry-run) posture, `network_access` (trusted-domain allowlist vs full access for the scout's sandbox), or output destinations. `skill_name` is fixed. Enabling records `enabled_by` and is activity-logged since it drives spend.
|
|
* @summary Update a scout config
|
|
*/
|
|
export const signalsScoutConfigUpdate = async (
|
|
projectId: string,
|
|
id: string,
|
|
patchedSignalScoutConfigUpdateApi?: PatchedSignalScoutConfigUpdateApi,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutConfigApi> => {
|
|
return apiMutator<SignalScoutConfigApi>(getSignalsScoutConfigUpdateUrl(projectId, id), {
|
|
...options,
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(patchedSignalScoutConfigUpdateApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutConfigDestroyUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/configs/${id}/`
|
|
}
|
|
|
|
/**
|
|
* Delete one scout config by its `id`, removing the per-(team, skill) schedule/emit row outright. The point is cleaning up an orphaned config whose `signals-scout-*` skill was archived or deleted — it lingers in `list` with an empty `description`, never runs (the coordinator skips it and the skill can't load), but can't otherwise be removed over the API. Deletion is activity-logged. Note: if the skill still exists, the coordinator re-creates a default-schedule config on its next tick — to retire a live scout, archive its skill (or set `enabled=false` to make it inert) rather than deleting the config.
|
|
* @summary Delete a scout config
|
|
*/
|
|
export const signalsScoutConfigDestroy = async (
|
|
projectId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<void> => {
|
|
return apiMutator<void>(getSignalsScoutConfigDestroyUrl(projectId, id), {
|
|
...options,
|
|
method: 'DELETE',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutConfigRunUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/configs/${id}/run/`
|
|
}
|
|
|
|
/**
|
|
* Dispatch one on-demand run of this scout immediately, regardless of its schedule. Useful to test a scout right after authoring it, or to refresh its findings on demand. The run executes asynchronously on the worker and inherits every guard the scheduled path has: it is forbidden if scouts are not enabled for the project (403), and skipped if the project is over its Signals credits quota or daily run budget (429) or a run for this scout is already in progress (409). A manual run counts against the same daily run budget as scheduled runs, so repeated manual runs of the same scout can exhaust the project's daily allowance. A manual run does not change the scout's schedule or `last_run_at`. A disabled scout can still be run this way (to test before enabling). Returns immediately with the workflow id — poll the scout's runs for the result.
|
|
* @summary Run a scout now
|
|
*/
|
|
export const signalsScoutConfigRun = async (
|
|
projectId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutManualRunApi> => {
|
|
return apiMutator<SignalScoutManualRunApi>(getSignalsScoutConfigRunUrl(projectId, id), {
|
|
...options,
|
|
method: 'POST',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutConfigSyncUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/configs/sync/`
|
|
}
|
|
|
|
/**
|
|
* Materialize the scout fleet for this project on demand (idempotent): seed the canonical `signals-scout-*` skills, create a default-schedule config for any scout lacking one, and return all scout configs. Normally the Temporal coordinator does this on its next tick; this action exists so setup flows (e.g. the wizard's self-driving program) can hand the user a tunable fleet immediately.
|
|
* @summary Sync scout configs
|
|
*/
|
|
export const signalsScoutConfigSync = async (
|
|
projectId: string,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutConfigApi[]> => {
|
|
return apiMutator<SignalScoutConfigApi[]>(getSignalsScoutConfigSyncUrl(projectId), {
|
|
...options,
|
|
method: 'POST',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutMembersListUrl = (projectId: string, params?: SignalsScoutMembersListParams) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/scout/members/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/scout/members/`
|
|
}
|
|
|
|
/**
|
|
* Return the people who can review work on this project — one row per member with access to it, each with their `user_uuid`, `email`, `first_name`/`last_name`, and resolved GitHub `login` (null when they have no linked GitHub identity). The cold-start reviewer-routing path: when a finding's owner can't be read off a fetched entity's `created_by` and there's no cached `reviewer:<area>` memory or inbox precedent, list members, match the owner by email/name, then put their resolved `github_login` in `suggested_reviewers` on `emit-report` / `edit-report`. Pass `search` to narrow a large roster; the result is capped at 200. Strictly team-scoped.
|
|
* @summary List project members for reviewer routing
|
|
*/
|
|
export const signalsScoutMembersList = async (
|
|
projectId: string,
|
|
params?: SignalsScoutMembersListParams,
|
|
options?: RequestInit
|
|
): Promise<ScoutMemberApi[]> => {
|
|
return apiMutator<ScoutMemberApi[]>(getSignalsScoutMembersListUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutMetadataGetUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/metadata/current/`
|
|
}
|
|
|
|
/**
|
|
* Return the project's scout metadata: whether it is enrolled, the current announcement banner (e.g. an alpha run-limit notice, or null when unset), and the enforced run limits with current usage. Limits reflect what the coordinator actually applies at dispatch, so a user can see the real throttle rather than what they assume they set. All values come from the `signals-scout` flag payload, so the banner and caps can change with no deploy.
|
|
* @summary Get scout metadata
|
|
*/
|
|
export const signalsScoutMetadataGet = async (projectId: string, options?: RequestInit): Promise<ScoutMetadataApi> => {
|
|
return apiMutator<ScoutMetadataApi>(getSignalsScoutMetadataGetUrl(projectId), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutNotesListUrl = (projectId: string, params?: SignalsScoutNotesListParams) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/scout/notes/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/scout/notes/`
|
|
}
|
|
|
|
/**
|
|
* Return the steering notes left for this project's scouts, newest first. Pass `skill_name` to get the notes addressed to one scout plus the general (blank-target) fleet-wide notes — the shape a scout run reads at cold start. Omit `skill_name` to browse every note. Expired notes are excluded unless `include_expired=true`. `date_from` / `date_to` are a half-open window on `created_at` (`>= date_from`, `< date_to`); pass `date_to` (the `created_at` of the oldest note seen) to walk past the cap. Results capped at 500.
|
|
* @summary List scout notes
|
|
*/
|
|
export const signalsScoutNotesList = async (
|
|
projectId: string,
|
|
params?: SignalsScoutNotesListParams,
|
|
options?: RequestInit
|
|
): Promise<ScoutNoteApi[]> => {
|
|
return apiMutator<ScoutNoteApi[]>(getSignalsScoutNotesListUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutNotesCreateUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/notes/`
|
|
}
|
|
|
|
/**
|
|
* Leave a steering note the scout fleet reads on its next runs. Address it to one scout via `skill_name` (`signals-scout-*`), or omit it for a general note every scout sees. Each call creates a new note (no upsert); delete retires one. Attributed to the authenticated user.
|
|
* @summary Leave a note for the scouts
|
|
*/
|
|
export const signalsScoutNotesCreate = async (
|
|
projectId: string,
|
|
scoutNoteCreateRequestApi: ScoutNoteCreateRequestApi,
|
|
options?: RequestInit
|
|
): Promise<ScoutNoteApi> => {
|
|
return apiMutator<ScoutNoteApi>(getSignalsScoutNotesCreateUrl(projectId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(scoutNoteCreateRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutNotesDestroyUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/notes/${id}/`
|
|
}
|
|
|
|
/**
|
|
* Delete one note by its `id`, retiring it from every scout's view. Use this when a note has been acted on or no longer applies; time-boxed notes can instead carry an `expires_at` and retire themselves.
|
|
* @summary Delete a scout note
|
|
*/
|
|
export const signalsScoutNotesDestroy = async (projectId: string, id: string, options?: RequestInit): Promise<void> => {
|
|
return apiMutator<void>(getSignalsScoutNotesDestroyUrl(projectId, id), {
|
|
...options,
|
|
method: 'DELETE',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutProjectProfileGetUrl = (
|
|
projectId: string,
|
|
params?: SignalsScoutProjectProfileGetParams
|
|
) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/scout/project_profile/current/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/scout/project_profile/current/`
|
|
}
|
|
|
|
/**
|
|
* Return the team's deterministic project profile. For the internal scout token the response reflects the newest non-expired cached row or a freshly-built one (lazy compute on cache miss); `force_refresh=true` skips the cache and rebuilds from authoritative sources. Public read callers (session auth or a `signal_scout:read` PAK) get the newest cached profile, or 404 if none has been built yet — they never trigger a rebuild. Read this at the start of a run to orient on the team's product mix, integrations, warehouse sources, signal coverage, and existing inbox surface.
|
|
* @summary Get the current project profile
|
|
*/
|
|
export const signalsScoutProjectProfileGet = async (
|
|
projectId: string,
|
|
params?: SignalsScoutProjectProfileGetParams,
|
|
options?: RequestInit
|
|
): Promise<ProjectProfileApi> => {
|
|
return apiMutator<ProjectProfileApi>(getSignalsScoutProjectProfileGetUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutRunsListUrl = (projectId: string, params?: SignalsScoutRunsListParams) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/scout/runs/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/scout/runs/`
|
|
}
|
|
|
|
/**
|
|
* Return the most recent `SignalScoutRun` summaries for this project, newest first. Used by the headless scout to dedupe against work other runs already covered. ILIKE matches on `summary`. `date_from` / `date_to` are a half-open window on `created_at` (`>= date_from`, `< date_to`); pass `date_to` on subsequent calls to walk past the 100-row cap. Pass `emitted=true` to see only runs that surfaced at least one finding. Pass `skill_name` (optionally with `skill_version`) to scope to a single scout. Results capped at 100.
|
|
* @summary Search recent agent runs
|
|
*/
|
|
export const signalsScoutRunsList = async (
|
|
projectId: string,
|
|
params?: SignalsScoutRunsListParams,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutRunSummaryApi[]> => {
|
|
return apiMutator<SignalScoutRunSummaryApi[]>(getSignalsScoutRunsListUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutRunsRetrieveUrl = (projectId: string, runId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/runs/${runId}/`
|
|
}
|
|
|
|
/**
|
|
* Return the full `SignalScoutRun` row. Status, timing, and error flow from the linked `tasks.TaskRun`. Strictly team-scoped — a UUID belonging to another team returns 404.
|
|
* @summary Get a run by ID
|
|
*/
|
|
export const signalsScoutRunsRetrieve = async (
|
|
projectId: string,
|
|
runId: string,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutRunDetailApi> => {
|
|
return apiMutator<SignalScoutRunDetailApi>(getSignalsScoutRunsRetrieveUrl(projectId, runId), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutEditReportUrl = (projectId: string, runId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/runs/${runId}/edit-report/`
|
|
}
|
|
|
|
/**
|
|
* Rewrite a report's title/summary, append a note, and/or set its suggested reviewers. Can target ANY of the project's inbox reports, not just scout-authored ones — so the edit is attributed to this scout. Setting reviewers is how you rescue a report that surfaced routed to no one: it replaces the reviewer list and re-runs autostart, so a report missing a qualifying reviewer can open a draft PR. Title/summary edits are best-effort: the pipeline may later re-research them.
|
|
* @summary Edit an existing report for a run
|
|
*/
|
|
export const signalsScoutEditReport = async (
|
|
projectId: string,
|
|
runId: string,
|
|
editReportRequestApi: EditReportRequestApi,
|
|
options?: RequestInit
|
|
): Promise<EditReportResponseApi> => {
|
|
return apiMutator<EditReportResponseApi>(getSignalsScoutEditReportUrl(projectId, runId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(editReportRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutRunsEmissionsUrl = (projectId: string, runId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/runs/${runId}/emissions/`
|
|
}
|
|
|
|
/**
|
|
* Return the findings a `SignalScoutRun` emitted to the inbox, newest first — one row per emit with its `description` (the finding text as surfaced), `weight`, `confidence`, `severity`, and the deterministic `source_id` that joins back to the underlying signal. Lets a team and its agents see *what* a run surfaced without parsing `emitted_finding_ids` or scanning the signal store. Strictly team-scoped — a run UUID belonging to another team returns 404.
|
|
* @summary List a run's emitted findings
|
|
*/
|
|
export const signalsScoutRunsEmissions = async (
|
|
projectId: string,
|
|
runId: string,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutEmissionApi[]> => {
|
|
return apiMutator<SignalScoutEmissionApi[]>(getSignalsScoutRunsEmissionsUrl(projectId, runId), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutRunsEmissionReportsUrl = (projectId: string, runId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/runs/${runId}/emissions/reports/`
|
|
}
|
|
|
|
/**
|
|
* Best-effort reverse of the report -> signals link. For each finding the run emitted, resolve the inbox `SignalReport` (if any) its underlying signal grouped into by walking the deterministic `source_id` back through the signal store. `report` is null when the finding hasn't grouped into a report yet, was de-duplicated away, or its signal was deleted. Lets the scout UI surface which inbox report a finding contributed to — the reverse of the report's evidence list. Strictly team-scoped — a run UUID belonging to another team returns 404.
|
|
* @summary List the inbox reports a run's findings linked to
|
|
*/
|
|
export const signalsScoutRunsEmissionReports = async (
|
|
projectId: string,
|
|
runId: string,
|
|
options?: RequestInit
|
|
): Promise<ScoutEmissionReportLinkApi[]> => {
|
|
return apiMutator<ScoutEmissionReportLinkApi[]>(getSignalsScoutRunsEmissionReportsUrl(projectId, runId), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutEmitReportUrl = (projectId: string, runId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/runs/${runId}/emit-report/`
|
|
}
|
|
|
|
/**
|
|
* The second emit channel: author a complete `SignalReport` directly instead of emitting a weak signal. The report passes the safety judge, then surfaces at the status the scout's `actionability` call implies (or is suppressed). Backing `evidence` is written as bound signals so the report behaves like a pipeline report. NOT idempotent — a retry authors a second report; use `reports` to find a prior report and `edit-report` to update it instead.
|
|
* @summary Author a full report for a run
|
|
*/
|
|
export const signalsScoutEmitReport = async (
|
|
projectId: string,
|
|
runId: string,
|
|
emitReportRequestApi: EmitReportRequestApi,
|
|
options?: RequestInit
|
|
): Promise<EmitReportResponseApi> => {
|
|
return apiMutator<EmitReportResponseApi>(getSignalsScoutEmitReportUrl(projectId, runId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(emitReportRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutEmitSignalUrl = (projectId: string, runId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/runs/${runId}/emit-signal/`
|
|
}
|
|
|
|
/**
|
|
* Fire `emit_signal` with `source_product = signals_scout`. The `finding_id` is baked into the deterministic `Signal.source_id = run:<id>:finding:<id>` for traceability, but this is NOT idempotent — a second call with the same `finding_id` emits a second signal, so do not retry an emit that may have already succeeded.
|
|
* @summary Emit a finding for a run
|
|
*/
|
|
export const signalsScoutEmitSignal = async (
|
|
projectId: string,
|
|
runId: string,
|
|
emitFindingRequestApi: EmitFindingRequestApi,
|
|
options?: RequestInit
|
|
): Promise<EmitFindingResponseApi> => {
|
|
return apiMutator<EmitFindingResponseApi>(getSignalsScoutEmitSignalUrl(projectId, runId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(emitFindingRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutRecordOutputUrl = (projectId: string, runId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/runs/${runId}/record-output/`
|
|
}
|
|
|
|
/**
|
|
* The structured-output channel: record schema-validated records this run produced. Opt-in via the scout config's `structured_output_schema` (a JSON Schema describing one record) — without it the call fails closed, as it does for a dry-run scout (emit off). All-or-nothing: any invalid record fails the whole call with nothing written, so fix and resubmit the batch. Each accepted record lands in the project's event stream as a `$scout_structured_output` event — query them like any event (insights, SQL over `events`). Recording is idempotent: event ids are deterministic, so resubmitting an identical batch (e.g. retrying after a 503) cannot double-count.
|
|
* @summary Record structured output for a run
|
|
*/
|
|
export const signalsScoutRecordOutput = async (
|
|
projectId: string,
|
|
runId: string,
|
|
recordStructuredOutputRequestApi: RecordStructuredOutputRequestApi,
|
|
options?: RequestInit
|
|
): Promise<RecordStructuredOutputResponseApi> => {
|
|
return apiMutator<RecordStructuredOutputResponseApi>(getSignalsScoutRecordOutputUrl(projectId, runId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(recordStructuredOutputRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutRunsEmissionsBatchUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/runs/emissions/batch/`
|
|
}
|
|
|
|
/**
|
|
* Batched form of the per-run emissions endpoint: return the findings every requested `SignalScoutRun` emitted, flattened newest-first, in a single request. Each row carries its `run_id`, so the caller can regroup by run. The findings UI uses this to load the whole recent window in one round-trip instead of one request per run. Strictly team-scoped — run ids belonging to another team contribute no rows (no per-run 404; one stale id never fails the batch).
|
|
* @summary List emitted findings for many runs at once
|
|
*/
|
|
export const signalsScoutRunsEmissionsBatch = async (
|
|
projectId: string,
|
|
scoutRunIdsBatchRequestApi: ScoutRunIdsBatchRequestApi,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutEmissionApi[]> => {
|
|
return apiMutator<SignalScoutEmissionApi[]>(getSignalsScoutRunsEmissionsBatchUrl(projectId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(scoutRunIdsBatchRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutRunsRecentEmissionsUrl = (
|
|
projectId: string,
|
|
params?: SignalsScoutRunsRecentEmissionsParams
|
|
) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/scout/runs/emissions/recent/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/scout/runs/emissions/recent/`
|
|
}
|
|
|
|
/**
|
|
* Return the team's recently emitted scout findings across *every* run, newest first — the cross-run counterpart to the per-run `emissions` action. Each row carries its `run_id`, so you can regroup by run without first listing runs and fanning out one `emissions` call each. Pass `skill_name` to scope to a single scout, and `date_from` / `date_to` (a half-open window on `emitted_at`) to bound or paginate — set `date_to` to the oldest emission's `emitted_at` to walk back past the limit. Pure Postgres, no Datastore round-trip. Capped at 200 rows (default 50).
|
|
* @summary List recent emitted findings across all runs
|
|
*/
|
|
export const signalsScoutRunsRecentEmissions = async (
|
|
projectId: string,
|
|
params?: SignalsScoutRunsRecentEmissionsParams,
|
|
options?: RequestInit
|
|
): Promise<SignalScoutEmissionApi[]> => {
|
|
return apiMutator<SignalScoutEmissionApi[]>(getSignalsScoutRunsRecentEmissionsUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutRunsEmissionReportsBatchUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/runs/emissions/reports/batch/`
|
|
}
|
|
|
|
/**
|
|
* Batched form of the per-run emission-reports endpoint. For every finding the requested runs emitted, resolve the inbox `SignalReport` (if any) its signal grouped into — all in a single Datastore round-trip rather than one query per run, which is what made the findings page slow to open. `report` is null when a finding hasn't grouped yet, was de-duplicated, or its signal was deleted. Strictly team-scoped — run ids belonging to another team contribute no rows.
|
|
* @summary List the inbox reports many runs' findings linked to
|
|
*/
|
|
export const signalsScoutRunsEmissionReportsBatch = async (
|
|
projectId: string,
|
|
scoutRunIdsBatchRequestApi: ScoutRunIdsBatchRequestApi,
|
|
options?: RequestInit
|
|
): Promise<ScoutEmissionReportLinkApi[]> => {
|
|
return apiMutator<ScoutEmissionReportLinkApi[]>(getSignalsScoutRunsEmissionReportsBatchUrl(projectId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(scoutRunIdsBatchRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutRunsFindingsSummaryUrl = (
|
|
projectId: string,
|
|
params?: SignalsScoutRunsFindingsSummaryParams
|
|
) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/scout/runs/findings/summary/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/scout/runs/findings/summary/`
|
|
}
|
|
|
|
/**
|
|
* Return a cheap fleet-wide tally of the output the scout troop produced in the recent window — the finding count, the distinct reports authored/edited via the report channel, the number of distinct scouts behind them, and the latest output time. Backs the 'Scout findings' callout so it renders from one query instead of the client paging through the whole runs window. Counts runs that emitted at least one finding (`emitted_count > 0`) or authored/edited an inbox report within the last `window_hours` (default 72), capped to the most recent 120 such runs so the count matches what the findings list renders. Strictly team-scoped.
|
|
* @summary Summarise recent scout output across the fleet
|
|
*/
|
|
export const signalsScoutRunsFindingsSummary = async (
|
|
projectId: string,
|
|
params?: SignalsScoutRunsFindingsSummaryParams,
|
|
options?: RequestInit
|
|
): Promise<FleetFindingsSummaryApi> => {
|
|
return apiMutator<FleetFindingsSummaryApi>(getSignalsScoutRunsFindingsSummaryUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutScratchpadSearchUrl = (projectId: string, params?: SignalsScoutScratchpadSearchParams) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/scout/scratchpad/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/scout/scratchpad/`
|
|
}
|
|
|
|
/**
|
|
* Return `SignalScratchpad` entries for this project, newest-first. ILIKE matches on `content` and `key`; pass `key` instead for an exact single-entry lookup. `date_from` / `date_to` are a half-open window on `updated_at` (`>= date_from`, `< date_to`); pass `date_to` (the `updated_at` of the oldest entry seen) on subsequent calls to walk past the cap. Pass `keys_only=true` to scan keys without pulling entry bodies, or `content_max_chars` to cap each `content` to a preview — both keep a wide orientation scan from returning every entry's full prose. Results capped at 1000.
|
|
* @summary Search the scout scratchpad
|
|
*/
|
|
export const signalsScoutScratchpadSearch = async (
|
|
projectId: string,
|
|
params?: SignalsScoutScratchpadSearchParams,
|
|
options?: RequestInit
|
|
): Promise<ScratchpadEntryApi[]> => {
|
|
return apiMutator<ScratchpadEntryApi[]>(getSignalsScoutScratchpadSearchUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutScratchpadRememberUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/scratchpad/`
|
|
}
|
|
|
|
/**
|
|
* Upsert a memory keyed on `(team, key)`. Re-using a key updates the existing entry in place.
|
|
* @summary Remember a scratchpad entry
|
|
*/
|
|
export const signalsScoutScratchpadRemember = async (
|
|
projectId: string,
|
|
rememberRequestApi: RememberRequestApi,
|
|
options?: RequestInit
|
|
): Promise<ScratchpadEntryApi> => {
|
|
return apiMutator<ScratchpadEntryApi>(getSignalsScoutScratchpadRememberUrl(projectId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(rememberRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsScoutScratchpadForgetUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/scout/scratchpad/forget/`
|
|
}
|
|
|
|
/**
|
|
* Delete an entry by key. Returns `deleted=false` if no row matched.
|
|
* @summary Forget a scratchpad entry by key
|
|
*/
|
|
export const signalsScoutScratchpadForget = async (
|
|
projectId: string,
|
|
forgetRequestApi: ForgetRequestApi,
|
|
options?: RequestInit
|
|
): Promise<ForgetResponseApi> => {
|
|
return apiMutator<ForgetResponseApi>(getSignalsScoutScratchpadForgetUrl(projectId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(forgetRequestApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsSourceConfigsListUrl = (projectId: string, params?: SignalsSourceConfigsListParams) => {
|
|
const normalizedParams = new URLSearchParams()
|
|
|
|
Object.entries(params || {}).forEach(([key, value]) => {
|
|
if (value !== undefined) {
|
|
normalizedParams.append(key, value === null ? 'null' : String(value))
|
|
}
|
|
})
|
|
|
|
const stringifiedParams = normalizedParams.toString()
|
|
|
|
return stringifiedParams.length > 0
|
|
? `/v1/projects/${projectId}/signals/source_configs/?${stringifiedParams}`
|
|
: `/v1/projects/${projectId}/signals/source_configs/`
|
|
}
|
|
|
|
export const signalsSourceConfigsList = async (
|
|
projectId: string,
|
|
params?: SignalsSourceConfigsListParams,
|
|
options?: RequestInit
|
|
): Promise<PaginatedSignalSourceConfigListApi> => {
|
|
return apiMutator<PaginatedSignalSourceConfigListApi>(getSignalsSourceConfigsListUrl(projectId, params), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsSourceConfigsCreateUrl = (projectId: string) => {
|
|
return `/v1/projects/${projectId}/signals/source_configs/`
|
|
}
|
|
|
|
export const signalsSourceConfigsCreate = async (
|
|
projectId: string,
|
|
signalSourceConfigApi: NonReadonly<SignalSourceConfigApi>,
|
|
options?: RequestInit
|
|
): Promise<SignalSourceConfigApi> => {
|
|
return apiMutator<SignalSourceConfigApi>(getSignalsSourceConfigsCreateUrl(projectId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(signalSourceConfigApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsSourceConfigsRetrieveUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/source_configs/${id}/`
|
|
}
|
|
|
|
export const signalsSourceConfigsRetrieve = async (
|
|
projectId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<SignalSourceConfigApi> => {
|
|
return apiMutator<SignalSourceConfigApi>(getSignalsSourceConfigsRetrieveUrl(projectId, id), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getSignalsSourceConfigsUpdateUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/source_configs/${id}/`
|
|
}
|
|
|
|
export const signalsSourceConfigsUpdate = async (
|
|
projectId: string,
|
|
id: string,
|
|
signalSourceConfigApi: NonReadonly<SignalSourceConfigApi>,
|
|
options?: RequestInit
|
|
): Promise<SignalSourceConfigApi> => {
|
|
return apiMutator<SignalSourceConfigApi>(getSignalsSourceConfigsUpdateUrl(projectId, id), {
|
|
...options,
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(signalSourceConfigApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsSourceConfigsPartialUpdateUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/source_configs/${id}/`
|
|
}
|
|
|
|
export const signalsSourceConfigsPartialUpdate = async (
|
|
projectId: string,
|
|
id: string,
|
|
patchedSignalSourceConfigApi?: NonReadonly<PatchedSignalSourceConfigApi>,
|
|
options?: RequestInit
|
|
): Promise<SignalSourceConfigApi> => {
|
|
return apiMutator<SignalSourceConfigApi>(getSignalsSourceConfigsPartialUpdateUrl(projectId, id), {
|
|
...options,
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(patchedSignalSourceConfigApi),
|
|
})
|
|
}
|
|
|
|
export const getSignalsSourceConfigsDestroyUrl = (projectId: string, id: string) => {
|
|
return `/v1/projects/${projectId}/signals/source_configs/${id}/`
|
|
}
|
|
|
|
export const signalsSourceConfigsDestroy = async (
|
|
projectId: string,
|
|
id: string,
|
|
options?: RequestInit
|
|
): Promise<void> => {
|
|
return apiMutator<void>(getSignalsSourceConfigsDestroyUrl(projectId, id), {
|
|
...options,
|
|
method: 'DELETE',
|
|
})
|
|
}
|
|
|
|
export const getUsersSignalAutonomyRetrieveUrl = (userId: string) => {
|
|
return `/v1/users/${userId}/signal_autonomy/`
|
|
}
|
|
|
|
/**
|
|
* Per-user signal autonomy config (singleton keyed by user).
|
|
*
|
|
* GET /v1/users/<id>/signal_autonomy/ → current config (or 404)
|
|
* POST /v1/users/<id>/signal_autonomy/ → create or update
|
|
* DELETE /v1/users/<id>/signal_autonomy/ → remove (opt out)
|
|
*/
|
|
export const usersSignalAutonomyRetrieve = async (
|
|
userId: string,
|
|
options?: RequestInit
|
|
): Promise<SignalUserAutonomyConfigApi> => {
|
|
return apiMutator<SignalUserAutonomyConfigApi>(getUsersSignalAutonomyRetrieveUrl(userId), {
|
|
...options,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
export const getUsersSignalAutonomyCreateUrl = (userId: string) => {
|
|
return `/v1/users/${userId}/signal_autonomy/`
|
|
}
|
|
|
|
/**
|
|
* Per-user signal autonomy config (singleton keyed by user).
|
|
*
|
|
* GET /v1/users/<id>/signal_autonomy/ → current config (or 404)
|
|
* POST /v1/users/<id>/signal_autonomy/ → create or update
|
|
* DELETE /v1/users/<id>/signal_autonomy/ → remove (opt out)
|
|
*/
|
|
export const usersSignalAutonomyCreate = async (
|
|
userId: string,
|
|
signalUserAutonomyConfigApi?: NonReadonly<SignalUserAutonomyConfigApi>,
|
|
options?: RequestInit
|
|
): Promise<SignalUserAutonomyConfigApi> => {
|
|
return apiMutator<SignalUserAutonomyConfigApi>(getUsersSignalAutonomyCreateUrl(userId), {
|
|
...options,
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', ...options?.headers },
|
|
body: JSON.stringify(signalUserAutonomyConfigApi),
|
|
})
|
|
}
|
|
|
|
export const getUsersSignalAutonomyDestroyUrl = (userId: string) => {
|
|
return `/v1/users/${userId}/signal_autonomy/`
|
|
}
|
|
|
|
/**
|
|
* Per-user signal autonomy config (singleton keyed by user).
|
|
*
|
|
* GET /v1/users/<id>/signal_autonomy/ → current config (or 404)
|
|
* POST /v1/users/<id>/signal_autonomy/ → create or update
|
|
* DELETE /v1/users/<id>/signal_autonomy/ → remove (opt out)
|
|
*/
|
|
export const usersSignalAutonomyDestroy = async (userId: string, options?: RequestInit): Promise<void> => {
|
|
return apiMutator<void>(getUsersSignalAutonomyDestroyUrl(userId), {
|
|
...options,
|
|
method: 'DELETE',
|
|
})
|
|
}
|