@follenfang/fupload 0.0.18 → 0.0.20

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/fupload/SKILL.md CHANGED
@@ -2,7 +2,7 @@
2
2
  name: fupload
3
3
  description: Explicit author-publishing workflow for World of Warcraft plugins, configuration shares, and WA/strings on NewBeeBox, NetEase DD, CurseForge, Heybox Workshop, and ModUs.Creator, including local Creator login reuse and plugin ZIP publishing. Use only when the user explicitly invokes `$fupload`, explicitly asks to use the Fupload Skill, or loads this Skill by path. Do not trigger from ordinary mentions of publishing, NewBeeBox, DD, CurseForge, Heybox, ModUs, plugins, configurations, or WA.
4
4
  metadata:
5
- version: "0.0.18"
5
+ version: "0.0.20"
6
6
  ---
7
7
 
8
8
  # Fupload
@@ -22,7 +22,7 @@ Map natural language consistently:
22
22
 
23
23
  - `create`: create the main record. If first content is a separate platform action, plan it as a following atomic step.
24
24
  - `update`: publish a plugin version, change selected configuration-backup content, or publish a WA/string version.
25
- - `edit`: change fields allowed by the target platform's action allowlist. For DD plugins, this is existing-record commercial, association, room/channel, and creation-statement settings; first-publication metadata, categories, media, and version fields are create/update-only.
25
+ - `edit`: change fields allowed by the target platform's action allowlist. For DD plugins, this includes `description` and existing-record commercial, association, room/channel, and creation-statement settings; other first-publication metadata, categories, media, and version fields are create/update-only. Description edits read both detail and author-list projections; either may confirm the value, but if neither matches, report verification-required.
26
26
  - `delete`: delete one main record only. It never deletes an individual version, media object, or associated record.
27
27
 
28
28
  Never offer bulk delete, drafts, guides, messages, or GUI control automation. Heybox supports individual version deletion with asynchronous readback; whole-module deletion is not supported. The DD task-session command may close verified official GUI processes only after the consent flow below.
@@ -109,7 +109,7 @@ For ModUs, require all four `modus session doctor` booleans to be true before an
109
109
 
110
110
  Before any DD live GET or write, run `dd session doctor`. If it reports `gui_running=true`, tell the user that continuing will close the listed official DD GUI instances and ask for explicit consent. Without consent, do not run start, do not close a process, and do not issue a native login. After consent, run `dd session start --confirm-close-gui`; when no GUI is running, run `dd session start` without that flag.
111
111
 
112
- `dd session start` automatically selects the native relogin flow from the official `Account.method`, `Cred.type`, and `Cred.modifier` enums. `urs + urs_token + normal` uses `UrsReLoginFlow` for an email session; `mobile + urs_mobile_token + mobile_password|mobile_uplink` uses `MobileReLoginFlow` for a mobile session. Missing, unknown, or contradictory combinations fail before any flow runs. Never infer the account kind from its text, coerce an enum, or try the other flow after a failure.
112
+ `dd session start` automatically selects the native relogin flow from the official `Account.method`, `Cred.type`, and `Cred.modifier` enums. `urs + urs_token + normal` uses `UrsReLoginFlow` for an email session; `mobile + urs_mobile_token + normal|mobile_password|mobile_uplink` uses `MobileReLoginFlow` for a mobile session. Missing, unknown, or contradictory combinations fail before any flow runs. Never infer the account kind from its text, coerce an enum, or try the other flow after a failure.
113
113
 
114
114
  Keep the returned opaque `session_id` only in task memory and pass it as `--session <id>` to every DD GET, write, readback, status, and delete. Reuse this one session for the complete task, serialize all commands, stop on the first failure, and never start one session per item in a batch. In a `finally` path, always run `dd session stop --session <id>` and require `cleanup_complete=true`; the ten-minute idle timeout is only an abnormal-exit fallback.
115
115
 
@@ -7,7 +7,7 @@ Run `dd session doctor` first. Doctor only discovers the installation, verifies
7
7
  `start` closes only identity- and signature-verified official GUI processes, starts one task broker, and reads the official `AccountCredStorage` auto account and credential. It selects the native relogin flow only from this strict enum matrix:
8
8
 
9
9
  - `Account.method=urs`, `Cred.type=urs_token`, `Cred.modifier=normal`: run `UrsReLoginFlow(controller, sdk, token, username)` for the email login state.
10
- - `Account.method=mobile`, `Cred.type=urs_mobile_token`, `Cred.modifier=mobile_password|mobile_uplink`: run `MobileReLoginFlow(controller, sdk, cgi, netconfig, token, isPassword, username)` for the mobile login state. `isPassword` is true only for `mobile_password`.
10
+ - `Account.method=mobile`, `Cred.type=urs_mobile_token`, `Cred.modifier=normal|mobile_password|mobile_uplink`: run `MobileReLoginFlow(controller, sdk, cgi, netconfig, token, isPassword, username)` for the mobile login state. `normal` is emitted by the official DD 100130 client for SMS/non-password mobile login. `isPassword` is true only for `mobile_password`.
11
11
 
12
12
  Missing, unknown, or contradictory enum combinations fail before either flow is called. Do not infer account kind from the account string, coerce a value, or fall back to the other flow after a login failure. Do not request or accept manual account names, passwords, tokens, credential values, or account-type overrides.
13
13
 
@@ -59,13 +59,21 @@ All three create/edit form models use `scope`, `share_code_life_type`, `need_buy
59
59
 
60
60
  Omission on edit preserves the remote value. Explicit false follows the field-specific official behavior: room and association children are cleared, while anchor VIP levels remain unless private scope or the outer free mode clears them.
61
61
 
62
+ ## Update description (`update_desc`)
63
+
64
+ `update_desc` is rendered as HTML on the DD web and client surface, for plugins, configuration shares, and WA alike. The renderer collapses plain-text line feeds, so a multi-line changelog must use markup: `<p>first line</p><p>second line</p>`, or `<br>` between lines. A JSON string that contains only `\n` is stored intact but renders as a single line.
65
+
66
+ The Python CLI copies the supplied string into the wire form unchanged and performs no HTML escaping, so callers may pass tags directly. The platform normalizes `\r\n` and `\n` to LF; the line-ending style itself has no effect on rendering. The 1000-character limit applies to the whole string, tags included.
67
+
68
+ A published version's `update_desc` cannot be corrected through the CLI: `plugin edit`, `config edit`, and `wa edit` do not accept the field, and plugin version fields are not edit fields. Correct the format by writing the next version's `update_desc` properly.
69
+
62
70
  ## Plugin
63
71
 
64
72
  `plugin create` fields: `game_type`, `scope`, `addon_type`, `name`, `description`, `logo`/`logo_file`, `detail_imgs`/`detail_img_files`, `primary_category_id`, `second_category_ids`, `html_desc`, `game_versions`, `detail_url`/`file`, `release_type`, `version`, `update_desc`, and all shared fields. Name, description, and version are at most 80 characters; update description is at most 1000; detail images are at most 8.
65
73
 
66
74
  Every path in `detail_img_files` must exist as a regular local file. Validation reports the exact indexed path, such as `$.detail_img_files[0]`, before any upload or mutation.
67
75
 
68
- `game_type` and the outer free/paid state are create-only. `plugin update` requires `sn`, `game_versions`, `version`, and `update_desc`; optional `file`, `detail_url`, and `release_type` publish a new version. `plugin edit` requires `sn` and only accepts the official existing-record commercial and association controls (`scope`, payment/lifetime/VIP fields, room/channel linkage, `creation_statement`, and associated content). First-publication metadata (`addon_type`, `name`, `description`, logo, detail images, categories, and `html_desc`) and version fields are not edit fields; in particular, sending `description` to `/addon/modify` can be accepted while leaving the remote value unchanged, so the CLI rejects it instead of reporting a false success.
76
+ `game_type` and the outer free/paid state are create-only. `plugin update` requires `sn`, `game_versions`, `version`, and `update_desc`; optional `file`, `detail_url`, and `release_type` publish a new version. `plugin edit` requires `sn` and accepts `description` plus the official existing-record commercial and association controls (`scope`, payment/lifetime/VIP fields, room/channel linkage, `creation_statement`, and associated content). Other first-publication metadata (`addon_type`, `name`, logo, detail images, categories, and `html_desc`) and version fields are not edit fields. The CLI verifies a description edit through both detail and author-list readback; if DD accepts the request but leaves the remote value unchanged, it reports a verification-required error rather than false success.
69
77
 
70
78
  When `assign_user_sn` is present, the official UI exposes only the public scope option. Python validates the final rebuilt form and rejects a private scope before upload or mutation.
71
79
 
@@ -191,6 +191,10 @@ CLI 全程非交互、支持 `-o json` 结构化输出,适合交给 AI 助手
191
191
 
192
192
  直接给文本,或 `@CHANGELOG.md` 从文件读取;未指定时若 ncc.json 配置了 `changelog_file` 且文件存在则自动读取。
193
193
 
194
+ **该字段按纯文本存储和展示,不渲染 Markdown**——注意这与插件详情不同,详情正文是 Markdown(见 `--description`):`#`、`##`、`**`、`-` 等标记在这里会原样显示成符号。建议一行一条、行首用 `•`,行与行之间不留空行;换行符统一用 `\r\n`,文末保留一个换行。
195
+
196
+ 单个版本的日志只写该版本内容,不要把整份 `CHANGELOG.md` 直接传给 `--changelog`(会把全部历史带进这一条)。历史版本可用 `ncc wow addons changelog <file_id> --set @<文本文件>` 修正,改完回读核对字数与行数。
197
+
194
198
  ## ncc.json 配置说明
195
199
 
196
200
  ```jsonc
@@ -1,3 +1,3 @@
1
1
  """Fupload Python CLI."""
2
2
 
3
- __version__ = "0.0.18"
3
+ __version__ = "0.0.20"
@@ -1463,10 +1463,12 @@ PLUGIN_CREATE_DEFAULTS = {
1463
1463
  "with_associate": False,
1464
1464
  }
1465
1465
 
1466
- # DD's modify form is not a second create form. The official edit page
1467
- # rebuilds the payload from the existing commercial/association controls;
1468
- # first-publication metadata and version fields belong to create/update.
1466
+ # DD's modify form is not a second create form. The official edit page
1467
+ # rebuilds the payload from existing commercial/association controls. The
1468
+ # brief description is the supported metadata exception and is verified by
1469
+ # detail and author-list readback after every edit.
1469
1470
  PLUGIN_EDIT_FIELDS = (
1471
+ "description",
1470
1472
  "scope", "share_code_life_type", "need_buy", "price_fen", "buy_life_type",
1471
1473
  "jump_room", "room_id", "channel_id", "channel_type", "sync_room",
1472
1474
  "creation_statement", "with_associate", "associated_acts", "need_anchor_vip",
@@ -625,8 +625,9 @@ def _create_relogin_flow(
625
625
  if (
626
626
  method == "mobile"
627
627
  and credential_type == "urs_mobile_token"
628
- and modifier in ("mobile_password", "mobile_uplink")
628
+ and modifier in ("normal", "mobile_password", "mobile_uplink")
629
629
  ):
630
+ # Official DD 100130 emits normal for SMS/non-password mobile credentials.
630
631
  return mobile_flow_class(
631
632
  controller, sdk, cgi, netconfig, credential.value,
632
633
  modifier == "mobile_password", account.name,
@@ -643,7 +644,7 @@ def _credential_kind(account, credential):
643
644
  if (
644
645
  method == "mobile"
645
646
  and credential_type == "urs_mobile_token"
646
- and modifier in ("mobile_password", "mobile_uplink")
647
+ and modifier in ("normal", "mobile_password", "mobile_uplink")
647
648
  ):
648
649
  return "mobile"
649
650
  raise RuntimeError("DD persisted login state uses an unsupported credential combination")
@@ -580,6 +580,7 @@ DD_PLUGIN_EDIT_META = {
580
580
  name: DD_COMMERCIAL[name]
581
581
  for name in DD_COMMERCIAL
582
582
  }
583
+ DD_PLUGIN_EDIT_META["description"] = DD_PLUGIN_META["description"]
583
584
  DD_PLUGIN_VERSION = {
584
585
  "game_versions": f("array", nonempty=True), "detail_url": f("string"),
585
586
  "file": f("string", local_file=True), "release_type": f("integer", choices=(1, 2, 3)),
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schema": "fupload.npm-skill-manifest.v1",
3
3
  "package_name": "@follenfang/fupload",
4
- "package_version": "0.0.18",
5
- "skill_version": "0.0.18",
6
- "tree_sha256": "36d839247defb278814b13da703acef8766aeb4f01efb8bda4c3d104367ac13b",
4
+ "package_version": "0.0.20",
5
+ "skill_version": "0.0.20",
6
+ "tree_sha256": "bea57f52a133edcd0062736fb1f7c0c560293cb51454275bb1d7bf2234c2d67c",
7
7
  "files": [
8
8
  {
9
9
  "path": "agents/openai.yaml",
@@ -87,8 +87,8 @@
87
87
  },
88
88
  {
89
89
  "path": "references/dd.md",
90
- "bytes": 19727,
91
- "sha256": "2804e4b77c000d0bd12ca3f69bbcd5720f759fd4e84b4127ea3461093bf5da7c"
90
+ "bytes": 20837,
91
+ "sha256": "583a3531cfabf6749c31088a88b3bbad2c516e1eae0b100433305f26894c153d"
92
92
  },
93
93
  {
94
94
  "path": "references/modus.md",
@@ -97,8 +97,8 @@
97
97
  },
98
98
  {
99
99
  "path": "references/newbee-official-cli.md",
100
- "bytes": 24919,
101
- "sha256": "f0ddeca7415f2351ca03cdb9a9f4cb7fd9f08d87a28b13003abe800e57c7f7dd"
100
+ "bytes": 25535,
101
+ "sha256": "2499add2a7a571ed85cc0cf1cfc31513dbbc57a6d001a47045087a48a646f080"
102
102
  },
103
103
  {
104
104
  "path": "references/newbee.md",
@@ -113,7 +113,7 @@
113
113
  {
114
114
  "path": "scripts/fupload_cli/__init__.py",
115
115
  "bytes": 50,
116
- "sha256": "b899101a4de87efa255361fb768398e6f03a68740eca391ba57991984bd77c55"
116
+ "sha256": "72c39ea05a04d5f631b53d5363ab86a8c974169c19c56245d7ab2c3c16498ba4"
117
117
  },
118
118
  {
119
119
  "path": "scripts/fupload_cli/blackbox_web.py",
@@ -142,13 +142,13 @@
142
142
  },
143
143
  {
144
144
  "path": "scripts/fupload_cli/dd_sidecar.py",
145
- "bytes": 39206,
146
- "sha256": "722038884c5b050c2c6030f5d4e7b1088c1fb9b614e99c3b241b539631cbc3e3"
145
+ "bytes": 39309,
146
+ "sha256": "fa0658f9cd4d5c85f4f1f84dd79bf7b33b5cafb74813107acc09fcf1f17d508c"
147
147
  },
148
148
  {
149
149
  "path": "scripts/fupload_cli/dd.py",
150
- "bytes": 115318,
151
- "sha256": "588102eb959e9f4737c39311cd689e400e2b0a8197abc231a145f342c03dbd68"
150
+ "bytes": 115390,
151
+ "sha256": "e160eeebb2914016d99f6dad1ad38b61fa201c884bb2314090839408fa70cd58"
152
152
  },
153
153
  {
154
154
  "path": "scripts/fupload_cli/errors.py",
@@ -182,8 +182,8 @@
182
182
  },
183
183
  {
184
184
  "path": "scripts/fupload_cli/schema.py",
185
- "bytes": 54561,
186
- "sha256": "17d57a9c9c53e556faf9e415020d47f84965283680c66f3f1c33beef6b83d104"
185
+ "bytes": 54628,
186
+ "sha256": "6eead57520d6f1d0db62d6da764c4e419cca24a267483dd3708f212a492e396a"
187
187
  },
188
188
  {
189
189
  "path": "scripts/fupload_cli/state_machine.py",
@@ -207,8 +207,8 @@
207
207
  },
208
208
  {
209
209
  "path": "SKILL.md",
210
- "bytes": 28383,
211
- "sha256": "512d6d5b7d34987009c12675e4cee4c540950e32ac808fbf4081d8db6c3157f0"
210
+ "bytes": 28568,
211
+ "sha256": "98335037547a916e251f65c39a686eb3c9a58468f113531c1e28a9ec225198e9"
212
212
  }
213
213
  ]
214
214
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@follenfang/fupload",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
4
4
  "description": "Install and run the Fuploader Agent Skill and Python CLI.",
5
5
  "type": "module",
6
6
  "bin": {