Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 59 additions & 48 deletions apps/google-docs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions apps/google-docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
"private": true,
"dependencies": {
"@ai-sdk/openai": "^2.0.56",
"@contentful/app-sdk": "^4.51.3",
"@contentful/app-sdk": "^4.55.1",
"@contentful/f36-components": "^5.6.0",
"@contentful/f36-icons": "^6.7.1",
"@contentful/f36-multiselect": "^6.7.1",
"@contentful/f36-tokens": "^5.1.0",
"@contentful/field-editor-json": "^3.3.38",
"@contentful/node-apps-toolkit": "^3.13.0",
"@contentful/react-apps-toolkit": "^1.2.16",
"@contentful/react-apps-toolkit": "^1.2.22",
"@emotion/css": "^11.13.4",
"ai": "^5.0.81",
"contentful-management": "^11.61.0",
"contentful-management": "^11.76.0",
"googleapis": "^166.0.0",
"mammoth": "^1.11.0",
"react": "^18.3.1",
Expand Down
1 change: 1 addition & 0 deletions apps/google-docs/src/hooks/useWorkflowAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ const getWorkflowRunResult = (

switch (status) {
case RunStatus.FAILED:
console.error('[getWorkflowRunResult] run FAILED. Full runData:', JSON.stringify(runData));
throw new Error(getRunErrorMessage(runData));

case RunStatus.PENDING_REVIEW: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,11 @@ export const ModalOrchestrator = forwardRef<ModalOrchestratorHandle, ModalOrches
...resumePayloadOverrides,
};

console.log('[continueWorkflow] resuming run', activeRunId, 'with payload:', resumePayload);
setFlowStep(FlowStep.LOADING);

const workflowRun = await resumeWorkflow(activeRunId, resumePayload);
console.log('[continueWorkflow] resume result:', workflowRun);
handleWorkflowResult(workflowRun);
};

Expand Down Expand Up @@ -231,7 +233,8 @@ export const ModalOrchestrator = forwardRef<ModalOrchestratorHandle, ModalOrches

try {
await continueWorkflow({ includeImages });
} catch {
} catch (error) {
console.error('[IncludeImages] continueWorkflow failed:', error);
showWorkflowError();
}
};
Expand Down
54 changes: 31 additions & 23 deletions apps/google-docs/src/services/agents-api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PageAppSDK } from '@contentful/app-sdk';
import { LOCAL_AGENTS_API_BASE_URL, WORKFLOW_AGENT_ID } from '../utils/constants/agent';
import { LOCAL_AGENTS_API_BASE_URL, USE_LOCAL_AGENTS_API, WORKFLOW_AGENT_ID } from '../utils/constants/agent';
import {
AgentRunMessage,
MappingReviewSuspendPayload,
Expand All @@ -13,6 +13,13 @@ const AGENTS_API_HEADERS = {
'X-Contentful-App-Definition-Id': '653vTnuQw3j5onU1tUoH6t',
};

function getJsonHeaders(): HeadersInit {
return {
...AGENTS_API_HEADERS,
'Content-Type': 'application/json',
};
}

export interface AgentGeneratePayload {
messages: Array<{
role: 'user';
Expand Down Expand Up @@ -46,20 +53,13 @@ export interface AgentRunData {
error?: Record<string, unknown>;
}

function getJsonHeaders(): HeadersInit {
return {
...AGENTS_API_HEADERS,
'Content-Type': 'application/json',
};
}

export async function getWorkflowRun(
sdk: PageAppSDK,
spaceId: string,
environmentId: string,
runId: string
): Promise<AgentRunData | null> {
if (LOCAL_AGENTS_API_BASE_URL) {
if (USE_LOCAL_AGENTS_API) {
const response = await fetch(
`${LOCAL_AGENTS_API_BASE_URL}/spaces/${spaceId}/environments/${environmentId}/ai_agents/runs/${runId}`,
{
Expand All @@ -79,12 +79,16 @@ export async function getWorkflowRun(
}

try {
return (await sdk.cma.agentRun.get({
console.log('[getWorkflowRun] calling sdk.cma.agentRun.get for run', runId);
const result = (await sdk.cma.agentRun.get({
spaceId,
environmentId,
runId,
})) as AgentRunData;
console.log('[getWorkflowRun] run status:', result?.sys?.status ?? result?.metadata?.status, 'full:', JSON.stringify(result));
return result;
} catch (error: unknown) {
console.error('[getWorkflowRun] error:', error);
const err = error as { code?: string };
if (err?.code === 'NotFound') {
return null;
Expand All @@ -102,7 +106,7 @@ export async function startAgentRun(
): Promise<string> {
let runData: AgentRunData;

if (LOCAL_AGENTS_API_BASE_URL) {
if (USE_LOCAL_AGENTS_API) {
const response = await fetch(
`${LOCAL_AGENTS_API_BASE_URL}/spaces/${spaceId}/environments/${environmentId}/ai_agents/agents/${WORKFLOW_AGENT_ID}/generate`,
{
Expand All @@ -121,19 +125,24 @@ export async function startAgentRun(
runData = (await response.json()) as AgentRunData;
} else {
try {
console.log('[startAgentRun] calling sdk.cma.agent.generate for agent', WORKFLOW_AGENT_ID, 'space', spaceId, 'env', environmentId, 'threadId', payload.threadId);
runData = (await sdk.cma.agent.generate(
{ agentId: WORKFLOW_AGENT_ID, spaceId, environmentId },
payload
)) as AgentRunData;
console.log('[startAgentRun] generate response:', JSON.stringify(runData));
} catch (error) {
console.error('[startAgentRun] sdk.cma.agent.generate failed:', error);
throw new Error(`Failed to start workflow agent run: ${error as Error}`);
}
}

if (!runData.sys?.id) {
console.error('[startAgentRun] no run ID in response:', JSON.stringify(runData));
throw new Error('Agent run started but no run ID was returned');
}

console.log('[startAgentRun] run started with ID', runData.sys.id);
return runData.sys.id;
}

Expand All @@ -150,7 +159,7 @@ export async function resumeWorkflowRun(
runId: string,
resumePayload: ResumePayload
): Promise<void> {
if (LOCAL_AGENTS_API_BASE_URL) {
if (USE_LOCAL_AGENTS_API) {
const response = await fetch(
`${LOCAL_AGENTS_API_BASE_URL}/spaces/${spaceId}/environments/${environmentId}/ai_agents/runs/${runId}/resume`,
{
Expand All @@ -167,16 +176,15 @@ export async function resumeWorkflowRun(
return;
}

const agentRunApi = sdk.cma.agentRun as {
resume?: (
params: { spaceId: string; environmentId: string; runId: string },
body: { resumePayload: ResumePayload }
) => Promise<unknown>;
};

if (!agentRunApi.resume) {
throw new Error('Agent run resume is not available in the current SDK.');
try {
console.log('[resumeWorkflowRun] calling sdk.cma.agentRun.resumeRun for run', runId, 'payload:', resumePayload);
await sdk.cma.agentRun.resumeRun(
{ spaceId, environmentId, runId },
{ resumePayload: resumePayload as Record<string, unknown> }
);
console.log('[resumeWorkflowRun] resumeRun succeeded');
} catch (error) {
console.error('[resumeWorkflowRun] resumeRun failed:', error);
throw error;
}

await agentRunApi.resume({ spaceId, environmentId, runId }, { resumePayload });
}
2 changes: 1 addition & 1 deletion apps/google-docs/src/types/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export interface CompletedWorkflowPayload {

export interface TabsImagesSuspendPayload {
reason?: string;
suspendStepId: 'select-tabs-images-step';
suspendStepId: 'document-scope-selection';
documentId?: string;
title?: string;
requiresImageSelection?: boolean;
Expand Down
Loading
Loading