Add HR agent onboarding model and actor enforcement
This commit is contained in:
@@ -21,6 +21,9 @@ import type {
|
||||
} from "@tanstack/react-query";
|
||||
|
||||
import type {
|
||||
AgentOnboarding,
|
||||
AgentOnboardingCreate,
|
||||
AgentOnboardingUpdate,
|
||||
EmploymentAction,
|
||||
EmploymentActionCreate,
|
||||
HTTPValidationError,
|
||||
@@ -748,3 +751,434 @@ export const useCreateEmploymentActionHrActionsPost = <
|
||||
queryClient,
|
||||
);
|
||||
};
|
||||
/**
|
||||
* @summary List Agent Onboarding
|
||||
*/
|
||||
export type listAgentOnboardingHrOnboardingGetResponse200 = {
|
||||
data: AgentOnboarding[];
|
||||
status: 200;
|
||||
};
|
||||
|
||||
export type listAgentOnboardingHrOnboardingGetResponseSuccess =
|
||||
listAgentOnboardingHrOnboardingGetResponse200 & {
|
||||
headers: Headers;
|
||||
};
|
||||
export type listAgentOnboardingHrOnboardingGetResponse =
|
||||
listAgentOnboardingHrOnboardingGetResponseSuccess;
|
||||
|
||||
export const getListAgentOnboardingHrOnboardingGetUrl = () => {
|
||||
return `/hr/onboarding`;
|
||||
};
|
||||
|
||||
export const listAgentOnboardingHrOnboardingGet = async (
|
||||
options?: RequestInit,
|
||||
): Promise<listAgentOnboardingHrOnboardingGetResponse> => {
|
||||
return customFetch<listAgentOnboardingHrOnboardingGetResponse>(
|
||||
getListAgentOnboardingHrOnboardingGetUrl(),
|
||||
{
|
||||
...options,
|
||||
method: "GET",
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const getListAgentOnboardingHrOnboardingGetQueryKey = () => {
|
||||
return [`/hr/onboarding`] as const;
|
||||
};
|
||||
|
||||
export const getListAgentOnboardingHrOnboardingGetQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError = unknown,
|
||||
>(options?: {
|
||||
query?: Partial<
|
||||
UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError,
|
||||
TData
|
||||
>
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
}) => {
|
||||
const { query: queryOptions, request: requestOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getListAgentOnboardingHrOnboardingGetQueryKey();
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>
|
||||
> = ({ signal }) =>
|
||||
listAgentOnboardingHrOnboardingGet({ signal, ...requestOptions });
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: DataTag<QueryKey, TData, TError> };
|
||||
};
|
||||
|
||||
export type ListAgentOnboardingHrOnboardingGetQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>
|
||||
>;
|
||||
export type ListAgentOnboardingHrOnboardingGetQueryError = unknown;
|
||||
|
||||
export function useListAgentOnboardingHrOnboardingGet<
|
||||
TData = Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError = unknown,
|
||||
>(
|
||||
options: {
|
||||
query: Partial<
|
||||
UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError,
|
||||
TData
|
||||
>
|
||||
> &
|
||||
Pick<
|
||||
DefinedInitialDataOptions<
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError,
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>
|
||||
>,
|
||||
"initialData"
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): DefinedUseQueryResult<TData, TError> & {
|
||||
queryKey: DataTag<QueryKey, TData, TError>;
|
||||
};
|
||||
export function useListAgentOnboardingHrOnboardingGet<
|
||||
TData = Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError = unknown,
|
||||
>(
|
||||
options?: {
|
||||
query?: Partial<
|
||||
UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError,
|
||||
TData
|
||||
>
|
||||
> &
|
||||
Pick<
|
||||
UndefinedInitialDataOptions<
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError,
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>
|
||||
>,
|
||||
"initialData"
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): UseQueryResult<TData, TError> & {
|
||||
queryKey: DataTag<QueryKey, TData, TError>;
|
||||
};
|
||||
export function useListAgentOnboardingHrOnboardingGet<
|
||||
TData = Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError = unknown,
|
||||
>(
|
||||
options?: {
|
||||
query?: Partial<
|
||||
UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError,
|
||||
TData
|
||||
>
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): UseQueryResult<TData, TError> & {
|
||||
queryKey: DataTag<QueryKey, TData, TError>;
|
||||
};
|
||||
/**
|
||||
* @summary List Agent Onboarding
|
||||
*/
|
||||
|
||||
export function useListAgentOnboardingHrOnboardingGet<
|
||||
TData = Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError = unknown,
|
||||
>(
|
||||
options?: {
|
||||
query?: Partial<
|
||||
UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listAgentOnboardingHrOnboardingGet>>,
|
||||
TError,
|
||||
TData
|
||||
>
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): UseQueryResult<TData, TError> & {
|
||||
queryKey: DataTag<QueryKey, TData, TError>;
|
||||
} {
|
||||
const queryOptions =
|
||||
getListAgentOnboardingHrOnboardingGetQueryOptions(options);
|
||||
|
||||
const query = useQuery(queryOptions, queryClient) as UseQueryResult<
|
||||
TData,
|
||||
TError
|
||||
> & { queryKey: DataTag<QueryKey, TData, TError> };
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Create Agent Onboarding
|
||||
*/
|
||||
export type createAgentOnboardingHrOnboardingPostResponse200 = {
|
||||
data: AgentOnboarding;
|
||||
status: 200;
|
||||
};
|
||||
|
||||
export type createAgentOnboardingHrOnboardingPostResponse422 = {
|
||||
data: HTTPValidationError;
|
||||
status: 422;
|
||||
};
|
||||
|
||||
export type createAgentOnboardingHrOnboardingPostResponseSuccess =
|
||||
createAgentOnboardingHrOnboardingPostResponse200 & {
|
||||
headers: Headers;
|
||||
};
|
||||
export type createAgentOnboardingHrOnboardingPostResponseError =
|
||||
createAgentOnboardingHrOnboardingPostResponse422 & {
|
||||
headers: Headers;
|
||||
};
|
||||
|
||||
export type createAgentOnboardingHrOnboardingPostResponse =
|
||||
| createAgentOnboardingHrOnboardingPostResponseSuccess
|
||||
| createAgentOnboardingHrOnboardingPostResponseError;
|
||||
|
||||
export const getCreateAgentOnboardingHrOnboardingPostUrl = () => {
|
||||
return `/hr/onboarding`;
|
||||
};
|
||||
|
||||
export const createAgentOnboardingHrOnboardingPost = async (
|
||||
agentOnboardingCreate: AgentOnboardingCreate,
|
||||
options?: RequestInit,
|
||||
): Promise<createAgentOnboardingHrOnboardingPostResponse> => {
|
||||
return customFetch<createAgentOnboardingHrOnboardingPostResponse>(
|
||||
getCreateAgentOnboardingHrOnboardingPostUrl(),
|
||||
{
|
||||
...options,
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||
body: JSON.stringify(agentOnboardingCreate),
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const getCreateAgentOnboardingHrOnboardingPostMutationOptions = <
|
||||
TError = HTTPValidationError,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createAgentOnboardingHrOnboardingPost>>,
|
||||
TError,
|
||||
{ data: AgentOnboardingCreate },
|
||||
TContext
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createAgentOnboardingHrOnboardingPost>>,
|
||||
TError,
|
||||
{ data: AgentOnboardingCreate },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ["createAgentOnboardingHrOnboardingPost"];
|
||||
const { mutation: mutationOptions, request: requestOptions } = options
|
||||
? options.mutation &&
|
||||
"mutationKey" in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey }, request: undefined };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createAgentOnboardingHrOnboardingPost>>,
|
||||
{ data: AgentOnboardingCreate }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return createAgentOnboardingHrOnboardingPost(data, requestOptions);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type CreateAgentOnboardingHrOnboardingPostMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createAgentOnboardingHrOnboardingPost>>
|
||||
>;
|
||||
export type CreateAgentOnboardingHrOnboardingPostMutationBody =
|
||||
AgentOnboardingCreate;
|
||||
export type CreateAgentOnboardingHrOnboardingPostMutationError =
|
||||
HTTPValidationError;
|
||||
|
||||
/**
|
||||
* @summary Create Agent Onboarding
|
||||
*/
|
||||
export const useCreateAgentOnboardingHrOnboardingPost = <
|
||||
TError = HTTPValidationError,
|
||||
TContext = unknown,
|
||||
>(
|
||||
options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createAgentOnboardingHrOnboardingPost>>,
|
||||
TError,
|
||||
{ data: AgentOnboardingCreate },
|
||||
TContext
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createAgentOnboardingHrOnboardingPost>>,
|
||||
TError,
|
||||
{ data: AgentOnboardingCreate },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(
|
||||
getCreateAgentOnboardingHrOnboardingPostMutationOptions(options),
|
||||
queryClient,
|
||||
);
|
||||
};
|
||||
/**
|
||||
* @summary Update Agent Onboarding
|
||||
*/
|
||||
export type updateAgentOnboardingHrOnboardingOnboardingIdPatchResponse200 = {
|
||||
data: AgentOnboarding;
|
||||
status: 200;
|
||||
};
|
||||
|
||||
export type updateAgentOnboardingHrOnboardingOnboardingIdPatchResponse422 = {
|
||||
data: HTTPValidationError;
|
||||
status: 422;
|
||||
};
|
||||
|
||||
export type updateAgentOnboardingHrOnboardingOnboardingIdPatchResponseSuccess =
|
||||
updateAgentOnboardingHrOnboardingOnboardingIdPatchResponse200 & {
|
||||
headers: Headers;
|
||||
};
|
||||
export type updateAgentOnboardingHrOnboardingOnboardingIdPatchResponseError =
|
||||
updateAgentOnboardingHrOnboardingOnboardingIdPatchResponse422 & {
|
||||
headers: Headers;
|
||||
};
|
||||
|
||||
export type updateAgentOnboardingHrOnboardingOnboardingIdPatchResponse =
|
||||
| updateAgentOnboardingHrOnboardingOnboardingIdPatchResponseSuccess
|
||||
| updateAgentOnboardingHrOnboardingOnboardingIdPatchResponseError;
|
||||
|
||||
export const getUpdateAgentOnboardingHrOnboardingOnboardingIdPatchUrl = (
|
||||
onboardingId: number,
|
||||
) => {
|
||||
return `/hr/onboarding/${onboardingId}`;
|
||||
};
|
||||
|
||||
export const updateAgentOnboardingHrOnboardingOnboardingIdPatch = async (
|
||||
onboardingId: number,
|
||||
agentOnboardingUpdate: AgentOnboardingUpdate,
|
||||
options?: RequestInit,
|
||||
): Promise<updateAgentOnboardingHrOnboardingOnboardingIdPatchResponse> => {
|
||||
return customFetch<updateAgentOnboardingHrOnboardingOnboardingIdPatchResponse>(
|
||||
getUpdateAgentOnboardingHrOnboardingOnboardingIdPatchUrl(onboardingId),
|
||||
{
|
||||
...options,
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||
body: JSON.stringify(agentOnboardingUpdate),
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const getUpdateAgentOnboardingHrOnboardingOnboardingIdPatchMutationOptions =
|
||||
<TError = HTTPValidationError, TContext = unknown>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<
|
||||
ReturnType<typeof updateAgentOnboardingHrOnboardingOnboardingIdPatch>
|
||||
>,
|
||||
TError,
|
||||
{ onboardingId: number; data: AgentOnboardingUpdate },
|
||||
TContext
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<
|
||||
ReturnType<typeof updateAgentOnboardingHrOnboardingOnboardingIdPatch>
|
||||
>,
|
||||
TError,
|
||||
{ onboardingId: number; data: AgentOnboardingUpdate },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ["updateAgentOnboardingHrOnboardingOnboardingIdPatch"];
|
||||
const { mutation: mutationOptions, request: requestOptions } = options
|
||||
? options.mutation &&
|
||||
"mutationKey" in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey }, request: undefined };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<
|
||||
ReturnType<typeof updateAgentOnboardingHrOnboardingOnboardingIdPatch>
|
||||
>,
|
||||
{ onboardingId: number; data: AgentOnboardingUpdate }
|
||||
> = (props) => {
|
||||
const { onboardingId, data } = props ?? {};
|
||||
|
||||
return updateAgentOnboardingHrOnboardingOnboardingIdPatch(
|
||||
onboardingId,
|
||||
data,
|
||||
requestOptions,
|
||||
);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type UpdateAgentOnboardingHrOnboardingOnboardingIdPatchMutationResult =
|
||||
NonNullable<
|
||||
Awaited<
|
||||
ReturnType<typeof updateAgentOnboardingHrOnboardingOnboardingIdPatch>
|
||||
>
|
||||
>;
|
||||
export type UpdateAgentOnboardingHrOnboardingOnboardingIdPatchMutationBody =
|
||||
AgentOnboardingUpdate;
|
||||
export type UpdateAgentOnboardingHrOnboardingOnboardingIdPatchMutationError =
|
||||
HTTPValidationError;
|
||||
|
||||
/**
|
||||
* @summary Update Agent Onboarding
|
||||
*/
|
||||
export const useUpdateAgentOnboardingHrOnboardingOnboardingIdPatch = <
|
||||
TError = HTTPValidationError,
|
||||
TContext = unknown,
|
||||
>(
|
||||
options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<
|
||||
ReturnType<typeof updateAgentOnboardingHrOnboardingOnboardingIdPatch>
|
||||
>,
|
||||
TError,
|
||||
{ onboardingId: number; data: AgentOnboardingUpdate },
|
||||
TContext
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): UseMutationResult<
|
||||
Awaited<
|
||||
ReturnType<typeof updateAgentOnboardingHrOnboardingOnboardingIdPatch>
|
||||
>,
|
||||
TError,
|
||||
{ onboardingId: number; data: AgentOnboardingUpdate },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(
|
||||
getUpdateAgentOnboardingHrOnboardingOnboardingIdPatchMutationOptions(
|
||||
options,
|
||||
),
|
||||
queryClient,
|
||||
);
|
||||
};
|
||||
|
||||
22
frontend/src/api/generated/model/agentOnboarding.ts
Normal file
22
frontend/src/api/generated/model/agentOnboarding.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Generated by orval v8.2.0 🍺
|
||||
* Do not edit manually.
|
||||
* OpenClaw Agency API
|
||||
* OpenAPI spec version: 0.3.0
|
||||
*/
|
||||
|
||||
export interface AgentOnboarding {
|
||||
id?: number | null;
|
||||
agent_name: string;
|
||||
role_title: string;
|
||||
prompt: string;
|
||||
cron_interval_ms?: number | null;
|
||||
tools_json?: string | null;
|
||||
owner_hr_id?: number | null;
|
||||
status?: string;
|
||||
spawned_agent_id?: string | null;
|
||||
session_key?: string | null;
|
||||
notes?: string | null;
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
}
|
||||
19
frontend/src/api/generated/model/agentOnboardingCreate.ts
Normal file
19
frontend/src/api/generated/model/agentOnboardingCreate.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Generated by orval v8.2.0 🍺
|
||||
* Do not edit manually.
|
||||
* OpenClaw Agency API
|
||||
* OpenAPI spec version: 0.3.0
|
||||
*/
|
||||
|
||||
export interface AgentOnboardingCreate {
|
||||
agent_name: string;
|
||||
role_title: string;
|
||||
prompt: string;
|
||||
cron_interval_ms?: number | null;
|
||||
tools_json?: string | null;
|
||||
owner_hr_id?: number | null;
|
||||
status?: string;
|
||||
spawned_agent_id?: string | null;
|
||||
session_key?: string | null;
|
||||
notes?: string | null;
|
||||
}
|
||||
19
frontend/src/api/generated/model/agentOnboardingUpdate.ts
Normal file
19
frontend/src/api/generated/model/agentOnboardingUpdate.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Generated by orval v8.2.0 🍺
|
||||
* Do not edit manually.
|
||||
* OpenClaw Agency API
|
||||
* OpenAPI spec version: 0.3.0
|
||||
*/
|
||||
|
||||
export interface AgentOnboardingUpdate {
|
||||
agent_name?: string | null;
|
||||
role_title?: string | null;
|
||||
prompt?: string | null;
|
||||
cron_interval_ms?: number | null;
|
||||
tools_json?: string | null;
|
||||
owner_hr_id?: number | null;
|
||||
status?: string | null;
|
||||
spawned_agent_id?: string | null;
|
||||
session_key?: string | null;
|
||||
notes?: string | null;
|
||||
}
|
||||
@@ -5,6 +5,9 @@
|
||||
* OpenAPI spec version: 0.3.0
|
||||
*/
|
||||
|
||||
export * from "./agentOnboarding";
|
||||
export * from "./agentOnboardingCreate";
|
||||
export * from "./agentOnboardingUpdate";
|
||||
export * from "./department";
|
||||
export * from "./departmentCreate";
|
||||
export * from "./departmentUpdate";
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
|
||||
function getActorId(): string | undefined {
|
||||
if (typeof window !== "undefined") {
|
||||
const stored = window.localStorage.getItem("actor_employee_id");
|
||||
if (stored) return stored;
|
||||
const env = process.env.NEXT_PUBLIC_ACTOR_EMPLOYEE_ID;
|
||||
if (env) {
|
||||
window.localStorage.setItem("actor_employee_id", env);
|
||||
return env;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return process.env.NEXT_PUBLIC_ACTOR_EMPLOYEE_ID;
|
||||
}
|
||||
export async function customFetch<T>(
|
||||
url: string,
|
||||
options: RequestInit,
|
||||
@@ -9,6 +23,7 @@ export async function customFetch<T>(
|
||||
...options,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...(getActorId() ? { "X-Actor-Employee-Id": String(getActorId()) } : {}),
|
||||
...(options.headers ?? {}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import styles from "./Shell.module.css";
|
||||
|
||||
const NAV = [
|
||||
@@ -14,6 +15,16 @@ const NAV = [
|
||||
|
||||
export function Shell({ children }: { children: React.ReactNode }) {
|
||||
const path = usePathname();
|
||||
const [actorId, setActorId] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
const stored = window.localStorage.getItem("actor_employee_id");
|
||||
if (stored) setActorId(stored);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<div className={styles.shell}>
|
||||
<aside className={styles.sidebar}>
|
||||
@@ -32,6 +43,25 @@ export function Shell({ children }: { children: React.ReactNode }) {
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
<div className={styles.mono} style={{ marginTop: 16 }}>
|
||||
<div style={{ fontWeight: 600, marginBottom: 6 }}>Actor ID</div>
|
||||
<input
|
||||
value={actorId}
|
||||
onChange={(e) => {
|
||||
const v = e.target.value;
|
||||
setActorId(v);
|
||||
try {
|
||||
if (v) window.localStorage.setItem("actor_employee_id", v);
|
||||
else window.localStorage.removeItem("actor_employee_id");
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}}
|
||||
placeholder="e.g. 1"
|
||||
style={{ width: "100%", padding: "6px 8px", borderRadius: 6, border: "1px solid #333", background: "transparent" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.mono} style={{ marginTop: "auto" }}>
|
||||
Tip: use your machine IP + ports<br />
|
||||
<span className={styles.kbd}>:3000</span> UI <span className={styles.kbd}>:8000</span> API
|
||||
|
||||
@@ -13,6 +13,9 @@ import {
|
||||
useCreateEmploymentActionHrActionsPost,
|
||||
useListHeadcountRequestsHrHeadcountGet,
|
||||
useListEmploymentActionsHrActionsGet,
|
||||
useListAgentOnboardingHrOnboardingGet,
|
||||
useCreateAgentOnboardingHrOnboardingPost,
|
||||
useUpdateAgentOnboardingHrOnboardingOnboardingIdPatch,
|
||||
} from "@/api/generated/hr/hr";
|
||||
import { useListDepartmentsDepartmentsGet, useListEmployeesEmployeesGet } from "@/api/generated/org/org";
|
||||
|
||||
@@ -35,6 +38,14 @@ export default function HRPage() {
|
||||
const [actType, setActType] = useState("praise");
|
||||
const [actNotes, setActNotes] = useState("");
|
||||
|
||||
|
||||
const [onboardAgentName, setOnboardAgentName] = useState("");
|
||||
const [onboardRole, setOnboardRole] = useState("");
|
||||
const [onboardPrompt, setOnboardPrompt] = useState("");
|
||||
const [onboardCronMs, setOnboardCronMs] = useState("");
|
||||
const [onboardTools, setOnboardTools] = useState("");
|
||||
const [onboardOwnerId, setOnboardOwnerId] = useState<string>("");
|
||||
const [onboardNotes, setOnboardNotes] = useState("");
|
||||
const createHeadcount = useCreateHeadcountRequestHrHeadcountPost({
|
||||
mutation: {
|
||||
onSuccess: () => {
|
||||
@@ -200,6 +211,100 @@ export default function HRPage() {
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
|
||||
<div className="mt-6 grid gap-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Agent onboarding</CardTitle>
|
||||
<CardDescription>HR logs prompts, cron, tools, and spawn status (Mission Control only).</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="grid gap-4 sm:grid-cols-2">
|
||||
<div className="space-y-3">
|
||||
<Input placeholder="Agent name" value={onboardAgentName} onChange={(e) => setOnboardAgentName(e.target.value)} />
|
||||
<Input placeholder="Role/title" value={onboardRole} onChange={(e) => setOnboardRole(e.target.value)} />
|
||||
<Textarea placeholder="Prompt / system instructions" value={onboardPrompt} onChange={(e) => setOnboardPrompt(e.target.value)} />
|
||||
<Input placeholder="Cron interval ms (e.g. 300000)" value={onboardCronMs} onChange={(e) => setOnboardCronMs(e.target.value)} />
|
||||
<Textarea placeholder="Tools/permissions (JSON or text)" value={onboardTools} onChange={(e) => setOnboardTools(e.target.value)} />
|
||||
<Select value={onboardOwnerId} onChange={(e) => setOnboardOwnerId(e.target.value)}>
|
||||
<option value="">Owner (HR)</option>
|
||||
{(employees.data ?? []).map((e) => (
|
||||
<option key={e.id ?? e.name} value={e.id ?? ""}>{e.name}</option>
|
||||
))}
|
||||
</Select>
|
||||
<Textarea placeholder="Notes" value={onboardNotes} onChange={(e) => setOnboardNotes(e.target.value)} />
|
||||
<Button
|
||||
onClick={() =>
|
||||
createOnboarding.mutate({
|
||||
data: {
|
||||
agent_name: onboardAgentName,
|
||||
role_title: onboardRole,
|
||||
prompt: onboardPrompt,
|
||||
cron_interval_ms: onboardCronMs ? Number(onboardCronMs) : null,
|
||||
tools_json: onboardTools.trim() ? onboardTools : null,
|
||||
owner_hr_id: onboardOwnerId ? Number(onboardOwnerId) : null,
|
||||
status: "planned",
|
||||
notes: onboardNotes.trim() ? onboardNotes : null,
|
||||
},
|
||||
})
|
||||
}
|
||||
disabled={!onboardAgentName.trim() || !onboardRole.trim() || !onboardPrompt.trim() || createOnboarding.isPending}
|
||||
>
|
||||
Create onboarding
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<div className="mb-2 text-sm font-medium">Current onboardings</div>
|
||||
<ul className="space-y-2">
|
||||
{(onboarding.data ?? []).map((o) => (
|
||||
<li key={String(o.id)} className="rounded-md border p-3 text-sm">
|
||||
<div className="font-medium">{o.agent_name} · {o.role_title}</div>
|
||||
<div className="text-xs text-muted-foreground">status: {o.status} · cron: {o.cron_interval_ms ?? "—"}</div>
|
||||
<div className="mt-2 grid gap-2">
|
||||
<Select
|
||||
value={o.status ?? ""}
|
||||
onChange={(e) =>
|
||||
updateOnboarding.mutate({ onboardingId: Number(o.id), data: { status: e.target.value || null } })
|
||||
}
|
||||
>
|
||||
<option value="planned">planned</option>
|
||||
<option value="spawning">spawning</option>
|
||||
<option value="spawned">spawned</option>
|
||||
<option value="verified">verified</option>
|
||||
<option value="blocked">blocked</option>
|
||||
</Select>
|
||||
<Input
|
||||
placeholder="Spawned agent id"
|
||||
defaultValue={o.spawned_agent_id ?? ""}
|
||||
onBlur={(e) =>
|
||||
updateOnboarding.mutate({ onboardingId: Number(o.id), data: { spawned_agent_id: e.currentTarget.value || null } })
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
placeholder="Session key"
|
||||
defaultValue={o.session_key ?? ""}
|
||||
onBlur={(e) =>
|
||||
updateOnboarding.mutate({ onboardingId: Number(o.id), data: { session_key: e.currentTarget.value || null } })
|
||||
}
|
||||
/>
|
||||
<Textarea
|
||||
placeholder="Notes"
|
||||
defaultValue={o.notes ?? ""}
|
||||
onBlur={(e) =>
|
||||
updateOnboarding.mutate({ onboardingId: Number(o.id), data: { notes: e.currentTarget.value || null } })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
{(onboarding.data ?? []).length === 0 ? (
|
||||
<li className="text-sm text-muted-foreground">No onboarding records yet.</li>
|
||||
) : null}
|
||||
</ul>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user