Skip to content

Commit d4d8cdc

Browse files
committed
feat: add beta completions
1 parent 68e59b5 commit d4d8cdc

5 files changed

Lines changed: 81 additions & 24 deletions

File tree

completions-cron/src/index.ts

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,25 @@ const BATCH_SIZE = 1000
66
async function getResourceId(
77
supabase: SupabaseClient,
88
resourceType: string,
9+
prerelease: boolean,
910
cache: Map<string, string>
1011
): Promise<string> {
11-
if (cache.has(resourceType)) {
12-
return cache.get(resourceType)!
12+
const cacheKey = `${resourceType}:${prerelease}`
13+
if (cache.has(cacheKey)) {
14+
return cache.get(cacheKey)!
1315
}
1416

1517
const { data, error } = await supabase
1618
.from('registry_resources')
1719
.select('id')
1820
.eq('type', resourceType)
21+
.eq('prerelease', prerelease)
1922

2023
if (error || !data?.[0]?.id) {
21-
throw new Error(`Resource type '${resourceType}' not found in registry_resources`)
24+
throw new Error(`Resource type '${resourceType}' (prerelease=${prerelease}) not found in registry_resources`)
2225
}
2326

24-
cache.set(resourceType, data[0].id)
27+
cache.set(cacheKey, data[0].id)
2528
return data[0].id
2629
}
2730

@@ -30,14 +33,15 @@ async function processModule(
3033
resourceType: string,
3134
parameterPath: string,
3235
fetchFn: () => Promise<string[]>,
36+
prerelease: boolean,
3337
resourceIdCache: Map<string, string>
3438
): Promise<void> {
3539
console.log(`Processing ${resourceType}${parameterPath}...`)
3640

3741
const values = await fetchFn()
3842
console.log(` [${resourceType}${parameterPath}] Fetched ${values.length} values`)
3943

40-
const resourceId = await getResourceId(supabase, resourceType, resourceIdCache)
44+
const resourceId = await getResourceId(supabase, resourceType, prerelease, resourceIdCache)
4145

4246
await supabase
4347
.from('resource_parameter_completions')
@@ -66,31 +70,44 @@ async function processModule(
6670
console.log(` [${resourceType}${parameterPath}] Done: inserted ${values.length} completions`)
6771
}
6872

73+
async function runCompletions(env: Env): Promise<void> {
74+
const supabase = createClient(env.SUPABASE_URL, env.SUPABASE_SERVICE_ROLE_KEY)
75+
const prerelease = env.PRERELEASE === 'true'
76+
const resourceIdCache = new Map<string, string>()
77+
78+
const results = await Promise.allSettled(
79+
completionModules.map(({ resourceType, parameterPath, fetch }: CompletionModule) =>
80+
processModule(supabase, resourceType, parameterPath, fetch, prerelease, resourceIdCache)
81+
)
82+
)
83+
84+
for (const result of results) {
85+
if (result.status === 'rejected') {
86+
console.error('Completion module failed:', result.reason)
87+
}
88+
}
89+
90+
console.log('Successfully processed all resource completion tasks')
91+
}
92+
6993
export default {
70-
async fetch(req: Request) {
94+
async fetch(req: Request, env: Env, ctx: ExecutionContext) {
7195
const url = new URL(req.url)
96+
97+
if (req.method === 'POST' && url.pathname === '/trigger') {
98+
if (req.headers.get('Authorization') !== env.TRIGGER_SECRET) {
99+
return new Response('Unauthorized', { status: 401 })
100+
}
101+
ctx.waitUntil(runCompletions(env))
102+
return new Response('Triggered', { status: 202 })
103+
}
104+
72105
url.pathname = '/__scheduled'
73106
url.searchParams.append('cron', '* * * * *')
74107
return new Response(`To test the scheduled handler, ensure you have used the "--test-scheduled" then try running "curl ${url.href}".`)
75108
},
76109

77110
async scheduled(_event: ScheduledEvent, env: Env, _ctx: ExecutionContext): Promise<void> {
78-
console.log('hihi')
79-
const supabase = createClient(env.SUPABASE_URL, env.SUPABASE_SERVICE_ROLE_KEY)
80-
const resourceIdCache = new Map<string, string>()
81-
82-
const results = await Promise.allSettled(
83-
completionModules.map(({ resourceType, parameterPath, fetch }: CompletionModule) =>
84-
processModule(supabase, resourceType, parameterPath, fetch, resourceIdCache)
85-
)
86-
)
87-
88-
for (const result of results) {
89-
if (result.status === 'rejected') {
90-
console.error('Completion module failed:', result.reason)
91-
}
92-
}
93-
94-
console.log('Successfully processed all resource completion tasks')
111+
await runCompletions(env)
95112
},
96113
} satisfies ExportedHandler<Env>

completions-cron/types/worker-configuration.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ declare namespace Cloudflare {
66
mainModule: typeof import("../src");
77
}
88
interface Env {
9+
SUPABASE_URL: string;
10+
SUPABASE_SERVICE_ROLE_KEY: string;
11+
PRERELEASE: string;
12+
TRIGGER_SECRET: string;
913
}
1014
}
1115
interface Env extends Cloudflare.Env {}

completions-cron/wrangler.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ head_sampling_rate = 1
1010

1111
[vars]
1212
SUPABASE_URL = "https://kdctbvqvqjfquplxhqrm.supabase.co"
13+
PRERELEASE = "false"
1314

1415
[triggers]
1516
crons = ["0 5 * * *"]
17+
18+
# Beta environment — deploys as a separate worker: resource-completions-cron-beta
19+
[env.beta]
20+
name = "resource-completions-cron-beta"
21+
22+
[env.beta.vars]
23+
SUPABASE_URL = "https://kdctbvqvqjfquplxhqrm.supabase.co"
24+
PRERELEASE = "true"
25+
26+
[env.beta.triggers]
27+
crons = ["0 5 * * *"]

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "default",
3-
"version": "1.12.0-beta.4",
3+
"version": "1.12.0-beta.5",
44
"description": "Default plugin for Codify - provides 50+ declarative resources for managing development tools and system configuration across macOS and Linux",
55
"main": "dist/index.js",
66
"scripts": {

scripts/deploy.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ const versionRow = await client.from('registry_plugin_versions').upsert({
8686
await uploadResources(isBeta);
8787

8888
if (isBeta) {
89+
console.log('Deploying beta completions worker...')
90+
cp.spawnSync('source ~/.zshrc; npm run build:completions && cd completions-cron && npx wrangler deploy --env beta', { shell: 'zsh', stdio: 'inherit' })
91+
8992
// Generate embeddings for prerelease resources so the AI agent can find them via semantic search
9093
console.log('Triggering vector reindex for prerelease resources...')
9194
const reindexKey = process.env.REINDEX_API_KEY
@@ -129,6 +132,27 @@ if (!isBeta) {
129132
}
130133
}
131134

135+
// Trigger an immediate completions run so completions are populated right after deploy
136+
// (the daily cron keeps them updated over time)
137+
console.log('Triggering completions run...')
138+
const workerUrl = isBeta
139+
? process.env.COMPLETIONS_BETA_WORKER_URL
140+
: process.env.COMPLETIONS_WORKER_URL
141+
const triggerSecret = process.env.COMPLETIONS_TRIGGER_SECRET
142+
if (!workerUrl || !triggerSecret) {
143+
console.warn('COMPLETIONS_WORKER_URL / COMPLETIONS_BETA_WORKER_URL / COMPLETIONS_TRIGGER_SECRET not set — skipping completions trigger')
144+
} else {
145+
const res = await fetch(`${workerUrl}/trigger`, {
146+
method: 'POST',
147+
headers: { Authorization: triggerSecret },
148+
})
149+
if (!res.ok) {
150+
console.error(`Completions trigger failed: ${res.status} ${await res.text()}`)
151+
} else {
152+
console.log('Completions trigger accepted (running in background on worker)')
153+
}
154+
}
155+
132156
async function uploadResources(prerelease: boolean) {
133157
const Metadata: Array<Record<string, any>> = require('../dist/metadata.json');
134158

0 commit comments

Comments
 (0)