promptlineapp 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +101 -40
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -2187,15 +2187,15 @@ function getApiKey() {
|
|
|
2187
2187
|
return localStorage.getItem(API_KEY_STORAGE) || ''
|
|
2188
2188
|
}
|
|
2189
2189
|
|
|
2190
|
-
//
|
|
2191
|
-
function
|
|
2192
|
-
return '/api/promptline
|
|
2190
|
+
// Get proxy path based on environment (local vs prod)
|
|
2191
|
+
function getProxyPath(env) {
|
|
2192
|
+
return env === 'local' ? '/api/promptline-local' : '/api/promptline'
|
|
2193
2193
|
}
|
|
2194
2194
|
|
|
2195
2195
|
// Call PromptLine API
|
|
2196
|
-
async function callPromptLineAPI(
|
|
2197
|
-
const
|
|
2198
|
-
const fullUrl =
|
|
2196
|
+
async function callPromptLineAPI(epData, apiKey, input, variables = {}) {
|
|
2197
|
+
const proxyPath = getProxyPath(epData.env)
|
|
2198
|
+
const fullUrl = proxyPath + '/' + epData.id + '?mode=sync'
|
|
2199
2199
|
|
|
2200
2200
|
const res = await fetch(fullUrl, {
|
|
2201
2201
|
method: 'POST',
|
|
@@ -2239,13 +2239,17 @@ export function usePromptLine(bindingName) {
|
|
|
2239
2239
|
const context = useContext(PromptLineContext)
|
|
2240
2240
|
const [isLoading, setIsLoading] = useState(false)
|
|
2241
2241
|
|
|
2242
|
-
const
|
|
2242
|
+
const epData = useMemo(() => {
|
|
2243
2243
|
const config = getConfig()
|
|
2244
|
-
|
|
2244
|
+
const data = config[bindingName]
|
|
2245
|
+
// Handle both new format { id, env } and legacy string format
|
|
2246
|
+
if (!data) return null
|
|
2247
|
+
if (typeof data === 'string') return { id: data, env: 'prod' }
|
|
2248
|
+
return data
|
|
2245
2249
|
}, [bindingName])
|
|
2246
2250
|
|
|
2247
2251
|
const execute = async (input, variables = {}) => {
|
|
2248
|
-
if (!
|
|
2252
|
+
if (!epData?.id) {
|
|
2249
2253
|
console.warn(\`[PromptLine] Binding "\${bindingName}" not configured. Go to /_dev\`)
|
|
2250
2254
|
return {
|
|
2251
2255
|
response: \`[Not Configured] Binding "\${bindingName}" not set. Go to /_dev to configure it.\`,
|
|
@@ -2263,7 +2267,7 @@ export function usePromptLine(bindingName) {
|
|
|
2263
2267
|
|
|
2264
2268
|
setIsLoading(true)
|
|
2265
2269
|
try {
|
|
2266
|
-
const result = await callPromptLineAPI(
|
|
2270
|
+
const result = await callPromptLineAPI(epData, apiKey, input, variables)
|
|
2267
2271
|
return result
|
|
2268
2272
|
} catch (err) {
|
|
2269
2273
|
console.error(\`[PromptLine] Error calling "\${bindingName}":\`, err)
|
|
@@ -2276,7 +2280,7 @@ export function usePromptLine(bindingName) {
|
|
|
2276
2280
|
return {
|
|
2277
2281
|
execute,
|
|
2278
2282
|
isLoading,
|
|
2279
|
-
isConfigured: !!
|
|
2283
|
+
isConfigured: !!epData?.id,
|
|
2280
2284
|
config: context?.config || {},
|
|
2281
2285
|
user: context?.user || {},
|
|
2282
2286
|
// Aliases for compatibility
|
|
@@ -2294,11 +2298,13 @@ export const sdk = {
|
|
|
2294
2298
|
ai: {
|
|
2295
2299
|
call: async (bindingName, input) => {
|
|
2296
2300
|
const config = getConfig()
|
|
2297
|
-
const
|
|
2298
|
-
|
|
2301
|
+
const data = config[bindingName]
|
|
2302
|
+
// Handle both new format { id, env } and legacy string format
|
|
2303
|
+
const epData = !data ? null : (typeof data === 'string' ? { id: data, env: 'prod' } : data)
|
|
2304
|
+
if (!epData?.id) {
|
|
2299
2305
|
throw new Error(\`Binding "\${bindingName}" not configured\`)
|
|
2300
2306
|
}
|
|
2301
|
-
return callPromptLineAPI(
|
|
2307
|
+
return callPromptLineAPI(epData, getApiKey(), input)
|
|
2302
2308
|
}
|
|
2303
2309
|
},
|
|
2304
2310
|
collections: {
|
|
@@ -2332,14 +2338,29 @@ import { availableBindings } from './sdk-mock'
|
|
|
2332
2338
|
const STORAGE_KEY = 'promptline_endpoints_config'
|
|
2333
2339
|
const API_KEY_STORAGE = 'promptline_api_key'
|
|
2334
2340
|
|
|
2335
|
-
// Helper to extract endpoint ID from URL
|
|
2336
|
-
function
|
|
2337
|
-
if (!value) return ''
|
|
2338
|
-
|
|
2341
|
+
// Helper to extract endpoint ID and environment from URL
|
|
2342
|
+
function parseEndpointUrl(value) {
|
|
2343
|
+
if (!value) return { id: '', env: 'prod' }
|
|
2344
|
+
|
|
2345
|
+
// Detect environment from URL
|
|
2346
|
+
let env = 'prod'
|
|
2347
|
+
if (value.includes('app.local.promptlineops.com')) {
|
|
2348
|
+
env = 'local'
|
|
2349
|
+
} else if (value.includes('app.promptlineops.com')) {
|
|
2350
|
+
env = 'prod'
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2353
|
+
// Extract endpoint ID from URL
|
|
2339
2354
|
const match = value.match(/\\/api\\/v1\\/live\\/([^?/]+)/) || value.match(/\\/live\\/([^?/]+)/)
|
|
2340
|
-
if (match) return match[1]
|
|
2341
|
-
|
|
2342
|
-
|
|
2355
|
+
if (match) return { id: match[1], env }
|
|
2356
|
+
|
|
2357
|
+
// If it starts with ep_ or similar, use as-is with prod default
|
|
2358
|
+
return { id: value.trim(), env }
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
// Get the proxy path for a given environment
|
|
2362
|
+
function getProxyPath(env) {
|
|
2363
|
+
return env === 'local' ? '/api/promptline-local' : '/api/promptline'
|
|
2343
2364
|
}
|
|
2344
2365
|
|
|
2345
2366
|
export default function DevAdmin() {
|
|
@@ -2363,14 +2384,18 @@ export default function DevAdmin() {
|
|
|
2363
2384
|
}, [])
|
|
2364
2385
|
|
|
2365
2386
|
const save = () => {
|
|
2366
|
-
//
|
|
2367
|
-
const
|
|
2387
|
+
// Parse endpoint values (extract IDs and environments from URLs)
|
|
2388
|
+
const parsedEndpoints = {}
|
|
2368
2389
|
Object.entries(endpoints).forEach(([key, value]) => {
|
|
2369
|
-
|
|
2390
|
+
if (typeof value === 'string') {
|
|
2391
|
+
parsedEndpoints[key] = parseEndpointUrl(value)
|
|
2392
|
+
} else {
|
|
2393
|
+
parsedEndpoints[key] = value // Already parsed
|
|
2394
|
+
}
|
|
2370
2395
|
})
|
|
2371
|
-
setEndpoints(
|
|
2396
|
+
setEndpoints(parsedEndpoints)
|
|
2372
2397
|
localStorage.setItem(API_KEY_STORAGE, apiKey)
|
|
2373
|
-
localStorage.setItem(STORAGE_KEY, JSON.stringify(
|
|
2398
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(parsedEndpoints))
|
|
2374
2399
|
setSaved(true)
|
|
2375
2400
|
setTimeout(() => setSaved(false), 2000)
|
|
2376
2401
|
}
|
|
@@ -2381,8 +2406,10 @@ export default function DevAdmin() {
|
|
|
2381
2406
|
|
|
2382
2407
|
// Check if endpoint is alive
|
|
2383
2408
|
const checkIsAlive = async (bindingName) => {
|
|
2384
|
-
const
|
|
2385
|
-
|
|
2409
|
+
const epData = typeof endpoints[bindingName] === 'string'
|
|
2410
|
+
? parseEndpointUrl(endpoints[bindingName])
|
|
2411
|
+
: endpoints[bindingName]
|
|
2412
|
+
if (!epData?.id) {
|
|
2386
2413
|
setEndpointStatus(prev => ({ ...prev, [bindingName]: { ...prev[bindingName], alive: false, error: 'No endpoint ID' } }))
|
|
2387
2414
|
return
|
|
2388
2415
|
}
|
|
@@ -2390,7 +2417,8 @@ export default function DevAdmin() {
|
|
|
2390
2417
|
setEndpointStatus(prev => ({ ...prev, [bindingName]: { ...prev[bindingName], loading: 'alive' } }))
|
|
2391
2418
|
|
|
2392
2419
|
try {
|
|
2393
|
-
const
|
|
2420
|
+
const proxyPath = getProxyPath(epData.env)
|
|
2421
|
+
const res = await fetch(proxyPath + '/' + epData.id + '/isAlive', {
|
|
2394
2422
|
method: 'GET',
|
|
2395
2423
|
headers: apiKey ? { 'X-API-Key': apiKey } : {}
|
|
2396
2424
|
})
|
|
@@ -2401,7 +2429,8 @@ export default function DevAdmin() {
|
|
|
2401
2429
|
...prev[bindingName],
|
|
2402
2430
|
alive: res.ok && data.alive === true,
|
|
2403
2431
|
loading: null,
|
|
2404
|
-
error: res.ok ? null : (data.detail || res.statusText)
|
|
2432
|
+
error: res.ok ? null : (data.detail || res.statusText),
|
|
2433
|
+
env: epData.env
|
|
2405
2434
|
}
|
|
2406
2435
|
}))
|
|
2407
2436
|
} catch (err) {
|
|
@@ -2414,8 +2443,10 @@ export default function DevAdmin() {
|
|
|
2414
2443
|
|
|
2415
2444
|
// Get endpoint info
|
|
2416
2445
|
const fetchInfo = async (bindingName) => {
|
|
2417
|
-
const
|
|
2418
|
-
|
|
2446
|
+
const epData = typeof endpoints[bindingName] === 'string'
|
|
2447
|
+
? parseEndpointUrl(endpoints[bindingName])
|
|
2448
|
+
: endpoints[bindingName]
|
|
2449
|
+
if (!epData?.id) {
|
|
2419
2450
|
setEndpointStatus(prev => ({ ...prev, [bindingName]: { ...prev[bindingName], error: 'No endpoint ID' } }))
|
|
2420
2451
|
return
|
|
2421
2452
|
}
|
|
@@ -2423,7 +2454,8 @@ export default function DevAdmin() {
|
|
|
2423
2454
|
setEndpointStatus(prev => ({ ...prev, [bindingName]: { ...prev[bindingName], loading: 'info' } }))
|
|
2424
2455
|
|
|
2425
2456
|
try {
|
|
2426
|
-
const
|
|
2457
|
+
const proxyPath = getProxyPath(epData.env)
|
|
2458
|
+
const res = await fetch(proxyPath + '/' + epData.id + '/info', {
|
|
2427
2459
|
method: 'GET',
|
|
2428
2460
|
headers: apiKey ? { 'X-API-Key': apiKey } : {}
|
|
2429
2461
|
})
|
|
@@ -2434,7 +2466,8 @@ export default function DevAdmin() {
|
|
|
2434
2466
|
...prev[bindingName],
|
|
2435
2467
|
info: res.ok ? data : null,
|
|
2436
2468
|
loading: null,
|
|
2437
|
-
error: res.ok ? null : (data.detail || res.statusText)
|
|
2469
|
+
error: res.ok ? null : (data.detail || res.statusText),
|
|
2470
|
+
env: epData.env
|
|
2438
2471
|
}
|
|
2439
2472
|
}))
|
|
2440
2473
|
} catch (err) {
|
|
@@ -2446,8 +2479,10 @@ export default function DevAdmin() {
|
|
|
2446
2479
|
}
|
|
2447
2480
|
|
|
2448
2481
|
const testEndpoint = async () => {
|
|
2449
|
-
const
|
|
2450
|
-
|
|
2482
|
+
const epData = typeof endpoints[testBinding] === 'string'
|
|
2483
|
+
? parseEndpointUrl(endpoints[testBinding])
|
|
2484
|
+
: endpoints[testBinding]
|
|
2485
|
+
if (!testBinding || !epData?.id) {
|
|
2451
2486
|
setTestResult('Error: Endpoint not configured')
|
|
2452
2487
|
return
|
|
2453
2488
|
}
|
|
@@ -2460,7 +2495,8 @@ export default function DevAdmin() {
|
|
|
2460
2495
|
setTestResult('Calling API...')
|
|
2461
2496
|
|
|
2462
2497
|
try {
|
|
2463
|
-
const
|
|
2498
|
+
const proxyPath = getProxyPath(epData.env)
|
|
2499
|
+
const res = await fetch(proxyPath + '/' + epData.id + '?mode=sync', {
|
|
2464
2500
|
method: 'POST',
|
|
2465
2501
|
headers: {
|
|
2466
2502
|
'Content-Type': 'application/json',
|
|
@@ -2537,6 +2573,10 @@ export default function DevAdmin() {
|
|
|
2537
2573
|
<tbody>
|
|
2538
2574
|
{availableBindings.map(b => {
|
|
2539
2575
|
const status = endpointStatus[b.name] || {}
|
|
2576
|
+
const epValue = endpoints[b.name]
|
|
2577
|
+
const displayValue = typeof epValue === 'object' ? epValue?.id || '' : epValue || ''
|
|
2578
|
+
const epEnv = typeof epValue === 'object' ? epValue?.env : (status.env || null)
|
|
2579
|
+
const hasValue = !!(typeof epValue === 'object' ? epValue?.id : epValue)
|
|
2540
2580
|
return (
|
|
2541
2581
|
<tr key={b.name} style={{ borderBottom: '1px solid #f3f4f6' }}>
|
|
2542
2582
|
<td style={{ padding: 8 }}>
|
|
@@ -2546,11 +2586,24 @@ export default function DevAdmin() {
|
|
|
2546
2586
|
<td style={{ padding: 8 }}>
|
|
2547
2587
|
<input
|
|
2548
2588
|
type="text"
|
|
2549
|
-
value={
|
|
2589
|
+
value={displayValue}
|
|
2550
2590
|
onChange={e => updateEndpoint(b.name, e.target.value)}
|
|
2551
|
-
placeholder="
|
|
2591
|
+
placeholder="Paste full endpoint URL (app.local or app)"
|
|
2552
2592
|
style={{ width: '100%', padding: 8, border: '1px solid #d1d5db', borderRadius: 4, fontSize: 12 }}
|
|
2553
2593
|
/>
|
|
2594
|
+
{epEnv && (
|
|
2595
|
+
<span style={{
|
|
2596
|
+
display: 'inline-block',
|
|
2597
|
+
marginTop: 4,
|
|
2598
|
+
padding: '2px 6px',
|
|
2599
|
+
fontSize: 10,
|
|
2600
|
+
borderRadius: 4,
|
|
2601
|
+
background: epEnv === 'local' ? '#dbeafe' : '#dcfce7',
|
|
2602
|
+
color: epEnv === 'local' ? '#1d4ed8' : '#166534'
|
|
2603
|
+
}}>
|
|
2604
|
+
{epEnv === 'local' ? 'LOCAL' : 'PROD'}
|
|
2605
|
+
</span>
|
|
2606
|
+
)}
|
|
2554
2607
|
</td>
|
|
2555
2608
|
<td style={{ padding: 8, textAlign: 'center' }}>
|
|
2556
2609
|
<button
|
|
@@ -2577,7 +2630,7 @@ export default function DevAdmin() {
|
|
|
2577
2630
|
width: 12,
|
|
2578
2631
|
height: 12,
|
|
2579
2632
|
borderRadius: '50%',
|
|
2580
|
-
background: status.alive === true ? '#22c55e' : status.alive === false ? '#ef4444' : (
|
|
2633
|
+
background: status.alive === true ? '#22c55e' : status.alive === false ? '#ef4444' : (hasValue ? '#fbbf24' : '#d1d5db')
|
|
2581
2634
|
}}
|
|
2582
2635
|
title={status.error || (status.alive ? 'Alive' : status.alive === false ? 'Not responding' : 'Not checked')}
|
|
2583
2636
|
/>
|
|
@@ -2691,6 +2744,14 @@ export default function DevAdmin() {
|
|
|
2691
2744
|
viteProxyConfig: `
|
|
2692
2745
|
// PromptLine API Proxy (added by npx promptlineapp get)
|
|
2693
2746
|
proxy: {
|
|
2747
|
+
// Local dev: app.local.promptlineops.com (more specific path first)
|
|
2748
|
+
'/api/promptline-local': {
|
|
2749
|
+
target: 'https://app.local.promptlineops.com',
|
|
2750
|
+
changeOrigin: true,
|
|
2751
|
+
rewrite: (path) => path.replace(/^\\/api\\/promptline-local/, '/api/v1/live'),
|
|
2752
|
+
secure: true
|
|
2753
|
+
},
|
|
2754
|
+
// Production: app.promptlineops.com
|
|
2694
2755
|
'/api/promptline': {
|
|
2695
2756
|
target: 'https://app.promptlineops.com',
|
|
2696
2757
|
changeOrigin: true,
|