Use real IDE authoring session
This commit is contained in:
@@ -39,6 +39,7 @@ import { Badge } from "@/components/ui/badge";
|
|||||||
import { Card } from "@/components/ui/card";
|
import { Card } from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
applyAuthoringChangeSet,
|
applyAuthoringChangeSet,
|
||||||
|
ensureAuthoringSession,
|
||||||
getAuthoringSemanticDiffPreview,
|
getAuthoringSemanticDiffPreview,
|
||||||
applyAuthoringMetadataObject,
|
applyAuthoringMetadataObject,
|
||||||
applyAuthoringRollback,
|
applyAuthoringRollback,
|
||||||
@@ -2048,8 +2049,7 @@ function EditorPanel({
|
|||||||
routine_name: data.editorSelectedRoutine ?? data.authoringPreview?.context.routine?.name ?? null,
|
routine_name: data.editorSelectedRoutine ?? data.authoringPreview?.context.routine?.name ?? null,
|
||||||
original_text: data.editorSourceText,
|
original_text: data.editorSourceText,
|
||||||
proposed_text: nextProposedText,
|
proposed_text: nextProposedText,
|
||||||
task_id: "task.preview",
|
...(await ensureAuthoringSession(data.projectId, data.apiUrl))
|
||||||
session_id: "session.preview"
|
|
||||||
},
|
},
|
||||||
data.apiUrl
|
data.apiUrl
|
||||||
);
|
);
|
||||||
@@ -2175,6 +2175,7 @@ function EditorPanel({
|
|||||||
const apiUrl =
|
const apiUrl =
|
||||||
data.apiUrl ??
|
data.apiUrl ??
|
||||||
(typeof window === "undefined" ? resolveApiUrl() : resolveApiUrl(window.location.host));
|
(typeof window === "undefined" ? resolveApiUrl() : resolveApiUrl(window.location.host));
|
||||||
|
const authoringSession = await ensureAuthoringSession(data.projectId, apiUrl);
|
||||||
const response = await applyAuthoringChangeSet(
|
const response = await applyAuthoringChangeSet(
|
||||||
data.projectId,
|
data.projectId,
|
||||||
{
|
{
|
||||||
@@ -2182,12 +2183,12 @@ function EditorPanel({
|
|||||||
routine_name: data.editorSelectedRoutine ?? data.authoringPreview?.context.routine?.name ?? null,
|
routine_name: data.editorSelectedRoutine ?? data.authoringPreview?.context.routine?.name ?? null,
|
||||||
original_text: data.editorSourceText ?? sourceText,
|
original_text: data.editorSourceText ?? sourceText,
|
||||||
proposed_text: proposedText ?? sourceText,
|
proposed_text: proposedText ?? sourceText,
|
||||||
task_id: null,
|
task_id: authoringSession.task_id,
|
||||||
session_id: "session.ide",
|
session_id: authoringSession.session_id,
|
||||||
user_id: "current-user",
|
user_id: authoringSession.user_id,
|
||||||
estimated_tokens: 2550,
|
estimated_tokens: 2550,
|
||||||
expected_next_version_id: versionPreview.next_version_id,
|
expected_next_version_id: versionPreview.next_version_id,
|
||||||
approved_by: "current-user",
|
approved_by: authoringSession.user_id,
|
||||||
approval_note: t.guardedApplyNote,
|
approval_note: t.guardedApplyNote,
|
||||||
apply_to_production: false
|
apply_to_production: false
|
||||||
},
|
},
|
||||||
@@ -2200,7 +2201,7 @@ function EditorPanel({
|
|||||||
status: response.status,
|
status: response.status,
|
||||||
target: response.preview.target,
|
target: response.preview.target,
|
||||||
version_id: response.version.version_id,
|
version_id: response.version.version_id,
|
||||||
approved_by: "current-user",
|
approved_by: authoringSession.user_id,
|
||||||
approval_note: t.guardedApplyNote,
|
approval_note: t.guardedApplyNote,
|
||||||
task_id: response.version.task_id,
|
task_id: response.version.task_id,
|
||||||
session_id: response.version.session_id,
|
session_id: response.version.session_id,
|
||||||
@@ -3261,10 +3262,7 @@ function MetadataDesignerPanel({
|
|||||||
.map((command) => ({
|
.map((command) => ({
|
||||||
name: command.name.trim(),
|
name: command.name.trim(),
|
||||||
handler: command.handler.trim() || null
|
handler: command.handler.trim() || null
|
||||||
})),
|
}))
|
||||||
task_id: null,
|
|
||||||
session_id: "session.ide.metadata",
|
|
||||||
user_id: "current-user"
|
|
||||||
};
|
};
|
||||||
const [draftState, setDraftState] = useState<"idle" | "previewing" | "applying" | "applied" | "error">("idle");
|
const [draftState, setDraftState] = useState<"idle" | "previewing" | "applying" | "applied" | "error">("idle");
|
||||||
const [draftMessage, setDraftMessage] = useState("");
|
const [draftMessage, setDraftMessage] = useState("");
|
||||||
@@ -3311,15 +3309,17 @@ function MetadataDesignerPanel({
|
|||||||
const apiUrl =
|
const apiUrl =
|
||||||
data.apiUrl ??
|
data.apiUrl ??
|
||||||
(typeof window === "undefined" ? resolveApiUrl() : resolveApiUrl(window.location.host));
|
(typeof window === "undefined" ? resolveApiUrl() : resolveApiUrl(window.location.host));
|
||||||
const preview = await getAuthoringMetadataObjectPreview(data.projectId, metadataDraft, apiUrl);
|
const authoringSession = await ensureAuthoringSession(data.projectId, apiUrl);
|
||||||
|
const sessionDraft = { ...metadataDraft, ...authoringSession };
|
||||||
|
const preview = await getAuthoringMetadataObjectPreview(data.projectId, sessionDraft, apiUrl);
|
||||||
setDraftDiff(preview.semantic_diff);
|
setDraftDiff(preview.semantic_diff);
|
||||||
setDraftState("applying");
|
setDraftState("applying");
|
||||||
const response = await applyAuthoringMetadataObject(
|
const response = await applyAuthoringMetadataObject(
|
||||||
data.projectId,
|
data.projectId,
|
||||||
{
|
{
|
||||||
...metadataDraft,
|
...sessionDraft,
|
||||||
expected_next_version_id: preview.version_preview.next_version_id,
|
expected_next_version_id: preview.version_preview.next_version_id,
|
||||||
approved_by: "current-user",
|
approved_by: authoringSession.user_id,
|
||||||
approval_note: t.metadataDraftDescription,
|
approval_note: t.metadataDraftDescription,
|
||||||
apply_to_production: false
|
apply_to_production: false
|
||||||
},
|
},
|
||||||
@@ -3332,7 +3332,7 @@ function MetadataDesignerPanel({
|
|||||||
status: response.status,
|
status: response.status,
|
||||||
target: response.preview.target,
|
target: response.preview.target,
|
||||||
version_id: response.version.version_id,
|
version_id: response.version.version_id,
|
||||||
approved_by: "current-user",
|
approved_by: authoringSession.user_id,
|
||||||
approval_note: t.metadataDraftDescription,
|
approval_note: t.metadataDraftDescription,
|
||||||
task_id: response.version.task_id,
|
task_id: response.version.task_id,
|
||||||
session_id: response.version.session_id,
|
session_id: response.version.session_id,
|
||||||
@@ -4469,15 +4469,16 @@ function HistoryPanel({
|
|||||||
setRollbackState("applying");
|
setRollbackState("applying");
|
||||||
setRollbackMessage("");
|
setRollbackMessage("");
|
||||||
try {
|
try {
|
||||||
|
const authoringSession = await ensureAuthoringSession(data.projectId, data.apiUrl);
|
||||||
const response = await applyAuthoringRollback(
|
const response = await applyAuthoringRollback(
|
||||||
data.projectId,
|
data.projectId,
|
||||||
rollbackPreview.change_id,
|
rollbackPreview.change_id,
|
||||||
{
|
{
|
||||||
expected_rollback_version_id: rollbackPreview.rollback_version_id,
|
expected_rollback_version_id: rollbackPreview.rollback_version_id,
|
||||||
approved_by: "current-user",
|
approved_by: authoringSession.user_id,
|
||||||
approval_note: t.rollbackApplyNote,
|
approval_note: t.rollbackApplyNote,
|
||||||
task_id: null,
|
task_id: authoringSession.task_id,
|
||||||
session_id: "session.ide.rollback",
|
session_id: authoringSession.session_id,
|
||||||
apply_to_production: false
|
apply_to_production: false
|
||||||
},
|
},
|
||||||
data.apiUrl
|
data.apiUrl
|
||||||
@@ -4489,7 +4490,7 @@ function HistoryPanel({
|
|||||||
status: response.status,
|
status: response.status,
|
||||||
target: response.preview.target,
|
target: response.preview.target,
|
||||||
version_id: response.version.version_id,
|
version_id: response.version.version_id,
|
||||||
approved_by: "current-user",
|
approved_by: authoringSession.user_id,
|
||||||
approval_note: t.rollbackApplyNote,
|
approval_note: t.rollbackApplyNote,
|
||||||
task_id: response.version.task_id,
|
task_id: response.version.task_id,
|
||||||
session_id: response.version.session_id,
|
session_id: response.version.session_id,
|
||||||
|
|||||||
@@ -389,6 +389,7 @@ export type AuthoringSemanticDiffPreviewRequest = {
|
|||||||
source_path?: string | null;
|
source_path?: string | null;
|
||||||
task_id?: string | null;
|
task_id?: string | null;
|
||||||
session_id?: string | null;
|
session_id?: string | null;
|
||||||
|
user_id?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AuthoringSemanticDiffPreview = {
|
export type AuthoringSemanticDiffPreview = {
|
||||||
@@ -581,6 +582,12 @@ export type AuthoringChangeSummary = {
|
|||||||
production_applied: boolean;
|
production_applied: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AuthoringSessionContext = {
|
||||||
|
user_id: string;
|
||||||
|
task_id: string;
|
||||||
|
session_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
export function resolveApiUrl(hostHeader?: string | null) {
|
export function resolveApiUrl(hostHeader?: string | null) {
|
||||||
const configuredUrl = process.env.SFERA_API_URL ?? process.env.NEXT_PUBLIC_SFERA_API_URL;
|
const configuredUrl = process.env.SFERA_API_URL ?? process.env.NEXT_PUBLIC_SFERA_API_URL;
|
||||||
if (configuredUrl) {
|
if (configuredUrl) {
|
||||||
@@ -686,6 +693,39 @@ async function postOptionalJson<T>(apiUrl: string, path: string, body: unknown,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ideAuthoringSessionContext(projectId: string): AuthoringSessionContext {
|
||||||
|
const safeProjectId = projectId.replace(/[^A-Za-z0-9_.-]/g, "-");
|
||||||
|
return {
|
||||||
|
user_id: "ide.developer",
|
||||||
|
task_id: `task.ide.${safeProjectId}`,
|
||||||
|
session_id: `session.ide.${safeProjectId}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function ensureAuthoringSession(projectId: string, apiUrl = resolveApiUrl()): Promise<AuthoringSessionContext> {
|
||||||
|
const context = ideAuthoringSessionContext(projectId);
|
||||||
|
await postJson(apiUrl, "/collaboration/users", {
|
||||||
|
user_id: context.user_id,
|
||||||
|
display_name: "SFERA IDE"
|
||||||
|
});
|
||||||
|
await postJson(apiUrl, `/security/users/${encodeURIComponent(context.user_id)}/roles/developer`, {});
|
||||||
|
await postJson(apiUrl, "/collaboration/tasks", {
|
||||||
|
task_id: context.task_id,
|
||||||
|
project_id: projectId,
|
||||||
|
title: "SFERA IDE authoring",
|
||||||
|
status: "IN_PROGRESS",
|
||||||
|
assignee_user_id: context.user_id
|
||||||
|
});
|
||||||
|
await postJson(apiUrl, "/collaboration/sessions", {
|
||||||
|
session: {
|
||||||
|
session_id: context.session_id,
|
||||||
|
task_id: context.task_id,
|
||||||
|
user_id: context.user_id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
export async function getDashboardData(apiUrl = resolveApiUrl()) {
|
export async function getDashboardData(apiUrl = resolveApiUrl()) {
|
||||||
const [health, summary, snapshots, neo4j, aiUsage, aiPolicy] = await Promise.all([
|
const [health, summary, snapshots, neo4j, aiUsage, aiPolicy] = await Promise.all([
|
||||||
getJson<Health>(apiUrl, "/health"),
|
getJson<Health>(apiUrl, "/health"),
|
||||||
@@ -874,6 +914,9 @@ export async function getProjectWorkspaceData(projectId: string, apiUrl = resolv
|
|||||||
: "";
|
: "";
|
||||||
const editorSelectedObject = selectedObjectName ?? snapshotModule?.qualified_name ?? null;
|
const editorSelectedObject = selectedObjectName ?? snapshotModule?.qualified_name ?? null;
|
||||||
const editorSelectedRoutine = selectedModuleRoutine ?? selectedRoutineName ?? null;
|
const editorSelectedRoutine = selectedModuleRoutine ?? selectedRoutineName ?? null;
|
||||||
|
const authoringSession = selectedObjectName && authoringSourceText
|
||||||
|
? await ensureAuthoringSession(projectId, apiUrl).catch(() => null)
|
||||||
|
: null;
|
||||||
const authoringPreview = needsObjectPanels && selectedObjectName && authoringSourceText
|
const authoringPreview = needsObjectPanels && selectedObjectName && authoringSourceText
|
||||||
? await postOptionalJson<AuthoringCompletionPreview | null>(
|
? await postOptionalJson<AuthoringCompletionPreview | null>(
|
||||||
apiUrl,
|
apiUrl,
|
||||||
@@ -883,8 +926,7 @@ export async function getProjectWorkspaceData(projectId: string, apiUrl = resolv
|
|||||||
routine_name: selectedModuleRoutine,
|
routine_name: selectedModuleRoutine,
|
||||||
source_path: selectedObjectModule?.source_path ?? null,
|
source_path: selectedObjectModule?.source_path ?? null,
|
||||||
source_text: authoringSourceText,
|
source_text: authoringSourceText,
|
||||||
task_id: "task.preview",
|
user_id: authoringSession?.user_id ?? null
|
||||||
session_id: "session.preview"
|
|
||||||
},
|
},
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
@@ -900,8 +942,9 @@ export async function getProjectWorkspaceData(projectId: string, apiUrl = resolv
|
|||||||
original_text: authoringSourceText,
|
original_text: authoringSourceText,
|
||||||
proposed_text: authoringProposedText,
|
proposed_text: authoringProposedText,
|
||||||
source_path: selectedObjectModule?.source_path ?? null,
|
source_path: selectedObjectModule?.source_path ?? null,
|
||||||
task_id: "task.preview",
|
task_id: authoringSession?.task_id ?? null,
|
||||||
session_id: "session.preview"
|
session_id: authoringSession?.session_id ?? null,
|
||||||
|
user_id: authoringSession?.user_id ?? null
|
||||||
},
|
},
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user