Skip to content

Commit 0d74ca4

Browse files
authored
fix: direct invoke (#134)
* fix: direct invoke * fix: direct invoke * fix: direct invocation * chore: debug info * fix: direct invocation * fix: include static prompts * fix: static prompts, move agents out of tasks * fix: move prompt files to static * fix: prompt path * fix: prompt path * fix: persist siteId
1 parent 97f6757 commit 0d74ca4

File tree

13 files changed

+98
-103
lines changed

13 files changed

+98
-103
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"timeout": 900000,
4343
"nodeVersion": 22,
4444
"static": [
45+
"static/prompts/",
4546
"static/cls1.md",
4647
"static/cls2.md",
4748
"static/inp1.md",

src/tasks/agents/base.js renamed to src/agents/base.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,10 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212
import { readFileSync } from 'fs';
13-
import { fileURLToPath } from 'url';
1413
import path from 'path';
1514

16-
export function readPromptFile(importMetaUrl, relPath) {
17-
const filename = fileURLToPath(importMetaUrl);
18-
const dirname = path.dirname(filename);
19-
const fullPath = path.resolve(dirname, relPath);
15+
export function readPromptFile(relPath) {
16+
const fullPath = path.resolve(process.cwd(), 'static/prompts/', relPath);
2017
return readFileSync(fullPath, 'utf-8');
2118
}
2219

src/tasks/agents/brand-profile/index.js renamed to src/agents/brand-profile/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ async function run(context, env, log) {
4242
throw new Error('brand-profile: context.baseURL is required');
4343
}
4444

45-
const systemPrompt = readPromptFile(import.meta.url, './prompts/system.prompt');
46-
const userTemplate = readPromptFile(import.meta.url, './prompts/user.prompt');
45+
const systemPrompt = readPromptFile('brand-profile/system.prompt');
46+
const userTemplate = readPromptFile('brand-profile/user.prompt');
4747
const userPrompt = renderTemplate(userTemplate, { baseURL, params: JSON.stringify(params) });
4848

4949
return callModel({
@@ -53,7 +53,7 @@ async function run(context, env, log) {
5353

5454
async function persist(message, context, result) {
5555
const { log, dataAccess } = context;
56-
const siteId = message?.context?.siteId;
56+
const siteId = message?.siteId;
5757

5858
if (!isValidUUID(siteId)) {
5959
log.warn(`brand-profile persist: invalid siteId ${siteId}`);
File renamed without changes.

src/index.js

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@ import wrap from '@adobe/helix-shared-wrap';
1313
import { helixStatus } from '@adobe/helix-status';
1414
import secrets from '@adobe/helix-shared-secrets';
1515
import dataAccess from '@adobe/spacecat-shared-data-access';
16-
import { sqsEventAdapter } from '@adobe/spacecat-shared-utils';
17-
import { internalServerError, notFound, ok } from '@adobe/spacecat-shared-http-utils';
16+
import {
17+
internalServerError,
18+
notFound,
19+
ok,
20+
badRequest,
21+
} from '@adobe/spacecat-shared-http-utils';
1822
import { imsClientWrapper } from '@adobe/spacecat-shared-ims-client';
23+
import { isNonEmptyObject, sqsEventAdapter } from '@adobe/spacecat-shared-utils';
1924

2025
import { runOpportunityStatusProcessor as opportunityStatusProcessor } from './tasks/opportunity-status-processor/handler.js';
2126
import { runDisableImportAuditProcessor as disableImportAuditProcessor } from './tasks/disable-import-audit-processor/handler.js';
@@ -31,7 +36,7 @@ const HANDLERS = {
3136
'agent-executor': agentExecutor,
3237
'slack-notify': slackNotify,
3338
'cwv-demo-suggestions-processor': cwvDemoSuggestionsProcessor,
34-
dummy: (message) => ok(message),
39+
dummy: (message) => ok(message), // for tests
3540
};
3641

3742
// Custom secret name resolver to use the correct secret path
@@ -93,17 +98,20 @@ const runDirect = wrap(processTask)
9398
.with(secrets, { name: getSecretName })
9499
.with(helixStatus);
95100

96-
function isSqsEvent(event, context) {
97-
if (Array.isArray(event?.Records)) {
98-
return true;
99-
}
100-
if (Array.isArray(context?.invocation?.event?.Records)) {
101-
return true;
102-
}
103-
return typeof event?.type !== 'string';
101+
function isSqsEvent(event) {
102+
return Array.isArray(event?.Records);
104103
}
105104

106105
export const main = async (event, context) => {
107-
const handler = isSqsEvent(event, context) ? runSQS : runDirect;
108-
return handler(event, context);
106+
if (isSqsEvent(event)) {
107+
return runSQS(event, context);
108+
}
109+
110+
const payload = context?.invocation?.event;
111+
if (!isNonEmptyObject(payload)) {
112+
context?.log?.warn?.('Direct invocation missing payload');
113+
return badRequest('Event does not contain a valid message body');
114+
}
115+
116+
return runDirect(payload, context);
109117
};

src/tasks/agent-executor/handler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import { ok, badRequest } from '@adobe/spacecat-shared-http-utils';
1313
import { hasText, isNonEmptyObject } from '@adobe/spacecat-shared-utils';
1414

15-
import { getAgent } from '../agents/registry.js';
15+
import { getAgent } from '../../agents/registry.js';
1616

1717
/**
1818
* Message shape:

test/tasks/agents/base.test.js renamed to test/agents/base.test.js

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,10 @@
1313
/* eslint-env mocha */
1414

1515
import { expect } from 'chai';
16-
import { fileURLToPath } from 'url';
1716
import path from 'path';
18-
import os from 'os';
1917
import fs from 'fs';
2018

21-
import { readPromptFile, renderTemplate } from '../../../src/tasks/agents/base.js';
19+
import { readPromptFile, renderTemplate } from '../../src/agents/base.js';
2220

2321
describe('agents/base utilities', () => {
2422
describe('renderTemplate', () => {
@@ -46,39 +44,22 @@ describe('agents/base utilities', () => {
4644
});
4745

4846
describe('readPromptFile', () => {
49-
const testDir = path.dirname(fileURLToPath(import.meta.url));
50-
5147
const unlink = (filePath) => {
5248
try {
5349
fs.unlinkSync(filePath);
5450
} catch (e) { /* ignore */ }
5551
};
5652

57-
it('reads a file via relative path against import.meta.url dirname', () => {
53+
it('reads a file via relative path against static prompt dirname', () => {
5854
const relName = 'tmp.prompt';
59-
const relPath = `./${relName}`;
60-
const absPath = path.resolve(testDir, relName);
55+
const absPath = path.resolve(process.cwd(), 'static/prompts/', relName);
6156
const content = 'relative content';
6257
try {
6358
fs.writeFileSync(absPath, content, 'utf-8');
64-
const read = readPromptFile(import.meta.url, relPath);
65-
expect(read).to.equal(content);
66-
} finally {
67-
unlink(absPath);
68-
}
69-
});
70-
71-
it('reads a file via absolute path ignoring dirname resolution', () => {
72-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'base-test-'));
73-
const absPath = path.join(tmpDir, 'abs.prompt');
74-
const content = 'absolute content';
75-
try {
76-
fs.writeFileSync(absPath, content, 'utf-8');
77-
const read = readPromptFile(import.meta.url, absPath);
59+
const read = readPromptFile('./tmp.prompt');
7860
expect(read).to.equal(content);
7961
} finally {
8062
unlink(absPath);
81-
unlink(tmpDir);
8263
}
8364
});
8465
});

test/tasks/agents/brand-profile/brand-profile.test.js renamed to test/agents/brand-profile/index.test.js

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ describe('agents/brand-profile', () => {
4949
});
5050
const createFrom = sandbox.stub().returns({ fetchChatCompletion });
5151

52-
const mod = await esmock('../../../../src/tasks/agents/brand-profile/index.js', {
52+
const mod = await esmock('../../../src/agents/brand-profile/index.js', {
5353
'@adobe/spacecat-shared-gpt-client': {
5454
AzureOpenAIClient: { createFrom },
5555
},
56-
'../../../../src/tasks/agents/base.js': {
56+
'../../../src/agents/base.js': {
5757
readPromptFile: sandbox.stub()
5858
.onFirstCall()
5959
.returns('SYS_PROMPT')
@@ -78,8 +78,8 @@ describe('agents/brand-profile', () => {
7878
});
7979

8080
it('run() throws on invalid baseURL', async () => {
81-
const mod = await esmock('../../../../src/tasks/agents/brand-profile/index.js', {
82-
'../../../../src/tasks/agents/base.js': {
81+
const mod = await esmock('../../../src/agents/brand-profile/index.js', {
82+
'../../../src/agents/base.js': {
8383
readPromptFile: sandbox.stub(),
8484
renderTemplate: sandbox.stub(),
8585
},
@@ -94,11 +94,11 @@ describe('agents/brand-profile', () => {
9494
});
9595
const createFrom = sandbox.stub().returns({ fetchChatCompletion });
9696

97-
const mod = await esmock('../../../../src/tasks/agents/brand-profile/index.js', {
97+
const mod = await esmock('../../../src/agents/brand-profile/index.js', {
9898
'@adobe/spacecat-shared-gpt-client': {
9999
AzureOpenAIClient: { createFrom },
100100
},
101-
'../../../../src/tasks/agents/base.js': {
101+
'../../../src/agents/base.js': {
102102
readPromptFile: sandbox.stub()
103103
.onFirstCall()
104104
.returns('SYS_PROMPT')
@@ -119,11 +119,11 @@ describe('agents/brand-profile', () => {
119119
});
120120
const createFrom = sandbox.stub().returns({ fetchChatCompletion });
121121

122-
const mod = await esmock('../../../../src/tasks/agents/brand-profile/index.js', {
122+
const mod = await esmock('../../../src/agents/brand-profile/index.js', {
123123
'@adobe/spacecat-shared-gpt-client': {
124124
AzureOpenAIClient: { createFrom },
125125
},
126-
'../../../../src/tasks/agents/base.js': {
126+
'../../../src/agents/base.js': {
127127
readPromptFile: sandbox.stub()
128128
.onFirstCall()
129129
.returns('SYS_PROMPT')
@@ -142,20 +142,20 @@ describe('agents/brand-profile', () => {
142142
});
143143

144144
it('persist() returns early for invalid siteId', async () => {
145-
const mod = await esmock('../../../../src/tasks/agents/brand-profile/index.js', {});
145+
const mod = await esmock('../../../src/agents/brand-profile/index.js', {});
146146

147147
await mod.default.persist(
148-
{ context: { siteId: 'invalid' } },
148+
{ siteId: 'invalid' },
149149
context,
150150
{ ok: true },
151151
);
152152
expect(log.warn).to.have.been.calledWith(sinon.match('brand-profile persist: invalid siteId'));
153153
});
154154

155155
it('persist() returns early for empty result', async () => {
156-
const mod = await esmock('../../../../src/tasks/agents/brand-profile/index.js', {});
156+
const mod = await esmock('../../../src/agents/brand-profile/index.js', {});
157157
await mod.default.persist(
158-
{ context: { siteId: '123e4567-e89b-12d3-a456-426614174000' } },
158+
{ siteId: '123e4567-e89b-12d3-a456-426614174000' },
159159
context,
160160
{},
161161
);
@@ -166,9 +166,9 @@ describe('agents/brand-profile', () => {
166166
const findById = sandbox.stub().resolves(null);
167167
context.dataAccess.Site = { findById };
168168

169-
const mod = await esmock('../../../../src/tasks/agents/brand-profile/index.js', {});
169+
const mod = await esmock('../../../src/agents/brand-profile/index.js', {});
170170
await mod.default.persist(
171-
{ context: { siteId: '123e4567-e89b-12d3-a456-426614174000' } },
171+
{ siteId: '123e4567-e89b-12d3-a456-426614174000' },
172172
context,
173173
{ ok: true },
174174
);
@@ -195,14 +195,14 @@ describe('agents/brand-profile', () => {
195195
context.dataAccess.Site = { findById };
196196

197197
const toDynamoItem = sandbox.stub().callsFake((c) => c);
198-
const mod = await esmock('../../../../src/tasks/agents/brand-profile/index.js', {
198+
const mod = await esmock('../../../src/agents/brand-profile/index.js', {
199199
'@adobe/spacecat-shared-data-access/src/models/site/config.js': {
200200
Config: { toDynamoItem },
201201
},
202202
});
203203

204204
await mod.default.persist(
205-
{ context: { siteId: '123e4567-e89b-12d3-a456-426614174000', baseURL: 'https://example.com' } },
205+
{ siteId: '123e4567-e89b-12d3-a456-426614174000', baseURL: 'https://example.com' },
206206
context,
207207
{ any: 'result' },
208208
);
@@ -230,14 +230,14 @@ describe('agents/brand-profile', () => {
230230
context.dataAccess.Site = { findById };
231231

232232
const toDynamoItem = sandbox.stub().callsFake((c) => c);
233-
const mod = await esmock('../../../../src/tasks/agents/brand-profile/index.js', {
233+
const mod = await esmock('../../../src/agents/brand-profile/index.js', {
234234
'@adobe/spacecat-shared-data-access/src/models/site/config.js': {
235235
Config: { toDynamoItem },
236236
},
237237
});
238238

239239
await mod.default.persist(
240-
{ context: { siteId: '123e4567-e89b-12d3-a456-426614174000', baseURL: 'https://example.com' } },
240+
{ siteId: '123e4567-e89b-12d3-a456-426614174000', baseURL: 'https://example.com' },
241241
context,
242242
{ unchanged: true },
243243
);
@@ -267,14 +267,14 @@ describe('agents/brand-profile', () => {
267267
context.dataAccess.Site = { findById };
268268

269269
const toDynamoItem = sandbox.stub().callsFake((c) => c);
270-
const mod = await esmock('../../../../src/tasks/agents/brand-profile/index.js', {
270+
const mod = await esmock('../../../src/agents/brand-profile/index.js', {
271271
'@adobe/spacecat-shared-data-access/src/models/site/config.js': {
272272
Config: { toDynamoItem },
273273
},
274274
});
275275

276276
await mod.default.persist(
277-
{ context: { siteId: '123e4567-e89b-12d3-a456-426614174000' } },
277+
{ siteId: '123e4567-e89b-12d3-a456-426614174000' },
278278
context,
279279
{ foo: 'bar' },
280280
);

0 commit comments

Comments
 (0)