Skip to content

Commit

Permalink
Merge pull request #24 from ferrislucas/remote-built-in-templates
Browse files Browse the repository at this point in the history
Retrieve built in templates from gists
  • Loading branch information
ferrislucas authored Apr 14, 2023
2 parents 1f2bcbd + 583c2d3 commit 02b25bd
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 118 deletions.
30 changes: 18 additions & 12 deletions src/services/templateLoaderService.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import { fileURLToPath } from 'url'
import { dirname } from 'path'
import { Liquid } from 'liquidjs'
import path from 'path'
import { FileService } from './fileService.js'

import TemplateUrl from './templateUrl.js'

class TemplateLoader {
static async loadTemplate(prompt, context, template) {
const templateText = template.startsWith("http://") || template.startsWith("https://") ?
await this.loadTemplateFromUrl(template) :
await this.loadTemplateFromPath(template)
let templateText;
if (template === 'refactor') {
templateText = await this.loadTemplateFromUrl(TemplateUrl.refactor);
} else if (template === 'empty') {
templateText = await this.loadTemplateFromUrl(TemplateUrl.empty);
} else if (template === 'swe') {
templateText = await this.loadTemplateFromUrl(TemplateUrl.swe);
} else if (template === 'test-first') {
templateText = await this.loadTemplateFromUrl(TemplateUrl.testFirst);
} else {
templateText = template.startsWith('http://') || template.startsWith('https://') ?
await this.loadTemplateFromUrl(template) :
await this.loadTemplateFromPath(template);
}
const engine = new Liquid()
engine.registerFilter("jsonToObject", (json) => JSON.parse(json));
const tpl = engine.parse(templateText)
Expand All @@ -27,14 +36,11 @@ class TemplateLoader {
}

static async loadTemplateFromPath(templatePath) {
if (!templatePath.startsWith("/")) {
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
templatePath = path.join(__dirname, "../../templates", `${templatePath}.txt`)
if (!templatePath.startsWith("/")) {
templatePath = path.join(process.cwd(), `${templatePath}`)
}
if (!await FileService.fileExists(templatePath)) {
console.log(`Template file ${templatePath} does not exist`)
process.exit(1)
throw new Error(`Template file ${templatePath} does not exist`)
}
return await FileService.load(templatePath)
}
Expand Down
8 changes: 8 additions & 0 deletions src/services/templateUrl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class TemplateUrl {
static refactor = 'https://gist.githubusercontent.com/ferrislucas/0c9c054133660e4f744e80b685417cfd/raw/6a19ad3f2084c67af4edbcdeb79f2f050433ff67/promptr-refactor-template-v3.0.2';
static empty = 'https://gist.githubusercontent.com/ferrislucas/e43ce36b49f37efe28e7414de4b71399/raw/7ef0afd5a094d392c255d7c0a98f6572dfc4bece/promptr-empty-template-v3.0.2';
static swe = 'https://gist.githubusercontent.com/ferrislucas/a6a18fdafe32910c95829a700c0887ed/raw/50e533d2db8e7e138bfa925739e5e1f5c4498e95/promptr-swe-template-v3.0.2';
static testFirst = 'https://gist.githubusercontent.com/ferrislucas/5d38034e1eefaec0a3d32bdbca3a9ac6/raw/48f1a47d179f568cf1d1fa9271d5ad13fbdc3c85/promptr-test-first-template-v3.0.2';
}

export default TemplateUrl;
11 changes: 0 additions & 11 deletions templates/empty.txt

This file was deleted.

30 changes: 0 additions & 30 deletions templates/refactor.txt

This file was deleted.

23 changes: 0 additions & 23 deletions templates/swe.txt

This file was deleted.

17 changes: 0 additions & 17 deletions templates/test-first.txt

This file was deleted.

8 changes: 5 additions & 3 deletions test/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ describe('Main', () => {
})

it('should pass the expected prompt to PluginService.call when prompt is a URL', async () => {
const url = 'https://example.com/test.txt'
const url = 'https://example.com/prompt.txt'
const templateUrl = 'https://example.com/template.txt'
const content = 'This is a test content from URL.'
fsExistsMock.withArgs(sinon.match(/empty.txt/)).returns(true)

const fetchMock = sinon.stub(global, 'fetch')
fetchMock.withArgs(sinon.match(url)).resolves({ text: () => content })
fetchMock.withArgs(sinon.match(templateUrl)).resolves({ text: () => "stub template content" })
const pluginServiceSpy = sinon.spy(PluginService, 'call')

await Main.call(['node', 'main.js', '-p', url, '-d', '-t', 'empty'])
await Main.call(['node', 'main.js', '-p', url, '-d', '-t', templateUrl])

assert.strictEqual(pluginServiceSpy.calledWith(content), true)
fetchMock.restore()
Expand Down
72 changes: 50 additions & 22 deletions test/templateLoader.test.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,11 @@
import assert from 'assert';
import sinon from 'sinon';
import PluginService from '../src/services/pluginService.js';
import Gpt3Service from '../src/services/gpt3Service.js';
import Gpt4Service from '../src/services/gpt4Service.js';
import CliState from '../src/cliState.js';
import RefactorResultProcessor from '../src/services/refactorResultProcessor.js';
import { FileService } from '../src/services/fileService.js';
import TemplateLoader from '../src/services/templateLoaderService.js';
import TemplateUrl from '../src/services/templateUrl.js';


describe('TemplateLoader', () => {
describe("loadTemplateFromPath", () => {
it('should call FileService.load with correct path when loadTemplateFromPath is passed the string "refactor"', async () => {
const fileServiceLoadStub = sinon.stub(FileService, 'load').resolves('Test content');

await TemplateLoader.loadTemplateFromPath('refactor');

assert(fileServiceLoadStub.called);

fileServiceLoadStub.restore();
});
});

describe("loadTemplate", () => {
describe('loadTemplate', () => {
it('should load template from URL when template starts with http:// or https://', async () => {
const loadTemplateFromUrlStub = sinon.stub(TemplateLoader, 'loadTemplateFromUrl').resolves('Test content from URL');

Expand All @@ -34,17 +17,62 @@ describe('TemplateLoader', () => {
});

it('should load template from path when template does not start with http:// or https://', async () => {
const loadTemplateFromPathStub = sinon.stub(TemplateLoader, 'loadTemplateFromPath').resolves('Test content from path');
const loadTemplateFromPathStub = sinon.stub(TemplateLoader, 'loadTemplateFromPath')
loadTemplateFromPathStub.resolves('Test content from path');

await TemplateLoader.loadTemplate('prompt', 'context', 'refactor');
await TemplateLoader.loadTemplate('prompt', 'context', 'userTemplate');

assert(loadTemplateFromPathStub.called);

loadTemplateFromPathStub.restore();
});

describe("testing built in templates", () => {
let loadTemplateFromUrlStub

beforeEach(() => {
loadTemplateFromUrlStub = sinon.stub(TemplateLoader, 'loadTemplateFromUrl');
})

afterEach(() => {
loadTemplateFromUrlStub.restore()
})

it('should return correct content for the refactor template', async () => {
loadTemplateFromUrlStub.withArgs(TemplateUrl.refactor).resolves('Refactor content');

const refactorContent = await TemplateLoader.loadTemplate('prompt', 'context', 'refactor');

assert.strictEqual(refactorContent, 'Refactor content');
})

it('should return correct content for the empty template', async () => {
loadTemplateFromUrlStub.withArgs(TemplateUrl.empty).resolves('Empty content');

const emptyContent = await TemplateLoader.loadTemplate('prompt', 'context', 'empty');

assert.strictEqual(emptyContent, 'Empty content');
})

it('should return correct content for the swe template', async () => {
loadTemplateFromUrlStub.withArgs(TemplateUrl.swe).resolves('SWE content')

const sweContent = await TemplateLoader.loadTemplate('prompt', 'context', 'swe')

assert.strictEqual(sweContent, 'SWE content');
})

it('should return correct content for the test-first template', async () => {
loadTemplateFromUrlStub.withArgs(TemplateUrl.testFirst).resolves('Test-First content');

const testFirstContent = await TemplateLoader.loadTemplate('prompt', 'context', 'test-first');

assert.strictEqual(testFirstContent, 'Test-First content');
})
})
});

describe("loadTemplateFromUrl", () => {
describe('loadTemplateFromUrl', () => {
it('should fetch content from URL when loadTemplateFromUrl is called', async () => {
const fetchStub = sinon.stub(global, 'fetch').resolves({ text: () => 'Test content from URL' });

Expand Down

0 comments on commit 02b25bd

Please sign in to comment.