import type { AiCfoSuggestedQuestionsPageContext } from '../../common/aiCfo/aiCfoSuggestedQuestionsPageContext'; import { ID } from '../../commonStateTypes/common'; import { AiCfoAnswerPayload, ChatSessionPayload } from '../../entity/aiCfo/aiCfoPayload'; import { UserRolePayload } from '../../entity/userRole/userRolePayload'; import { ZeniAPIResponse } from '../../responsePayload'; export type FeedbackType = 'positive' | 'negative'; export interface SubmitFeedbackPayload { chatMessageId: ID; chatSessionId: ID; feedbackType: FeedbackType; answerText?: string; model?: string; questionText?: string; } export type ContextStatus = 'NONE' | 'NOT_FOUND' | 'PERMISSION_DENIED' | 'SUCCESS'; export interface CreateSessionResponseData { chat_session_id: string; created_at: string; context_message?: string; context_status?: ContextStatus; } interface SessionsResponseData { next_page_token: string | null; sessions: ChatSessionPayload[]; } export interface StopSubmitResponseData { message: string; } export type FetchChatSessionsForUserResponse = ZeniAPIResponse; export type CreateSessionResponse = ZeniAPIResponse; export type SubmitQuestionResponse = ZeniAPIResponse; export type StopSubmitResponse = ZeniAPIResponse; interface AcceptMasterTOSPayload { user_roles: UserRolePayload[]; } export type AcceptMasterTOSResponse = ZeniAPIResponse; export interface SuggestedQuestionsDataPayload { generated_at: string; page_context: AiCfoSuggestedQuestionsPageContext; suggested_questions: string[]; } export type FetchSuggestedQuestionsResponse = ZeniAPIResponse; /** One entry in the `/` skill menu — from GET {chat}/1.0/skills (SkillSummary). */ export interface SkillSummaryPayload { description: string | null; display_name: string | null; has_scripts: boolean; macro_id: string; name: string; parameter_hints: Record | null; semver: string | null; /** * Optional because the endpoint is not schema-validated and older server builds omit * these three entirely. Typing them required made the defensive coercions in both * epics (`=== true`, `?? null`) read as no-ops on fields TypeScript believed were * always present — the guard was real, but its reason was invisible. */ /** * Whether the CALLER authored this skill. Writes require ownership, not merely the same * tenant, so a client without this offers Edit, Delete and Publish on a colleague's * shared skill — all of which the API refuses. Absent reads as false: withhold the * write controls rather than offer ones that fail. */ is_mine?: boolean; is_owned_by_tenant?: boolean; updated_at?: string | null; visibility?: string | null; } export interface SkillListDataPayload { skills: SkillSummaryPayload[]; /** * Whether THIS caller may publish a skill tenant-wide. Not derivable client-side: * roles live in the tenant service and the browser never sees a scope list. Absent * reads as false, so a server that predates the field hides the control rather than * offering a button the API refuses. */ can_publish?: boolean; /** * Whether the skills feature is on for this tenant. Distinct from an empty * `skills` array, which also happens when the feature IS on and the tenant has * no skills — the Skills menu entry is hidden on the former and shown (empty) * on the latter, so the two must be told apart. */ skills_enabled?: boolean; } export interface SkillDetailDataPayload { /** The verbatim prompt the skill sends to the agent. */ instructions: string; skill: SkillSummaryPayload; /** * Optional for the same reason as the four on `SkillSummaryPayload` above, and marked * here rather than downstream so there is one idiom for one problem: the endpoint is * not schema-validated, so any field may be absent. * * `instructions` and `skill` stay REQUIRED because they are the two fields every * consumer dereferences unsafely — so the guards in `toSkillDetail.ts` check exactly * those two, and a predicate narrowing to this type is then telling the truth. These * three are unchecked, so the compiler makes the mapper coerce them; typing them * required is what let a `?? ''` sit next to a field TypeScript believed was always * there, each one silently claiming the other was wrong. */ artifact?: string; artifact_title?: string; instructions_char_count?: number; } export interface SkillVersionSummaryPayload { version: number; /** Menu name AT this version — a rename shows up as a change here. */ display_name?: string | null; /** Prompt length, so a history row can show that something changed without a diff. */ instructions_char_count?: number; is_active?: boolean; /** Whether this is the version the `/` menu runs. */ is_latest?: boolean; semver?: string | null; updated_at?: string | null; } export interface SkillVersionListDataPayload { versions?: SkillVersionSummaryPayload[]; } /** * What the client may send when authoring. Narrower than the skill itself on purpose: * the server rejects (not ignores) `scripts`, `tenant_id`, `macro_id` and * `is_visible_in_chat`, so sending any of them is a 400 rather than a silent no-op. */ export interface SkillWritePayload extends Record { instructions: string; name: string; description?: string | null; display_name?: string | null; parameter_hints?: Record | null; /** Omitted means unchanged on update, private on create. */ visibility?: string | null; } export type FetchSkillsResponse = ZeniAPIResponse; /** The detail route with `?version=N` answers with the same shape as a live read. */ export type FetchSkillVersionBodyResponse = ZeniAPIResponse; export type FetchSkillVersionsResponse = ZeniAPIResponse; /** Create and update both answer with the same shape a detail read returns. */ export type SaveSkillResponse = ZeniAPIResponse; export type FetchSkillDetailResponse = ZeniAPIResponse; /** * One routine as the server sends it, from GET/POST/PUT /1.0/routines. * * Every field past the identity trio is optional here because the mapper is the * only place that decides what a missing one means. Typing them required would * let a `?? fallback` sit beside a field the compiler believed was always * present — each silently claiming the other is wrong. */ export interface RoutinePayload { name: string; schedule_id: string; consecutive_failures?: number; day_of_month?: number | null; enabled?: boolean; hour?: number; is_ad_hoc?: boolean; last_run_at?: string | null; last_status?: string | null; /** * Absent on a routine whose skill was deleted, which the mapper turns into * "" and the detail page reports. Typed required, it was the exact thing the * note above warns against: `toRoutine` fell back with `?? ''`, the guard * deliberately did not require it, and a test had to cast to build one — all * three disagreeing with the type. */ macro_id?: string | null; minute?: number; next_run_at?: string | null; pinned_version?: number | null; recurrence?: string; session_id?: string | null; tz_name?: string; unread_runs?: number; weekday?: number | null; } export interface RoutineListDataPayload { max_routines?: number; routines?: RoutinePayload[]; routines_enabled?: boolean; } /** * What the client may send. Narrower than a routine: `schedule_id`, * `pinned_version` on create, and every run-outcome field are the server's to * set, so sending them is a 400 rather than a silent no-op. */ export interface RoutineWritePayload extends Record { hour: number; name: string; recurrence: string; tz_name: string; day_of_month?: number; enabled?: boolean; /** Exactly one of macro_id and prompt. Both, or neither, is refused. */ macro_id?: string; minute?: number; prompt?: string; weekday?: number; } export type FetchRoutinesResponse = ZeniAPIResponse; /** Create and update both answer with a single routine. */ export type SaveRoutineResponse = ZeniAPIResponse; /** * The answer to a Run-now. `status` is 'queued', or 'already_running' when the * same routine was already started this minute — both are 200s, and neither * carries the routine. */ export interface RunRoutineDataPayload { run_id?: string; schedule_id?: string; status?: string; } export type RunRoutineResponse = ZeniAPIResponse; /** One past or in-flight run, as GET /1.0/routines/{id}/runs returns it. */ export interface RoutineRunPayload { run_id: string; attempt?: number; error?: string | null; finished_at?: string | null; is_manual?: boolean; question_answer_id?: string | null; scheduled_for?: string | null; session_id?: string | null; started_at?: string | null; status?: string; } export interface RoutineRunsDataPayload { runs?: RoutineRunPayload[]; session_id?: string | null; } export type RoutineRunsResponse = ZeniAPIResponse; export {};