@inquir/compute-cli 0.1.4 → 0.2.1
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/README.md +79 -5
- package/dist/commands/apps.d.ts +21 -0
- package/dist/commands/apps.d.ts.map +1 -0
- package/dist/commands/apps.js +857 -0
- package/dist/commands/apps.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +19 -2
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +207 -93
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +4 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp.d.ts +15 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +269 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/upgrade.d.ts +6 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +72 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/index.js +26 -3
- package/dist/index.js.map +1 -1
- package/dist/utils/api.d.ts +52 -2
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/api.js +95 -2
- package/dist/utils/api.js.map +1 -1
- package/dist/utils/apps-presentation.d.ts +25 -0
- package/dist/utils/apps-presentation.d.ts.map +1 -0
- package/dist/utils/apps-presentation.js +71 -0
- package/dist/utils/apps-presentation.js.map +1 -0
- package/dist/utils/args.d.ts.map +1 -1
- package/dist/utils/args.js +1 -0
- package/dist/utils/args.js.map +1 -1
- package/dist/utils/auth.d.ts +2 -0
- package/dist/utils/auth.d.ts.map +1 -1
- package/dist/utils/auth.js +13 -5
- package/dist/utils/auth.js.map +1 -1
- package/dist/utils/auto-update.d.ts +84 -0
- package/dist/utils/auto-update.d.ts.map +1 -0
- package/dist/utils/auto-update.js +232 -0
- package/dist/utils/auto-update.js.map +1 -0
- package/dist/utils/context.d.ts.map +1 -1
- package/dist/utils/context.js +3 -1
- package/dist/utils/context.js.map +1 -1
- package/dist/utils/detect.d.ts +45 -0
- package/dist/utils/detect.d.ts.map +1 -0
- package/dist/utils/detect.js +358 -0
- package/dist/utils/detect.js.map +1 -0
- package/dist/utils/ensure-auth.d.ts.map +1 -1
- package/dist/utils/ensure-auth.js +7 -1
- package/dist/utils/ensure-auth.js.map +1 -1
- package/package.json +5 -4
- package/skill/SKILL.md +60 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-config app detection (Railway-style).
|
|
3
|
+
*
|
|
4
|
+
* Given a directory, figure out: runtime, entry file, mode (lambda handler vs
|
|
5
|
+
* web server), handler spec or start command, and a deployable name — without
|
|
6
|
+
* requiring an inquir config or the TypeScript SDK contract.
|
|
7
|
+
*
|
|
8
|
+
* Detection is intentionally boring and transparent: every decision appends a
|
|
9
|
+
* human-readable line to `reasons` so `inquir deploy` can print exactly why it
|
|
10
|
+
* chose what it chose (and how to override it).
|
|
11
|
+
*/
|
|
12
|
+
import fs from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
export class DetectionError extends Error {
|
|
15
|
+
hints;
|
|
16
|
+
constructor(message, hints = []) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.hints = hints;
|
|
19
|
+
this.name = 'DetectionError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const NODE_EXTENSIONS = ['.mjs', '.cjs', '.js', '.ts', '.mts', '.cts'];
|
|
23
|
+
const NODE_ENTRY_BASENAMES = ['index', 'main', 'app', 'server', 'handler'];
|
|
24
|
+
const PYTHON_ENTRY_FILES = ['main.py', 'app.py', 'index.py', 'server.py', 'handler.py', 'application.py'];
|
|
25
|
+
/** Handler export patterns per runtime family. */
|
|
26
|
+
const NODE_HANDLER_PATTERN = /(?:exports\.handler\s*=|module\.exports\.handler\s*=|export\s+(?:async\s+)?function\s+handler\b|export\s+const\s+handler\s*=|module\.exports\s*=\s*{[^}]*\bhandler\b)/;
|
|
27
|
+
const PYTHON_HANDLER_PATTERN = /^def\s+(?:handler|lambda_handler)\s*\(/m;
|
|
28
|
+
const GO_HANDLER_PATTERN = /func\s+Handler\s*\(/;
|
|
29
|
+
/** Signals that a Node entry file is a server, not a handler module. */
|
|
30
|
+
const NODE_SERVER_PATTERN = /(?:\.listen\s*\(|createServer\s*\(|require\(['"](?:express|fastify|koa|hapi|@hapi\/hapi|restify)['"]\)|from\s+['"](?:express|fastify|koa|hapi|@hapi\/hapi|restify)['"])/;
|
|
31
|
+
/** Web-server frameworks in dependencies count as server evidence. */
|
|
32
|
+
const NODE_WEB_FRAMEWORK_DEPS = [
|
|
33
|
+
'express', 'fastify', 'koa', 'hapi', '@hapi/hapi', 'restify',
|
|
34
|
+
'next', '@nestjs/core', '@remix-run/serve', 'astro', 'nuxt',
|
|
35
|
+
];
|
|
36
|
+
/** Web-server evidence for Python (deps text or entry source). */
|
|
37
|
+
const PYTHON_WEB_DEPS_PATTERN = /\b(?:fastapi|flask|django|uvicorn|gunicorn|starlette|aiohttp|sanic|tornado)\b/;
|
|
38
|
+
const PYTHON_WEB_SOURCE_PATTERN = /(?:app\.run\s*\(|http\.server|make_server\s*\(|run_simple\s*\()/;
|
|
39
|
+
/** Dirs the deploy artifact never includes (mirrors the SDK zip excludes) —
|
|
40
|
+
* an entry inside them would deploy as a dangling reference. */
|
|
41
|
+
const ARTIFACT_EXCLUDED_ENTRY = /^(?:dist|node_modules|\.git|\.inquir)\//;
|
|
42
|
+
function exists(dir, rel) {
|
|
43
|
+
try {
|
|
44
|
+
return fs.existsSync(path.join(dir, rel));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function readText(dir, rel) {
|
|
51
|
+
try {
|
|
52
|
+
return fs.readFileSync(path.join(dir, rel), 'utf8');
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function readPackageJson(dir) {
|
|
59
|
+
const raw = readText(dir, 'package.json');
|
|
60
|
+
if (!raw)
|
|
61
|
+
return null;
|
|
62
|
+
try {
|
|
63
|
+
return JSON.parse(raw);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** List top-level files with any of the given extensions (sorted, non-recursive). */
|
|
70
|
+
function listByExtension(dir, extensions) {
|
|
71
|
+
let entries;
|
|
72
|
+
try {
|
|
73
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
return entries
|
|
79
|
+
.filter((e) => e.isFile() && extensions.includes(path.extname(e.name)))
|
|
80
|
+
.map((e) => e.name)
|
|
81
|
+
.sort();
|
|
82
|
+
}
|
|
83
|
+
/** Sanitize an arbitrary string into a deployable function name. */
|
|
84
|
+
export function sanitizeName(raw) {
|
|
85
|
+
const cleaned = raw
|
|
86
|
+
.toLowerCase()
|
|
87
|
+
.replace(/^@[^/]+\//, '') // scoped npm package → drop scope
|
|
88
|
+
.replace(/[^a-z0-9-]+/g, '-')
|
|
89
|
+
.replace(/-{2,}/g, '-')
|
|
90
|
+
.replace(/^-+|-+$/g, '');
|
|
91
|
+
return cleaned || 'app';
|
|
92
|
+
}
|
|
93
|
+
/** Find the first existing entry file among conventional Node names. */
|
|
94
|
+
function findNodeEntry(dir, pkg) {
|
|
95
|
+
// package.json "main" wins when it exists on disk — unless it points into a
|
|
96
|
+
// dir the artifact excludes (dist/ etc.): deploying that reference would 404.
|
|
97
|
+
if (pkg?.main) {
|
|
98
|
+
const main = pkg.main.replace(/\\/g, '/');
|
|
99
|
+
if (exists(dir, main) && !ARTIFACT_EXCLUDED_ENTRY.test(main))
|
|
100
|
+
return main;
|
|
101
|
+
}
|
|
102
|
+
for (const prefix of ['', 'src/']) {
|
|
103
|
+
for (const base of NODE_ENTRY_BASENAMES) {
|
|
104
|
+
for (const ext of NODE_EXTENSIONS) {
|
|
105
|
+
const candidate = `${prefix}${base}${ext}`;
|
|
106
|
+
if (exists(dir, candidate))
|
|
107
|
+
return candidate;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Single top-level source file → that's the entry.
|
|
112
|
+
const files = listByExtension(dir, NODE_EXTENSIONS);
|
|
113
|
+
return files.length === 1 ? files[0] : null;
|
|
114
|
+
}
|
|
115
|
+
function findPythonEntry(dir) {
|
|
116
|
+
for (const prefix of ['', 'src/']) {
|
|
117
|
+
for (const name of PYTHON_ENTRY_FILES) {
|
|
118
|
+
const candidate = `${prefix}${name}`;
|
|
119
|
+
if (exists(dir, candidate))
|
|
120
|
+
return candidate;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const files = listByExtension(dir, ['.py']);
|
|
124
|
+
return files.length === 1 ? files[0] : null;
|
|
125
|
+
}
|
|
126
|
+
/** "src/api.mjs" → "src/api" (handler module spec base). */
|
|
127
|
+
function stripExtension(rel) {
|
|
128
|
+
return rel.replace(/\.[^./]+$/, '');
|
|
129
|
+
}
|
|
130
|
+
function detectRuntime(dir, reasons) {
|
|
131
|
+
if (exists(dir, 'go.mod')) {
|
|
132
|
+
reasons.push('runtime: go122 (go.mod present)');
|
|
133
|
+
return 'go122';
|
|
134
|
+
}
|
|
135
|
+
const hasPyMarker = exists(dir, 'requirements.txt') || exists(dir, 'pyproject.toml') || exists(dir, 'Pipfile');
|
|
136
|
+
const pkg = readPackageJson(dir);
|
|
137
|
+
if (hasPyMarker && !pkg) {
|
|
138
|
+
reasons.push('runtime: python312 (requirements.txt/pyproject.toml present)');
|
|
139
|
+
return 'python312';
|
|
140
|
+
}
|
|
141
|
+
if (pkg) {
|
|
142
|
+
reasons.push('runtime: nodejs22 (package.json present)');
|
|
143
|
+
return 'nodejs22';
|
|
144
|
+
}
|
|
145
|
+
// No manifests — fall back to source files.
|
|
146
|
+
if (listByExtension(dir, ['.go']).length > 0) {
|
|
147
|
+
reasons.push('runtime: go122 (.go sources present)');
|
|
148
|
+
return 'go122';
|
|
149
|
+
}
|
|
150
|
+
if (listByExtension(dir, ['.py']).length > 0 || findPythonEntry(dir)) {
|
|
151
|
+
reasons.push('runtime: python312 (.py sources present)');
|
|
152
|
+
return 'python312';
|
|
153
|
+
}
|
|
154
|
+
if (listByExtension(dir, NODE_EXTENSIONS).length > 0 || findNodeEntry(dir, null)) {
|
|
155
|
+
reasons.push('runtime: nodejs22 (JS/TS sources present)');
|
|
156
|
+
return 'nodejs22';
|
|
157
|
+
}
|
|
158
|
+
throw new DetectionError(`Could not detect a runtime in ${dir}`, [
|
|
159
|
+
'Supported: Node.js (package.json / *.js), Python (requirements.txt / *.py), Go (go.mod).',
|
|
160
|
+
'Override with --runtime nodejs22|python312|go122.',
|
|
161
|
+
]);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Resolve the command that starts a Node web app.
|
|
165
|
+
* npm start is inlined (its script body) so the runtime image does not need npm
|
|
166
|
+
* at all — the harness runs the command through sh with PORT set.
|
|
167
|
+
*/
|
|
168
|
+
function nodeStartCommand(entryFile, pkg, reasons) {
|
|
169
|
+
const start = pkg?.scripts?.start?.trim();
|
|
170
|
+
if (start && !/^npm\s+/.test(start) && !/^yarn\s+/.test(start) && !/^pnpm\s+/.test(start)) {
|
|
171
|
+
reasons.push(`start: "${start}" (package.json scripts.start, inlined)`);
|
|
172
|
+
return start;
|
|
173
|
+
}
|
|
174
|
+
if (/\.(?:ts|mts|cts)$/.test(entryFile)) {
|
|
175
|
+
// Web deploys skip bundling; Node 22 cannot execute .ts directly.
|
|
176
|
+
throw new DetectionError(`Web entry ${entryFile} is TypeScript, which the runtime cannot run directly`, [
|
|
177
|
+
'Add a scripts.start that runs compiled output, or pass --start "<command>".',
|
|
178
|
+
'Handler-mode functions support TypeScript via bundling; web apps run your sources as-is.',
|
|
179
|
+
]);
|
|
180
|
+
}
|
|
181
|
+
reasons.push(`start: "node ${entryFile}" (entry file)`);
|
|
182
|
+
return `node ${entryFile}`;
|
|
183
|
+
}
|
|
184
|
+
/** Resolve the command that starts a Python web app. */
|
|
185
|
+
function pythonStartCommand(dir, entryFile, reasons) {
|
|
186
|
+
const requirements = (readText(dir, 'requirements.txt') ?? '').toLowerCase();
|
|
187
|
+
const pyproject = (readText(dir, 'pyproject.toml') ?? '').toLowerCase();
|
|
188
|
+
const deps = requirements + '\n' + pyproject;
|
|
189
|
+
const module = stripExtension(entryFile).replace(/\//g, '.');
|
|
190
|
+
const entrySource = readText(dir, entryFile) ?? '';
|
|
191
|
+
if (/\bfastapi\b/.test(deps)) {
|
|
192
|
+
const cmd = `python -m uvicorn ${module}:app --host 0.0.0.0 --port \${PORT}`;
|
|
193
|
+
reasons.push(`start: "${cmd}" (FastAPI detected)`);
|
|
194
|
+
return cmd;
|
|
195
|
+
}
|
|
196
|
+
if (/\bflask\b/.test(deps)) {
|
|
197
|
+
if (/\bgunicorn\b/.test(deps)) {
|
|
198
|
+
const cmd = `python -m gunicorn -b 0.0.0.0:\${PORT} ${module}:app`;
|
|
199
|
+
reasons.push(`start: "${cmd}" (Flask + gunicorn detected)`);
|
|
200
|
+
return cmd;
|
|
201
|
+
}
|
|
202
|
+
if (/app\.run\s*\(/.test(entrySource) && /\bPORT\b/.test(entrySource)) {
|
|
203
|
+
// Only trust app.run() when the app reads the PORT env itself — a bare
|
|
204
|
+
// app.run() binds Flask's default 5000 and the adapter waits forever.
|
|
205
|
+
reasons.push(`start: "python ${entryFile}" (Flask app.run entry, PORT-aware)`);
|
|
206
|
+
return `python ${entryFile}`;
|
|
207
|
+
}
|
|
208
|
+
const cmd = `python -m flask --app ${module} run --host 0.0.0.0 --port \${PORT}`;
|
|
209
|
+
reasons.push(`start: "${cmd}" (Flask detected)`);
|
|
210
|
+
return cmd;
|
|
211
|
+
}
|
|
212
|
+
reasons.push(`start: "python ${entryFile}" (entry file)`);
|
|
213
|
+
return `python ${entryFile}`;
|
|
214
|
+
}
|
|
215
|
+
function assertRuntimeOverride(value) {
|
|
216
|
+
if (value === 'nodejs22' || value === 'python312' || value === 'go122')
|
|
217
|
+
return value;
|
|
218
|
+
throw new DetectionError(`Unknown --runtime "${value}"`, [
|
|
219
|
+
'Supported runtimes: nodejs22, python312, go122.',
|
|
220
|
+
]);
|
|
221
|
+
}
|
|
222
|
+
function assertModeOverride(value) {
|
|
223
|
+
if (value === 'handler' || value === 'web')
|
|
224
|
+
return value;
|
|
225
|
+
throw new DetectionError(`Unknown --mode "${value}"`, ['Supported modes: handler, web.']);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Detect a deployable app in `dir`. Overrides always win over sniffing; every
|
|
229
|
+
* decision is recorded in `reasons` for the deploy plan output.
|
|
230
|
+
*/
|
|
231
|
+
export function detectApp(dir, overrides = {}) {
|
|
232
|
+
const resolved = path.resolve(dir);
|
|
233
|
+
if (!fs.existsSync(resolved) || !fs.statSync(resolved).isDirectory()) {
|
|
234
|
+
throw new DetectionError(`Not a directory: ${dir}`);
|
|
235
|
+
}
|
|
236
|
+
const reasons = [];
|
|
237
|
+
if (exists(resolved, 'Dockerfile') && !overrides.runtime) {
|
|
238
|
+
reasons.push('Dockerfile found but Dockerfile builds are not supported yet — using language detection');
|
|
239
|
+
}
|
|
240
|
+
const runtime = overrides.runtime
|
|
241
|
+
? assertRuntimeOverride(overrides.runtime)
|
|
242
|
+
: detectRuntime(resolved, reasons);
|
|
243
|
+
if (overrides.runtime)
|
|
244
|
+
reasons.push(`runtime: ${runtime} (--runtime)`);
|
|
245
|
+
const pkg = runtime === 'nodejs22' ? readPackageJson(resolved) : null;
|
|
246
|
+
// Name resolution: flag > manifest name > directory basename.
|
|
247
|
+
let name;
|
|
248
|
+
if (overrides.name) {
|
|
249
|
+
name = sanitizeName(overrides.name);
|
|
250
|
+
reasons.push(`name: ${name} (--name)`);
|
|
251
|
+
}
|
|
252
|
+
else if (pkg?.name) {
|
|
253
|
+
name = sanitizeName(pkg.name);
|
|
254
|
+
reasons.push(`name: ${name} (package.json name)`);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
name = sanitizeName(path.basename(resolved));
|
|
258
|
+
reasons.push(`name: ${name} (directory name)`);
|
|
259
|
+
}
|
|
260
|
+
// Entry file.
|
|
261
|
+
let entryFile = null;
|
|
262
|
+
if (runtime === 'nodejs22')
|
|
263
|
+
entryFile = findNodeEntry(resolved, pkg);
|
|
264
|
+
else if (runtime === 'python312')
|
|
265
|
+
entryFile = findPythonEntry(resolved);
|
|
266
|
+
else
|
|
267
|
+
entryFile = exists(resolved, 'main.go') ? 'main.go' : listByExtension(resolved, ['.go'])[0] ?? null;
|
|
268
|
+
if (overrides.handler) {
|
|
269
|
+
// Explicit handler spec: trust it, derive the entry from its module part.
|
|
270
|
+
const moduleBase = overrides.handler.replace(/\.[^.]+$/, '');
|
|
271
|
+
reasons.push(`handler: ${overrides.handler} (--handler)`);
|
|
272
|
+
return {
|
|
273
|
+
name,
|
|
274
|
+
runtime,
|
|
275
|
+
mode: 'handler',
|
|
276
|
+
handler: overrides.handler,
|
|
277
|
+
entryFile: entryFile ?? `${moduleBase}.*`,
|
|
278
|
+
reasons,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
if (!entryFile) {
|
|
282
|
+
throw new DetectionError(`Could not find an entry file in ${dir} (runtime ${runtime})`, [
|
|
283
|
+
runtime === 'nodejs22'
|
|
284
|
+
? 'Expected index/main/app/server.(js|mjs|ts) at the root or in src/, or package.json "main".'
|
|
285
|
+
: runtime === 'python312'
|
|
286
|
+
? 'Expected main.py/app.py/index.py at the root or in src/.'
|
|
287
|
+
: 'Expected main.go.',
|
|
288
|
+
'Override with --handler <module>.<export> or --start "<command>".',
|
|
289
|
+
]);
|
|
290
|
+
}
|
|
291
|
+
const entryPosix = entryFile.replace(/\\/g, '/');
|
|
292
|
+
reasons.push(`entry: ${entryPosix}`);
|
|
293
|
+
const entrySource = readText(resolved, entryPosix) ?? '';
|
|
294
|
+
const forcedMode = overrides.mode ? assertModeOverride(overrides.mode) : null;
|
|
295
|
+
// Handler sniffing per runtime.
|
|
296
|
+
const hasHandlerExport = runtime === 'nodejs22'
|
|
297
|
+
? NODE_HANDLER_PATTERN.test(entrySource)
|
|
298
|
+
: runtime === 'python312'
|
|
299
|
+
? PYTHON_HANDLER_PATTERN.test(entrySource)
|
|
300
|
+
: GO_HANDLER_PATTERN.test(entrySource);
|
|
301
|
+
// Web mode needs positive server evidence — a lone scripts.start or a plain
|
|
302
|
+
// Python script without one would deploy as a crash-looping "web app".
|
|
303
|
+
const nodeDeps = { ...pkg?.dependencies, ...pkg?.devDependencies };
|
|
304
|
+
const pyDepsText = runtime === 'python312'
|
|
305
|
+
? `${readText(resolved, 'requirements.txt') ?? ''}\n${readText(resolved, 'pyproject.toml') ?? ''}`.toLowerCase()
|
|
306
|
+
: '';
|
|
307
|
+
const serverEvidence = runtime === 'nodejs22'
|
|
308
|
+
? NODE_SERVER_PATTERN.test(entrySource) || NODE_WEB_FRAMEWORK_DEPS.some((d) => d in nodeDeps)
|
|
309
|
+
: runtime === 'python312'
|
|
310
|
+
? PYTHON_WEB_DEPS_PATTERN.test(pyDepsText) || PYTHON_WEB_SOURCE_PATTERN.test(entrySource)
|
|
311
|
+
: false;
|
|
312
|
+
const wantsWeb = forcedMode === 'web' ||
|
|
313
|
+
Boolean(overrides.start) ||
|
|
314
|
+
(forcedMode !== 'handler' && !hasHandlerExport && serverEvidence);
|
|
315
|
+
if (wantsWeb) {
|
|
316
|
+
if (runtime === 'go122') {
|
|
317
|
+
throw new DetectionError('Web mode is not supported for Go yet', [
|
|
318
|
+
'Export a handler instead: func Handler(event map[string]any, ctx obs.Context) (any, error).',
|
|
319
|
+
]);
|
|
320
|
+
}
|
|
321
|
+
let startCommand;
|
|
322
|
+
if (overrides.start) {
|
|
323
|
+
startCommand = overrides.start;
|
|
324
|
+
reasons.push(`start: "${startCommand}" (--start)`);
|
|
325
|
+
}
|
|
326
|
+
else if (runtime === 'nodejs22') {
|
|
327
|
+
startCommand = nodeStartCommand(entryPosix, pkg, reasons);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
startCommand = pythonStartCommand(resolved, entryPosix, reasons);
|
|
331
|
+
}
|
|
332
|
+
reasons.push('mode: web (server app — the platform will run it with PORT and proxy requests)');
|
|
333
|
+
return { name, runtime, mode: 'web', entryFile: entryPosix, startCommand, reasons };
|
|
334
|
+
}
|
|
335
|
+
if (!hasHandlerExport) {
|
|
336
|
+
if (runtime === 'go122') {
|
|
337
|
+
throw new DetectionError(`No exported Handler found in ${entryPosix}`, [
|
|
338
|
+
'Go apps must export: func Handler(event map[string]any, ctx obs.Context) (any, error).',
|
|
339
|
+
]);
|
|
340
|
+
}
|
|
341
|
+
// Handler mode was forced (or nothing server-like found): default export name,
|
|
342
|
+
// let it fail loudly at invoke time if truly absent — but say so.
|
|
343
|
+
reasons.push(`handler: ${stripExtension(entryPosix)}.handler (default — no handler export detected, verify)`);
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
reasons.push(`handler: ${stripExtension(entryPosix)}.handler (handler export found)`);
|
|
347
|
+
}
|
|
348
|
+
reasons.push('mode: handler');
|
|
349
|
+
return {
|
|
350
|
+
name,
|
|
351
|
+
runtime,
|
|
352
|
+
mode: 'handler',
|
|
353
|
+
handler: `${stripExtension(entryPosix)}.handler`,
|
|
354
|
+
entryFile: entryPosix,
|
|
355
|
+
reasons,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/utils/detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensure-auth.d.ts","sourceRoot":"","sources":["../../src/utils/ensure-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAK/D;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,UAAU,GAAE,iBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"ensure-auth.d.ts","sourceRoot":"","sources":["../../src/utils/ensure-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAK/D;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,UAAU,GAAE,iBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBlF"}
|
|
@@ -16,7 +16,13 @@ export async function ensureAuth(apiOptions = {}) {
|
|
|
16
16
|
if (canPrompt() && (await confirm('You are not logged in. Log in now?', true))) {
|
|
17
17
|
printLine('');
|
|
18
18
|
const { loginCommand } = await import('../commands/login.js');
|
|
19
|
-
|
|
19
|
+
// Forward the original command's API URL / named environment — logging in
|
|
20
|
+
// with bare defaults would pair the device against the wrong server and
|
|
21
|
+
// store the token under the wrong environment slice
|
|
22
|
+
await loginCommand([
|
|
23
|
+
...(apiOptions.apiUrl ? ['--api-url', apiOptions.apiUrl] : []),
|
|
24
|
+
...(apiOptions.environment ? ['--env', apiOptions.environment] : []),
|
|
25
|
+
]);
|
|
20
26
|
printLine('');
|
|
21
27
|
await requireAuth(apiOptions); // still throws (mapped) if it didn't take
|
|
22
28
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensure-auth.js","sourceRoot":"","sources":["../../src/utils/ensure-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0B,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,aAAgC,EAAE;IACjE,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,SAAS,EAAE,IAAI,CAAC,MAAM,OAAO,CAAC,oCAAoC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YAC/E,SAAS,CAAC,EAAE,CAAC,CAAC;YACd,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;YAC9D,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ensure-auth.js","sourceRoot":"","sources":["../../src/utils/ensure-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0B,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,aAAgC,EAAE;IACjE,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,SAAS,EAAE,IAAI,CAAC,MAAM,OAAO,CAAC,oCAAoC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YAC/E,SAAS,CAAC,EAAE,CAAC,CAAC;YACd,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;YAC9D,0EAA0E;YAC1E,wEAAwE;YACxE,oDAAoD;YACpD,MAAM,YAAY,CAAC;gBACjB,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9D,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aACrE,CAAC,CAAC;YACH,SAAS,CAAC,EAAE,CAAC,CAAC;YACd,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,0CAA0C;YACzE,OAAO;QACT,CAAC;QACD,MAAM,iBAAiB,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inquir/compute-cli",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Workspace-first CLI for Inquir Compute.",
|
|
6
6
|
"bin": {
|
|
7
7
|
"inquir": "./dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"skill"
|
|
11
12
|
],
|
|
12
13
|
"scripts": {
|
|
13
14
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
@@ -20,11 +21,11 @@
|
|
|
20
21
|
"access": "public"
|
|
21
22
|
},
|
|
22
23
|
"dependencies": {
|
|
23
|
-
"@inquir/compute": "^0.
|
|
24
|
+
"@inquir/compute": "^0.2.0",
|
|
24
25
|
"tsx": "^4.19.2"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@types/node": "^22.9.0",
|
|
28
29
|
"typescript": "^5.6.3"
|
|
29
30
|
}
|
|
30
|
-
}
|
|
31
|
+
}
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: inquir-compute
|
|
3
|
+
description: Deploy and run functions, background jobs, and web apps on Inquir Compute — use when code needs to run remotely, on a schedule, longer than a request cycle, or behind a stable URL. Zero-config deploys via `inquir deploy` or the inquir MCP tools.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Inquir Compute — deploy & run workloads
|
|
7
|
+
|
|
8
|
+
Inquir Compute runs three kinds of workloads in isolated containers:
|
|
9
|
+
|
|
10
|
+
1. **Functions** — Lambda-compatible handlers (`exports.handler`, `def handler`, Go `Handler`). Best for event processing, API routes, webhooks, cron.
|
|
11
|
+
2. **Web apps** — any HTTP server (Express, Fastify, FastAPI, Flask, raw `http`). Deployed as-is; the platform runs it with `PORT` set and proxies requests. No code changes needed.
|
|
12
|
+
3. **Jobs / durable orchestrations** — async invocations with retries, queues, timers, `waitForEvent`, and human-approval waits that survive process restarts.
|
|
13
|
+
|
|
14
|
+
## When to reach for Inquir instead of local code
|
|
15
|
+
|
|
16
|
+
- The user's code must run **after this session ends** (schedules, webhooks, background processing).
|
|
17
|
+
- A task will outlive an HTTP request → use `invoke-async` (jobs) or a durable orchestration, not a long request.
|
|
18
|
+
- The user asks to "deploy", "host", or "get a URL for" something.
|
|
19
|
+
|
|
20
|
+
## Deploying (zero config)
|
|
21
|
+
|
|
22
|
+
From a directory — no config file, no SDK, any of Node / Python / Go:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
inquir deploy # deploy current directory, auto-detect everything
|
|
26
|
+
inquir deploy ./api --name billing --set LOG_LEVEL=debug
|
|
27
|
+
inquir deploy --dry-run # show the detection plan without deploying
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Detection rules:
|
|
31
|
+
- `exports.handler` / `def handler` / `func Handler` in the entry file → **function**.
|
|
32
|
+
- A server app (`.listen(`, Express/FastAPI/Flask imports, or a `start` script) → **web app**; start command is auto-derived (`node server.js`, `python -m uvicorn main:app …`). Override with `--start "<cmd>"`.
|
|
33
|
+
- Entry file: package.json `main`, then `index/main/app/server.*` at root or `src/`.
|
|
34
|
+
- Dependencies are installed **server-side at deploy** (npm/pip) — never commit `node_modules`.
|
|
35
|
+
|
|
36
|
+
Overrides when detection guesses wrong: `--runtime`, `--handler <module.export>`, `--mode handler|web`, `--start "<cmd>"`.
|
|
37
|
+
|
|
38
|
+
## MCP tools (preferred for agents)
|
|
39
|
+
|
|
40
|
+
Register once: `claude mcp add inquir -- inquir mcp`
|
|
41
|
+
|
|
42
|
+
- `deploy {path, name?, start?, env?}` — detect + deploy a directory; returns detection reasons, deploy status, and error logs on failure.
|
|
43
|
+
- `invoke {function, payload}` — run a function and get result + logs.
|
|
44
|
+
- `exec {function, command, target?}` — run a shell command inside the function's container (its runtime image + code). `target: "source"` (default) is read-write: use it for installing deps, running tests, debugging.
|
|
45
|
+
- `list_invocations {function}` — recent runs with errors and logs: the debugging entry point.
|
|
46
|
+
- `deploy_status {deployId}`, `rollback {function, deployId}`, `list_functions`.
|
|
47
|
+
|
|
48
|
+
## Debug loop that works
|
|
49
|
+
|
|
50
|
+
1. `deploy` → read `deploy.error` and status.
|
|
51
|
+
2. If failing at runtime: `list_invocations` → read logs.
|
|
52
|
+
3. Reproduce inside the container: `exec {command: "npm test"}` or `exec {command: "python -c '...'"}`.
|
|
53
|
+
4. Fix code locally, `deploy` again. Deploys are versioned; `rollback` restores any previous success.
|
|
54
|
+
|
|
55
|
+
## Contracts that matter
|
|
56
|
+
|
|
57
|
+
- Handlers: return JSON-serializable values; HTTP-fronted functions return `{statusCode, headers, body}`.
|
|
58
|
+
- Web apps MUST listen on `process.env.PORT` / `$PORT` (any host binding on `0.0.0.0`).
|
|
59
|
+
- Web apps get no streaming invocations (SSE) yet; use a function for streaming responses.
|
|
60
|
+
- Secrets: pass with `--set KEY=VALUE` or `--env-file`; never hardcode.
|