@drawcall/market 0.1.98 → 0.2.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/README.md +7 -4
- package/dist/asset-implementation.d.ts +3 -3
- package/dist/asset-implementation.d.ts.map +1 -1
- package/dist/cli.js +15 -3
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +14 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +18 -0
- package/dist/client.js.map +1 -1
- package/dist/commands/install.js +10 -7
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/list.d.ts +5 -5
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +22 -9
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/pack.d.ts.map +1 -1
- package/dist/commands/pack.js +2 -2
- package/dist/commands/pack.js.map +1 -1
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +14 -2
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/sync.d.ts +6 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +22 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +20 -10
- package/dist/commands/upload.js.map +1 -1
- package/dist/contract.d.ts +4 -6
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +1 -2
- package/dist/contract.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +69 -27
- package/dist/install.js.map +1 -1
- package/dist/output.d.ts +3 -4
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +40 -7
- package/dist/output.js.map +1 -1
- package/dist/pack.d.ts +36 -6
- package/dist/pack.d.ts.map +1 -1
- package/dist/pack.js +230 -57
- package/dist/pack.js.map +1 -1
- package/dist/package-json.d.ts +4 -3
- package/dist/package-json.d.ts.map +1 -1
- package/dist/package-json.js +3 -1
- package/dist/package-json.js.map +1 -1
- package/dist/resolve.d.ts +8 -1
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +35 -3
- package/dist/resolve.js.map +1 -1
- package/dist/schemas.d.ts +19 -7
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +22 -7
- package/dist/schemas.js.map +1 -1
- package/dist/skill.d.ts +1 -1
- package/dist/skill.d.ts.map +1 -1
- package/dist/skill.js +4 -2
- package/dist/skill.js.map +1 -1
- package/dist/v1/client.d.ts +15 -0
- package/dist/v1/client.d.ts.map +1 -0
- package/dist/v1/client.js +18 -0
- package/dist/v1/client.js.map +1 -0
- package/dist/v1/contract.d.ts +206 -0
- package/dist/v1/contract.d.ts.map +1 -0
- package/dist/v1/contract.js +77 -0
- package/dist/v1/contract.js.map +1 -0
- package/dist/v1/index.d.ts +3 -0
- package/dist/v1/index.d.ts.map +1 -0
- package/dist/v1/index.js +3 -0
- package/dist/v1/index.js.map +1 -0
- package/package.json +2 -1
- package/skills/market/SKILL.md +4 -2
- package/src/asset-implementation.ts +3 -3
- package/src/cli.ts +20 -4
- package/src/client.ts +26 -0
- package/src/commands/install.ts +11 -8
- package/src/commands/list.ts +28 -14
- package/src/commands/pack.ts +7 -2
- package/src/commands/search.ts +21 -2
- package/src/commands/sync.ts +30 -0
- package/src/commands/upload.ts +26 -11
- package/src/contract.ts +0 -3
- package/src/index.ts +13 -3
- package/src/install.ts +89 -35
- package/src/output.ts +52 -11
- package/src/pack.ts +317 -70
- package/src/package-json.ts +7 -4
- package/src/resolve.ts +47 -4
- package/src/schemas.ts +32 -8
- package/src/skill.ts +4 -2
- package/src/v1/client.ts +28 -0
- package/src/v1/contract.ts +140 -0
- package/src/v1/index.ts +2 -0
- package/dist/market-lock.d.ts +0 -16
- package/dist/market-lock.d.ts.map +0 -1
- package/dist/market-lock.js +0 -48
- package/dist/market-lock.js.map +0 -1
- package/src/market-lock.ts +0 -68
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { oc } from '@orpc/contract';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { MAX_UPLOAD_ZIP_SIZE_BYTES, agentRunStatusSchema, agentStartSchema, agentStatusSchema, assetFilesSchema, exactAssetSchema, fileManifestSchema, generateAssetSchema, generateJobStatusSchema, generateResponseSchema, generateStatusInputSchema, listAssetsSchema, updateProfileSchema, uploadZipSchema, } from '../schemas.js';
|
|
4
|
+
/**
|
|
5
|
+
* The v1 contract: the same procedure tree as the legacy RPC surface (so call sites migrate by
|
|
6
|
+
* swapping only the client), with HTTP routes attached — served as plain REST under `/api/v1`.
|
|
7
|
+
* The route annotations here ARE the control-plane URL contract.
|
|
8
|
+
*/
|
|
9
|
+
export const contract = {
|
|
10
|
+
asset: {
|
|
11
|
+
search: oc
|
|
12
|
+
.route({ method: 'GET', path: '/assets' })
|
|
13
|
+
.input(listAssetsSchema)
|
|
14
|
+
.output(z.custom()),
|
|
15
|
+
exact: oc
|
|
16
|
+
.route({ method: 'GET', path: '/assets/{name}' })
|
|
17
|
+
.input(exactAssetSchema)
|
|
18
|
+
.output(z.custom()),
|
|
19
|
+
// The manifest is new in v1 — it merges the legacy `files` + metadata into one GET.
|
|
20
|
+
manifest: oc
|
|
21
|
+
.route({ method: 'GET', path: '/assets/{name}/{version}' })
|
|
22
|
+
.input(assetFilesSchema)
|
|
23
|
+
.output(z.custom()),
|
|
24
|
+
files: oc
|
|
25
|
+
.route({ method: 'GET', path: '/assets/{name}/{version}/files' })
|
|
26
|
+
.input(assetFilesSchema)
|
|
27
|
+
.output(z.custom()),
|
|
28
|
+
fileManifest: oc
|
|
29
|
+
.route({ method: 'GET', path: '/assets/{name}/{version}/file-manifest' })
|
|
30
|
+
.input(fileManifestSchema)
|
|
31
|
+
.output(z.custom()),
|
|
32
|
+
uploadZip: oc
|
|
33
|
+
.route({ method: 'PUT', path: '/assets/{name}/{version}' })
|
|
34
|
+
.input(uploadZipSchema
|
|
35
|
+
.extend({ zip: z.instanceof(File) })
|
|
36
|
+
.refine((input) => input.zip.size < MAX_UPLOAD_ZIP_SIZE_BYTES, {
|
|
37
|
+
message: 'Upload zip must be smaller than 1 GB',
|
|
38
|
+
path: ['zip'],
|
|
39
|
+
}))
|
|
40
|
+
.output(z.custom()),
|
|
41
|
+
installMetadata: oc
|
|
42
|
+
.route({ method: 'GET', path: '/types' })
|
|
43
|
+
.output(z.custom()),
|
|
44
|
+
generate: oc
|
|
45
|
+
.route({ method: 'POST', path: '/generations' })
|
|
46
|
+
.input(generateAssetSchema)
|
|
47
|
+
.output(generateResponseSchema),
|
|
48
|
+
generateStatus: oc
|
|
49
|
+
.route({ method: 'GET', path: '/generations/{jobId}' })
|
|
50
|
+
.input(generateStatusInputSchema)
|
|
51
|
+
.output(generateJobStatusSchema),
|
|
52
|
+
agent: {
|
|
53
|
+
start: oc
|
|
54
|
+
.route({ method: 'POST', path: '/agent-runs' })
|
|
55
|
+
.input(agentStartSchema)
|
|
56
|
+
.output(z.object({ runId: z.string() })),
|
|
57
|
+
status: oc
|
|
58
|
+
.route({ method: 'GET', path: '/agent-runs/{runId}' })
|
|
59
|
+
.input(agentStatusSchema)
|
|
60
|
+
.output(agentRunStatusSchema),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
user: {
|
|
64
|
+
getProfile: oc.route({ method: 'GET', path: '/me' }).output(z.custom()),
|
|
65
|
+
updateProfile: oc
|
|
66
|
+
.route({ method: 'PATCH', path: '/me' })
|
|
67
|
+
.input(updateProfileSchema)
|
|
68
|
+
.output(z.custom()),
|
|
69
|
+
getAuthToken: oc
|
|
70
|
+
.route({ method: 'GET', path: '/me/auth-token' })
|
|
71
|
+
.output(z.custom()),
|
|
72
|
+
createAuthToken: oc
|
|
73
|
+
.route({ method: 'POST', path: '/me/auth-token' })
|
|
74
|
+
.output(z.object({ token: z.string(), prefix: z.string() })),
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/v1/contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/v1/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,UAAU,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpF,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/v1/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/v1/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAA8C,MAAM,eAAe,CAAA;AACpF,OAAO,EAAE,YAAY,EAAmD,MAAM,aAAa,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drawcall/market",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/drawcall-ai/market",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@orpc/client": "^1.0.0",
|
|
39
39
|
"@orpc/contract": "^1.0.0",
|
|
40
|
+
"@orpc/openapi-client": "1.13.14",
|
|
40
41
|
"chalk": "^5.6.2",
|
|
41
42
|
"commander": "^14.0.3",
|
|
42
43
|
"fflate": "^0.8.2",
|
package/skills/market/SKILL.md
CHANGED
|
@@ -31,7 +31,9 @@ Install exact refs together in one call; names need no `--type`:
|
|
|
31
31
|
|
|
32
32
|
Install prints the exact files it wrote and records the dependency so packing and later rebuilds can restore it. It never searches or generates. With no refs it installs `assetDependencies` from the nearest `package.json`. Assets may install declared skill dependencies with `npx skills add`. Use `--force` only with permission to overwrite changed local files.
|
|
33
33
|
|
|
34
|
-
`list --cwd "$PWD"` is an offline, compact inventory
|
|
34
|
+
`list --cwd "$PWD"` is an offline, compact inventory of the `assetDependencies` in the nearest `package.json`, including file aliases. When selected refs are already installed, read this inventory instead of reinstalling them.
|
|
35
|
+
|
|
36
|
+
An `assetDependencies` entry is either a range string or `{ "version": "<range>", "alias": { "<canonical path>": "<current path>" } }`. An alias records where the project keeps a renamed installed file: install writes the file at the aliased path, and packing omits exactly that one copy (extra duplicates ship as project content). Run `sync --cwd "$PWD"` after renaming installed files to record aliases in `package.json`; template packing runs the same update automatically.
|
|
35
37
|
|
|
36
38
|
## Generate
|
|
37
39
|
|
|
@@ -47,6 +49,6 @@ Add `--access public` or `--access private` when visibility matters. Omitted acc
|
|
|
47
49
|
|
|
48
50
|
## Publish only when asked
|
|
49
51
|
|
|
50
|
-
Use `pack <source> --out <zip>` to create a Market zip and `upload <name> <source> "<description>" --type <type>` to publish it. Both accept repeatable `--npm name@range`, `--asset name@range`, and `--skill label=source` dependencies. Template packing reads root `assetDependencies` and may use the API to omit
|
|
52
|
+
Use `pack <source> --out <zip>` to create a Market zip and `upload <name> <source> "<description>" --type <type>` to publish it. Both accept repeatable `--npm name@range`, `--asset name@range`, and `--skill label=source` dependencies. Template packing reads root `assetDependencies` and may use the API to omit installed dependency files matched by content hash — even when renamed — recording renames as aliases. A skill source is `owner/repo`, a git URL, a full GitHub `tree/<branch>/<subpath>` URL, or a local skill directory inside the zip. Use the command's `--help` for syntax.
|
|
51
53
|
|
|
52
54
|
Use `--unapproved` only when explicitly requested. Do not install an unapproved asset without acceptance. If login is required, ask before running `npx @drawcall/market login`.
|
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
GenerateAssetResult,
|
|
7
7
|
PaginatedList,
|
|
8
8
|
} from './contract.js'
|
|
9
|
-
import type { AssetAccess, AssetType, GenerateJobStatus } from './schemas.js'
|
|
9
|
+
import type { AssetAccess, AssetDependencies, AssetType, GenerateJobStatus } from './schemas.js'
|
|
10
10
|
|
|
11
11
|
export const ASSET_RELEVANCE_SCORE: unique symbol = Symbol('assetRelevanceScore')
|
|
12
12
|
|
|
@@ -38,7 +38,7 @@ export interface AssetUploadZipInput {
|
|
|
38
38
|
version: string
|
|
39
39
|
description?: string
|
|
40
40
|
npmDependencies: Record<string, string>
|
|
41
|
-
assetDependencies:
|
|
41
|
+
assetDependencies: AssetDependencies
|
|
42
42
|
skillDependencies: Record<string, string>
|
|
43
43
|
tags: string[]
|
|
44
44
|
zip: File
|
|
@@ -46,7 +46,7 @@ export interface AssetUploadZipInput {
|
|
|
46
46
|
access?: AssetAccess
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export interface
|
|
49
|
+
export interface AssetVersionRef {
|
|
50
50
|
name: string
|
|
51
51
|
version: string
|
|
52
52
|
/** The asset's capability key, an alternative credential to identity for private/unapproved assets. */
|
package/src/cli.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { generateCommand } from './commands/generate.js'
|
|
|
13
13
|
import { generateInstallCommand } from './commands/generate-install.js'
|
|
14
14
|
import { listCommand } from './commands/list.js'
|
|
15
15
|
import { packCommand } from './commands/pack.js'
|
|
16
|
+
import { syncCommand } from './commands/sync.js'
|
|
16
17
|
import { previewCommand } from './commands/preview.js'
|
|
17
18
|
import { uploadCommand } from './commands/upload.js'
|
|
18
19
|
import { typesCommand } from './commands/types.js'
|
|
@@ -125,13 +126,25 @@ program
|
|
|
125
126
|
|
|
126
127
|
program
|
|
127
128
|
.command('list')
|
|
128
|
-
.description('List
|
|
129
|
-
.option('--files', 'Include installed file paths', false)
|
|
129
|
+
.description('List asset dependencies declared in package.json, including file aliases')
|
|
130
130
|
.option('--cwd <dir>', 'Project directory')
|
|
131
|
-
.action(async (opts: { cwd?: string
|
|
131
|
+
.action(async (opts: { cwd?: string }) => {
|
|
132
132
|
await listCommand({
|
|
133
133
|
cwd: opts.cwd,
|
|
134
|
-
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
program
|
|
138
|
+
.command('sync')
|
|
139
|
+
.description(
|
|
140
|
+
'Update package.json assetDependencies aliases to match where installed files live now',
|
|
141
|
+
)
|
|
142
|
+
.addOption(apiOption)
|
|
143
|
+
.option('--cwd <dir>', 'Project directory')
|
|
144
|
+
.action(async (opts: { api?: string; cwd?: string }) => {
|
|
145
|
+
await syncCommand({
|
|
146
|
+
baseUrl: opts.api,
|
|
147
|
+
cwd: opts.cwd,
|
|
135
148
|
})
|
|
136
149
|
})
|
|
137
150
|
|
|
@@ -176,6 +189,7 @@ program
|
|
|
176
189
|
.addOption(apiOption)
|
|
177
190
|
.option('--unapproved', 'Include unapproved versions', false)
|
|
178
191
|
.option('--limit <n>', 'Max results, 1-5', parseSearchLimit, 5)
|
|
192
|
+
.option('--json', 'Emit a machine-readable JSON array instead of the summary lines', false)
|
|
179
193
|
.action(
|
|
180
194
|
async (
|
|
181
195
|
query: string,
|
|
@@ -184,6 +198,7 @@ program
|
|
|
184
198
|
api?: string
|
|
185
199
|
unapproved: boolean
|
|
186
200
|
limit: number
|
|
201
|
+
json: boolean
|
|
187
202
|
},
|
|
188
203
|
) => {
|
|
189
204
|
requireType(opts.type, 'Search')
|
|
@@ -192,6 +207,7 @@ program
|
|
|
192
207
|
baseUrl: opts.api,
|
|
193
208
|
unapproved: opts.unapproved,
|
|
194
209
|
limit: opts.limit,
|
|
210
|
+
json: opts.json,
|
|
195
211
|
})
|
|
196
212
|
},
|
|
197
213
|
)
|
package/src/client.ts
CHANGED
|
@@ -26,3 +26,29 @@ export function createMarketClient(opts: MarketClientOptions = {}): MarketClient
|
|
|
26
26
|
})
|
|
27
27
|
return createORPCClient<MarketClient>(link)
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The `GET /download` zip view of a version as bytes. The stream is deterministic (store-mode
|
|
32
|
+
* entries, fixed mtimes), so two calls for the same immutable version are byte-identical — which is
|
|
33
|
+
* what upload's "unchanged, skip publishing" check compares against.
|
|
34
|
+
*/
|
|
35
|
+
export async function downloadAssetZipBytes(opts: {
|
|
36
|
+
name: string
|
|
37
|
+
version: string
|
|
38
|
+
baseUrl?: string
|
|
39
|
+
authToken?: string
|
|
40
|
+
/** The asset's capability key, an alternative credential to identity for private/unapproved assets. */
|
|
41
|
+
key?: string
|
|
42
|
+
fetch?: typeof globalThis.fetch
|
|
43
|
+
}): Promise<Uint8Array> {
|
|
44
|
+
const url = new URL('/download', opts.baseUrl ?? DEFAULT_BASE_URL)
|
|
45
|
+
url.searchParams.set('name', opts.name)
|
|
46
|
+
url.searchParams.set('version', opts.version)
|
|
47
|
+
if (opts.key) url.searchParams.set('key', opts.key)
|
|
48
|
+
const doFetch = opts.fetch ?? globalThis.fetch
|
|
49
|
+
const response = await doFetch(url.toString(), { headers: buildHeaders(opts.authToken) })
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
throw new Error(`Download of ${opts.name}@${opts.version} failed (${response.status})`)
|
|
52
|
+
}
|
|
53
|
+
return new Uint8Array(await response.arrayBuffer())
|
|
54
|
+
}
|
package/src/commands/install.ts
CHANGED
|
@@ -4,7 +4,7 @@ import ora from 'ora'
|
|
|
4
4
|
import { resolve } from '../resolve.js'
|
|
5
5
|
import { findInstallRoot, install as runInstall, type InstallRootRequest } from '../install.js'
|
|
6
6
|
import { packageJsonAssetDependencies } from '../package-json.js'
|
|
7
|
-
import { assetNameSchema } from '../schemas.js'
|
|
7
|
+
import { assetDependencyRange, assetNameSchema, type AssetDependencies } from '../schemas.js'
|
|
8
8
|
import { getCliClient } from '../cli-client.js'
|
|
9
9
|
import { installResult } from '../output.js'
|
|
10
10
|
import type { MarketClient } from '../client.js'
|
|
@@ -125,12 +125,15 @@ async function packageJsonRequests(cwd: string | undefined): Promise<AssetReques
|
|
|
125
125
|
const installRoot = await findInstallRoot(cwd ?? process.cwd())
|
|
126
126
|
const pkgPath = path.join(installRoot, 'package.json')
|
|
127
127
|
const dependencies = await readPackageJsonAssetDependencies(pkgPath)
|
|
128
|
-
const requests = Object.entries(dependencies).map(([name,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
const requests = Object.entries(dependencies).map(([name, value]) => {
|
|
129
|
+
const range = assetDependencyRange(value)
|
|
130
|
+
return {
|
|
131
|
+
name,
|
|
132
|
+
range,
|
|
133
|
+
saveRange: range,
|
|
134
|
+
save: false,
|
|
135
|
+
}
|
|
136
|
+
})
|
|
134
137
|
|
|
135
138
|
if (requests.length === 0) {
|
|
136
139
|
throw new Error(
|
|
@@ -141,7 +144,7 @@ async function packageJsonRequests(cwd: string | undefined): Promise<AssetReques
|
|
|
141
144
|
return requests
|
|
142
145
|
}
|
|
143
146
|
|
|
144
|
-
async function readPackageJsonAssetDependencies(pkgPath: string): Promise<
|
|
147
|
+
async function readPackageJsonAssetDependencies(pkgPath: string): Promise<AssetDependencies> {
|
|
145
148
|
try {
|
|
146
149
|
return packageJsonAssetDependencies(await fs.readFile(pkgPath, 'utf-8'), pkgPath)
|
|
147
150
|
} catch (error) {
|
package/src/commands/list.ts
CHANGED
|
@@ -1,48 +1,62 @@
|
|
|
1
|
+
import * as fs from 'fs/promises'
|
|
1
2
|
import * as path from 'path'
|
|
2
3
|
import { findInstallRoot } from '../install.js'
|
|
3
|
-
import {
|
|
4
|
+
import { packageJsonAssetDependencies } from '../package-json.js'
|
|
5
|
+
import { assetDependencyAlias, assetDependencyRange } from '../schemas.js'
|
|
4
6
|
import { listResult } from '../output.js'
|
|
5
7
|
|
|
6
8
|
export interface ListCommandOptions {
|
|
7
9
|
cwd?: string
|
|
8
|
-
files?: boolean
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export interface InstalledAssetListing {
|
|
12
13
|
name: string
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
range: string
|
|
15
|
+
/** Canonical install path → the project's current path, for files renamed after install. */
|
|
16
|
+
alias: Record<string, string>
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export interface ListInstalledAssetsResult {
|
|
19
20
|
projectRoot: string
|
|
20
|
-
|
|
21
|
+
packageJsonPath: string
|
|
21
22
|
assets: InstalledAssetListing[]
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export async function listCommand(opts: ListCommandOptions): Promise<void> {
|
|
25
26
|
const result = await listInstalledAssets(opts.cwd)
|
|
26
|
-
console.log(listResult(result
|
|
27
|
+
console.log(listResult(result))
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
/** The project's declared asset dependencies — package.json is the single source of truth. */
|
|
29
31
|
export async function listInstalledAssets(
|
|
30
32
|
cwd: string | undefined,
|
|
31
33
|
): Promise<ListInstalledAssetsResult> {
|
|
32
34
|
const projectRoot = await findInstallRoot(cwd ?? process.cwd())
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
35
|
+
const packageJsonPath = path.join(projectRoot, 'package.json')
|
|
36
|
+
const dependencies = await readAssetDependencies(packageJsonPath)
|
|
37
|
+
const assets = Object.entries(dependencies)
|
|
38
|
+
.map(([name, value]) => ({
|
|
36
39
|
name,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
files: [...asset.files].sort((a, b) => a.localeCompare(b)),
|
|
40
|
+
range: assetDependencyRange(value),
|
|
41
|
+
alias: assetDependencyAlias(value),
|
|
40
42
|
}))
|
|
41
43
|
.sort((a, b) => a.name.localeCompare(b.name))
|
|
42
44
|
|
|
43
45
|
return {
|
|
44
46
|
projectRoot,
|
|
45
|
-
|
|
47
|
+
packageJsonPath,
|
|
46
48
|
assets,
|
|
47
49
|
}
|
|
48
50
|
}
|
|
51
|
+
|
|
52
|
+
async function readAssetDependencies(packageJsonPath: string) {
|
|
53
|
+
try {
|
|
54
|
+
return packageJsonAssetDependencies(
|
|
55
|
+
await fs.readFile(packageJsonPath, 'utf-8'),
|
|
56
|
+
packageJsonPath,
|
|
57
|
+
)
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') return {}
|
|
60
|
+
throw error
|
|
61
|
+
}
|
|
62
|
+
}
|
package/src/commands/pack.ts
CHANGED
|
@@ -2,7 +2,12 @@ import * as fs from 'fs/promises'
|
|
|
2
2
|
import * as path from 'path'
|
|
3
3
|
import ora from 'ora'
|
|
4
4
|
import { getCliClient } from '../cli-client.js'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
fileManifestForRange,
|
|
7
|
+
packAsset,
|
|
8
|
+
packPolicyForType,
|
|
9
|
+
parsePackDependencies,
|
|
10
|
+
} from '../pack.js'
|
|
6
11
|
import { packResult } from '../output.js'
|
|
7
12
|
import type { AssetType } from '../schemas.js'
|
|
8
13
|
|
|
@@ -39,7 +44,7 @@ export async function packCommand(zipFilter: string, opts: PackCommandOptions):
|
|
|
39
44
|
skill: opts.skill,
|
|
40
45
|
}),
|
|
41
46
|
policy: packPolicyForType(opts.type),
|
|
42
|
-
fetchFileManifest: (
|
|
47
|
+
fetchFileManifest: fileManifestForRange(client.asset),
|
|
43
48
|
})
|
|
44
49
|
const out = opts.out ? path.resolve(cwd, opts.out) : defaultPackPath(packed.sourcePath)
|
|
45
50
|
|
package/src/commands/search.ts
CHANGED
|
@@ -10,6 +10,8 @@ export interface SearchCommandOptions {
|
|
|
10
10
|
unapproved?: boolean
|
|
11
11
|
baseUrl?: string
|
|
12
12
|
limit?: number
|
|
13
|
+
/** Emit a machine-readable JSON array instead of the human-readable lines. */
|
|
14
|
+
json?: boolean
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
export async function searchCommand(query: string, opts: SearchCommandOptions): Promise<void> {
|
|
@@ -17,8 +19,8 @@ export async function searchCommand(query: string, opts: SearchCommandOptions):
|
|
|
17
19
|
|
|
18
20
|
const spinner = ora({
|
|
19
21
|
text: `Searching "${query}"`,
|
|
20
|
-
isEnabled: Boolean(process.stderr.isTTY),
|
|
21
|
-
isSilent: !process.stderr.isTTY,
|
|
22
|
+
isEnabled: Boolean(process.stderr.isTTY) && !opts.json,
|
|
23
|
+
isSilent: !process.stderr.isTTY || Boolean(opts.json),
|
|
22
24
|
}).start()
|
|
23
25
|
const results = await client.asset
|
|
24
26
|
.search({
|
|
@@ -31,6 +33,23 @@ export async function searchCommand(query: string, opts: SearchCommandOptions):
|
|
|
31
33
|
})
|
|
32
34
|
.finally(() => spinner.stop())
|
|
33
35
|
|
|
36
|
+
if (opts.json) {
|
|
37
|
+
// Stable machine-readable shape for scripts; the human-readable lines below may change freely.
|
|
38
|
+
console.log(
|
|
39
|
+
JSON.stringify(
|
|
40
|
+
results.items.map((item) => ({
|
|
41
|
+
name: item.name,
|
|
42
|
+
version: item.latestVersion,
|
|
43
|
+
type: item.type,
|
|
44
|
+
approved: item.approved,
|
|
45
|
+
access: item.access,
|
|
46
|
+
description: item.description,
|
|
47
|
+
})),
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
34
53
|
console.log(
|
|
35
54
|
searchSummary({
|
|
36
55
|
query,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import ora from 'ora'
|
|
2
|
+
import { getCliClient } from '../cli-client.js'
|
|
3
|
+
import { fileManifestForRange, syncAssetDependencies } from '../pack.js'
|
|
4
|
+
import { syncResult } from '../output.js'
|
|
5
|
+
|
|
6
|
+
export interface SyncCommandOptions {
|
|
7
|
+
cwd?: string
|
|
8
|
+
baseUrl?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function syncCommand(opts: SyncCommandOptions): Promise<void> {
|
|
12
|
+
const spinner = ora({
|
|
13
|
+
text: 'Syncing assetDependencies',
|
|
14
|
+
isEnabled: Boolean(process.stderr.isTTY),
|
|
15
|
+
isSilent: !process.stderr.isTTY,
|
|
16
|
+
}).start()
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const { client } = await getCliClient({ baseUrl: opts.baseUrl })
|
|
20
|
+
const result = await syncAssetDependencies(
|
|
21
|
+
opts.cwd ?? process.cwd(),
|
|
22
|
+
fileManifestForRange(client.asset),
|
|
23
|
+
)
|
|
24
|
+
spinner.stop()
|
|
25
|
+
console.log(syncResult(result))
|
|
26
|
+
} catch (err) {
|
|
27
|
+
spinner.stop()
|
|
28
|
+
throw err
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/commands/upload.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import ora from 'ora'
|
|
2
2
|
import semver from 'semver'
|
|
3
|
+
import { downloadAssetZipBytes } from '../client.js'
|
|
3
4
|
import { getCliClient } from '../cli-client.js'
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
fileManifestForRange,
|
|
7
|
+
packAsset,
|
|
8
|
+
packPolicyFromInstallMetadata,
|
|
9
|
+
parsePackDependencies,
|
|
10
|
+
} from '../pack.js'
|
|
5
11
|
import { unchangedUploadResult, uploadResult } from '../output.js'
|
|
6
12
|
import {
|
|
7
13
|
assetDescriptionSchema,
|
|
@@ -51,13 +57,16 @@ export async function uploadCommand(
|
|
|
51
57
|
})
|
|
52
58
|
const cwd = opts.cwd ?? process.cwd()
|
|
53
59
|
const type = opts.type
|
|
54
|
-
const { client } = await getCliClient({
|
|
60
|
+
const { client, baseUrl, authToken } = await getCliClient({
|
|
61
|
+
baseUrl: opts.baseUrl,
|
|
62
|
+
requireAuth: true,
|
|
63
|
+
})
|
|
55
64
|
const installMetadata = await client.asset.installMetadata()
|
|
56
65
|
const packed = await packAsset(zipFilter, {
|
|
57
66
|
cwd,
|
|
58
67
|
dependencies,
|
|
59
68
|
policy: packPolicyFromInstallMetadata(installMetadata[type]),
|
|
60
|
-
fetchFileManifest: (
|
|
69
|
+
fetchFileManifest: fileManifestForRange(client.asset),
|
|
61
70
|
})
|
|
62
71
|
const { zip, npmDependencies, assetDependencies, skillDependencies } = packed
|
|
63
72
|
const profile = await client.user.getProfile()
|
|
@@ -75,11 +84,12 @@ export async function uploadCommand(
|
|
|
75
84
|
}
|
|
76
85
|
|
|
77
86
|
if (existing) {
|
|
78
|
-
const
|
|
87
|
+
const latestBytes = await downloadAssetZipBytes({
|
|
79
88
|
name: parsedName,
|
|
80
89
|
version: existing.latestVersion,
|
|
90
|
+
baseUrl,
|
|
91
|
+
authToken,
|
|
81
92
|
})
|
|
82
|
-
const latestBytes = new Uint8Array(await latestZip.arrayBuffer())
|
|
83
93
|
if (
|
|
84
94
|
existing.description === parsedDescription &&
|
|
85
95
|
depsEqual(existing.npmDependencies, npmDependencies) &&
|
|
@@ -128,16 +138,21 @@ export function parseUploadDescription(description: string): string {
|
|
|
128
138
|
}
|
|
129
139
|
}
|
|
130
140
|
|
|
131
|
-
/** Compare a stored dependency JSON string against a freshly parsed record.
|
|
132
|
-
|
|
133
|
-
|
|
141
|
+
/** Compare a stored dependency JSON string against a freshly parsed record. Values may be nested
|
|
142
|
+
* (asset dependencies carry `{ version, alias }`), so equality is structural with sorted keys. */
|
|
143
|
+
function depsEqual(storedJson: string, next: Record<string, unknown>): boolean {
|
|
134
144
|
try {
|
|
135
|
-
|
|
145
|
+
return stableJson(JSON.parse(storedJson || '{}')) === stableJson(next)
|
|
136
146
|
} catch {
|
|
137
147
|
return false
|
|
138
148
|
}
|
|
139
|
-
|
|
140
|
-
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function stableJson(value: unknown): string {
|
|
152
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return JSON.stringify(value)
|
|
153
|
+
const record = value as Record<string, unknown>
|
|
154
|
+
const keys = Object.keys(record).sort()
|
|
155
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`).join(',')}}`
|
|
141
156
|
}
|
|
142
157
|
|
|
143
158
|
function nextVersion(latest?: string): string {
|
package/src/contract.ts
CHANGED
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
agentStartSchema,
|
|
8
8
|
agentStatusSchema,
|
|
9
9
|
assetFilesSchema,
|
|
10
|
-
downloadZipSchema,
|
|
11
10
|
exactAssetSchema,
|
|
12
11
|
fileManifestSchema,
|
|
13
12
|
generateAssetSchema,
|
|
@@ -147,8 +146,6 @@ export const contract = {
|
|
|
147
146
|
)
|
|
148
147
|
.output(z.custom<AssetVersion>()),
|
|
149
148
|
|
|
150
|
-
downloadZip: oc.input(downloadZipSchema).output(z.instanceof(Blob)),
|
|
151
|
-
|
|
152
149
|
// The derived file index of a version — every stored file's path, size and md5 etag plus the
|
|
153
150
|
// fetch-ready data-plane URLs, so installs fetch files in parallel through the same edge cache
|
|
154
151
|
// browsers warm.
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
// The v1 REST surface (`/api/v1`): routed contract + typed client. Prefer this; the legacy RPC
|
|
2
|
+
// client below is deprecated and retires together with `/api/rpc`.
|
|
3
|
+
export * as v1 from './v1/index.js'
|
|
4
|
+
|
|
1
5
|
// Client
|
|
2
|
-
export { createMarketClient } from './client.js'
|
|
6
|
+
export { createMarketClient, downloadAssetZipBytes } from './client.js'
|
|
3
7
|
export type { MarketClient, MarketClientOptions } from './client.js'
|
|
4
8
|
|
|
5
9
|
// Contracts
|
|
@@ -21,7 +25,7 @@ export type {
|
|
|
21
25
|
} from './contract.js'
|
|
22
26
|
|
|
23
27
|
export type {
|
|
24
|
-
|
|
28
|
+
AssetVersionRef,
|
|
25
29
|
AssetExactInput,
|
|
26
30
|
AssetGenerateInput,
|
|
27
31
|
AssetImplementation,
|
|
@@ -62,9 +66,13 @@ export {
|
|
|
62
66
|
assetAccessSchema,
|
|
63
67
|
npmDependenciesSchema,
|
|
64
68
|
assetDependenciesSchema,
|
|
69
|
+
assetDependencyAliasSchema,
|
|
70
|
+
assetDependencyValueSchema,
|
|
71
|
+
assetDependencyRange,
|
|
72
|
+
assetDependencyAlias,
|
|
73
|
+
assetDependencyValue,
|
|
65
74
|
skillDependenciesSchema,
|
|
66
75
|
uploadZipSchema,
|
|
67
|
-
downloadZipSchema,
|
|
68
76
|
exactAssetSchema,
|
|
69
77
|
fileManifestSchema,
|
|
70
78
|
generateAssetSchema,
|
|
@@ -83,6 +91,8 @@ export {
|
|
|
83
91
|
export type {
|
|
84
92
|
AssetType,
|
|
85
93
|
AssetAccess,
|
|
94
|
+
AssetDependencies,
|
|
95
|
+
AssetDependencyValue,
|
|
86
96
|
AssetFileManifest,
|
|
87
97
|
AgentResultAsset,
|
|
88
98
|
AgentResult,
|