@martini-film/cli 0.3.0 → 0.4.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 +169 -44
- package/dist/api.js +71 -23
- package/dist/api.js.map +1 -1
- package/dist/approve.js +16 -1
- package/dist/approve.js.map +1 -1
- package/dist/cli.js +487 -142
- package/dist/cli.js.map +1 -1
- package/dist/commands/assets.js +165 -29
- package/dist/commands/assets.js.map +1 -1
- package/dist/commands/call.js +131 -0
- package/dist/commands/call.js.map +1 -0
- package/dist/commands/context.js +11 -2
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/files.js +117 -9
- package/dist/commands/files.js.map +1 -1
- package/dist/commands/guide.js +71 -0
- package/dist/commands/guide.js.map +1 -0
- package/dist/commands/init.js +213 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.js +37 -6
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/tools.js +88 -80
- package/dist/commands/tools.js.map +1 -1
- package/dist/commands/use.js +148 -0
- package/dist/commands/use.js.map +1 -0
- package/dist/config.js +87 -6
- package/dist/config.js.map +1 -1
- package/dist/generated/guide.json +104 -0
- package/dist/generated/manifest.json +73 -24
- package/dist/guideCache.js +204 -0
- package/dist/guideCache.js.map +1 -0
- package/dist/help.js +391 -34
- package/dist/help.js.map +1 -1
- package/dist/manifest.js +27 -0
- package/dist/manifest.js.map +1 -1
- package/dist/manifestCache.js +196 -0
- package/dist/manifestCache.js.map +1 -0
- package/dist/output.js +289 -30
- package/dist/output.js.map +1 -1
- package/dist/schema.js +281 -16
- package/dist/schema.js.map +1 -1
- package/dist/wait.js +33 -2
- package/dist/wait.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"hash": "
|
|
3
|
+
"hash": "5bb190df5eb33f307ac548a2fcce6be7fa87590bcd777893a93c541963c6fdfa",
|
|
4
4
|
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
5
5
|
"tools": [
|
|
6
6
|
{
|
|
@@ -2155,7 +2155,7 @@
|
|
|
2155
2155
|
},
|
|
2156
2156
|
"agentId": {
|
|
2157
2157
|
"default": "opus-5.5",
|
|
2158
|
-
"description": "Executor chat model — same catalog as the in-app chat: 'opus-5.5' (Claude Opus 5.5, default), 'chat-gpt' (GPT-6 Sol — cheaper, for routine steps), 'chat-sonnet' (Claude Sonnet), 'gpt-6-astra' (GPT-6 Astra) and 'fable-5.1' (Claude Fable 5.1) — the premium tier, 'chat-grok' (Grok 4.7), 'chat-minimax' (MiniMax M3 — the economical choice for bulk mechanical steps). Drives the plan pass, unit sessions, and judge — not the media model, which the brief's @Model tags or the plan decide.",
|
|
2158
|
+
"description": "Executor chat model — same catalog as the in-app chat: 'opus-5.5' (Claude Opus 5.5, default), 'chat-gpt' (GPT-6.1 Sol — cheaper, for routine steps), 'chat-sonnet' (Claude Sonnet 5.5), 'gpt-6-astra' (GPT-6 Astra) and 'fable-5.1' (Claude Fable 5.1) — the premium tier, 'chat-grok' (Grok 4.7), 'chat-minimax' (MiniMax M3 — the economical choice for bulk mechanical steps). Drives the plan pass, unit sessions, and judge — not the media model, which the brief's @Model tags or the plan decide.",
|
|
2159
2159
|
"type": "string",
|
|
2160
2160
|
"minLength": 1,
|
|
2161
2161
|
"maxLength": 80
|
|
@@ -2736,7 +2736,7 @@
|
|
|
2736
2736
|
"type": "string"
|
|
2737
2737
|
},
|
|
2738
2738
|
"startFrameUrl": {
|
|
2739
|
-
"description": "Start-frame image URL (https workspace asset URL) to stage on the draft for image-to-video.",
|
|
2739
|
+
"description": "Start-frame image URL (https workspace asset URL, or its asset id) to stage on the draft for image-to-video.",
|
|
2740
2740
|
"type": "string",
|
|
2741
2741
|
"maxLength": 2048
|
|
2742
2742
|
},
|
|
@@ -2784,7 +2784,7 @@
|
|
|
2784
2784
|
}
|
|
2785
2785
|
},
|
|
2786
2786
|
"referenceImages": {
|
|
2787
|
-
"description": "Ordered reference image URLs stored on the draft and shown in its Reference Images panel. Bind them in draftPrompt as @Image1, @Image2, … https URLs with a public hostname only — Martini asset URLs (from get_asset / get_board_assets) live-bind to their source node; data:/blob:/http:/localhost/private-IP URLs are rejected.",
|
|
2787
|
+
"description": "Ordered reference image URLs stored on the draft and shown in its Reference Images panel. Bind them in draftPrompt as @Image1, @Image2, … https URLs with a public hostname only — Martini asset URLs (from get_asset / get_board_assets) live-bind to their source node, as does an asset id; data:/blob:/http:/localhost/private-IP URLs are rejected.",
|
|
2788
2788
|
"maxItems": 20,
|
|
2789
2789
|
"type": "array",
|
|
2790
2790
|
"items": {
|
|
@@ -3622,11 +3622,11 @@
|
|
|
3622
3622
|
"exclusiveMinimum": 0
|
|
3623
3623
|
},
|
|
3624
3624
|
"imageUrl": {
|
|
3625
|
-
"description": "Start frame image URL (for image-to-video)",
|
|
3625
|
+
"description": "Start frame image URL or asset id (for image-to-video)",
|
|
3626
3626
|
"type": "string"
|
|
3627
3627
|
},
|
|
3628
3628
|
"endFrameUrl": {
|
|
3629
|
-
"description": "End frame image URL",
|
|
3629
|
+
"description": "End frame image URL or asset id",
|
|
3630
3630
|
"type": "string"
|
|
3631
3631
|
},
|
|
3632
3632
|
"middleFrameUrl": {
|
|
@@ -3665,7 +3665,7 @@
|
|
|
3665
3665
|
}
|
|
3666
3666
|
},
|
|
3667
3667
|
"referenceImages": {
|
|
3668
|
-
"description": "Ordered reference image URLs for style consistency. Must be Martini CDN URLs from uploaded assets or get_asset. Bind them in the prompt as @Image1, @Image2, …; bare names do not bind media. One contact sheet is one reference. For recurring characters, props, or locations, prefer Library elements instead.",
|
|
3668
|
+
"description": "Ordered reference image URLs for style consistency. Must be Martini CDN URLs from uploaded assets or get_asset, or their asset ids. Bind them in the prompt as @Image1, @Image2, …; bare names do not bind media. One contact sheet is one reference. For recurring characters, props, or locations, prefer Library elements instead.",
|
|
3669
3669
|
"type": "array",
|
|
3670
3670
|
"items": {
|
|
3671
3671
|
"type": "string"
|
|
@@ -4449,7 +4449,7 @@
|
|
|
4449
4449
|
}
|
|
4450
4450
|
},
|
|
4451
4451
|
"referenceImages": {
|
|
4452
|
-
"description": "Ordered reference image URLs stored on the draft and shown in its Reference Images panel. Bind them in draftPrompt as @Image1, @Image2, … https URLs with a public hostname only — Martini asset URLs (from get_asset / get_board_assets) live-bind to their source node; data:/blob:/http:/localhost/private-IP URLs are rejected.",
|
|
4452
|
+
"description": "Ordered reference image URLs stored on the draft and shown in its Reference Images panel. Bind them in draftPrompt as @Image1, @Image2, … https URLs with a public hostname only — Martini asset URLs (from get_asset / get_board_assets) live-bind to their source node, as does an asset id; data:/blob:/http:/localhost/private-IP URLs are rejected.",
|
|
4453
4453
|
"maxItems": 20,
|
|
4454
4454
|
"type": "array",
|
|
4455
4455
|
"items": {
|
|
@@ -4794,7 +4794,7 @@
|
|
|
4794
4794
|
}
|
|
4795
4795
|
},
|
|
4796
4796
|
"startFrameUrl": {
|
|
4797
|
-
"description": "Start-frame image URL (https workspace asset URL) to stage on the draft for image-to-video.",
|
|
4797
|
+
"description": "Start-frame image URL (https workspace asset URL, or its asset id) to stage on the draft for image-to-video.",
|
|
4798
4798
|
"type": "string",
|
|
4799
4799
|
"maxLength": 2048
|
|
4800
4800
|
},
|
|
@@ -5428,11 +5428,11 @@
|
|
|
5428
5428
|
"exclusiveMinimum": 0
|
|
5429
5429
|
},
|
|
5430
5430
|
"imageUrl": {
|
|
5431
|
-
"description": "Start frame image URL (for image-to-video)",
|
|
5431
|
+
"description": "Start frame image URL or asset id (for image-to-video)",
|
|
5432
5432
|
"type": "string"
|
|
5433
5433
|
},
|
|
5434
5434
|
"endFrameUrl": {
|
|
5435
|
-
"description": "End frame image URL",
|
|
5435
|
+
"description": "End frame image URL or asset id",
|
|
5436
5436
|
"type": "string"
|
|
5437
5437
|
},
|
|
5438
5438
|
"middleFrameUrl": {
|
|
@@ -5471,7 +5471,7 @@
|
|
|
5471
5471
|
}
|
|
5472
5472
|
},
|
|
5473
5473
|
"referenceImages": {
|
|
5474
|
-
"description": "Ordered reference image URLs for style consistency. Must be Martini CDN URLs from uploaded assets or get_asset. Bind them in the prompt as @Image1, @Image2, …; bare names do not bind media. One contact sheet is one reference. For recurring characters, props, or locations, prefer Library elements instead.",
|
|
5474
|
+
"description": "Ordered reference image URLs for style consistency. Must be Martini CDN URLs from uploaded assets or get_asset, or their asset ids. Bind them in the prompt as @Image1, @Image2, …; bare names do not bind media. One contact sheet is one reference. For recurring characters, props, or locations, prefer Library elements instead.",
|
|
5475
5475
|
"type": "array",
|
|
5476
5476
|
"items": {
|
|
5477
5477
|
"type": "string"
|
|
@@ -6176,7 +6176,7 @@
|
|
|
6176
6176
|
{
|
|
6177
6177
|
"name": "create_project",
|
|
6178
6178
|
"title": "Create Project",
|
|
6179
|
-
"description": "Create a new Martini project for the authenticated user. Optionally pass a teamId to create a private team project. After creating an empty project, use create_canvas before adding board content.",
|
|
6179
|
+
"description": "Create a new Martini project for the authenticated user. Optionally pass a teamId to create a private team project. A personal project starts with link sharing on (anyone with its link can edit; the result reports it as visibility, visibilityLabel, and accessLabel) unless visibility says otherwise: pass visibility \"private\" for confidential material (it needs a Pro or Team plan), and say so when you leave the default. After creating an empty project, use create_canvas before adding board content.",
|
|
6180
6180
|
"inputSchema": {
|
|
6181
6181
|
"type": "object",
|
|
6182
6182
|
"properties": {
|
|
@@ -6190,6 +6190,15 @@
|
|
|
6190
6190
|
"type": "string",
|
|
6191
6191
|
"format": "uuid",
|
|
6192
6192
|
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
|
|
6193
|
+
},
|
|
6194
|
+
"visibility": {
|
|
6195
|
+
"description": "Sharing for a personal project: private (members only; needs a Pro or Team plan), link_view (anyone with the link can view), or link_edit (anyone with the link can edit; the default). A team project is always private.",
|
|
6196
|
+
"type": "string",
|
|
6197
|
+
"enum": [
|
|
6198
|
+
"private",
|
|
6199
|
+
"link_view",
|
|
6200
|
+
"link_edit"
|
|
6201
|
+
]
|
|
6193
6202
|
}
|
|
6194
6203
|
},
|
|
6195
6204
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
@@ -7424,11 +7433,11 @@
|
|
|
7424
7433
|
"exclusiveMinimum": 0
|
|
7425
7434
|
},
|
|
7426
7435
|
"imageUrl": {
|
|
7427
|
-
"description": "Start frame image URL (for image-to-video)",
|
|
7436
|
+
"description": "Start frame image URL or asset id (for image-to-video)",
|
|
7428
7437
|
"type": "string"
|
|
7429
7438
|
},
|
|
7430
7439
|
"endFrameUrl": {
|
|
7431
|
-
"description": "End frame image URL",
|
|
7440
|
+
"description": "End frame image URL or asset id",
|
|
7432
7441
|
"type": "string"
|
|
7433
7442
|
},
|
|
7434
7443
|
"middleFrameUrl": {
|
|
@@ -7441,7 +7450,7 @@
|
|
|
7441
7450
|
"exclusiveMinimum": 0
|
|
7442
7451
|
},
|
|
7443
7452
|
"referenceImages": {
|
|
7444
|
-
"description": "Ordered reference image URLs for style consistency. Bind them in the prompt as @Image1, @Image2, …; bare names do not bind media. One contact sheet is one reference. Use elements instead for character/subject references.",
|
|
7453
|
+
"description": "Ordered reference image URLs (or asset ids) for style consistency. Bind them in the prompt as @Image1, @Image2, …; bare names do not bind media. One contact sheet is one reference. Use elements instead for character/subject references.",
|
|
7445
7454
|
"type": "array",
|
|
7446
7455
|
"items": {
|
|
7447
7456
|
"type": "string"
|
|
@@ -7998,7 +8007,7 @@
|
|
|
7998
8007
|
{
|
|
7999
8008
|
"name": "generate_nodes",
|
|
8000
8009
|
"title": "Generate Draft Nodes (Batch)",
|
|
8001
|
-
"description": "Generate existing draft nodes from their staged settings (model, prompt, frames, references). First call without batchApproval: Martini returns a server-computed olive estimate and generates nothing. Present the plan and total to the user, then re-call with batchApproval and the returned planHash. Submission has per-node error isolation;
|
|
8010
|
+
"description": "Generate existing draft nodes from their staged settings (model, prompt, frames, references). First call without batchApproval: Martini returns a server-computed olive estimate and generates nothing. Present the plan and total to the user, then re-call with batchApproval and the returned planHash. Submission has per-node error isolation; then wait with wait_for_jobs, not a get_jobs poll. Board variables expand at submit time. FLUX.3 drafts staged with flux3RenderQuality \"draft\" are estimated and billed at draft rates, and auto-duration drafts are quoted at their full hold with the unused seconds refunded on completion.",
|
|
8002
8011
|
"inputSchema": {
|
|
8003
8012
|
"type": "object",
|
|
8004
8013
|
"properties": {
|
|
@@ -8225,6 +8234,14 @@
|
|
|
8225
8234
|
"type": "object",
|
|
8226
8235
|
"properties": {
|
|
8227
8236
|
"nodeId": {
|
|
8237
|
+
"type": "string",
|
|
8238
|
+
"description": "Draft node id (asset-<uuid>)."
|
|
8239
|
+
},
|
|
8240
|
+
"assetId": {
|
|
8241
|
+
"description": "The same node as a bare asset id: what get_asset, the wait, and the review take.",
|
|
8242
|
+
"type": "string"
|
|
8243
|
+
},
|
|
8244
|
+
"displayName": {
|
|
8228
8245
|
"type": "string"
|
|
8229
8246
|
},
|
|
8230
8247
|
"modelId": {
|
|
@@ -14548,6 +14565,10 @@
|
|
|
14548
14565
|
"refundedAmount": {
|
|
14549
14566
|
"type": "number"
|
|
14550
14567
|
},
|
|
14568
|
+
"chargedOlives": {
|
|
14569
|
+
"description": "Olives this job cost: the hold less any refund.",
|
|
14570
|
+
"type": "number"
|
|
14571
|
+
},
|
|
14551
14572
|
"imageBilling": {
|
|
14552
14573
|
"type": "object",
|
|
14553
14574
|
"properties": {
|
|
@@ -14740,6 +14761,10 @@
|
|
|
14740
14761
|
"refundedAmount": {
|
|
14741
14762
|
"type": "number"
|
|
14742
14763
|
},
|
|
14764
|
+
"chargedOlives": {
|
|
14765
|
+
"description": "Olives this job cost: the hold less any refund.",
|
|
14766
|
+
"type": "number"
|
|
14767
|
+
},
|
|
14743
14768
|
"imageBilling": {
|
|
14744
14769
|
"type": "object",
|
|
14745
14770
|
"properties": {
|
|
@@ -14888,7 +14913,7 @@
|
|
|
14888
14913
|
{
|
|
14889
14914
|
"name": "get_models",
|
|
14890
14915
|
"title": "Get Models",
|
|
14891
|
-
"description": "List models (compact, paged), resolve a model/provider name, or inspect one exact model in full. query resolves names like \"GPT image\" or \"Kling\"; modelId inspects one exact ID (guidance and inputs live there); omit both to list.",
|
|
14916
|
+
"description": "List models (compact, paged), resolve a model/provider name, or inspect one exact model in full. query resolves names like \"GPT image\" or \"Kling\"; modelId inspects one exact ID (guidance and inputs live there); omit both to list. Costs are in olives.",
|
|
14892
14917
|
"inputSchema": {
|
|
14893
14918
|
"type": "object",
|
|
14894
14919
|
"properties": {
|
|
@@ -15028,7 +15053,7 @@
|
|
|
15028
15053
|
}
|
|
15029
15054
|
},
|
|
15030
15055
|
"mcpInputBindings": {
|
|
15031
|
-
"description": "Per input: whether it is settable
|
|
15056
|
+
"description": "Per input: whether it is settable, and its argument names (draftParameterNames: on the draft tools).",
|
|
15032
15057
|
"type": "object",
|
|
15033
15058
|
"propertyNames": {
|
|
15034
15059
|
"type": "string"
|
|
@@ -15043,6 +15068,14 @@
|
|
|
15043
15068
|
"type": "boolean"
|
|
15044
15069
|
},
|
|
15045
15070
|
"parameterNames": {
|
|
15071
|
+
"description": "The input's argument names on generate.",
|
|
15072
|
+
"type": "array",
|
|
15073
|
+
"items": {
|
|
15074
|
+
"type": "string"
|
|
15075
|
+
}
|
|
15076
|
+
},
|
|
15077
|
+
"draftParameterNames": {
|
|
15078
|
+
"description": "Its names on the draft tools, where they differ (durationSeconds).",
|
|
15046
15079
|
"type": "array",
|
|
15047
15080
|
"items": {
|
|
15048
15081
|
"type": "string"
|
|
@@ -15175,7 +15208,7 @@
|
|
|
15175
15208
|
}
|
|
15176
15209
|
},
|
|
15177
15210
|
"mcpInputBindings": {
|
|
15178
|
-
"description": "Per input: whether it is settable
|
|
15211
|
+
"description": "Per input: whether it is settable, and its argument names (draftParameterNames: on the draft tools).",
|
|
15179
15212
|
"type": "object",
|
|
15180
15213
|
"propertyNames": {
|
|
15181
15214
|
"type": "string"
|
|
@@ -15190,6 +15223,14 @@
|
|
|
15190
15223
|
"type": "boolean"
|
|
15191
15224
|
},
|
|
15192
15225
|
"parameterNames": {
|
|
15226
|
+
"description": "The input's argument names on generate.",
|
|
15227
|
+
"type": "array",
|
|
15228
|
+
"items": {
|
|
15229
|
+
"type": "string"
|
|
15230
|
+
}
|
|
15231
|
+
},
|
|
15232
|
+
"draftParameterNames": {
|
|
15233
|
+
"description": "Its names on the draft tools, where they differ (durationSeconds).",
|
|
15193
15234
|
"type": "array",
|
|
15194
15235
|
"items": {
|
|
15195
15236
|
"type": "string"
|
|
@@ -15283,7 +15324,7 @@
|
|
|
15283
15324
|
}
|
|
15284
15325
|
},
|
|
15285
15326
|
"mcpInputBindings": {
|
|
15286
|
-
"description": "Per input: whether it is settable
|
|
15327
|
+
"description": "Per input: whether it is settable, and its argument names (draftParameterNames: on the draft tools).",
|
|
15287
15328
|
"type": "object",
|
|
15288
15329
|
"propertyNames": {
|
|
15289
15330
|
"type": "string"
|
|
@@ -15298,6 +15339,14 @@
|
|
|
15298
15339
|
"type": "boolean"
|
|
15299
15340
|
},
|
|
15300
15341
|
"parameterNames": {
|
|
15342
|
+
"description": "The input's argument names on generate.",
|
|
15343
|
+
"type": "array",
|
|
15344
|
+
"items": {
|
|
15345
|
+
"type": "string"
|
|
15346
|
+
}
|
|
15347
|
+
},
|
|
15348
|
+
"draftParameterNames": {
|
|
15349
|
+
"description": "Its names on the draft tools, where they differ (durationSeconds).",
|
|
15301
15350
|
"type": "array",
|
|
15302
15351
|
"items": {
|
|
15303
15352
|
"type": "string"
|
|
@@ -20259,7 +20308,7 @@
|
|
|
20259
20308
|
{
|
|
20260
20309
|
"name": "render_timeline_frame",
|
|
20261
20310
|
"title": "Render Timeline Frame",
|
|
20262
|
-
"description": "See the COMPOSED timeline as it plays: renders the top visible clip at a given time (or a strip of frames across a range) into a JPEG image block, so you can QA an edit you just made — clip order, trims, ordering, nested sequences, and track priority. This is editor-preview compositing (the winning clip at each instant); it does NOT bake in transitions, opacity, or filters — use the full render/export for final output. Gaps render as black frames. Read-only; reads from R2 on every call.",
|
|
20311
|
+
"description": "See the COMPOSED timeline as it plays: renders the top visible clip at a given time (or a strip of frames across a range) into a JPEG image block, so you can QA an edit you just made — clip order, trims, ordering, nested sequences, and track priority. This is editor-preview compositing (the winning clip at each instant); it does NOT bake in transitions, opacity, or filters — use the full render/export for final output. It is a small labelled preview (extract_video_frame gives a full-size still). Gaps render as black frames. Read-only; reads from R2 on every call.",
|
|
20263
20312
|
"inputSchema": {
|
|
20264
20313
|
"type": "object",
|
|
20265
20314
|
"properties": {
|
|
@@ -22059,7 +22108,7 @@
|
|
|
22059
22108
|
"type": "string"
|
|
22060
22109
|
},
|
|
22061
22110
|
"startFrameUrl": {
|
|
22062
|
-
"description": "Start-frame image URL (https workspace asset URL) to stage on the draft for image-to-video. Pass null to clear the staged frame.",
|
|
22111
|
+
"description": "Start-frame image URL (https workspace asset URL, or its asset id) to stage on the draft for image-to-video. Pass null to clear the staged frame.",
|
|
22063
22112
|
"anyOf": [
|
|
22064
22113
|
{
|
|
22065
22114
|
"type": "string",
|
|
@@ -22109,7 +22158,7 @@
|
|
|
22109
22158
|
}
|
|
22110
22159
|
},
|
|
22111
22160
|
"referenceImages": {
|
|
22112
|
-
"description": "Ordered reference image URLs stored on the draft and shown in its Reference Images panel. Bind them in draftPrompt as @Image1, @Image2, … https URLs with a public hostname only — Martini asset URLs (from get_asset / get_board_assets) live-bind to their source node; data:/blob:/http:/localhost/private-IP URLs are rejected.",
|
|
22161
|
+
"description": "Ordered reference image URLs stored on the draft and shown in its Reference Images panel. Bind them in draftPrompt as @Image1, @Image2, … https URLs with a public hostname only — Martini asset URLs (from get_asset / get_board_assets) live-bind to their source node, as does an asset id; data:/blob:/http:/localhost/private-IP URLs are rejected.",
|
|
22113
22162
|
"maxItems": 20,
|
|
22114
22163
|
"type": "array",
|
|
22115
22164
|
"items": {
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { readFileSync, rmSync } from 'node:fs';
|
|
2
|
+
import { CLI_VERSION, MANIFEST_FETCH_TIMEOUT_MS, userAgent } from './api.js';
|
|
3
|
+
import { isRunKey } from './config.js';
|
|
4
|
+
import guideJson from './generated/guide.json' with { type: 'json' };
|
|
5
|
+
import { credentialCachePath, MANIFEST_REFRESH_ENV, refreshDisabled, writePrivateFileAtomic, } from './manifestCache.js';
|
|
6
|
+
export const GUIDE_TRANSPORT = 'cli';
|
|
7
|
+
export const GUIDE_HASH_HEADER = 'x-martini-guide-hash';
|
|
8
|
+
export function loadBakedGuide() {
|
|
9
|
+
return guideJson;
|
|
10
|
+
}
|
|
11
|
+
export function guideCachePath(env, apiUrl, apiKey) {
|
|
12
|
+
return credentialCachePath('guide', env, apiUrl, apiKey);
|
|
13
|
+
}
|
|
14
|
+
export function openGuide(options) {
|
|
15
|
+
const { baked, apiUrl, apiKey, env, warn } = options;
|
|
16
|
+
const now = options.now ?? Date.now;
|
|
17
|
+
const runKey = isRunKey(apiKey);
|
|
18
|
+
const cachePath = apiKey && !runKey ? guideCachePath(env, apiUrl, apiKey) : null;
|
|
19
|
+
let cached = cachePath ? readCache(cachePath, warn) : null;
|
|
20
|
+
return {
|
|
21
|
+
get state() {
|
|
22
|
+
if (cached)
|
|
23
|
+
return { source: 'cache', guide: cached.guide, fetchedAt: cached.fetchedAt, cachePath };
|
|
24
|
+
return { source: 'baked', guide: baked, cachePath };
|
|
25
|
+
},
|
|
26
|
+
async refresh({ force = false } = {}) {
|
|
27
|
+
if (!apiKey || runKey)
|
|
28
|
+
return 'skipped';
|
|
29
|
+
if (refreshDisabled(env)) {
|
|
30
|
+
if (force) {
|
|
31
|
+
warn('GUIDE_REFRESH_DISABLED', `${MANIFEST_REFRESH_ENV}=${env[MANIFEST_REFRESH_ENV]} turns refreshes off, so the guide was not fetched. Unset it to refresh.`);
|
|
32
|
+
}
|
|
33
|
+
return 'skipped';
|
|
34
|
+
}
|
|
35
|
+
const inUse = cached ? `the cached guide from ${cached.fetchedAt}` : "this build's guide";
|
|
36
|
+
let answer;
|
|
37
|
+
try {
|
|
38
|
+
answer = await options.fetchGuide(force || !cached ? undefined : cached.guide.hash);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
warn('GUIDE_REFRESH_FAILED', `Could not refresh the guide from ${apiUrl} (${messageOf(error)}); printing ${inUse}.`);
|
|
42
|
+
return 'failed';
|
|
43
|
+
}
|
|
44
|
+
if (answer.notModified)
|
|
45
|
+
return 'unchanged';
|
|
46
|
+
const guide = usableGuide(answer.body, answer.etag);
|
|
47
|
+
if (!guide) {
|
|
48
|
+
warn('GUIDE_REFRESH_FAILED', `The server answered GET /v1/guide without a usable guide; printing ${inUse}.`);
|
|
49
|
+
return 'failed';
|
|
50
|
+
}
|
|
51
|
+
cached = { guide, fetchedAt: new Date(now()).toISOString() };
|
|
52
|
+
if (cachePath) {
|
|
53
|
+
try {
|
|
54
|
+
writePrivateFileAtomic(cachePath, JSON.stringify({ ...cached.guide, fetchedAt: cached.fetchedAt }));
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
warn('GUIDE_CACHE_WRITE_FAILED', `Could not save the guide to ${cachePath} (${messageOf(error)}); only this command uses it.`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return 'updated';
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export function guideFetcher(options) {
|
|
65
|
+
return async (ifNoneMatch) => {
|
|
66
|
+
const headers = {
|
|
67
|
+
'User-Agent': userAgent(options.env),
|
|
68
|
+
'X-Martini-Client': `martini-cli/${CLI_VERSION}`,
|
|
69
|
+
...(options.apiKey ? { Authorization: `Bearer ${options.apiKey}` } : {}),
|
|
70
|
+
...(ifNoneMatch ? { 'If-None-Match': `"${ifNoneMatch}"` } : {}),
|
|
71
|
+
};
|
|
72
|
+
const response = await options.fetch(`${options.apiUrl}/v1/guide?transport=${GUIDE_TRANSPORT}`, {
|
|
73
|
+
method: 'GET',
|
|
74
|
+
headers,
|
|
75
|
+
signal: AbortSignal.timeout(MANIFEST_FETCH_TIMEOUT_MS),
|
|
76
|
+
});
|
|
77
|
+
if (response.status === 304)
|
|
78
|
+
return { notModified: true };
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
let detail = '';
|
|
81
|
+
try {
|
|
82
|
+
const body = (await response.json());
|
|
83
|
+
if (typeof body.error === 'string')
|
|
84
|
+
detail = `: ${body.error}`;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
}
|
|
88
|
+
throw new Error(`GET /v1/guide answered ${response.status}${detail}`);
|
|
89
|
+
}
|
|
90
|
+
const etag = response.headers
|
|
91
|
+
.get('etag')
|
|
92
|
+
?.replace(/^W\//, '')
|
|
93
|
+
.replace(/^"(.*)"$/, '$1');
|
|
94
|
+
return { notModified: false, body: await response.json(), etag: etag ?? null };
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function isRecord(value) {
|
|
98
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
99
|
+
}
|
|
100
|
+
function isTopic(value) {
|
|
101
|
+
return (isRecord(value) &&
|
|
102
|
+
typeof value.id === 'string' &&
|
|
103
|
+
value.id.length > 0 &&
|
|
104
|
+
typeof value.title === 'string' &&
|
|
105
|
+
Array.isArray(value.lines) &&
|
|
106
|
+
value.lines.every(line => typeof line === 'string'));
|
|
107
|
+
}
|
|
108
|
+
export function usableGuide(body, etag) {
|
|
109
|
+
if (!isRecord(body) || body.version !== 1 || body.transport !== GUIDE_TRANSPORT)
|
|
110
|
+
return null;
|
|
111
|
+
const hash = typeof body.hash === 'string' && body.hash ? body.hash : etag;
|
|
112
|
+
if (!hash || !Array.isArray(body.topics) || body.topics.length === 0 || !body.topics.every(isTopic))
|
|
113
|
+
return null;
|
|
114
|
+
return {
|
|
115
|
+
version: 1,
|
|
116
|
+
transport: GUIDE_TRANSPORT,
|
|
117
|
+
hash,
|
|
118
|
+
generatedAt: typeof body.generatedAt === 'string' ? body.generatedAt : '',
|
|
119
|
+
topics: body.topics.map(({ id, title, lines }) => ({ id, title, lines: [...lines] })),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export function guideHashNotice(options) {
|
|
123
|
+
const { apiKey } = options;
|
|
124
|
+
if (options.quiet)
|
|
125
|
+
return () => undefined;
|
|
126
|
+
const keyed = apiKey && !isRunKey(apiKey) ? apiKey : null;
|
|
127
|
+
const cachePath = keyed ? guideCachePath(options.env, options.apiUrl, keyed) : null;
|
|
128
|
+
const noticePath = keyed ? credentialCachePath('guide-notice', options.env, options.apiUrl, keyed) : null;
|
|
129
|
+
let localHash;
|
|
130
|
+
let said = false;
|
|
131
|
+
return serverHash => {
|
|
132
|
+
if (!cachePath || !noticePath || said || !serverHash)
|
|
133
|
+
return;
|
|
134
|
+
localHash ??= peekGuideHash(cachePath) ?? options.baked.hash;
|
|
135
|
+
if (serverHash === localHash)
|
|
136
|
+
return;
|
|
137
|
+
const notice = readNotice(noticePath);
|
|
138
|
+
if (notice?.serverHash === serverHash && notice.localHash === localHash)
|
|
139
|
+
return;
|
|
140
|
+
said = true;
|
|
141
|
+
options.warn('GUIDE_CHANGED', `The operator guide changed since the copy this CLI has (${localHash.slice(0, 12)} → ${serverHash.slice(0, 12)}). Run martini guide (or martini guide <topic>) before relying on it.`);
|
|
142
|
+
try {
|
|
143
|
+
writePrivateFileAtomic(noticePath, JSON.stringify({ localHash, serverHash }));
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function peekGuideHash(path) {
|
|
150
|
+
try {
|
|
151
|
+
const entry = JSON.parse(readFileSync(path, 'utf8'));
|
|
152
|
+
return usableGuide(entry, null)?.hash ?? null;
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function readNotice(path) {
|
|
159
|
+
try {
|
|
160
|
+
const entry = JSON.parse(readFileSync(path, 'utf8'));
|
|
161
|
+
if (!entry || typeof entry !== 'object')
|
|
162
|
+
return null;
|
|
163
|
+
const { localHash, serverHash } = entry;
|
|
164
|
+
return typeof localHash === 'string' && typeof serverHash === 'string' ? { localHash, serverHash } : null;
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function messageOf(error) {
|
|
171
|
+
return error instanceof Error ? error.message : String(error);
|
|
172
|
+
}
|
|
173
|
+
function readCache(path, warn) {
|
|
174
|
+
let text;
|
|
175
|
+
try {
|
|
176
|
+
text = readFileSync(path, 'utf8');
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
const code = error.code;
|
|
180
|
+
if (code === 'ENOENT' || code === 'ENOTDIR')
|
|
181
|
+
return null;
|
|
182
|
+
warn('GUIDE_CACHE_IGNORED', `Could not read the cached guide ${path} (${messageOf(error)}); printing this build's.`);
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
let entry;
|
|
186
|
+
try {
|
|
187
|
+
entry = JSON.parse(text);
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
entry = null;
|
|
191
|
+
}
|
|
192
|
+
const guide = usableGuide(entry, null);
|
|
193
|
+
if (!guide || !isRecord(entry) || typeof entry.fetchedAt !== 'string') {
|
|
194
|
+
try {
|
|
195
|
+
rmSync(path, { force: true });
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
}
|
|
199
|
+
warn('GUIDE_CACHE_IGNORED', `The cached guide ${path} was not valid and has been removed.`);
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
return { guide, fetchedAt: entry.fetchedAt };
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=guideCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guideCache.js","sourceRoot":"","sources":["../src/guideCache.ts"],"names":[],"mappings":"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"}
|