@nebutra/play-marketplace 0.1.3 → 0.1.4
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/package.json +19 -9
- package/.nebutra/debug/content-store.jsonl +0 -28
- package/.nebutra/debug/event-log.jsonl +0 -14
- package/.nebutra/debug/play-marketplace.jsonl +0 -21
- package/.turbo/turbo-build.log +0 -22
- package/.turbo/turbo-test.log +0 -16
- package/.turbo/turbo-typecheck.log +0 -4
- package/examples/doctor.ts +0 -11
- package/examples/paid-gate.ts +0 -31
- package/examples/quickstart.ts +0 -33
- package/plays/publish_play/SKILL.md +0 -24
- package/src/cli.ts +0 -28
- package/src/index.test.ts +0 -84
- package/src/index.ts +0 -279
- package/tsconfig.json +0 -9
- package/tsup.config.ts +0 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nebutra/play-marketplace",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Local registry, publishing, install, metrics, and billing handoff surface for SKILL.md Plays",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,18 +23,22 @@
|
|
|
23
23
|
"category": "ai",
|
|
24
24
|
"summary": "SKILL.md Play marketplace surface with quality gates and real usage stats"
|
|
25
25
|
},
|
|
26
|
-
"main": "./
|
|
27
|
-
"types": "./
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
28
|
"exports": {
|
|
29
|
-
".":
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
}
|
|
30
34
|
},
|
|
31
35
|
"dependencies": {
|
|
32
|
-
"@nebutra/capability-kit": "0.2.2",
|
|
33
36
|
"@nebutra/errors": "0.1.2",
|
|
34
|
-
"@nebutra/content-store": "0.1.
|
|
35
|
-
"@nebutra/
|
|
36
|
-
"@nebutra/
|
|
37
|
-
"@nebutra/
|
|
37
|
+
"@nebutra/content-store": "0.1.4",
|
|
38
|
+
"@nebutra/generation-context": "0.1.3",
|
|
39
|
+
"@nebutra/event-log": "0.1.4",
|
|
40
|
+
"@nebutra/play-loader": "0.1.3",
|
|
41
|
+
"@nebutra/capability-kit": "0.2.4"
|
|
38
42
|
},
|
|
39
43
|
"devDependencies": {
|
|
40
44
|
"@types/node": "^25.9.1",
|
|
@@ -55,6 +59,12 @@
|
|
|
55
59
|
"publishConfig": {
|
|
56
60
|
"access": "public"
|
|
57
61
|
},
|
|
62
|
+
"files": [
|
|
63
|
+
"dist",
|
|
64
|
+
"README.md",
|
|
65
|
+
"LICENSE",
|
|
66
|
+
"CHANGELOG.md"
|
|
67
|
+
],
|
|
58
68
|
"scripts": {
|
|
59
69
|
"build": "tsup",
|
|
60
70
|
"test": "vitest run",
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{"at":"2026-05-18T15:31:16.860Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
2
|
-
{"at":"2026-05-18T15:31:16.870Z","type":"write","tenantId":"tenant_a","path":"marketplace/plays/cold_email_pro@1.0.0.json"}
|
|
3
|
-
{"at":"2026-05-18T15:31:16.873Z","type":"write","tenantId":"tenant_a","path":"marketplace/installed/cold_email_pro@1.0.0.json"}
|
|
4
|
-
{"at":"2026-05-18T15:31:16.881Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
5
|
-
{"at":"2026-05-18T15:35:58.672Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
6
|
-
{"at":"2026-05-18T15:35:58.681Z","type":"write","tenantId":"tenant_a","path":"marketplace/plays/cold_email_pro@1.0.0.json"}
|
|
7
|
-
{"at":"2026-05-18T15:35:58.688Z","type":"write","tenantId":"tenant_a","path":"marketplace/installed/cold_email_pro@1.0.0.json"}
|
|
8
|
-
{"at":"2026-05-18T15:35:58.699Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
9
|
-
{"at":"2026-05-18T15:37:37.887Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
10
|
-
{"at":"2026-05-18T15:37:37.895Z","type":"write","tenantId":"tenant_a","path":"marketplace/plays/cold_email_pro@1.0.0.json"}
|
|
11
|
-
{"at":"2026-05-18T15:37:37.902Z","type":"write","tenantId":"tenant_a","path":"marketplace/installed/cold_email_pro@1.0.0.json"}
|
|
12
|
-
{"at":"2026-05-18T15:37:37.914Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
13
|
-
{"at":"2026-05-19T05:21:59.714Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
14
|
-
{"at":"2026-05-19T05:21:59.718Z","type":"write","tenantId":"tenant_a","path":"marketplace/plays/cold_email_pro@1.0.0.json"}
|
|
15
|
-
{"at":"2026-05-19T05:21:59.721Z","type":"write","tenantId":"tenant_a","path":"marketplace/installed/cold_email_pro@1.0.0.json"}
|
|
16
|
-
{"at":"2026-05-19T05:21:59.726Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
17
|
-
{"at":"2026-05-19T05:25:40.112Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
18
|
-
{"at":"2026-05-19T05:25:40.119Z","type":"write","tenantId":"tenant_a","path":"marketplace/plays/cold_email_pro@1.0.0.json"}
|
|
19
|
-
{"at":"2026-05-19T05:25:40.127Z","type":"write","tenantId":"tenant_a","path":"marketplace/installed/cold_email_pro@1.0.0.json"}
|
|
20
|
-
{"at":"2026-05-19T05:25:40.138Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
21
|
-
{"at":"2026-05-30T21:07:17.985Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
22
|
-
{"at":"2026-05-30T21:07:17.997Z","type":"write","tenantId":"tenant_a","path":"marketplace/plays/cold_email_pro@1.0.0.json"}
|
|
23
|
-
{"at":"2026-05-30T21:07:18.018Z","type":"write","tenantId":"tenant_a","path":"marketplace/installed/cold_email_pro@1.0.0.json"}
|
|
24
|
-
{"at":"2026-05-30T21:07:18.036Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
25
|
-
{"at":"2026-07-01T01:40:46.767Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
26
|
-
{"at":"2026-07-01T01:40:46.777Z","type":"write","tenantId":"tenant_a","path":"marketplace/plays/cold_email_pro@1.0.0.json"}
|
|
27
|
-
{"at":"2026-07-01T01:40:46.786Z","type":"write","tenantId":"tenant_a","path":"marketplace/installed/cold_email_pro@1.0.0.json"}
|
|
28
|
-
{"at":"2026-07-01T01:40:46.908Z","type":"reindex","tenantId":"tenant_a","files":0}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{"traceId":"play_marketplace_publish_cold_email_pro_1_0_0_mpbd347a","kind":"content_write","affected":["marketplace/plays/cold_email_pro@1.0.0.json"],"parent":null,"snapshot":{"marketplace/plays/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"visibility\": \"public\",\n \"pricing\": {\n \"model\": \"free\"\n },\n \"quality\": {\n \"verified\": false,\n \"successRate\": 0,\n \"avgCostUsd\": 0,\n \"avgDurationMinutes\": 0\n },\n \"requiredSkills\": [\n \"content_store.write\"\n ],\n \"subAgents\": [\n \"writer\"\n ],\n \"signature\": \"play_sig_cold_email_pro_1_0_0_mpbd3472\"\n}\n"},"id":"a19b61a4587fcfcb4831f7d15f7d004e88d381cf0c5f8310651dc578b52de678","tenantId":"tenant_a","at":"2026-05-18T15:31:16.871Z","summary":"content_write touched 1 path(s)","objectHashes":["ed6f6e32a293f966a7a30c9b2525b6c5e313e2f18bee4dd1dc9076da0710ae81"]}
|
|
2
|
-
{"traceId":"play_marketplace_install_cold_email_pro_1_0_0_mpbd347d","kind":"content_write","affected":["marketplace/installed/cold_email_pro@1.0.0.json"],"parent":"a19b61a4587fcfcb4831f7d15f7d004e88d381cf0c5f8310651dc578b52de678","snapshot":{"marketplace/installed/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"status\": \"installed\",\n \"registeredSkill\": \"cold_email_pro\",\n \"installPath\": \"marketplace/installed/cold_email_pro@1.0.0.json\"\n}\n"},"id":"15801ebcd287201db35fb1f12d487dde1431ffb5442be9267f1684d0c1f4a43c","tenantId":"tenant_a","at":"2026-05-18T15:31:16.873Z","summary":"content_write touched 1 path(s)","objectHashes":["89fe9552893b352e9ca705cb34fe56dc9bf47789617cacf7cc0ba4a2db32b2d1"]}
|
|
3
|
-
{"traceId":"play_marketplace_publish_cold_email_pro_1_0_0_mpbd95ne","kind":"content_write","affected":["marketplace/plays/cold_email_pro@1.0.0.json"],"parent":null,"snapshot":{"marketplace/plays/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"visibility\": \"public\",\n \"pricing\": {\n \"model\": \"free\"\n },\n \"quality\": {\n \"verified\": false,\n \"successRate\": 0,\n \"avgCostUsd\": 0,\n \"avgDurationMinutes\": 0\n },\n \"requiredSkills\": [\n \"content_store.write\"\n ],\n \"subAgents\": [\n \"writer\"\n ],\n \"signature\": \"play_sig_cold_email_pro_1_0_0_mpbd95n9\"\n}\n"},"id":"a2dd2ed071ab529bd5032cfa4f2cd98415c048d0f2c70a6e533422fd96710d16","tenantId":"tenant_a","at":"2026-05-18T15:35:58.683Z","summary":"content_write touched 1 path(s)","objectHashes":["c1698cb31fab502a69b4355867ff5aa6bb9b197f83e8fe691df10ef9d8b0caa0"]}
|
|
4
|
-
{"traceId":"play_marketplace_install_cold_email_pro_1_0_0_mpbd95nk","kind":"content_write","affected":["marketplace/installed/cold_email_pro@1.0.0.json"],"parent":"a2dd2ed071ab529bd5032cfa4f2cd98415c048d0f2c70a6e533422fd96710d16","snapshot":{"marketplace/installed/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"status\": \"installed\",\n \"registeredSkill\": \"cold_email_pro\",\n \"installPath\": \"marketplace/installed/cold_email_pro@1.0.0.json\"\n}\n"},"id":"6b6ded8d02de1263e66207ce4da3e9aa468f20c2e9a67072a4254ce3386099ba","tenantId":"tenant_a","at":"2026-05-18T15:35:58.689Z","summary":"content_write touched 1 path(s)","objectHashes":["89fe9552893b352e9ca705cb34fe56dc9bf47789617cacf7cc0ba4a2db32b2d1"]}
|
|
5
|
-
{"traceId":"play_marketplace_publish_cold_email_pro_1_0_0_mpbdba7c","kind":"content_write","affected":["marketplace/plays/cold_email_pro@1.0.0.json"],"parent":null,"snapshot":{"marketplace/plays/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"visibility\": \"public\",\n \"pricing\": {\n \"model\": \"free\"\n },\n \"quality\": {\n \"verified\": false,\n \"successRate\": 0,\n \"avgCostUsd\": 0,\n \"avgDurationMinutes\": 0\n },\n \"requiredSkills\": [\n \"content_store.write\"\n ],\n \"subAgents\": [\n \"writer\"\n ],\n \"signature\": \"play_sig_cold_email_pro_1_0_0_mpbdba78\"\n}\n"},"id":"10a8020246cf8c43bc9d838e57f90be265d902abc8e3be84c2df0b9d1dffd597","tenantId":"tenant_a","at":"2026-05-18T15:37:37.898Z","summary":"content_write touched 1 path(s)","objectHashes":["bc80db8640ecf5b9389e1eee6c185dc0f424910debcce88cc5746c201c581bdd"]}
|
|
6
|
-
{"traceId":"play_marketplace_install_cold_email_pro_1_0_0_mpbdba7i","kind":"content_write","affected":["marketplace/installed/cold_email_pro@1.0.0.json"],"parent":"10a8020246cf8c43bc9d838e57f90be265d902abc8e3be84c2df0b9d1dffd597","snapshot":{"marketplace/installed/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"status\": \"installed\",\n \"registeredSkill\": \"cold_email_pro\",\n \"installPath\": \"marketplace/installed/cold_email_pro@1.0.0.json\"\n}\n"},"id":"707d3a4ca7d4e2018b81a09914ab3b308f3a10c4e5e7991e3791b7fe7cbcc814","tenantId":"tenant_a","at":"2026-05-18T15:37:37.903Z","summary":"content_write touched 1 path(s)","objectHashes":["89fe9552893b352e9ca705cb34fe56dc9bf47789617cacf7cc0ba4a2db32b2d1"]}
|
|
7
|
-
{"traceId":"play_marketplace_publish_cold_email_pro_1_0_0_mpc6rf6v","kind":"content_write","affected":["marketplace/plays/cold_email_pro@1.0.0.json"],"parent":null,"snapshot":{"marketplace/plays/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"visibility\": \"public\",\n \"pricing\": {\n \"model\": \"free\"\n },\n \"quality\": {\n \"verified\": false,\n \"successRate\": 0,\n \"avgCostUsd\": 0,\n \"avgDurationMinutes\": 0\n },\n \"requiredSkills\": [\n \"content_store.write\"\n ],\n \"subAgents\": [\n \"writer\"\n ],\n \"signature\": \"play_sig_cold_email_pro_1_0_0_mpc6rf6t\"\n}\n"},"id":"db9abb324d8ff6017b66d688204fbaa2bba63b8bd5b2ab27bbc4a440c086c106","tenantId":"tenant_a","at":"2026-05-19T05:21:59.719Z","summary":"content_write touched 1 path(s)","objectHashes":["4aabefb73f00ddf3d08c558cb313ddcf6303f83c993facac4c03ece51d7768af"]}
|
|
8
|
-
{"traceId":"play_marketplace_install_cold_email_pro_1_0_0_mpc6rf6x","kind":"content_write","affected":["marketplace/installed/cold_email_pro@1.0.0.json"],"parent":"db9abb324d8ff6017b66d688204fbaa2bba63b8bd5b2ab27bbc4a440c086c106","snapshot":{"marketplace/installed/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"status\": \"installed\",\n \"registeredSkill\": \"cold_email_pro\",\n \"installPath\": \"marketplace/installed/cold_email_pro@1.0.0.json\"\n}\n"},"id":"3e5c4ff4ec2b4fe4b3136bec1e09b54a1e50f958ab065bf3482d52445e36b619","tenantId":"tenant_a","at":"2026-05-19T05:21:59.722Z","summary":"content_write touched 1 path(s)","objectHashes":["89fe9552893b352e9ca705cb34fe56dc9bf47789617cacf7cc0ba4a2db32b2d1"]}
|
|
9
|
-
{"traceId":"play_marketplace_publish_cold_email_pro_1_0_0_mpc6w594","kind":"content_write","affected":["marketplace/plays/cold_email_pro@1.0.0.json"],"parent":null,"snapshot":{"marketplace/plays/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"visibility\": \"public\",\n \"pricing\": {\n \"model\": \"free\"\n },\n \"quality\": {\n \"verified\": false,\n \"successRate\": 0,\n \"avgCostUsd\": 0,\n \"avgDurationMinutes\": 0\n },\n \"requiredSkills\": [\n \"content_store.write\"\n ],\n \"subAgents\": [\n \"writer\"\n ],\n \"signature\": \"play_sig_cold_email_pro_1_0_0_mpc6w591\"\n}\n"},"id":"ad797aef11b5a3240227dc499af89f9419d548b7881b3f824e6040ec099706b5","tenantId":"tenant_a","at":"2026-05-19T05:25:40.122Z","summary":"content_write touched 1 path(s)","objectHashes":["aae0ae0ba4bfc6957460d6b6c7ed661c0fc4539695714eef60a40f6f1d2a5f0a"]}
|
|
10
|
-
{"traceId":"play_marketplace_install_cold_email_pro_1_0_0_mpc6w59b","kind":"content_write","affected":["marketplace/installed/cold_email_pro@1.0.0.json"],"parent":"ad797aef11b5a3240227dc499af89f9419d548b7881b3f824e6040ec099706b5","snapshot":{"marketplace/installed/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"status\": \"installed\",\n \"registeredSkill\": \"cold_email_pro\",\n \"installPath\": \"marketplace/installed/cold_email_pro@1.0.0.json\"\n}\n"},"id":"4a66b8cc25736f92f267b0148d9a2a8ea661cab7876391f8940b48df5f779924","tenantId":"tenant_a","at":"2026-05-19T05:25:40.128Z","summary":"content_write touched 1 path(s)","objectHashes":["89fe9552893b352e9ca705cb34fe56dc9bf47789617cacf7cc0ba4a2db32b2d1"]}
|
|
11
|
-
{"at":"2026-05-30T21:07:18.001Z","traceId":"play_marketplace_publish_cold_email_pro_1_0_0_mpsudgml","kind":"content_write","affected":["marketplace/plays/cold_email_pro@1.0.0.json"],"parent":null,"snapshot":{"marketplace/plays/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"visibility\": \"public\",\n \"pricing\": {\n \"model\": \"free\"\n },\n \"quality\": {\n \"verified\": false,\n \"successRate\": 0,\n \"avgCostUsd\": 0,\n \"avgDurationMinutes\": 0\n },\n \"requiredSkills\": [\n \"content_store.write\"\n ],\n \"subAgents\": [\n \"writer\"\n ],\n \"signature\": \"play_sig_cold_email_pro_1_0_0_mpsudgmg\"\n}\n"},"id":"68f6b9737aaa8d50589d72fe08415ed6acf85c684a8f471d3e274a80736f02f2","tenantId":"tenant_a","summary":"content_write touched 1 path(s)","objectHashes":["91ee10f3e1f4651fb91b4730985f08006e9baf5832edc160ca671e9e04c951ee"]}
|
|
12
|
-
{"at":"2026-05-30T21:07:18.020Z","traceId":"play_marketplace_install_cold_email_pro_1_0_0_mpsudgn7","kind":"content_write","affected":["marketplace/installed/cold_email_pro@1.0.0.json"],"parent":"68f6b9737aaa8d50589d72fe08415ed6acf85c684a8f471d3e274a80736f02f2","snapshot":{"marketplace/installed/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"status\": \"installed\",\n \"registeredSkill\": \"cold_email_pro\",\n \"installPath\": \"marketplace/installed/cold_email_pro@1.0.0.json\"\n}\n"},"id":"2ed75f6d27cc650d2d1a04a0cb549261ebb28572b5cf223b16e7c5af3c871de9","tenantId":"tenant_a","summary":"content_write touched 1 path(s)","objectHashes":["89fe9552893b352e9ca705cb34fe56dc9bf47789617cacf7cc0ba4a2db32b2d1"]}
|
|
13
|
-
{"at":"2026-07-01T01:40:46.781Z","traceId":"play_marketplace_publish_cold_email_pro_1_0_0_mr1eske2","kind":"content_write","affected":["marketplace/plays/cold_email_pro@1.0.0.json"],"parent":null,"snapshot":{"marketplace/plays/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"visibility\": \"public\",\n \"pricing\": {\n \"model\": \"free\"\n },\n \"quality\": {\n \"verified\": false,\n \"successRate\": 0,\n \"avgCostUsd\": 0,\n \"avgDurationMinutes\": 0\n },\n \"requiredSkills\": [\n \"content_store.write\"\n ],\n \"subAgents\": [\n \"writer\"\n ],\n \"signature\": \"play_sig_cold_email_pro_1_0_0_mr1eskdv\"\n}\n"},"id":"8358de98a19ada40f93f016ec839737485a8e9d2a4f5e2abe9c61aa1db546e9e","tenantId":"tenant_a","summary":"content_write touched 1 path(s)","objectHashes":["1af626eae202d688c1d5762f25f4904594c935372000676b172c8afdd38bb4e7"]}
|
|
14
|
-
{"at":"2026-07-01T01:40:46.788Z","traceId":"play_marketplace_install_cold_email_pro_1_0_0_mr1eskeb","kind":"content_write","affected":["marketplace/installed/cold_email_pro@1.0.0.json"],"parent":"8358de98a19ada40f93f016ec839737485a8e9d2a4f5e2abe9c61aa1db546e9e","snapshot":{"marketplace/installed/cold_email_pro@1.0.0.json":"{\n \"playId\": \"cold_email_pro\",\n \"version\": \"1.0.0\",\n \"status\": \"installed\",\n \"registeredSkill\": \"cold_email_pro\",\n \"installPath\": \"marketplace/installed/cold_email_pro@1.0.0.json\"\n}\n"},"id":"0a5e91dbe2bb7a0f37b5f6632928daae8dbea653557e43e43fe0879488e22218","tenantId":"tenant_a","summary":"content_write touched 1 path(s)","objectHashes":["89fe9552893b352e9ca705cb34fe56dc9bf47789617cacf7cc0ba4a2db32b2d1"]}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{"at":"2026-05-18T15:31:16.872Z","type":"publish","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
2
|
-
{"at":"2026-05-18T15:31:16.872Z","type":"search","tenantId":"tenant_a","query":"email","hits":1}
|
|
3
|
-
{"at":"2026-05-18T15:31:16.874Z","type":"install","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
4
|
-
{"at":"2026-05-18T15:35:58.684Z","type":"publish","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
5
|
-
{"at":"2026-05-18T15:35:58.685Z","type":"search","tenantId":"tenant_a","query":"email","hits":1}
|
|
6
|
-
{"at":"2026-05-18T15:35:58.689Z","type":"install","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
7
|
-
{"at":"2026-05-18T15:37:37.899Z","type":"publish","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
8
|
-
{"at":"2026-05-18T15:37:37.900Z","type":"search","tenantId":"tenant_a","query":"email","hits":1}
|
|
9
|
-
{"at":"2026-05-18T15:37:37.904Z","type":"install","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
10
|
-
{"at":"2026-05-19T05:21:59.720Z","type":"publish","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
11
|
-
{"at":"2026-05-19T05:21:59.720Z","type":"search","tenantId":"tenant_a","query":"email","hits":1}
|
|
12
|
-
{"at":"2026-05-19T05:21:59.722Z","type":"install","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
13
|
-
{"at":"2026-05-19T05:25:40.123Z","type":"publish","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
14
|
-
{"at":"2026-05-19T05:25:40.124Z","type":"search","tenantId":"tenant_a","query":"email","hits":1}
|
|
15
|
-
{"at":"2026-05-19T05:25:40.129Z","type":"install","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
16
|
-
{"at":"2026-05-30T21:07:18.003Z","type":"publish","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
17
|
-
{"at":"2026-05-30T21:07:18.004Z","type":"search","tenantId":"tenant_a","query":"email","hits":1}
|
|
18
|
-
{"at":"2026-05-30T21:07:18.021Z","type":"install","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
19
|
-
{"at":"2026-07-01T01:40:46.783Z","type":"publish","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
|
20
|
-
{"at":"2026-07-01T01:40:46.784Z","type":"search","tenantId":"tenant_a","query":"email","hits":1}
|
|
21
|
-
{"at":"2026-07-01T01:40:46.789Z","type":"install","tenantId":"tenant_a","playId":"cold_email_pro","version":"1.0.0"}
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @nebutra/play-marketplace@0.1.3 build /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/play-marketplace
|
|
3
|
-
> tsup
|
|
4
|
-
|
|
5
|
-
CLI Building entry: src/cli.ts, src/index.ts
|
|
6
|
-
CLI Using tsconfig: tsconfig.json
|
|
7
|
-
CLI tsup v8.5.1
|
|
8
|
-
CLI Using tsup config: /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/play-marketplace/tsup.config.ts
|
|
9
|
-
CLI Target: es2022
|
|
10
|
-
CLI Cleaning output folder
|
|
11
|
-
ESM Build start
|
|
12
|
-
ESM dist/cli.js 1.06 KB
|
|
13
|
-
ESM dist/index.js 222.00 B
|
|
14
|
-
ESM dist/chunk-BRGFNH5O.js 6.30 KB
|
|
15
|
-
ESM dist/cli.js.map 1.87 KB
|
|
16
|
-
ESM dist/chunk-BRGFNH5O.js.map 13.50 KB
|
|
17
|
-
ESM dist/index.js.map 71.00 B
|
|
18
|
-
ESM ⚡️ Build success in 25ms
|
|
19
|
-
DTS Build start
|
|
20
|
-
DTS ⚡️ Build success in 1669ms
|
|
21
|
-
DTS dist/cli.d.ts 13.00 B
|
|
22
|
-
DTS dist/index.d.ts 3.07 KB
|
package/.turbo/turbo-test.log
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @nebutra/play-marketplace@0.1.2 test /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/play-marketplace
|
|
3
|
-
> vitest run
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
RUN v4.1.4 /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/play-marketplace
|
|
7
|
-
|
|
8
|
-
(node:57827) ExperimentalWarning: SQLite is an experimental feature and might change at any time
|
|
9
|
-
(Use `node --trace-warnings ...` to show where the warning was created)
|
|
10
|
-
✓ src/index.test.ts (3 tests) 205ms
|
|
11
|
-
|
|
12
|
-
Test Files 1 passed (1)
|
|
13
|
-
Tests 3 passed (3)
|
|
14
|
-
Start at 09:40:45
|
|
15
|
-
Duration 1.27s (transform 270ms, setup 0ms, import 472ms, tests 205ms, environment 0ms)
|
|
16
|
-
|
package/examples/doctor.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { PlayMarketplace } from "../src/index";
|
|
2
|
-
|
|
3
|
-
const marketplace = await PlayMarketplace.open(".nebutra/play-marketplace-example", {
|
|
4
|
-
tenantId: "local",
|
|
5
|
-
});
|
|
6
|
-
|
|
7
|
-
try {
|
|
8
|
-
process.stdout.write(`${JSON.stringify(await marketplace.doctor(), null, 2)}\n`);
|
|
9
|
-
} finally {
|
|
10
|
-
await marketplace.close();
|
|
11
|
-
}
|
package/examples/paid-gate.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { PlayMarketplace } from "../src/index";
|
|
2
|
-
|
|
3
|
-
const skillMarkdown = `---
|
|
4
|
-
name: paid_demo
|
|
5
|
-
kind: play
|
|
6
|
-
version: 1.0.0
|
|
7
|
-
description: Paid demo play
|
|
8
|
-
required_skills: []
|
|
9
|
-
sub_agents: []
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## What this play does
|
|
13
|
-
|
|
14
|
-
Demonstrates the paid publish gate.`;
|
|
15
|
-
|
|
16
|
-
const marketplace = await PlayMarketplace.open(".nebutra/play-marketplace-paid-gate-example", {
|
|
17
|
-
tenantId: "local",
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
await marketplace.publish({
|
|
22
|
-
skillMarkdown,
|
|
23
|
-
visibility: "public",
|
|
24
|
-
pricing: { model: "subscription", amountUsd: 29, interval: "month" },
|
|
25
|
-
invitedAuthor: false,
|
|
26
|
-
});
|
|
27
|
-
} catch (error) {
|
|
28
|
-
process.stdout.write(`${JSON.stringify(error, null, 2)}\n`);
|
|
29
|
-
} finally {
|
|
30
|
-
await marketplace.close();
|
|
31
|
-
}
|
package/examples/quickstart.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { PlayMarketplace } from "../src/index";
|
|
2
|
-
|
|
3
|
-
const skillMarkdown = `---
|
|
4
|
-
name: cold_email_pro
|
|
5
|
-
kind: play
|
|
6
|
-
version: 1.0.0
|
|
7
|
-
description: Cold email draft play
|
|
8
|
-
required_skills:
|
|
9
|
-
- content_store.write
|
|
10
|
-
sub_agents: []
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## What this play does
|
|
14
|
-
|
|
15
|
-
Drafts a reviewed campaign.`;
|
|
16
|
-
|
|
17
|
-
const marketplace = await PlayMarketplace.open(".nebutra/play-marketplace-example", {
|
|
18
|
-
tenantId: "local",
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
const play = await marketplace.publish({
|
|
23
|
-
skillMarkdown,
|
|
24
|
-
visibility: "public",
|
|
25
|
-
pricing: { model: "free" },
|
|
26
|
-
invitedAuthor: true,
|
|
27
|
-
});
|
|
28
|
-
process.stdout.write(
|
|
29
|
-
`${JSON.stringify(await marketplace.install(play.playId, play.version), null, 2)}\n`,
|
|
30
|
-
);
|
|
31
|
-
} finally {
|
|
32
|
-
await marketplace.close();
|
|
33
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: publish_play
|
|
3
|
-
kind: play
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
description: Validate and publish a SKILL.md Play into the controlled marketplace registry
|
|
6
|
-
required_skills:
|
|
7
|
-
- play_loader.parse
|
|
8
|
-
- content_store.write
|
|
9
|
-
- event_log.commit
|
|
10
|
-
sub_agents:
|
|
11
|
-
- role: registry_reviewer
|
|
12
|
-
allowed_skills: [play_loader.parse, content_store.write]
|
|
13
|
-
depends_on_plays: []
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## What this play does
|
|
17
|
-
|
|
18
|
-
Validates a Play declaration, writes a signed registry artifact, and prepares install metadata.
|
|
19
|
-
|
|
20
|
-
## Boundaries
|
|
21
|
-
|
|
22
|
-
- SKILL.md parsing belongs to play-loader.
|
|
23
|
-
- Paid publishing stays gated during controlled launch.
|
|
24
|
-
- Billing and remote registry transport are explicit handoffs.
|
package/src/cli.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { PlayMarketplace, readPlayMarketplaceDebug } from "./index";
|
|
2
|
-
|
|
3
|
-
const command = process.argv[2] ?? "doctor";
|
|
4
|
-
const root = process.env.PLAY_MARKETPLACE_ROOT ?? ".nebutra/play-marketplace";
|
|
5
|
-
const tenantId = process.env.NEBUTRA_TENANT_ID ?? "local";
|
|
6
|
-
|
|
7
|
-
if (command === "doctor") {
|
|
8
|
-
const marketplace = await PlayMarketplace.open(root, { tenantId });
|
|
9
|
-
try {
|
|
10
|
-
process.stdout.write(`${JSON.stringify(await marketplace.doctor(), null, 2)}\n`);
|
|
11
|
-
} finally {
|
|
12
|
-
await marketplace.close();
|
|
13
|
-
}
|
|
14
|
-
} else if (command === "quickstart") {
|
|
15
|
-
const marketplace = await PlayMarketplace.open(root, { tenantId });
|
|
16
|
-
try {
|
|
17
|
-
process.stdout.write(`${JSON.stringify(await marketplace.doctor(), null, 2)}\n`);
|
|
18
|
-
} finally {
|
|
19
|
-
await marketplace.close();
|
|
20
|
-
}
|
|
21
|
-
} else if (command === "debug") {
|
|
22
|
-
process.stdout.write(
|
|
23
|
-
`${JSON.stringify({ capability: "play-marketplace", entries: await readPlayMarketplaceDebug() }, null, 2)}\n`,
|
|
24
|
-
);
|
|
25
|
-
} else {
|
|
26
|
-
process.stderr.write(`Unknown play-marketplace command: ${command}\n`);
|
|
27
|
-
process.exitCode = 1;
|
|
28
|
-
}
|
package/src/index.test.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
-
import { PlayMarketplace, readPlayMarketplaceDebug, validatePlayPackage } from "./index";
|
|
6
|
-
|
|
7
|
-
let root: string | undefined;
|
|
8
|
-
let marketplace: PlayMarketplace | undefined;
|
|
9
|
-
|
|
10
|
-
const skillMarkdown = [
|
|
11
|
-
"---",
|
|
12
|
-
"name: cold_email_pro",
|
|
13
|
-
"kind: play",
|
|
14
|
-
"version: 1.0.0",
|
|
15
|
-
"description: Cold email campaign play",
|
|
16
|
-
"required_skills:",
|
|
17
|
-
" - content_store.write",
|
|
18
|
-
"sub_agents:",
|
|
19
|
-
" - role: writer",
|
|
20
|
-
" allowed_skills: [content_store.write]",
|
|
21
|
-
"---",
|
|
22
|
-
"",
|
|
23
|
-
"## What this play does",
|
|
24
|
-
"",
|
|
25
|
-
"Builds a reviewed campaign draft.",
|
|
26
|
-
].join("\n");
|
|
27
|
-
|
|
28
|
-
afterEach(async () => {
|
|
29
|
-
if (marketplace) await marketplace.close();
|
|
30
|
-
if (root) await rm(root, { recursive: true, force: true });
|
|
31
|
-
root = undefined;
|
|
32
|
-
marketplace = undefined;
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
async function open(): Promise<PlayMarketplace> {
|
|
36
|
-
root = await mkdtemp(join(tmpdir(), "play-marketplace-"));
|
|
37
|
-
marketplace = await PlayMarketplace.open(root, { tenantId: "tenant_a" });
|
|
38
|
-
return marketplace;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
describe("play-marketplace", () => {
|
|
42
|
-
it("validates Plays through play-loader instead of local YAML parsing", () => {
|
|
43
|
-
const report = validatePlayPackage({ skillMarkdown });
|
|
44
|
-
|
|
45
|
-
expect(report.ok).toBe(true);
|
|
46
|
-
expect(report.playName).toBe("cold_email_pro");
|
|
47
|
-
expect(report.requiredSkills).toContain("content_store.write");
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("publishes, searches, and installs signed Play registry records", async () => {
|
|
51
|
-
const runtime = await open();
|
|
52
|
-
const published = await runtime.publish({
|
|
53
|
-
skillMarkdown,
|
|
54
|
-
visibility: "public",
|
|
55
|
-
pricing: { model: "free" },
|
|
56
|
-
invitedAuthor: true,
|
|
57
|
-
});
|
|
58
|
-
const results = await runtime.search({ query: "email", sort: "success_rate" });
|
|
59
|
-
const install = await runtime.install(published.playId, "1.0.0");
|
|
60
|
-
|
|
61
|
-
expect(published.registryPath).toBe(`marketplace/plays/${published.playId}@1.0.0.json`);
|
|
62
|
-
expect(published.quality.verified).toBe(false);
|
|
63
|
-
expect(results.items.map((item) => item.playId)).toContain(published.playId);
|
|
64
|
-
expect(install.status).toBe("installed");
|
|
65
|
-
expect(install.registeredSkill).toBe("cold_email_pro");
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it("blocks uninvited paid publishing during controlled marketplace launch", async () => {
|
|
69
|
-
const runtime = await open();
|
|
70
|
-
|
|
71
|
-
await expect(
|
|
72
|
-
runtime.publish({
|
|
73
|
-
skillMarkdown,
|
|
74
|
-
visibility: "public",
|
|
75
|
-
pricing: { model: "subscription", amountUsd: 29, interval: "month" },
|
|
76
|
-
invitedAuthor: false,
|
|
77
|
-
}),
|
|
78
|
-
).rejects.toMatchObject({
|
|
79
|
-
capability: "play-marketplace",
|
|
80
|
-
suggestion: expect.stringContaining("invited"),
|
|
81
|
-
});
|
|
82
|
-
await expect(readPlayMarketplaceDebug(root)).resolves.toEqual(expect.any(Array));
|
|
83
|
-
});
|
|
84
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import { mkdir } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { requireCapabilityTenant } from "@nebutra/capability-kit";
|
|
4
|
-
import { appendCapabilityDebug, readCapabilityDebug } from "@nebutra/capability-kit/debug";
|
|
5
|
-
import { ContentStore } from "@nebutra/content-store";
|
|
6
|
-
import { CapabilityError } from "@nebutra/errors";
|
|
7
|
-
import { EventLog } from "@nebutra/event-log";
|
|
8
|
-
import { assetId } from "@nebutra/generation-context";
|
|
9
|
-
import { parsePlayMarkdown } from "@nebutra/play-loader";
|
|
10
|
-
|
|
11
|
-
export type Visibility = "private" | "public";
|
|
12
|
-
export type Pricing =
|
|
13
|
-
| { readonly model: "free" }
|
|
14
|
-
| { readonly model: "one_time"; readonly amountUsd: number }
|
|
15
|
-
| {
|
|
16
|
-
readonly model: "subscription";
|
|
17
|
-
readonly amountUsd: number;
|
|
18
|
-
readonly interval: "month" | "year";
|
|
19
|
-
}
|
|
20
|
-
| { readonly model: "per_run"; readonly amountUsd: number };
|
|
21
|
-
|
|
22
|
-
export interface ValidatePlayPackageRequest {
|
|
23
|
-
readonly skillMarkdown: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface PlayValidationReport {
|
|
27
|
-
readonly ok: boolean;
|
|
28
|
-
readonly playName: string;
|
|
29
|
-
readonly version: string;
|
|
30
|
-
readonly requiredSkills: readonly string[];
|
|
31
|
-
readonly subAgents: readonly string[];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface PublishPlayRequest {
|
|
35
|
-
readonly skillMarkdown: string;
|
|
36
|
-
readonly visibility: Visibility;
|
|
37
|
-
readonly pricing: Pricing;
|
|
38
|
-
readonly invitedAuthor: boolean;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface PublishedPlay {
|
|
42
|
-
readonly playId: string;
|
|
43
|
-
readonly version: string;
|
|
44
|
-
readonly registryPath: string;
|
|
45
|
-
readonly visibility: Visibility;
|
|
46
|
-
readonly pricing: Pricing;
|
|
47
|
-
readonly quality: {
|
|
48
|
-
readonly verified: boolean;
|
|
49
|
-
readonly successRate: number;
|
|
50
|
-
readonly avgCostUsd: number;
|
|
51
|
-
readonly avgDurationMinutes: number;
|
|
52
|
-
};
|
|
53
|
-
readonly eventId: string;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface MarketplaceSearchRequest {
|
|
57
|
-
readonly query: string;
|
|
58
|
-
readonly sort: "success_rate" | "new";
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface MarketplaceSearchResult {
|
|
62
|
-
readonly items: readonly PublishedPlay[];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface InstalledPlay {
|
|
66
|
-
readonly playId: string;
|
|
67
|
-
readonly version: string;
|
|
68
|
-
readonly status: "installed";
|
|
69
|
-
readonly registeredSkill: string;
|
|
70
|
-
readonly installPath: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface PlayMarketplaceDoctorReport {
|
|
74
|
-
readonly capability: "play-marketplace";
|
|
75
|
-
readonly ok: boolean;
|
|
76
|
-
readonly checkedAt: string;
|
|
77
|
-
readonly features: readonly string[];
|
|
78
|
-
readonly suggestion?: string;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export interface PlayMarketplaceOptions {
|
|
82
|
-
readonly tenantId?: string;
|
|
83
|
-
readonly debugRoot?: string;
|
|
84
|
-
readonly contentStore?: ContentStore;
|
|
85
|
-
readonly eventLog?: EventLog;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function isPaid(pricing: Pricing): boolean {
|
|
89
|
-
return pricing.model !== "free";
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export function validatePlayPackage(request: ValidatePlayPackageRequest): PlayValidationReport {
|
|
93
|
-
const play = parsePlayMarkdown(request.skillMarkdown);
|
|
94
|
-
return {
|
|
95
|
-
ok: true,
|
|
96
|
-
playName: play.meta.name,
|
|
97
|
-
version: play.meta.version,
|
|
98
|
-
requiredSkills: play.requiredSkills,
|
|
99
|
-
subAgents: play.subAgents.map((agent) => agent.role),
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export class PlayMarketplace {
|
|
104
|
-
readonly #tenantId: string;
|
|
105
|
-
readonly #debugRoot: string;
|
|
106
|
-
readonly #contentStore: ContentStore;
|
|
107
|
-
readonly #eventLog: EventLog;
|
|
108
|
-
readonly #plays = new Map<string, PublishedPlay & { readonly skillMarkdown: string }>();
|
|
109
|
-
|
|
110
|
-
private constructor(
|
|
111
|
-
options: Required<Pick<PlayMarketplaceOptions, "tenantId" | "contentStore" | "eventLog">> &
|
|
112
|
-
Pick<PlayMarketplaceOptions, "debugRoot">,
|
|
113
|
-
) {
|
|
114
|
-
this.#tenantId = requireCapabilityTenant({
|
|
115
|
-
explicit: options.tenantId,
|
|
116
|
-
onMissing: () =>
|
|
117
|
-
new CapabilityError("play-marketplace", "Play Marketplace requires tenant context", {
|
|
118
|
-
suggestion: "Pass tenantId so registry and install artifacts stay tenant-scoped.",
|
|
119
|
-
statusCode: 400,
|
|
120
|
-
}),
|
|
121
|
-
});
|
|
122
|
-
this.#debugRoot = options.debugRoot ?? process.cwd();
|
|
123
|
-
this.#contentStore = options.contentStore;
|
|
124
|
-
this.#eventLog = options.eventLog;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
static async open(
|
|
128
|
-
root = ".nebutra/play-marketplace",
|
|
129
|
-
options: Omit<PlayMarketplaceOptions, "contentStore" | "eventLog"> = {},
|
|
130
|
-
): Promise<PlayMarketplace> {
|
|
131
|
-
const tenantId = options.tenantId ?? "local";
|
|
132
|
-
await mkdir(root, { recursive: true });
|
|
133
|
-
const contentStore = await ContentStore.open(join(root, "content"), { tenantId });
|
|
134
|
-
const eventLog = await EventLog.open(join(root, "event-log"), { tenantId });
|
|
135
|
-
return new PlayMarketplace({ ...options, tenantId, contentStore, eventLog });
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
async publish(request: PublishPlayRequest): Promise<PublishedPlay> {
|
|
139
|
-
if (isPaid(request.pricing) && !request.invitedAuthor) {
|
|
140
|
-
throw new CapabilityError(
|
|
141
|
-
"play-marketplace",
|
|
142
|
-
"Paid Play publishing is limited during controlled launch",
|
|
143
|
-
{
|
|
144
|
-
suggestion:
|
|
145
|
-
"Use an invited author account or publish a free Play until paid publishing opens.",
|
|
146
|
-
statusCode: 403,
|
|
147
|
-
},
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const validation = validatePlayPackage({ skillMarkdown: request.skillMarkdown });
|
|
152
|
-
const playId = validation.playName;
|
|
153
|
-
const registryPath = `marketplace/plays/${playId}@${validation.version}.json`;
|
|
154
|
-
const record = {
|
|
155
|
-
playId,
|
|
156
|
-
version: validation.version,
|
|
157
|
-
visibility: request.visibility,
|
|
158
|
-
pricing: request.pricing,
|
|
159
|
-
quality: {
|
|
160
|
-
verified: false,
|
|
161
|
-
successRate: 0,
|
|
162
|
-
avgCostUsd: 0,
|
|
163
|
-
avgDurationMinutes: 0,
|
|
164
|
-
},
|
|
165
|
-
requiredSkills: validation.requiredSkills,
|
|
166
|
-
subAgents: validation.subAgents,
|
|
167
|
-
signature: assetId("play_sig", `${playId}_${validation.version}`),
|
|
168
|
-
};
|
|
169
|
-
const snapshot = `${JSON.stringify(record, null, 2)}\n`;
|
|
170
|
-
await this.#contentStore.write(registryPath, snapshot);
|
|
171
|
-
const eventId = await this.#eventLog.commit({
|
|
172
|
-
traceId: assetId("play_marketplace_publish", `${playId}_${validation.version}`),
|
|
173
|
-
kind: "content_write",
|
|
174
|
-
affected: [registryPath],
|
|
175
|
-
parent: null,
|
|
176
|
-
snapshot: { [registryPath]: snapshot },
|
|
177
|
-
});
|
|
178
|
-
const published: PublishedPlay & { readonly skillMarkdown: string } = {
|
|
179
|
-
playId,
|
|
180
|
-
version: validation.version,
|
|
181
|
-
registryPath,
|
|
182
|
-
visibility: request.visibility,
|
|
183
|
-
pricing: request.pricing,
|
|
184
|
-
quality: record.quality,
|
|
185
|
-
eventId,
|
|
186
|
-
skillMarkdown: request.skillMarkdown,
|
|
187
|
-
};
|
|
188
|
-
this.#plays.set(`${playId}@${validation.version}`, published);
|
|
189
|
-
await this.#debug({
|
|
190
|
-
type: "publish",
|
|
191
|
-
tenantId: this.#tenantId,
|
|
192
|
-
playId,
|
|
193
|
-
version: validation.version,
|
|
194
|
-
});
|
|
195
|
-
return published;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
async search(request: MarketplaceSearchRequest): Promise<MarketplaceSearchResult> {
|
|
199
|
-
const probe = request.query.toLowerCase();
|
|
200
|
-
const items = [...this.#plays.values()]
|
|
201
|
-
.filter(
|
|
202
|
-
(play) =>
|
|
203
|
-
play.playId.toLowerCase().includes(probe) ||
|
|
204
|
-
play.skillMarkdown.toLowerCase().includes(probe),
|
|
205
|
-
)
|
|
206
|
-
.sort((left, right) =>
|
|
207
|
-
request.sort === "success_rate"
|
|
208
|
-
? right.quality.successRate - left.quality.successRate ||
|
|
209
|
-
left.playId.localeCompare(right.playId)
|
|
210
|
-
: right.eventId.localeCompare(left.eventId),
|
|
211
|
-
);
|
|
212
|
-
await this.#debug({
|
|
213
|
-
type: "search",
|
|
214
|
-
tenantId: this.#tenantId,
|
|
215
|
-
query: request.query,
|
|
216
|
-
hits: items.length,
|
|
217
|
-
});
|
|
218
|
-
return { items };
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
async install(playId: string, version: string): Promise<InstalledPlay> {
|
|
222
|
-
const key = `${playId}@${version}`;
|
|
223
|
-
const play = this.#plays.get(key);
|
|
224
|
-
if (!play) {
|
|
225
|
-
throw new CapabilityError("play-marketplace", "Play registry record not found", {
|
|
226
|
-
suggestion: "Search the marketplace and install an available version.",
|
|
227
|
-
metadata: { playId, version },
|
|
228
|
-
statusCode: 404,
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
const installPath = `marketplace/installed/${playId}@${version}.json`;
|
|
232
|
-
const install: InstalledPlay = {
|
|
233
|
-
playId,
|
|
234
|
-
version,
|
|
235
|
-
status: "installed",
|
|
236
|
-
registeredSkill: playId,
|
|
237
|
-
installPath,
|
|
238
|
-
};
|
|
239
|
-
const snapshot = `${JSON.stringify(install, null, 2)}\n`;
|
|
240
|
-
await this.#contentStore.write(installPath, snapshot);
|
|
241
|
-
await this.#eventLog.commit({
|
|
242
|
-
traceId: assetId("play_marketplace_install", `${playId}_${version}`),
|
|
243
|
-
kind: "content_write",
|
|
244
|
-
affected: [installPath],
|
|
245
|
-
parent: play.eventId,
|
|
246
|
-
snapshot: { [installPath]: snapshot },
|
|
247
|
-
});
|
|
248
|
-
await this.#debug({ type: "install", tenantId: this.#tenantId, playId, version });
|
|
249
|
-
return install;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
async doctor(): Promise<PlayMarketplaceDoctorReport> {
|
|
253
|
-
const report: PlayMarketplaceDoctorReport = {
|
|
254
|
-
capability: "play-marketplace",
|
|
255
|
-
ok: true,
|
|
256
|
-
checkedAt: new Date().toISOString(),
|
|
257
|
-
features: ["validate-skill", "publish", "search", "install", "paid-launch-gate"],
|
|
258
|
-
suggestion:
|
|
259
|
-
"Local registry artifacts are active; remote registry, billing, and verified review queues remain handoffs.",
|
|
260
|
-
};
|
|
261
|
-
await this.#debug({ type: "doctor", tenantId: this.#tenantId, plays: this.#plays.size });
|
|
262
|
-
return report;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
async close(): Promise<void> {
|
|
266
|
-
await this.#contentStore.close();
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
async #debug(entry: Record<string, unknown>): Promise<void> {
|
|
270
|
-
await appendCapabilityDebug("play-marketplace", entry, { root: this.#debugRoot });
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
export async function readPlayMarketplaceDebug(
|
|
275
|
-
root = process.cwd(),
|
|
276
|
-
limit = 20,
|
|
277
|
-
): Promise<unknown[]> {
|
|
278
|
-
return readCapabilityDebug("play-marketplace", { root, limit });
|
|
279
|
-
}
|
package/tsconfig.json
DELETED