mirror of
https://github.com/jcreek/AutomatedAssessmentFeedbackAgent.git
synced 2026-07-14 19:43:54 +00:00
refactor(*): Change CI to use secrets instead of fallbacks
This commit is contained in:
@@ -9,6 +9,7 @@ on:
|
||||
jobs:
|
||||
test-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
environment: test
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js
|
||||
@@ -24,8 +25,7 @@ jobs:
|
||||
- name: Run Playwright/BDD tests
|
||||
run: npm run bdd:full
|
||||
env:
|
||||
NODE_ENV: test
|
||||
AI_FOUNDRY_PROJECT_CONNECTION_STRING: test
|
||||
AI_FOUNDRY_PROJECT_CONNECTION_STRING: ${{ secrets.AI_FOUNDRY_PROJECT_CONNECTION_STRING }}
|
||||
AI_MODEL: gpt-4o
|
||||
VITE_PARTYKIT_BASE_URL: wss://partykit.jcreek.partykit.dev
|
||||
PARTYKIT_BASE_URL: wss://partykit.jcreek.partykit.dev
|
||||
VITE_PARTYKIT_BASE_URL: ${{ secrets.VITE_PARTYKIT_BASE_URL }}
|
||||
PARTYKIT_BASE_URL: ${{ secrets.PARTYKIT_BASE_URL }}
|
||||
|
||||
@@ -11,21 +11,17 @@ import {
|
||||
} from '../tools/index';
|
||||
import { AI_FOUNDRY_PROJECT_CONNECTION_STRING, AI_MODEL } from '$env/static/private';
|
||||
|
||||
const isTestEnv = process.env.NODE_ENV === 'test' || AI_FOUNDRY_PROJECT_CONNECTION_STRING === 'test';
|
||||
|
||||
const safeConnString = AI_FOUNDRY_PROJECT_CONNECTION_STRING || (isTestEnv ? 'dummy-connection-string' : undefined);
|
||||
const safeModel = AI_MODEL || (isTestEnv ? 'dummy-model' : undefined);
|
||||
|
||||
if (!safeConnString && !isTestEnv) {
|
||||
if (!AI_FOUNDRY_PROJECT_CONNECTION_STRING) {
|
||||
throw new Error('AI_FOUNDRY_PROJECT_CONNECTION_STRING is not set');
|
||||
}
|
||||
if (!safeModel && !isTestEnv) {
|
||||
if (!AI_MODEL) {
|
||||
throw new Error('AI_MODEL is not set');
|
||||
}
|
||||
|
||||
export const client = !isTestEnv && safeConnString
|
||||
? AIProjectsClient.fromConnectionString(safeConnString, new DefaultAzureCredential())
|
||||
: undefined;
|
||||
export const client = AIProjectsClient.fromConnectionString(
|
||||
AI_FOUNDRY_PROJECT_CONNECTION_STRING,
|
||||
new DefaultAzureCredential()
|
||||
);
|
||||
|
||||
// const codeInterpreterTool = ToolUtility.createCodeInterpreterTool([]);
|
||||
|
||||
@@ -70,8 +66,7 @@ export const toolResources = allTools.reduce<Record<string, any>>((map, t) => {
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
export const agent = client
|
||||
? await client.agents.createAgent(AI_MODEL, {
|
||||
export const agent = await client.agents.createAgent(AI_MODEL, {
|
||||
name: `assessment-feedback-agent`,
|
||||
instructions,
|
||||
temperature: 0.5,
|
||||
@@ -80,5 +75,4 @@ export const agent = client
|
||||
requestOptions: {
|
||||
headers: { 'x-ms-enable-preview': 'true' }
|
||||
}
|
||||
})
|
||||
: undefined;
|
||||
});
|
||||
+12
-28
@@ -1,9 +1,5 @@
|
||||
import { client, agent, toolResources } from '../agent/services/agentService';
|
||||
import {
|
||||
RunStreamEvent,
|
||||
ErrorEvent,
|
||||
type ThreadRunOutput
|
||||
} from '@azure/ai-projects';
|
||||
import { RunStreamEvent, ErrorEvent, type ThreadRunOutput } from '@azure/ai-projects';
|
||||
import { PARTYKIT_BASE_URL } from '$env/static/private';
|
||||
import type { OpenAIResponse } from './types';
|
||||
|
||||
@@ -60,8 +56,8 @@ function fallbackGrade(submission: string, task: string): OpenAIResponse {
|
||||
|
||||
function extractTextFromMessage(msg: { content: any[] }): string {
|
||||
return msg.content
|
||||
.filter(c => c.type === 'text')
|
||||
.map(c => (typeof c.text === 'string' ? c.text : c.text.value ?? ''))
|
||||
.filter((c) => c.type === 'text')
|
||||
.map((c) => (typeof c.text === 'string' ? c.text : (c.text.value ?? '')))
|
||||
.join('\n')
|
||||
.trim();
|
||||
}
|
||||
@@ -83,17 +79,14 @@ async function processRunStream(
|
||||
|
||||
// notify PartyKit
|
||||
await Promise.all(
|
||||
calls.map(async call => {
|
||||
calls.map(async (call) => {
|
||||
if (!PARTYKIT_BASE_URL) return;
|
||||
const wsCtor = typeof WebSocket !== 'undefined'
|
||||
? WebSocket
|
||||
: (await import('ws')).default;
|
||||
const ws = new wsCtor(
|
||||
`${PARTYKIT_BASE_URL}/party/tool-usage-server-${roomId}`
|
||||
);
|
||||
const wsCtor =
|
||||
typeof WebSocket !== 'undefined' ? WebSocket : (await import('ws')).default;
|
||||
const ws = new wsCtor(`${PARTYKIT_BASE_URL}/party/tool-usage-server-${roomId}`);
|
||||
await new Promise<void>((res, rej) => {
|
||||
ws.onopen = () => res();
|
||||
ws.onerror = e => rej(e);
|
||||
ws.onerror = (e) => rej(e);
|
||||
});
|
||||
ws.send(JSON.stringify({ tool: call.function.name, time: new Date().toISOString() }));
|
||||
ws.close();
|
||||
@@ -102,7 +95,7 @@ async function processRunStream(
|
||||
|
||||
// invoke the tools
|
||||
const toolOutputs = await Promise.all(
|
||||
calls.map(async call => {
|
||||
calls.map(async (call) => {
|
||||
const name = call.function.name;
|
||||
const args = call.arguments!;
|
||||
try {
|
||||
@@ -119,11 +112,7 @@ async function processRunStream(
|
||||
);
|
||||
|
||||
// resume the run
|
||||
const resumed = client.agents.submitToolOutputsToRun(
|
||||
threadId,
|
||||
runOutput.id,
|
||||
toolOutputs
|
||||
);
|
||||
const resumed = client.agents.submitToolOutputsToRun(threadId, runOutput.id, toolOutputs);
|
||||
const nextStream = await resumed.stream();
|
||||
return processRunStream(threadId, nextStream, roomId);
|
||||
}
|
||||
@@ -145,12 +134,7 @@ export async function gradeSubmissionWithAgent(
|
||||
task: string,
|
||||
roomId: string
|
||||
): Promise<OpenAIResponse> {
|
||||
if (!client) {
|
||||
// In test/CI mode, return fallback data
|
||||
return fallbackGrade(submission, task);
|
||||
}
|
||||
|
||||
if (!agent) {
|
||||
if (!client || !agent) {
|
||||
throw new Error('Agent not available');
|
||||
}
|
||||
|
||||
@@ -181,7 +165,7 @@ export async function gradeSubmissionWithAgent(
|
||||
}
|
||||
|
||||
const msgs = await client.agents.listMessages(thread.id);
|
||||
const assistant = msgs.data.find(m => m.role === 'assistant');
|
||||
const assistant = msgs.data.find((m) => m.role === 'assistant');
|
||||
const raw = assistant ? extractTextFromMessage(assistant) : '';
|
||||
|
||||
// strip anything before the JSON object
|
||||
|
||||
@@ -2,12 +2,6 @@ import { Given, When, Then, Before } from '@cucumber/cucumber';
|
||||
import { expect } from '@playwright/test';
|
||||
import { UploadPage } from '../pages/UploadPage.ts';
|
||||
|
||||
Before(function () {
|
||||
if (process.env.AI_FOUNDRY_PROJECT_CONNECTION_STRING === 'test') {
|
||||
console.log('Skipping in CI');
|
||||
return 'skipped';
|
||||
}
|
||||
});
|
||||
|
||||
Given('I have submitted an assignment for assessment', async function () {
|
||||
await this.uploadPage.navigateTo();
|
||||
|
||||
Reference in New Issue
Block a user