@astrale-os/cli 1.0.0-beta.0 → 1.0.0-beta.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/dist/astrale.js
CHANGED
|
@@ -9738,7 +9738,7 @@ var package_default;
|
|
|
9738
9738
|
var init_package = __esm(() => {
|
|
9739
9739
|
package_default = {
|
|
9740
9740
|
name: "@astrale-os/cli",
|
|
9741
|
-
version: "1.0.0-beta.
|
|
9741
|
+
version: "1.0.0-beta.1",
|
|
9742
9742
|
description: "Astrale CLI — connect to existing Astrale kernels",
|
|
9743
9743
|
keywords: [
|
|
9744
9744
|
"astrale",
|
|
@@ -86817,10 +86817,6 @@ async function connectAdminInstances(context, dependencies = {}) {
|
|
|
86817
86817
|
throw new AdminHostNotFoundError(hostId);
|
|
86818
86818
|
return instanceFromSummary(await binding6.$.invoke(Host.$.method("createInstance"), Path.parse(host.path), input));
|
|
86819
86819
|
}
|
|
86820
|
-
const inventory = await hostInventory(context.graph, binding6, Host, fleet);
|
|
86821
|
-
const eligible = inventory.hosts.filter((host) => host.state === "ready" && host.path !== inventory.reserved);
|
|
86822
|
-
if (eligible.length > 1)
|
|
86823
|
-
throw hostSelectionRequired(eligible.map((host) => host.id));
|
|
86824
86820
|
return instanceFromSummary(await binding6.$.invoke(Fleet.$.method("createInstance"), fleet, input));
|
|
86825
86821
|
},
|
|
86826
86822
|
status: (identifier) => invokeInstance("status", identifier),
|
|
@@ -86864,9 +86860,6 @@ async function hostInventory(graph, binding6, Host, fleet) {
|
|
|
86864
86860
|
...reserved === undefined ? {} : { reserved }
|
|
86865
86861
|
});
|
|
86866
86862
|
}
|
|
86867
|
-
function hostSelectionRequired(ids2) {
|
|
86868
|
-
return new Error(`alphaCreate could not choose a host: ${ids2.length} ready hosts are assigned (${[...ids2].sort().join(", ")}). ` + "Specify host_id once multi-host placement is enabled.");
|
|
86869
|
-
}
|
|
86870
86863
|
function instanceFromSummary(input) {
|
|
86871
86864
|
const value2 = record9(input, "Admin Instance summary");
|
|
86872
86865
|
const failure = value2.failure === undefined ? undefined : record9(value2.failure, "Admin failure");
|
|
@@ -89779,7 +89772,9 @@ var init_update = __esm(() => {
|
|
|
89779
89772
|
// src/commands/update.ts
|
|
89780
89773
|
var exports_update = {};
|
|
89781
89774
|
__export(exports_update, {
|
|
89782
|
-
|
|
89775
|
+
cliStale: () => cliStale,
|
|
89776
|
+
default: () => update_default,
|
|
89777
|
+
fetchNpmTargetVersion: () => fetchNpmTargetVersion
|
|
89783
89778
|
});
|
|
89784
89779
|
async function refreshSkills() {
|
|
89785
89780
|
if (!detectSkill(ASTRALE_CLI_SKILL).installed) {
|
|
@@ -89828,29 +89823,35 @@ async function refreshSdkDeps(check3, assumeYes = false) {
|
|
|
89828
89823
|
}
|
|
89829
89824
|
return true;
|
|
89830
89825
|
}
|
|
89831
|
-
async function cliStale(opts) {
|
|
89826
|
+
async function cliStale(opts, dependencies = CLI_STALE_DEPENDENCIES) {
|
|
89832
89827
|
const running = package_default.version;
|
|
89833
|
-
const latest = await fetchNpmLatestVersion().catch(() => {
|
|
89834
|
-
return;
|
|
89835
|
-
});
|
|
89836
89828
|
try {
|
|
89837
|
-
const r = await
|
|
89829
|
+
const r = await dependencies.update({
|
|
89838
89830
|
check: true,
|
|
89839
89831
|
channel: opts.channel,
|
|
89840
89832
|
version: opts.version,
|
|
89841
89833
|
currentVersion: running
|
|
89842
89834
|
});
|
|
89843
89835
|
if (r.status === "updated") {
|
|
89844
|
-
return {
|
|
89836
|
+
return {
|
|
89837
|
+
stale: false,
|
|
89838
|
+
managed: false,
|
|
89839
|
+
current: r.currentVersion,
|
|
89840
|
+
latest: r.currentVersion,
|
|
89841
|
+
channel: r.channel
|
|
89842
|
+
};
|
|
89845
89843
|
}
|
|
89846
89844
|
return {
|
|
89847
|
-
stale:
|
|
89845
|
+
stale: r.status === "available",
|
|
89848
89846
|
managed: false,
|
|
89849
|
-
current:
|
|
89850
|
-
latest:
|
|
89851
|
-
channel:
|
|
89847
|
+
current: r.currentVersion,
|
|
89848
|
+
latest: r.latestVersion,
|
|
89849
|
+
channel: r.channel
|
|
89852
89850
|
};
|
|
89853
89851
|
} catch {
|
|
89852
|
+
const latest = await dependencies.fetchPackageVersion(opts).catch(() => {
|
|
89853
|
+
return;
|
|
89854
|
+
});
|
|
89854
89855
|
return {
|
|
89855
89856
|
stale: latest !== undefined && latest !== running,
|
|
89856
89857
|
managed: true,
|
|
@@ -89859,8 +89860,9 @@ async function cliStale(opts) {
|
|
|
89859
89860
|
};
|
|
89860
89861
|
}
|
|
89861
89862
|
}
|
|
89862
|
-
async function
|
|
89863
|
-
const
|
|
89863
|
+
async function fetchNpmTargetVersion(opts) {
|
|
89864
|
+
const target2 = opts.version ?? (opts.channel === "stable" ? "latest" : opts.channel) ?? "latest";
|
|
89865
|
+
const response2 = await fetch(`https://registry.npmjs.org/@astrale-os/cli/${target2}`);
|
|
89864
89866
|
if (!response2.ok)
|
|
89865
89867
|
throw new Error(`npm registry HTTP ${response2.status}`);
|
|
89866
89868
|
const body = await response2.json();
|
|
@@ -89876,7 +89878,7 @@ async function sdkStale() {
|
|
|
89876
89878
|
const outdated = await findSdkOutdated();
|
|
89877
89879
|
return { stale: outdated.length > 0, inProject: true, outdated };
|
|
89878
89880
|
}
|
|
89879
|
-
var update_default;
|
|
89881
|
+
var CLI_STALE_DEPENDENCIES, update_default;
|
|
89880
89882
|
var init_update2 = __esm(() => {
|
|
89881
89883
|
init_package();
|
|
89882
89884
|
init_log();
|
|
@@ -89885,6 +89887,10 @@ var init_update2 = __esm(() => {
|
|
|
89885
89887
|
init_sdk_deps();
|
|
89886
89888
|
init_skills();
|
|
89887
89889
|
init_update();
|
|
89890
|
+
CLI_STALE_DEPENDENCIES = {
|
|
89891
|
+
update: updateAstrale,
|
|
89892
|
+
fetchPackageVersion: fetchNpmTargetVersion
|
|
89893
|
+
};
|
|
89888
89894
|
update_default = {
|
|
89889
89895
|
name: "update",
|
|
89890
89896
|
description: "Check for and install Astrale CLI updates",
|
package/package.json
CHANGED
|
@@ -153,7 +153,7 @@ describe('V2 Admin Instance adapter', () => {
|
|
|
153
153
|
)
|
|
154
154
|
})
|
|
155
155
|
|
|
156
|
-
test('
|
|
156
|
+
test('delegates default placement to Fleet without reading Host inventory', async () => {
|
|
157
157
|
const created = {
|
|
158
158
|
id: '@instance-node',
|
|
159
159
|
slug: 'demo',
|
|
@@ -179,6 +179,8 @@ describe('V2 Admin Instance adapter', () => {
|
|
|
179
179
|
Path.id(NodeId('fleet')),
|
|
180
180
|
{ operationId: 'cli.instance.create:test', slug: 'demo' },
|
|
181
181
|
)
|
|
182
|
+
expect(contract.graph.query).not.toHaveBeenCalled()
|
|
183
|
+
expect(contract.graph.neighbors).not.toHaveBeenCalled()
|
|
182
184
|
})
|
|
183
185
|
|
|
184
186
|
test('resolves --host-id to an exact Host receiver and rejects the reserved Admin Host', async () => {
|
|
@@ -119,15 +119,9 @@ export async function connectAdminInstances(
|
|
|
119
119
|
)
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
const inventory = await hostInventory(context.graph, binding, Host, fleet)
|
|
126
|
-
const eligible = inventory.hosts.filter(
|
|
127
|
-
(host) => host.state === 'ready' && host.path !== inventory.reserved,
|
|
128
|
-
)
|
|
129
|
-
if (eligible.length > 1) throw hostSelectionRequired(eligible.map((host) => host.id))
|
|
130
|
-
|
|
122
|
+
// Default placement belongs to Admin. Avoid a redundant Host graph read:
|
|
123
|
+
// it requires broader graph authority than this Fleet operation and can
|
|
124
|
+
// deny an otherwise authorized caller before the server selects a Host.
|
|
131
125
|
return instanceFromSummary(
|
|
132
126
|
await binding.$.invoke(Fleet.$.method('createInstance') as never, fleet, input as never),
|
|
133
127
|
)
|
|
@@ -200,13 +194,6 @@ async function hostInventory(
|
|
|
200
194
|
})
|
|
201
195
|
}
|
|
202
196
|
|
|
203
|
-
function hostSelectionRequired(ids: readonly string[]): Error {
|
|
204
|
-
return new Error(
|
|
205
|
-
`alphaCreate could not choose a host: ${ids.length} ready hosts are assigned (${[...ids].sort().join(', ')}). ` +
|
|
206
|
-
'Specify host_id once multi-host placement is enabled.',
|
|
207
|
-
)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
197
|
type DynamicDefinition = ReturnType<DomainBinding['$']['class']>
|
|
211
198
|
|
|
212
199
|
function instanceFromSummary(input: unknown): InstanceInfo {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, expect, mock, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import { cliStale, fetchNpmTargetVersion } from '../update'
|
|
4
|
+
|
|
5
|
+
describe('CLI update staleness', () => {
|
|
6
|
+
test('trusts the release manifest for a script install without consulting npm latest', async () => {
|
|
7
|
+
const fetchPackageVersion = mock(async () => '0.8.1-alpha.7')
|
|
8
|
+
const result = await cliStale(
|
|
9
|
+
{ channel: 'beta' },
|
|
10
|
+
{
|
|
11
|
+
update: async () => ({
|
|
12
|
+
status: 'up-to-date',
|
|
13
|
+
currentVersion: '1.0.0-beta.0',
|
|
14
|
+
latestVersion: '1.0.0-beta.0',
|
|
15
|
+
channel: 'beta',
|
|
16
|
+
}),
|
|
17
|
+
fetchPackageVersion,
|
|
18
|
+
},
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
expect(result).toEqual({
|
|
22
|
+
stale: false,
|
|
23
|
+
managed: false,
|
|
24
|
+
current: '1.0.0-beta.0',
|
|
25
|
+
latest: '1.0.0-beta.0',
|
|
26
|
+
channel: 'beta',
|
|
27
|
+
})
|
|
28
|
+
expect(fetchPackageVersion).not.toHaveBeenCalled()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('uses the selected npm dist-tag only for package-managed installs', async () => {
|
|
32
|
+
const result = await cliStale(
|
|
33
|
+
{ channel: 'beta' },
|
|
34
|
+
{
|
|
35
|
+
update: async () => {
|
|
36
|
+
throw new Error('package managed')
|
|
37
|
+
},
|
|
38
|
+
fetchPackageVersion: async ({ channel }) => {
|
|
39
|
+
expect(channel).toBe('beta')
|
|
40
|
+
return '1.0.0-beta.0'
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
expect(result).toMatchObject({
|
|
46
|
+
managed: true,
|
|
47
|
+
latest: '1.0.0-beta.0',
|
|
48
|
+
channel: 'npm',
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test('maps the stable channel to the npm latest dist-tag', async () => {
|
|
53
|
+
const originalFetch = globalThis.fetch
|
|
54
|
+
const fetchMock = mock(async (input: RequestInfo | URL) => {
|
|
55
|
+
expect(String(input)).toBe('https://registry.npmjs.org/@astrale-os/cli/latest')
|
|
56
|
+
return Response.json({ version: '1.0.0' })
|
|
57
|
+
})
|
|
58
|
+
globalThis.fetch = fetchMock as unknown as typeof fetch
|
|
59
|
+
try {
|
|
60
|
+
expect(await fetchNpmTargetVersion({ channel: 'stable' })).toBe('1.0.0')
|
|
61
|
+
expect(fetchMock).toHaveBeenCalledTimes(1)
|
|
62
|
+
} finally {
|
|
63
|
+
globalThis.fetch = originalFetch
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
})
|
package/src/commands/update.ts
CHANGED
|
@@ -115,27 +115,46 @@ export type StaleReport = {
|
|
|
115
115
|
sdk: { stale: boolean; inProject: boolean; outdated: SdkOutdated[] }
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
type CliStaleDependencies = {
|
|
119
|
+
update: typeof updateAstrale
|
|
120
|
+
fetchPackageVersion: (opts: Pick<UpdateOpts, 'channel' | 'version'>) => Promise<string>
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const CLI_STALE_DEPENDENCIES: CliStaleDependencies = {
|
|
124
|
+
update: updateAstrale,
|
|
125
|
+
fetchPackageVersion: fetchNpmTargetVersion,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export async function cliStale(
|
|
129
|
+
opts: Pick<UpdateOpts, 'channel' | 'version'>,
|
|
130
|
+
dependencies: CliStaleDependencies = CLI_STALE_DEPENDENCIES,
|
|
131
|
+
): Promise<StaleReport['cli']> {
|
|
119
132
|
const running = pkg.version
|
|
120
|
-
const latest = await fetchNpmLatestVersion().catch(() => undefined)
|
|
121
133
|
try {
|
|
122
|
-
const r = await
|
|
134
|
+
const r = await dependencies.update({
|
|
123
135
|
check: true,
|
|
124
136
|
channel: opts.channel,
|
|
125
137
|
version: opts.version,
|
|
126
138
|
currentVersion: running,
|
|
127
139
|
})
|
|
128
140
|
if (r.status === 'updated') {
|
|
129
|
-
return {
|
|
141
|
+
return {
|
|
142
|
+
stale: false,
|
|
143
|
+
managed: false,
|
|
144
|
+
current: r.currentVersion,
|
|
145
|
+
latest: r.currentVersion,
|
|
146
|
+
channel: r.channel,
|
|
147
|
+
}
|
|
130
148
|
}
|
|
131
149
|
return {
|
|
132
|
-
stale:
|
|
150
|
+
stale: r.status === 'available',
|
|
133
151
|
managed: false,
|
|
134
|
-
current:
|
|
135
|
-
latest:
|
|
136
|
-
channel:
|
|
152
|
+
current: r.currentVersion,
|
|
153
|
+
latest: r.latestVersion,
|
|
154
|
+
channel: r.channel,
|
|
137
155
|
}
|
|
138
156
|
} catch {
|
|
157
|
+
const latest = await dependencies.fetchPackageVersion(opts).catch(() => undefined)
|
|
139
158
|
return {
|
|
140
159
|
stale: latest !== undefined && latest !== running,
|
|
141
160
|
managed: true,
|
|
@@ -145,8 +164,11 @@ async function cliStale(opts: UpdateOpts): Promise<StaleReport['cli']> {
|
|
|
145
164
|
}
|
|
146
165
|
}
|
|
147
166
|
|
|
148
|
-
async function
|
|
149
|
-
|
|
167
|
+
export async function fetchNpmTargetVersion(
|
|
168
|
+
opts: Pick<UpdateOpts, 'channel' | 'version'>,
|
|
169
|
+
): Promise<string> {
|
|
170
|
+
const target = opts.version ?? (opts.channel === 'stable' ? 'latest' : opts.channel) ?? 'latest'
|
|
171
|
+
const response = await fetch(`https://registry.npmjs.org/@astrale-os/cli/${target}`)
|
|
150
172
|
if (!response.ok) throw new Error(`npm registry HTTP ${response.status}`)
|
|
151
173
|
const body: unknown = await response.json()
|
|
152
174
|
if (
|