@gaia-ai/gaia 0.15.0 → 0.15.2
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/dist/src/config.js +78 -6
- package/package.json +24 -24
package/dist/src/config.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { hostname } from 'node:os';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { createInterface } from 'node:readline';
|
|
4
4
|
import { pathToFileURL } from 'node:url';
|
|
5
|
-
import { reportLoadedGaiaConfigFields, resolveGaiaConnectionSelection, } from '@gaia-ai/core';
|
|
5
|
+
import { homeGaiaDir, reportLoadedGaiaConfigFields, resolveGaiaConnectionSelection, } from '@gaia-ai/core';
|
|
6
6
|
import { Option } from 'commander';
|
|
7
7
|
/** Terminal-only input. Secret characters are never echoed. */
|
|
8
8
|
async function promptInput(label, secret = false) {
|
|
@@ -42,6 +42,10 @@ export function renderConfigReport(report, dryRun = false) {
|
|
|
42
42
|
];
|
|
43
43
|
for (const file of report.files.filter((file) => file.selected))
|
|
44
44
|
lines.push(`${file.layer}: ${file.path} (${file.state}; schema ${file.version.effective ?? 'unversioned'} → ${file.version.current ?? 'unversioned'}; ${file.fingerprint ?? 'absent'})`);
|
|
45
|
+
if (report.machine_policy) {
|
|
46
|
+
const { tunnel, source } = report.machine_policy;
|
|
47
|
+
lines.push(`Machine tunnel: ${tunnel === null ? 'unresolved' : tunnel} (from ${source})`);
|
|
48
|
+
}
|
|
45
49
|
if (report.connection_resolution) {
|
|
46
50
|
const selected = report.connection_resolution;
|
|
47
51
|
lines.push(`Connection: ${selected.id} (${selected.selected_by}) — ${selected.path}`);
|
|
@@ -102,6 +106,8 @@ function buildConfigCommand(parent, operation, deps, hiddenScope, description) {
|
|
|
102
106
|
.option('--workspace-id <uuid>', 'explicit workspace UUID')
|
|
103
107
|
.option('--workspace <name>', 'committed project workspace name')
|
|
104
108
|
.option('--secret-env <name>', 'environment variable containing the OAuth secret')
|
|
109
|
+
.option('--after-create <command>', "committed conductor config's after_create hook; empty means none, gaia-cli names no provisioning tool")
|
|
110
|
+
.option('--after-done <command>', "committed conductor config's after_done hook; empty means none, gaia-cli names no provisioning tool")
|
|
105
111
|
.addOption(new Option('--auth-type <type>', 'sign in with device code (default, no secret) or a client secret (internal/CI)').choices(['client_credentials', 'device']));
|
|
106
112
|
command.action(async (options) => {
|
|
107
113
|
if (hiddenScope !== undefined && options.scope === undefined)
|
|
@@ -149,10 +155,17 @@ function buildConfigCommand(parent, operation, deps, hiddenScope, description) {
|
|
|
149
155
|
options.authType === 'client_credentials'
|
|
150
156
|
? 'oauth2_client_credentials'
|
|
151
157
|
: 'oauth2_device_code';
|
|
158
|
+
if (options.afterCreate !== undefined || options.afterDone !== undefined)
|
|
159
|
+
inputs.hooks = {
|
|
160
|
+
...(options.afterCreate ? { after_create: options.afterCreate } : {}),
|
|
161
|
+
...(options.afterDone ? { after_done: options.afterDone } : {}),
|
|
162
|
+
};
|
|
152
163
|
const planning = {
|
|
153
164
|
operation,
|
|
154
165
|
cwd,
|
|
155
|
-
|
|
166
|
+
// Only forward an explicitly injected home; absent, core resolves the
|
|
167
|
+
// `.gaia` root itself and honours GAIA_HOME.
|
|
168
|
+
...(deps.home !== undefined ? { home: deps.home } : {}),
|
|
156
169
|
inputs,
|
|
157
170
|
// `gaia init` (hiddenScope !== undefined) never pulls the project
|
|
158
171
|
// layer in, even inside a project checkout (GAIA-496 finding 1).
|
|
@@ -168,7 +181,7 @@ function buildConfigCommand(parent, operation, deps, hiddenScope, description) {
|
|
|
168
181
|
else if (options.connection !== undefined) {
|
|
169
182
|
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(options.connection))
|
|
170
183
|
throw new Error('--connection must be an identifier containing letters, numbers, dot, underscore or hyphen.');
|
|
171
|
-
planning.connectionPath = join(deps.home
|
|
184
|
+
planning.connectionPath = join(homeGaiaDir(deps.home), 'connections', `${options.connection}.js`);
|
|
172
185
|
}
|
|
173
186
|
let selectedConnection;
|
|
174
187
|
const initializesNamedConnection = operation === 'init' &&
|
|
@@ -177,7 +190,12 @@ function buildConfigCommand(parent, operation, deps, hiddenScope, description) {
|
|
|
177
190
|
if (!initializesNamedConnection && options.scope !== 'machine') {
|
|
178
191
|
selectedConnection = await resolveGaiaConnectionSelection({
|
|
179
192
|
cwd,
|
|
180
|
-
|
|
193
|
+
// Only forward an explicitly injected home; absent, core resolves
|
|
194
|
+
// the `.gaia` root itself and honours GAIA_HOME (same rule as the
|
|
195
|
+
// `planning` object above — a stray `?? homedir()` here would
|
|
196
|
+
// resolve this command's connection selection under `~/.gaia` while
|
|
197
|
+
// the rest of it honours the override).
|
|
198
|
+
...(deps.home !== undefined ? { home: deps.home } : {}),
|
|
181
199
|
env,
|
|
182
200
|
...(options.config ? { explicit: options.config } : {}),
|
|
183
201
|
...(options.connection ? { connection: options.connection } : {}),
|
|
@@ -291,8 +309,46 @@ function buildConfigCommand(parent, operation, deps, hiddenScope, description) {
|
|
|
291
309
|
report.verification = current.verification;
|
|
292
310
|
}
|
|
293
311
|
}
|
|
312
|
+
// A device-code connection authenticates from a session that sign-in
|
|
313
|
+
// creates, and nothing has signed in yet when `init` has only just
|
|
314
|
+
// written the file. Verifying here therefore reports
|
|
315
|
+
// `authentication_failure` on a perfectly correct machine — a symptom
|
|
316
|
+
// named in place of its cause, and the reason `gaia init` used to end
|
|
317
|
+
// `failed` on every fresh setup. Writing the connection and signing in
|
|
318
|
+
// are two steps, so `init` reports the second as outstanding instead.
|
|
319
|
+
// An explicit `--online` still verifies, so the deferral is gated on
|
|
320
|
+
// the whole predicate rather than on the file read alone — otherwise
|
|
321
|
+
// `--auth-type device` defers the very check the operator asked for.
|
|
322
|
+
// Read the grant off the connection that is about to be verified, not
|
|
323
|
+
// off `--auth-type`: a repeat `gaia init` supplies no flag and writes
|
|
324
|
+
// nothing, and keying on the input would leave exactly that run — the
|
|
325
|
+
// one an operator uses as a diagnostic — reporting a failure again. A
|
|
326
|
+
// read that fails falls through to verifying, so a broken file is
|
|
327
|
+
// reported rather than quietly skipped.
|
|
328
|
+
let connectionGrant;
|
|
329
|
+
if (operation === 'init' && planning.connectionPath)
|
|
330
|
+
try {
|
|
331
|
+
const fields = await reportLoadedGaiaConfigFields(planning.connectionPath);
|
|
332
|
+
// Locate the OAuth plugin by identity. Its grant is the only one
|
|
333
|
+
// that says anything about signing in, and any plugin may carry a
|
|
334
|
+
// `with.type` of its own, so matching on field shape alone reads
|
|
335
|
+
// whichever happens to come first.
|
|
336
|
+
const prefix = fields
|
|
337
|
+
.find((field) => /^plugins\[\d+\]\.plugin$/.test(field.key) &&
|
|
338
|
+
field.value === '@dropsh/plugin-oauth2')
|
|
339
|
+
?.key.replace(/\.plugin$/, '');
|
|
340
|
+
if (prefix !== undefined)
|
|
341
|
+
connectionGrant = fields.find((field) => field.key === `${prefix}.with.type`)?.value;
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
// Inventory findings already describe an unreadable or malformed file.
|
|
345
|
+
}
|
|
346
|
+
const awaitsSignIn = !options.online &&
|
|
347
|
+
(inputs.authType === 'oauth2_device_code' ||
|
|
348
|
+
connectionGrant === 'oauth2_device_code');
|
|
294
349
|
if (!cancelled &&
|
|
295
350
|
!options.dryRun &&
|
|
351
|
+
!awaitsSignIn &&
|
|
296
352
|
(operation === 'init' || options.online) &&
|
|
297
353
|
!report.findings.some((f) => f.severity === 'error')) {
|
|
298
354
|
const { verifyConfigConnections } = await import('@gaia-ai/core');
|
|
@@ -314,7 +370,23 @@ function buildConfigCommand(parent, operation, deps, hiddenScope, description) {
|
|
|
314
370
|
else if (!options.dryRun &&
|
|
315
371
|
(operation === 'init' || options.online) &&
|
|
316
372
|
report.verification.online.status !== 'not_applicable') {
|
|
317
|
-
|
|
373
|
+
// `gaia init` is also the diagnostic an operator re-runs on a finished
|
|
374
|
+
// setup. Naming sign-in as the next step there is the one instruction
|
|
375
|
+
// that is certainly wrong, so say which of the two situations this is.
|
|
376
|
+
const { hasStoredGaiaSession } = await import('@gaia-ai/core');
|
|
377
|
+
const reason = awaitsSignIn
|
|
378
|
+
? (await hasStoredGaiaSession(deps.host ?? {
|
|
379
|
+
resolveBases: [import.meta.url, pathToFileURL(`${cwd}/`).href],
|
|
380
|
+
}, {
|
|
381
|
+
cwd,
|
|
382
|
+
...(planning.connectionPath
|
|
383
|
+
? { explicit: planning.connectionPath }
|
|
384
|
+
: {}),
|
|
385
|
+
...(deps.stateDir ? { stateDir: deps.stateDir } : {}),
|
|
386
|
+
}))
|
|
387
|
+
? 'A session for this connection already exists; verify it with gaia config check --scope connection --online.'
|
|
388
|
+
: 'Sign-in is the next step: run gaia dropsh auth login, then gaia config check --scope connection --online.'
|
|
389
|
+
: 'Online validation skipped because offline errors require repair or input was cancelled.';
|
|
318
390
|
report.verification.online.reason = reason;
|
|
319
391
|
report.verification.skipped.push({
|
|
320
392
|
path: report.roots.connection,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaia-ai/gaia",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.2",
|
|
4
4
|
"description": "GAIA meta package: the `gaia` plugin-host CLI + all runtime plugins. Global install target.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,29 +38,29 @@
|
|
|
38
38
|
"jsonapi"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@gaia-ai/addon-agents": "^0.15.
|
|
42
|
-
"@gaia-ai/addon-auth-basic": "^0.15.
|
|
43
|
-
"@gaia-ai/addon-claude": "^0.15.
|
|
44
|
-
"@gaia-ai/addon-codex": "^0.15.
|
|
45
|
-
"@gaia-ai/addon-deployment": "^0.15.
|
|
46
|
-
"@gaia-ai/addon-dropsh": "^0.15.
|
|
47
|
-
"@gaia-ai/addon-essentials": "^0.15.
|
|
48
|
-
"@gaia-ai/addon-gaia-ui": "^0.15.
|
|
49
|
-
"@gaia-ai/addon-gaia-ui-artifacts": "^0.15.
|
|
50
|
-
"@gaia-ai/addon-grok": "^0.15.
|
|
51
|
-
"@gaia-ai/addon-herdr": "^0.15.
|
|
52
|
-
"@gaia-ai/addon-info": "^0.15.
|
|
53
|
-
"@gaia-ai/addon-kimi": "^0.15.
|
|
54
|
-
"@gaia-ai/addon-opencode": "^0.15.
|
|
55
|
-
"@gaia-ai/addon-pi": "^0.15.
|
|
56
|
-
"@gaia-ai/addon-ports": "^0.15.
|
|
57
|
-
"@gaia-ai/addon-ports-ui": "^0.15.
|
|
58
|
-
"@gaia-ai/addon-remote-drupal": "^0.15.
|
|
59
|
-
"@gaia-ai/addon-workspace": "^0.15.
|
|
60
|
-
"@gaia-ai/addon-workspace-git": "^0.15.
|
|
61
|
-
"@gaia-ai/conductor": "^0.15.
|
|
62
|
-
"@gaia-ai/core": "^0.15.
|
|
63
|
-
"@gaia-ai/ui": "^0.15.
|
|
41
|
+
"@gaia-ai/addon-agents": "^0.15.2",
|
|
42
|
+
"@gaia-ai/addon-auth-basic": "^0.15.2",
|
|
43
|
+
"@gaia-ai/addon-claude": "^0.15.2",
|
|
44
|
+
"@gaia-ai/addon-codex": "^0.15.2",
|
|
45
|
+
"@gaia-ai/addon-deployment": "^0.15.2",
|
|
46
|
+
"@gaia-ai/addon-dropsh": "^0.15.2",
|
|
47
|
+
"@gaia-ai/addon-essentials": "^0.15.2",
|
|
48
|
+
"@gaia-ai/addon-gaia-ui": "^0.15.2",
|
|
49
|
+
"@gaia-ai/addon-gaia-ui-artifacts": "^0.15.2",
|
|
50
|
+
"@gaia-ai/addon-grok": "^0.15.2",
|
|
51
|
+
"@gaia-ai/addon-herdr": "^0.15.2",
|
|
52
|
+
"@gaia-ai/addon-info": "^0.15.2",
|
|
53
|
+
"@gaia-ai/addon-kimi": "^0.15.2",
|
|
54
|
+
"@gaia-ai/addon-opencode": "^0.15.2",
|
|
55
|
+
"@gaia-ai/addon-pi": "^0.15.2",
|
|
56
|
+
"@gaia-ai/addon-ports": "^0.15.2",
|
|
57
|
+
"@gaia-ai/addon-ports-ui": "^0.15.2",
|
|
58
|
+
"@gaia-ai/addon-remote-drupal": "^0.15.2",
|
|
59
|
+
"@gaia-ai/addon-workspace": "^0.15.2",
|
|
60
|
+
"@gaia-ai/addon-workspace-git": "^0.15.2",
|
|
61
|
+
"@gaia-ai/conductor": "^0.15.2",
|
|
62
|
+
"@gaia-ai/core": "^0.15.2",
|
|
63
|
+
"@gaia-ai/ui": "^0.15.2",
|
|
64
64
|
"commander": "^12.1.0"
|
|
65
65
|
}
|
|
66
66
|
}
|