dsh-codex-connect 0.1.0-alpha.4.48 → 0.1.0-alpha.4.49
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/docs/agent-notes/issue-272-post-release-fixes.md +30 -0
- package/docs/agent-notes/issue-273-independent-review.md +19 -0
- package/docs/experiments/evidence/alpha-449-release-verification.json +70 -0
- package/docs/experiments/evidence/issue-272-post-release-fix.json +94 -0
- package/docs/experiments/evidence/issue-273-independent-review.json +22 -0
- package/docs/reference.i18n.yaml +2 -2
- package/docs/reference.md +6 -1
- package/docs/reference.zh.md +6 -1
- package/lib/bin.js +1 -1
- package/lib/client.js +107 -6
- package/lib/index.js +322 -244
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# PR #272 post-release fixes — 2026-09-26
|
|
2
|
+
|
|
3
|
+
Status: unreleased patch; independent re-review required. Do not use the earlier review pass as approval for these fixes.
|
|
4
|
+
|
|
5
|
+
## Affected baseline and correction
|
|
6
|
+
|
|
7
|
+
The user supplied three independent reproduction tests for `5acc87399203700726475ad5e76e282d2631b28c`. PR #272 had already been merged as `8e685d736da8e605ead11808a7daab5cdaf4b481` and released as `0.1.0-alpha.4.48` before the report reached this workflow. Both P2 findings are valid. The original three tests were preserved, independently re-executed against the released code, and all three failed. Their fixtures and assertions were not weakened to make the patch pass.
|
|
8
|
+
|
|
9
|
+
The previous assistant's “independent review — pass” was overstated: a new WebCodex workflow session records a separate task but does not constitute a separate reviewer or model. It missed these cases. Green existing tests did not cover them. That pass should be read as withdrawn, not as a completed external approval.
|
|
10
|
+
|
|
11
|
+
## Repairs
|
|
12
|
+
|
|
13
|
+
1. Keep explicit user upload occurrences separate from generated-result/preview mappings. A complete recorded upload reference selects its attachment bytes, even if the filename, dimensions and content ID match an old generated preview. An unqualified ID shared across both origins is refused with an ambiguity explanation. Explicit `assetId` selection still uses the original, and missing originals still fail without fallback. The rule applies equally to target and reference inputs; serialization, forks and user inbox image admission are covered. This is not a most-recent-image heuristic.
|
|
14
|
+
2. Project a complete validated attachment reference next to request images so the conversational model can select the uploaded copy without making users look up opaque IDs. Do not persist relative ordinals or grant new access. Older explicit original handles stay supported.
|
|
15
|
+
3. Share a fixed public failure catalog between input validation, transport-facing tool errors and the browser. Only exact allowlisted strings are shown; an upstream string beginning with a known message and then containing a path, bearer value or other data is rejected. Unknown errors get a generic safe explanation. Input errors show recovery guidance and omit ineffective unchanged-retry controls; timeout/uncertain-outcome notices and explicitly initiated transient retries remain.
|
|
16
|
+
|
|
17
|
+
## Executed checks
|
|
18
|
+
|
|
19
|
+
- Original reproduction cases: before **0 passed / 3 failed**, after **3 passed / 0 failed**. Other cases excluded by the name filter were explicitly skipped, not counted as passed.
|
|
20
|
+
- Complete `pnpm run check`: **125 files / 1,440 tests passed**, including source lint, host/client types, build, import isolation, compatibility and package audit.
|
|
21
|
+
- Chromium `pnpm run test:browser`: **13 files / 73 tests passed**. Includes English/Chinese failure recovery and raw-detail suppression.
|
|
22
|
+
- Additional tests cover uploaded-copy byte identity, explicit original selection, missing-original refusal, reference ambiguity, repeated canonical selections, restored inherited-event prefixes, user inbox admission and adjacent full-reference wire data.
|
|
23
|
+
- The first full validation of the new tests found an unsupported inline `seedSource` test-option field; it was removed to use the actual `PrepareSessionOptions` contract, then the full check passed. No production behavior was changed to silence it.
|
|
24
|
+
- Exact DSH `0.1.7-rc.1` installation matrix: **passed**, with unchanged defaults, two synthetic generations, two synthetic edits, inherited-access/source/refusal checks and zero real provider requests. Tested archive SHA-256: `e3cc631c29a5e7453cd080a07ee5eb475763278394ba962cafb211489befbd23`. The archive predates only this final evidence annotation; all runtime fingerprints remain unchanged.
|
|
25
|
+
|
|
26
|
+
Compact evidence and runtime SHA-256 fingerprints: `docs/experiments/evidence/issue-272-post-release-fix.json`.
|
|
27
|
+
|
|
28
|
+
## Delivery boundaries
|
|
29
|
+
|
|
30
|
+
No real model or image service calls, credential inspection, daily-service restart, published-package replacement, tag move, latest-tag promotion or new release in this fix round. Alpha 4.48 on npm is not fixed by this branch. Public recommendations remain unpromoted while the correction awaits review. The changed guidance has offline wire coverage, not a new live-model reliability claim. Tests and a self-review are not a replacement for an independent review of the final patch.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# PR #273 independent source review — 2026-09-26
|
|
2
|
+
|
|
3
|
+
Reviewed source: `804c0820024618016297889bc6c2df35d78bebbd`, base `8e685d736da8e605ead11808a7daab5cdaf4b481`.
|
|
4
|
+
|
|
5
|
+
A separate ephemeral Codex CLI 0.153.4 process reviewed the exact committed patch and selected full source/test files. It had no implementation conversation history and ran in read-only mode. Its actual model was **gpt-6-astra**, selected by the CLI default after the explicit gpt-6-sol attempt returned an unsupported-model error without a report. This is a separate model review, not a new WebCodex workflow labeled independent.
|
|
6
|
+
|
|
7
|
+
The report below is verbatim. Its scope is source review; it does not replace executed local checks, current-head CI, or real-provider acceptance. The source under `src/` remains unchanged from the reviewed commit while Alpha 4.49 release metadata is prepared. Input/output hashes and the rejected attempt are recorded in `../experiments/evidence/issue-273-independent-review.json`.
|
|
8
|
+
|
|
9
|
+
## Reviewer report
|
|
10
|
+
|
|
11
|
+
**PASS** — 对所提供的提交 `804c0820024618016297889bc6c2df35d78bebbd` 源码,未发现本次范围内可具体成立的阻塞缺陷或回归。
|
|
12
|
+
|
|
13
|
+
- **身份解析**:target 与 references 共用解析路径;上传与生成结果共享裸 ID 时拒绝歧义,完整上传引用保留上传字节,`assetId` 明确选择原图。同名同字节重传仍能由上传记录识别。
|
|
14
|
+
- **来源与投影**:上传标记检查用户来源;文本中的引用不会被当作上传。完整引用经过统一解码后投影、匹配。
|
|
15
|
+
- **错误与重试**:错误展示采用完整固定字符串白名单;覆盖全部四个参考图编号。已识别的输入、账户和存储错误会抑制直接重试,未知原始错误不会直接展示。
|
|
16
|
+
|
|
17
|
+
**发现项/严重性:无。**
|
|
18
|
+
|
|
19
|
+
**剩余限制**:仅审查所提供源码和测试内容;未独立核验 Git 提交、执行测试或验证宿主事件生成、错误封装及真实服务行为。PASS 仅表示此次限定源码审查未发现缺陷,不代表线上验收或正确性保证。
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"candidate": "0.1.0-alpha.4.49",
|
|
4
|
+
"reviewedSourceCommit": "804c0820024618016297889bc6c2df35d78bebbd",
|
|
5
|
+
"baseCommit": "8e685d736da8e605ead11808a7daab5cdaf4b481",
|
|
6
|
+
"recordedAt": "2026-09-26T02:39:12.095297+00:00",
|
|
7
|
+
"checks": {
|
|
8
|
+
"frozenInstall": "passed",
|
|
9
|
+
"completeCheck": {
|
|
10
|
+
"files": 125,
|
|
11
|
+
"tests": 1440,
|
|
12
|
+
"status": "passed"
|
|
13
|
+
},
|
|
14
|
+
"chromium": {
|
|
15
|
+
"files": 13,
|
|
16
|
+
"tests": 73,
|
|
17
|
+
"status": "passed"
|
|
18
|
+
},
|
|
19
|
+
"originalReproductions": {
|
|
20
|
+
"passed": 3,
|
|
21
|
+
"failed": 0,
|
|
22
|
+
"skipped": 47
|
|
23
|
+
},
|
|
24
|
+
"finalMetadataAndPackage": {
|
|
25
|
+
"status": "passed",
|
|
26
|
+
"files": 4,
|
|
27
|
+
"tests": 27,
|
|
28
|
+
"packedFiles": 126,
|
|
29
|
+
"diffCheck": "passed"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"matrix": {
|
|
33
|
+
"sameArtifact": true,
|
|
34
|
+
"reports": [
|
|
35
|
+
{
|
|
36
|
+
"dshVersion": "0.1.7-rc.1",
|
|
37
|
+
"pluginVersion": "0.1.0-alpha.4.49",
|
|
38
|
+
"archiveSha256": "cdaf5593959147614476fdf6a3b5ead7067f4633e56b317aa4452eb1175a06bd",
|
|
39
|
+
"defaultsUnchanged": true,
|
|
40
|
+
"images": {
|
|
41
|
+
"syntheticOnly": true,
|
|
42
|
+
"generated": 2,
|
|
43
|
+
"edited": 2,
|
|
44
|
+
"codeRuns": 2,
|
|
45
|
+
"dispatchEvent": "tool/ptc-dispatch",
|
|
46
|
+
"originalDownloadVerified": true,
|
|
47
|
+
"inheritedOriginalVerified": true,
|
|
48
|
+
"earlierForkDenied": true,
|
|
49
|
+
"unrelatedSessionDenied": true,
|
|
50
|
+
"editSourcesVerified": true,
|
|
51
|
+
"inheritedEditVerified": true,
|
|
52
|
+
"invalidEditRefused": true,
|
|
53
|
+
"realProviderRequests": 0
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"fileSha256": {
|
|
59
|
+
"src/image-history.ts": "a2971f2c2740c7330a2d1ffdd1b6ab07babd0d72b9c006e3318ccf30cd3820b3",
|
|
60
|
+
"src/image-inputs.ts": "113d41533ff8ee0cde9c6415aa5d11657de779a10fe45ac7c944521c3e26d98d",
|
|
61
|
+
"src/image-error-contract.ts": "64780e03d3d856d3a4f096fe1cf72ae6d40a63aa8b8f3d846d999557aef1cb5e",
|
|
62
|
+
"src/adapter.ts": "81d3134d7b448aa78d0017924aee609fad2d3e636469f18948923d63dd4c2e90",
|
|
63
|
+
"src/client/CodexImageToolView.tsx": "c1343156d7cd3a88c8078b70a2bd1b3f8f904ef0a62864a5647224a843301801",
|
|
64
|
+
"lib/index.js": "81ac3c27b06e8892e7d77e84561564c04abb57caa02233cf228b0fddfc73e4e9",
|
|
65
|
+
"lib/client.js": "6839b6f07e1e5b92a6037eb973d41ba6a0629d40f1d89103c301b633502b7c63",
|
|
66
|
+
"lib/bin.js": "fce137eb91bf3e5ea13035d36bff4077a7db6f4254cf62c6e578bbe5fc332a45"
|
|
67
|
+
},
|
|
68
|
+
"scope": "local synthetic tests plus separate source review; no additional live image or model-selection acceptance",
|
|
69
|
+
"archiveBoundary": "Matrix package precedes only final verified-pair and evidence/reference annotations. Runtime hashes unchanged; final CI and publish workflow must verify the exact merged candidate."
|
|
70
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"reviewedHead": "5acc87399203700726475ad5e76e282d2631b28c",
|
|
4
|
+
"releasedBase": "8e685d736da8e605ead11808a7daab5cdaf4b481",
|
|
5
|
+
"affectedRelease": "0.1.0-alpha.4.48",
|
|
6
|
+
"createdAt": "2026-09-26T01:40:45.823426+00:00",
|
|
7
|
+
"realModelRequests": 0,
|
|
8
|
+
"realImageRequests": 0,
|
|
9
|
+
"before": {
|
|
10
|
+
"passed": 0,
|
|
11
|
+
"failed": 3,
|
|
12
|
+
"skipped": 42,
|
|
13
|
+
"cases": [
|
|
14
|
+
{
|
|
15
|
+
"test": "session-owned image edit tool PR272 review: a reuploaded preview handle must not silently select the old generated original",
|
|
16
|
+
"status": "failed"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"test": "session-owned image edit tool PR272 review: a complete reuploaded reference stays usable after the old original is removed",
|
|
20
|
+
"status": "failed"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"test": "Codex image Tool view PR272 review: shows the safe actionable reason for a rejected edit selection",
|
|
24
|
+
"status": "failed"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"after": {
|
|
29
|
+
"passed": 3,
|
|
30
|
+
"failed": 0,
|
|
31
|
+
"skipped": 47,
|
|
32
|
+
"cases": [
|
|
33
|
+
{
|
|
34
|
+
"test": "session-owned image edit tool PR272 review: a reuploaded preview handle must not silently select the old generated original",
|
|
35
|
+
"status": "passed"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"test": "session-owned image edit tool PR272 review: a complete reuploaded reference stays usable after the old original is removed",
|
|
39
|
+
"status": "passed"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"test": "Codex image Tool view PR272 review: shows the safe actionable reason for a rejected edit selection",
|
|
43
|
+
"status": "passed"
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"fullCheck": {
|
|
48
|
+
"exitCode": 0,
|
|
49
|
+
"files": 125,
|
|
50
|
+
"tests": 1440
|
|
51
|
+
},
|
|
52
|
+
"chromium": {
|
|
53
|
+
"exitCode": 0,
|
|
54
|
+
"files": 13,
|
|
55
|
+
"tests": 73
|
|
56
|
+
},
|
|
57
|
+
"runtimeSha256": {
|
|
58
|
+
"lib/index.js": "ab39bf865cc53433a36e1d2de4824863a7c140aaf7f8dc98a3266657f37af64e",
|
|
59
|
+
"lib/client.js": "89cc7b43cf36bfc54b615e51f75c162f4ec3502f6ca52c8979960d7c53ccfb38",
|
|
60
|
+
"src/image-inputs.ts": "113d41533ff8ee0cde9c6415aa5d11657de779a10fe45ac7c944521c3e26d98d",
|
|
61
|
+
"src/image-history.ts": "a2971f2c2740c7330a2d1ffdd1b6ab07babd0d72b9c006e3318ccf30cd3820b3",
|
|
62
|
+
"src/image-error-contract.ts": "64780e03d3d856d3a4f096fe1cf72ae6d40a63aa8b8f3d846d999557aef1cb5e",
|
|
63
|
+
"src/adapter.ts": "81d3134d7b448aa78d0017924aee609fad2d3e636469f18948923d63dd4c2e90",
|
|
64
|
+
"src/client/CodexImageToolView.tsx": "c1343156d7cd3a88c8078b70a2bd1b3f8f904ef0a62864a5647224a843301801"
|
|
65
|
+
},
|
|
66
|
+
"dshMatrix": {
|
|
67
|
+
"exitCode": 0,
|
|
68
|
+
"sameArtifact": true,
|
|
69
|
+
"unreleasedCandidate": true,
|
|
70
|
+
"reports": [
|
|
71
|
+
{
|
|
72
|
+
"dshVersion": "0.1.7-rc.1",
|
|
73
|
+
"artifactSha256": "e3cc631c29a5e7453cd080a07ee5eb475763278394ba962cafb211489befbd23",
|
|
74
|
+
"defaultsUnchanged": true,
|
|
75
|
+
"images": {
|
|
76
|
+
"syntheticOnly": true,
|
|
77
|
+
"generated": 2,
|
|
78
|
+
"edited": 2,
|
|
79
|
+
"codeRuns": 2,
|
|
80
|
+
"dispatchEvent": "tool/ptc-dispatch",
|
|
81
|
+
"originalDownloadVerified": true,
|
|
82
|
+
"inheritedOriginalVerified": true,
|
|
83
|
+
"earlierForkDenied": true,
|
|
84
|
+
"unrelatedSessionDenied": true,
|
|
85
|
+
"editSourcesVerified": true,
|
|
86
|
+
"inheritedEditVerified": true,
|
|
87
|
+
"invalidEditRefused": true,
|
|
88
|
+
"realProviderRequests": 0
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
"artifactNote": "The matrix archive predates only final evidence-note updates. Runtime fingerprints are unchanged. This is an unreleased fix candidate, not a replacement npm 4.48 package."
|
|
94
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"reviewedCommit": "804c0820024618016297889bc6c2df35d78bebbd",
|
|
4
|
+
"reviewedBase": "8e685d736da8e605ead11808a7daab5cdaf4b481",
|
|
5
|
+
"reviewer": "separate Codex CLI process",
|
|
6
|
+
"cliVersion": "0.153.4",
|
|
7
|
+
"model": "gpt-6-astra",
|
|
8
|
+
"mode": "ephemeral read-only, source bundle via stdin, no shared implementation history",
|
|
9
|
+
"verdict": "PASS",
|
|
10
|
+
"findingCount": 0,
|
|
11
|
+
"scope": "source and supplied test review only; reviewer did not run tests or live image/model-selection acceptance",
|
|
12
|
+
"inputSha256": "cebada34d7c424f5b772939c6131c57d033eeb4fee3d4dbf7dd893e5fa1ad044",
|
|
13
|
+
"reportSha256": "fbfbf658b22d50bf66ad0295c5ce8fde50ad75a5bf5965f18a6a20e97aa6dc21",
|
|
14
|
+
"recordedAt": "2026-09-26T02:35:08.868293+00:00",
|
|
15
|
+
"previousAttempt": {
|
|
16
|
+
"model": "gpt-6-sol",
|
|
17
|
+
"status": "unsupported model with this Codex ChatGPT account",
|
|
18
|
+
"reportProduced": false
|
|
19
|
+
},
|
|
20
|
+
"releaseCandidate": "0.1.0-alpha.4.49",
|
|
21
|
+
"sourceUnchangedSinceReview": true
|
|
22
|
+
}
|
package/docs/reference.i18n.yaml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
# Bilingual-pair consistency record for the operational reference. Re-record with:
|
|
2
2
|
# git hash-object docs/reference.md docs/reference.zh.md
|
|
3
|
-
docs/reference.md:
|
|
4
|
-
docs/reference.zh.md:
|
|
3
|
+
docs/reference.md: 824fad33dad0fe6e3b1bb7ab5ec10629e5d31459
|
|
4
|
+
docs/reference.zh.md: ebd88277a1177598016e51566aabbee78f7a46b0
|
package/docs/reference.md
CHANGED
|
@@ -92,7 +92,12 @@ Generated originals are stored under `$DSH_HOME/dsh-codex-connect/images/v1`; th
|
|
|
92
92
|
<img src="https://raw.githubusercontent.com/franksong2702/dsh-codex-connect/main/docs/assets/en/image-generation.png" alt="GPT Image result with prompt, download actions, and image details" width="780">
|
|
93
93
|
</p>
|
|
94
94
|
|
|
95
|
-
#### Image editing in Alpha 4.
|
|
95
|
+
#### Image editing in Alpha 4.49
|
|
96
|
+
|
|
97
|
+
**Post-release review:** published Alpha 4.48 has two confirmed defects: a re-uploaded preview can select a historical original, and safe edit failure details are hidden. The fixes below apply to Alpha 4.49; the published 4.48 package is not changed or republished.
|
|
98
|
+
|
|
99
|
+
In Alpha 4.49, a complete `attachment` selector matched to an actual user upload selects that copy's bytes, even when its ID, filename and dimensions match a generated preview. A bare `attachmentId` shared by uploads and generated results fails with an ambiguity message; `assetId` continues to select the exact stored original. Re-uploaded copies remain usable after the historical original is deleted. The model receives the complete bounded reference next to each image; no user lookup of opaque IDs is required. Failed input selections display only fixed, allowlisted reasons and recovery guidance and do not offer an unchanged retry. Unrecognized service errors stay hidden behind a generic explanation.
|
|
100
|
+
|
|
96
101
|
|
|
97
102
|
With the existing image capability enabled, attach a target and optional references and describe their roles, for example: “Edit the first image; use only the colors of the second image and keep the subject.” You can also choose **Edit based on this image** on a previous result. The form waits for your instructions before submitting.
|
|
98
103
|
|
package/docs/reference.zh.md
CHANGED
|
@@ -92,7 +92,12 @@ Reserve 使用 Luna 目录中的 272,000 token 上下文窗口,不沿用原模
|
|
|
92
92
|
<img src="https://raw.githubusercontent.com/franksong2702/dsh-codex-connect/main/docs/assets/zh/image-generation.png" alt="包含提示词、下载操作与图片详情的 GPT Image 结果" width="780">
|
|
93
93
|
</p>
|
|
94
94
|
|
|
95
|
-
#### Alpha 4.
|
|
95
|
+
#### Alpha 4.49 图片编辑
|
|
96
|
+
|
|
97
|
+
**发布后复审:** 已发布的 Alpha 4.48 存在两个已确认缺陷:重新上传的预览可能错误选中历史原图;安全的编辑失败详情未显示。以下修复适用于 Alpha 4.49;已发布的 4.48 安装包不会改写或重新发布。
|
|
98
|
+
|
|
99
|
+
Alpha 4.49 中,完整 `attachment` 选择器匹配到实际用户上传记录时使用该副本的字节,即使编号、文件名和尺寸与生成预览相同也不自动换成原图。单独的 `attachmentId` 同时对应上传图和生成结果时会提示歧义;`assetId` 仍明确选择历史原图。删除历史原图后,重新上传的副本仍可使用。模型会在图片旁收到完整、有界的附件引用,普通用户无需查找内部编号。输入有误时,界面只显示白名单内的固定原因和处理办法,不再提供原样重试;未知服务端错误仅显示安全的通用说明。
|
|
100
|
+
|
|
96
101
|
|
|
97
102
|
开启原有图片能力后,上传一张主图和可选参考图,并说明用途,例如:“修改第一张,只参考第二张的颜色,保留主体。”也可以在旧结果上点击“基于此图修改”。表单会等待你填写修改说明,不会一打开就提交。
|
|
98
103
|
|
package/lib/bin.js
CHANGED
|
@@ -765,7 +765,7 @@ async function detectCompatibility(options = {}) {
|
|
|
765
765
|
}
|
|
766
766
|
//#endregion
|
|
767
767
|
//#region src/version.ts
|
|
768
|
-
const CODEX_CONNECT_VERSION = "0.1.0-alpha.4.
|
|
768
|
+
const CODEX_CONNECT_VERSION = "0.1.0-alpha.4.49";
|
|
769
769
|
//#endregion
|
|
770
770
|
//#region src/doctor.ts
|
|
771
771
|
/** Secret-free diagnostics and duplicate-provider guidance. */
|
package/lib/client.js
CHANGED
|
@@ -4886,6 +4886,9 @@ window.__ModuleLoader__.load({
|
|
|
4886
4886
|
retryImageEdit: "Repeat this edit",
|
|
4887
4887
|
editFrom: "Edited from {source}; {count} reference image(s).",
|
|
4888
4888
|
imageRequestUncertain: "The service may still be processing this request. Repeating it can consume additional quota.",
|
|
4889
|
+
imageUnknownFailure: "The image request failed. Private service details are hidden; check the selected images and account before trying again.",
|
|
4890
|
+
imageInputRecovery: "Correct the selection or instructions in the conversation before retrying. Specify whether to edit the uploaded copy or the stored original; repeating these inputs will not resolve this error.",
|
|
4891
|
+
imageStorageRecovery: "Check local storage and available space before trying again. The service may already have processed this request.",
|
|
4889
4892
|
retryRequest: "Retry the previous image generation.",
|
|
4890
4893
|
regenerateRequest: "Generate another image with the previous image prompt unchanged.",
|
|
4891
4894
|
editRequest: "Continue from the previous image. Ask me what I want to change before generating a new image.",
|
|
@@ -5226,6 +5229,9 @@ window.__ModuleLoader__.load({
|
|
|
5226
5229
|
retryImageEdit: "重做本次修改",
|
|
5227
5230
|
editFrom: "修改自 {source};使用了 {count} 张参考图。",
|
|
5228
5231
|
imageRequestUncertain: "服务可能仍在处理这次请求,重复提交可能额外消耗额度。",
|
|
5232
|
+
imageUnknownFailure: "图片请求失败。已隐藏服务端私有细节;请先检查所选图片和账户状态,再决定是否重试。",
|
|
5233
|
+
imageInputRecovery: "请先在对话中修正选图或修改要求,并明确使用本次上传的图片还是历史原图。原样重复这次请求无法解决该错误。",
|
|
5234
|
+
imageStorageRecovery: "请先检查本地存储和剩余空间,再决定是否重试。服务端可能已经处理了这次请求。",
|
|
5229
5235
|
retryRequest: "重试上一张图片生成。",
|
|
5230
5236
|
regenerateRequest: "再生成一张,保持上一张图片的提示词不变。",
|
|
5231
5237
|
editRequest: "基于上一张图片继续修改。请先询问我需要修改什么,再生成新图片。",
|
|
@@ -5469,7 +5475,7 @@ window.__ModuleLoader__.load({
|
|
|
5469
5475
|
const IMAGE_INPUT_SCHEMA = {
|
|
5470
5476
|
type: "object",
|
|
5471
5477
|
additionalProperties: false,
|
|
5472
|
-
description: "Select exactly one: assetId for an original result, attachmentId from this session, or a complete attachment reference. For
|
|
5478
|
+
description: "Select exactly one: assetId for an original result, attachmentId from this session, or a complete attachment reference. For uploaded copies, including first/second attached image, copy the complete attachment reference from the adjacent handle line. A bare attachmentId shared with a generated result is ambiguous; assetId explicitly selects a stored original. usePreview=true is only for an explicitly chosen lower-resolution preview.",
|
|
5473
5479
|
properties: {
|
|
5474
5480
|
assetId: { type: "string" },
|
|
5475
5481
|
attachmentId: { type: "string" },
|
|
@@ -5709,6 +5715,88 @@ window.__ModuleLoader__.load({
|
|
|
5709
5715
|
return prompt === void 0 ? void 0 : decodeImageResultContent(block.content, prompt);
|
|
5710
5716
|
}
|
|
5711
5717
|
//#endregion
|
|
5718
|
+
//#region src/image-error-contract.ts
|
|
5719
|
+
/** Node-free, fixed public image failures. Unknown provider/host text is never rendered. */
|
|
5720
|
+
const IMAGE_INPUT_FAILURE_REASONS = [
|
|
5721
|
+
"shorten the instructions or reference descriptions.",
|
|
5722
|
+
"requires valid, bounded image selections.",
|
|
5723
|
+
"requires the current session and its image history.",
|
|
5724
|
+
"requires complete host image limits.",
|
|
5725
|
+
"too many inputs for this deployment.",
|
|
5726
|
+
"is unavailable in this session. Select or attach the image again.",
|
|
5727
|
+
"is unavailable or does not match a reference in this session. Select or attach the image again.",
|
|
5728
|
+
"identifies both an upload and a generated result. Select the uploaded attachment explicitly or choose an exact original image.",
|
|
5729
|
+
"matches several original results. Select one exact original image.",
|
|
5730
|
+
"only a preview is available. Explicitly choose that preview or attach an original.",
|
|
5731
|
+
"has unsupported attachment metadata.",
|
|
5732
|
+
"exceeds this deployment's image limits or uses an unsupported format.",
|
|
5733
|
+
"exceeds this deployment's total input limit.",
|
|
5734
|
+
"the original is unavailable or failed integrity checks; no preview was substituted.",
|
|
5735
|
+
"the stored bytes do not match the image reference.",
|
|
5736
|
+
"cannot be read or validated. No image request was sent.",
|
|
5737
|
+
"is required."
|
|
5738
|
+
];
|
|
5739
|
+
function imageInputFailureMessage(label, reason) {
|
|
5740
|
+
return `${label}: ${reason}`;
|
|
5741
|
+
}
|
|
5742
|
+
const TRANSPORT_MESSAGES = {
|
|
5743
|
+
OPENAI_CODEX_SIGNED_OUT: "Sign in to OpenAI Codex before generating images.",
|
|
5744
|
+
OPENAI_CODEX_REAUTH_REQUIRED: "Renew OpenAI Codex authorization before generating images.",
|
|
5745
|
+
OPENAI_CODEX_RATE_LIMITED: "Image generation is temporarily unavailable. Try again later.",
|
|
5746
|
+
OPENAI_CODEX_TIMEOUT: "Image generation timed out. The request may still be processing.",
|
|
5747
|
+
OPENAI_CODEX_CANCELED: "Image generation was canceled. The request may still be processing.",
|
|
5748
|
+
OPENAI_CODEX_NETWORK_ERROR: "The image generation request lost its network connection. The request may still be processing.",
|
|
5749
|
+
OPENAI_CODEX_UPSTREAM_REJECTED: "The image generation request was rejected.",
|
|
5750
|
+
OPENAI_CODEX_UPSTREAM_UNAVAILABLE: "Image generation is temporarily unavailable.",
|
|
5751
|
+
OPENAI_CODEX_RESPONSE_TOO_LARGE: "The image generation response exceeded the safe size limit.",
|
|
5752
|
+
OPENAI_CODEX_MALFORMED_RESPONSE: "The image generation response was unreadable."
|
|
5753
|
+
};
|
|
5754
|
+
const UNKNOWN_TRANSPORT_MESSAGE = "Image generation failed without exposing private response details.";
|
|
5755
|
+
const failures = /* @__PURE__ */ new Map();
|
|
5756
|
+
function register(message, retryable, recovery) {
|
|
5757
|
+
for (const prefix of ["", "Error: "]) {
|
|
5758
|
+
const text = prefix + message;
|
|
5759
|
+
failures.set(text, {
|
|
5760
|
+
message: text,
|
|
5761
|
+
retryable,
|
|
5762
|
+
...recovery === void 0 ? {} : { recovery }
|
|
5763
|
+
});
|
|
5764
|
+
}
|
|
5765
|
+
}
|
|
5766
|
+
for (const label of [
|
|
5767
|
+
"Edit instructions",
|
|
5768
|
+
"Image editing",
|
|
5769
|
+
"Image batch",
|
|
5770
|
+
"Target image",
|
|
5771
|
+
"Reference image 1",
|
|
5772
|
+
"Reference image 2",
|
|
5773
|
+
"Reference image 3",
|
|
5774
|
+
"Reference image 4"
|
|
5775
|
+
]) for (const reason of IMAGE_INPUT_FAILURE_REASONS) register(imageInputFailureMessage(label, reason), false, "input");
|
|
5776
|
+
for (const [code, message] of Object.entries(TRANSPORT_MESSAGES)) {
|
|
5777
|
+
const account = code === "OPENAI_CODEX_SIGNED_OUT" || code === "OPENAI_CODEX_REAUTH_REQUIRED";
|
|
5778
|
+
register(message, !account, account ? "account" : void 0);
|
|
5779
|
+
}
|
|
5780
|
+
register(UNKNOWN_TRANSPORT_MESSAGE, true);
|
|
5781
|
+
register("Invalid image request. Editing requires operation=edit, one explicit target and valid references; no generation was attempted.", false, "input");
|
|
5782
|
+
register("This Codex Connect transport does not support editing. No generation was attempted.", false, "input");
|
|
5783
|
+
register("The Codex Connect image transport is unavailable.", false, "input");
|
|
5784
|
+
for (const message of [
|
|
5785
|
+
"The generated original images could not be saved.",
|
|
5786
|
+
"The generated images could not be saved; no attachment references were returned.",
|
|
5787
|
+
"The image stores returned an incomplete image batch."
|
|
5788
|
+
]) register(message, false, "storage");
|
|
5789
|
+
/** Match complete fixed strings, not prefixes or arbitrary text that merely looks safe. */
|
|
5790
|
+
function safeImageFailure(content) {
|
|
5791
|
+
for (const block of content.slice(0, 8)) {
|
|
5792
|
+
if (typeof block !== "object" || block === null) continue;
|
|
5793
|
+
const value = block;
|
|
5794
|
+
if (value.type !== "text" || typeof value.text !== "string" || value.text.length > 1500) continue;
|
|
5795
|
+
const safe = failures.get(value.text);
|
|
5796
|
+
if (safe !== void 0) return { ...safe };
|
|
5797
|
+
}
|
|
5798
|
+
}
|
|
5799
|
+
//#endregion
|
|
5712
5800
|
//#region src/client/CodexImageGallery.tsx
|
|
5713
5801
|
/** Self-contained result-image gallery for the tool-call view.
|
|
5714
5802
|
*
|
|
@@ -6558,12 +6646,17 @@ window.__ModuleLoader__.load({
|
|
|
6558
6646
|
const code = block.error?.code;
|
|
6559
6647
|
if (code === "ABORTED" || code === "ABORTED_BEFORE_DISPATCH" || code === "TOOL_ABORTED") return {
|
|
6560
6648
|
title: t("canceled"),
|
|
6561
|
-
detail: t("canceledDetail")
|
|
6649
|
+
detail: t("canceledDetail"),
|
|
6650
|
+
retryable: true,
|
|
6651
|
+
recovery: void 0
|
|
6562
6652
|
};
|
|
6563
|
-
const
|
|
6653
|
+
const safe = safeImageFailure(block.content);
|
|
6654
|
+
const reauth = code === "OPENAI_CODEX_REAUTH_REQUIRED" || safe?.recovery === "account";
|
|
6564
6655
|
return {
|
|
6565
6656
|
title: t("failed"),
|
|
6566
|
-
detail: reauth ? t("reauthRequired") :
|
|
6657
|
+
detail: reauth ? t("reauthRequired") : safe?.message ?? t("imageUnknownFailure"),
|
|
6658
|
+
retryable: !reauth && (safe?.retryable ?? true),
|
|
6659
|
+
recovery: safe?.recovery
|
|
6567
6660
|
};
|
|
6568
6661
|
}
|
|
6569
6662
|
function CodexImageToolView({ block, sessionId, t, sessions, configScope }) {
|
|
@@ -6637,7 +6730,15 @@ window.__ModuleLoader__.load({
|
|
|
6637
6730
|
style: detail,
|
|
6638
6731
|
children: t("imageRequestUncertain")
|
|
6639
6732
|
}) : null,
|
|
6640
|
-
|
|
6733
|
+
state.recovery === "input" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6734
|
+
style: detail,
|
|
6735
|
+
children: t("imageInputRecovery")
|
|
6736
|
+
}) : null,
|
|
6737
|
+
state.recovery === "storage" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6738
|
+
style: detail,
|
|
6739
|
+
children: t("imageStorageRecovery")
|
|
6740
|
+
}) : null,
|
|
6741
|
+
request === void 0 || !actionsEnabled || !state.retryable ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6641
6742
|
style: actionRow,
|
|
6642
6743
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6643
6744
|
type: "button",
|
|
@@ -7005,7 +7106,7 @@ window.__ModuleLoader__.load({
|
|
|
7005
7106
|
}
|
|
7006
7107
|
//#endregion
|
|
7007
7108
|
//#region src/version.ts
|
|
7008
|
-
const CODEX_CONNECT_VERSION = "0.1.0-alpha.4.
|
|
7109
|
+
const CODEX_CONNECT_VERSION = "0.1.0-alpha.4.49";
|
|
7009
7110
|
//#endregion
|
|
7010
7111
|
//#region src/client/OpenAICodexModelsCard.tsx
|
|
7011
7112
|
/** Compact Models account entry with quota disclosure and shared configuration. */
|
package/lib/index.js
CHANGED
|
@@ -2460,6 +2460,226 @@ function withAdaptiveTaskProvider(provider) {
|
|
|
2460
2460
|
};
|
|
2461
2461
|
}
|
|
2462
2462
|
//#endregion
|
|
2463
|
+
//#region src/image-assets-contract.ts
|
|
2464
|
+
/** Same-origin endpoint serving one session-owned original generated image. */
|
|
2465
|
+
const OPENAI_CODEX_ORIGINAL_IMAGE_PATH = "/plugins/dsh-codex-connect/images/original";
|
|
2466
|
+
/** Opaque identifier format for one plugin-owned original image. */
|
|
2467
|
+
const OPENAI_CODEX_IMAGE_ASSET_ID_PATTERN = /^img_[0-9a-f]{32}$/u;
|
|
2468
|
+
function positiveSafeInteger$3(value) {
|
|
2469
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
2470
|
+
}
|
|
2471
|
+
/** Decode session-log metadata without trusting an asset id, filename, or media type. */
|
|
2472
|
+
function decodeOpenAICodexOriginalImageRef(value) {
|
|
2473
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
2474
|
+
const candidate = value;
|
|
2475
|
+
if (typeof candidate.assetId !== "string" || !OPENAI_CODEX_IMAGE_ASSET_ID_PATTERN.test(candidate.assetId) || candidate.mediaType !== "image/png" && candidate.mediaType !== "image/jpeg" && candidate.mediaType !== "image/webp" || !positiveSafeInteger$3(candidate.width) || !positiveSafeInteger$3(candidate.height) || !positiveSafeInteger$3(candidate.bytes) || candidate.bytes > 50331648 || typeof candidate.name !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(candidate.name) || typeof candidate.sha256 !== "string" || !/^[0-9a-f]{64}$/u.test(candidate.sha256)) return void 0;
|
|
2476
|
+
return {
|
|
2477
|
+
assetId: candidate.assetId,
|
|
2478
|
+
mediaType: candidate.mediaType,
|
|
2479
|
+
width: candidate.width,
|
|
2480
|
+
height: candidate.height,
|
|
2481
|
+
bytes: candidate.bytes,
|
|
2482
|
+
name: candidate.name,
|
|
2483
|
+
sha256: candidate.sha256
|
|
2484
|
+
};
|
|
2485
|
+
}
|
|
2486
|
+
function imageInputObject(value) {
|
|
2487
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
2488
|
+
}
|
|
2489
|
+
function positive(value) {
|
|
2490
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
2491
|
+
}
|
|
2492
|
+
function identifier(value) {
|
|
2493
|
+
return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9:._-]{0,255}$/u.test(value);
|
|
2494
|
+
}
|
|
2495
|
+
function only(value, keys) {
|
|
2496
|
+
return Object.keys(value).every((key) => keys.includes(key));
|
|
2497
|
+
}
|
|
2498
|
+
/** Copy the exact published host reference vocabulary, including normalization metadata. */
|
|
2499
|
+
function decodeImageInputAttachment(value) {
|
|
2500
|
+
const ref = imageInputObject(value);
|
|
2501
|
+
if (ref === void 0 || !only(ref, [
|
|
2502
|
+
"attachmentId",
|
|
2503
|
+
"mediaType",
|
|
2504
|
+
"width",
|
|
2505
|
+
"height",
|
|
2506
|
+
"bytes",
|
|
2507
|
+
"name",
|
|
2508
|
+
"originalDimensions"
|
|
2509
|
+
]) || !identifier(ref.attachmentId) || ![
|
|
2510
|
+
"image/png",
|
|
2511
|
+
"image/jpeg",
|
|
2512
|
+
"image/webp"
|
|
2513
|
+
].includes(String(ref.mediaType)) || !positive(ref.width) || !positive(ref.height) || !positive(ref.bytes) || ref.name !== void 0 && (typeof ref.name !== "string" || ref.name.length < 1 || ref.name.length > 512)) return void 0;
|
|
2514
|
+
const dimensions = ref.originalDimensions === void 0 ? void 0 : imageInputObject(ref.originalDimensions);
|
|
2515
|
+
if (ref.originalDimensions !== void 0 && (dimensions === void 0 || !only(dimensions, ["width", "height"]) || !positive(dimensions.width) || !positive(dimensions.height))) return void 0;
|
|
2516
|
+
return {
|
|
2517
|
+
attachmentId: ref.attachmentId,
|
|
2518
|
+
mediaType: ref.mediaType,
|
|
2519
|
+
width: ref.width,
|
|
2520
|
+
height: ref.height,
|
|
2521
|
+
bytes: ref.bytes,
|
|
2522
|
+
...ref.name === void 0 ? {} : { name: ref.name },
|
|
2523
|
+
...dimensions === void 0 ? {} : { originalDimensions: {
|
|
2524
|
+
width: dimensions.width,
|
|
2525
|
+
height: dimensions.height
|
|
2526
|
+
} }
|
|
2527
|
+
};
|
|
2528
|
+
}
|
|
2529
|
+
/** Exactly one selector; a guessed ID or caller-provided metadata is not an authorization proof. */
|
|
2530
|
+
function decodeImageInputRef(value) {
|
|
2531
|
+
const ref = imageInputObject(value);
|
|
2532
|
+
if (ref === void 0) return void 0;
|
|
2533
|
+
if (typeof ref.assetId === "string" && OPENAI_CODEX_IMAGE_ASSET_ID_PATTERN.test(ref.assetId) && only(ref, ["assetId"])) return { assetId: ref.assetId };
|
|
2534
|
+
const preview = ref.usePreview === true ? { usePreview: true } : {};
|
|
2535
|
+
if (ref.usePreview !== void 0 && ref.usePreview !== true) return void 0;
|
|
2536
|
+
if (identifier(ref.attachmentId) && only(ref, ["attachmentId", "usePreview"])) return {
|
|
2537
|
+
attachmentId: ref.attachmentId,
|
|
2538
|
+
...preview
|
|
2539
|
+
};
|
|
2540
|
+
const attachment = decodeImageInputAttachment(ref.attachment);
|
|
2541
|
+
if (attachment !== void 0 && only(ref, ["attachment", "usePreview"])) return {
|
|
2542
|
+
attachment,
|
|
2543
|
+
...preview
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
function decodeImageEditSources(value) {
|
|
2547
|
+
const candidate = imageInputObject(value);
|
|
2548
|
+
if (candidate === void 0 || !only(candidate, ["target", "references"])) return void 0;
|
|
2549
|
+
const target = decodeImageInputRef(candidate.target);
|
|
2550
|
+
if (target === void 0 || !Array.isArray(candidate.references) || candidate.references.length >= 5) return void 0;
|
|
2551
|
+
const references = [];
|
|
2552
|
+
for (const item of candidate.references) {
|
|
2553
|
+
const ref = imageInputObject(item);
|
|
2554
|
+
if (ref === void 0 || !only(ref, ["image", "purpose"]) || typeof ref.purpose !== "string" || ref.purpose.trim().length === 0 || ref.purpose.length > 512) return void 0;
|
|
2555
|
+
const image = decodeImageInputRef(ref.image);
|
|
2556
|
+
if (image === void 0) return void 0;
|
|
2557
|
+
references.push({
|
|
2558
|
+
image,
|
|
2559
|
+
purpose: ref.purpose.trim()
|
|
2560
|
+
});
|
|
2561
|
+
}
|
|
2562
|
+
return {
|
|
2563
|
+
target,
|
|
2564
|
+
references
|
|
2565
|
+
};
|
|
2566
|
+
}
|
|
2567
|
+
/** Preserve prompt-only calls; edit intent can never degrade to generation on invalid inputs. */
|
|
2568
|
+
function decodeImageToolRequest(value) {
|
|
2569
|
+
const request = imageInputObject(value);
|
|
2570
|
+
if (request === void 0 || typeof request.prompt !== "string") return void 0;
|
|
2571
|
+
const prompt = request.prompt.trim();
|
|
2572
|
+
if (prompt.length < 1 || prompt.length > 32e3) return void 0;
|
|
2573
|
+
if ((request.operation === void 0 || request.operation === "generate") && only(request, ["prompt", "operation"])) return {
|
|
2574
|
+
operation: "generate",
|
|
2575
|
+
prompt
|
|
2576
|
+
};
|
|
2577
|
+
if (request.operation !== "edit" || !only(request, [
|
|
2578
|
+
"operation",
|
|
2579
|
+
"prompt",
|
|
2580
|
+
"target",
|
|
2581
|
+
"references"
|
|
2582
|
+
])) return void 0;
|
|
2583
|
+
const edit = decodeImageEditSources({
|
|
2584
|
+
target: request.target,
|
|
2585
|
+
references: request.references === void 0 ? [] : request.references
|
|
2586
|
+
});
|
|
2587
|
+
return edit === void 0 ? void 0 : {
|
|
2588
|
+
operation: "edit",
|
|
2589
|
+
prompt,
|
|
2590
|
+
edit
|
|
2591
|
+
};
|
|
2592
|
+
}
|
|
2593
|
+
const IMAGE_INPUT_SCHEMA = {
|
|
2594
|
+
type: "object",
|
|
2595
|
+
additionalProperties: false,
|
|
2596
|
+
description: "Select exactly one: assetId for an original result, attachmentId from this session, or a complete attachment reference. For uploaded copies, including first/second attached image, copy the complete attachment reference from the adjacent handle line. A bare attachmentId shared with a generated result is ambiguous; assetId explicitly selects a stored original. usePreview=true is only for an explicitly chosen lower-resolution preview.",
|
|
2597
|
+
properties: {
|
|
2598
|
+
assetId: { type: "string" },
|
|
2599
|
+
attachmentId: { type: "string" },
|
|
2600
|
+
attachment: {
|
|
2601
|
+
type: "object",
|
|
2602
|
+
additionalProperties: false,
|
|
2603
|
+
properties: {
|
|
2604
|
+
attachmentId: {
|
|
2605
|
+
type: "string",
|
|
2606
|
+
required: true
|
|
2607
|
+
},
|
|
2608
|
+
mediaType: {
|
|
2609
|
+
type: "string",
|
|
2610
|
+
required: true,
|
|
2611
|
+
enum: [
|
|
2612
|
+
"image/png",
|
|
2613
|
+
"image/jpeg",
|
|
2614
|
+
"image/webp"
|
|
2615
|
+
]
|
|
2616
|
+
},
|
|
2617
|
+
width: {
|
|
2618
|
+
type: "integer",
|
|
2619
|
+
required: true
|
|
2620
|
+
},
|
|
2621
|
+
height: {
|
|
2622
|
+
type: "integer",
|
|
2623
|
+
required: true
|
|
2624
|
+
},
|
|
2625
|
+
bytes: {
|
|
2626
|
+
type: "integer",
|
|
2627
|
+
required: true
|
|
2628
|
+
},
|
|
2629
|
+
name: { type: "string" },
|
|
2630
|
+
originalDimensions: {
|
|
2631
|
+
type: "object",
|
|
2632
|
+
additionalProperties: false,
|
|
2633
|
+
properties: {
|
|
2634
|
+
width: {
|
|
2635
|
+
type: "integer",
|
|
2636
|
+
required: true
|
|
2637
|
+
},
|
|
2638
|
+
height: {
|
|
2639
|
+
type: "integer",
|
|
2640
|
+
required: true
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
},
|
|
2646
|
+
usePreview: { type: "boolean" }
|
|
2647
|
+
}
|
|
2648
|
+
};
|
|
2649
|
+
const IMAGE_REFERENCES_SCHEMA = {
|
|
2650
|
+
type: "array",
|
|
2651
|
+
description: "Reference images only, kept in the same order the user specified; never place the edit target here.",
|
|
2652
|
+
items: {
|
|
2653
|
+
type: "object",
|
|
2654
|
+
additionalProperties: false,
|
|
2655
|
+
properties: {
|
|
2656
|
+
image: {
|
|
2657
|
+
...IMAGE_INPUT_SCHEMA,
|
|
2658
|
+
required: true
|
|
2659
|
+
},
|
|
2660
|
+
purpose: {
|
|
2661
|
+
type: "string",
|
|
2662
|
+
required: true,
|
|
2663
|
+
description: "What to borrow, such as colors or texture, without replacing the target."
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
};
|
|
2668
|
+
const IMAGE_EDIT_SOURCES_SCHEMA = {
|
|
2669
|
+
type: "object",
|
|
2670
|
+
additionalProperties: false,
|
|
2671
|
+
properties: {
|
|
2672
|
+
target: {
|
|
2673
|
+
...IMAGE_INPUT_SCHEMA,
|
|
2674
|
+
required: true
|
|
2675
|
+
},
|
|
2676
|
+
references: {
|
|
2677
|
+
...IMAGE_REFERENCES_SCHEMA,
|
|
2678
|
+
required: true
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
};
|
|
2682
|
+
//#endregion
|
|
2463
2683
|
//#region src/adapter.ts
|
|
2464
2684
|
/** OpenAI Codex adapter assembled from public dsh-llm-pi-ai extension points. */
|
|
2465
2685
|
/** Provider idle ceiling used by the composite route. */
|
|
@@ -2613,9 +2833,11 @@ function withOpenAICodexImageSelectionHandles(options) {
|
|
|
2613
2833
|
if (block.type !== "image") continue;
|
|
2614
2834
|
imageIndex += 1;
|
|
2615
2835
|
const name = block.attachment.name === void 0 ? "" : ` ${JSON.stringify(block.attachment.name)}`;
|
|
2836
|
+
const attachment = decodeImageInputAttachment(block.attachment);
|
|
2837
|
+
const exactSelection = attachment === void 0 ? "" : ` To edit this uploaded copy, use attachment=${JSON.stringify(attachment)}. For a generated original, use its result assetId instead.`;
|
|
2616
2838
|
content.push({
|
|
2617
2839
|
type: "text",
|
|
2618
|
-
text: `[Codex Connect image ${String(imageIndex)} in this message:${name} attachmentId=${String(block.attachment.attachmentId)}. For image editing,
|
|
2840
|
+
text: `[Codex Connect image ${String(imageIndex)} in this message:${name} attachmentId=${String(block.attachment.attachmentId)}. For image editing, this ID alone may also identify a historical generated preview.${exactSelection}]`
|
|
2619
2841
|
});
|
|
2620
2842
|
contentChanged = true;
|
|
2621
2843
|
}
|
|
@@ -5301,226 +5523,6 @@ function registerOpenAICodexModelCatalogRoute(ctx, resolveCatalog, trustedOrigin
|
|
|
5301
5523
|
}), "dsh-codex-connect: model catalog route");
|
|
5302
5524
|
}
|
|
5303
5525
|
//#endregion
|
|
5304
|
-
//#region src/image-assets-contract.ts
|
|
5305
|
-
/** Same-origin endpoint serving one session-owned original generated image. */
|
|
5306
|
-
const OPENAI_CODEX_ORIGINAL_IMAGE_PATH = "/plugins/dsh-codex-connect/images/original";
|
|
5307
|
-
/** Opaque identifier format for one plugin-owned original image. */
|
|
5308
|
-
const OPENAI_CODEX_IMAGE_ASSET_ID_PATTERN = /^img_[0-9a-f]{32}$/u;
|
|
5309
|
-
function positiveSafeInteger$3(value) {
|
|
5310
|
-
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
5311
|
-
}
|
|
5312
|
-
/** Decode session-log metadata without trusting an asset id, filename, or media type. */
|
|
5313
|
-
function decodeOpenAICodexOriginalImageRef(value) {
|
|
5314
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
5315
|
-
const candidate = value;
|
|
5316
|
-
if (typeof candidate.assetId !== "string" || !OPENAI_CODEX_IMAGE_ASSET_ID_PATTERN.test(candidate.assetId) || candidate.mediaType !== "image/png" && candidate.mediaType !== "image/jpeg" && candidate.mediaType !== "image/webp" || !positiveSafeInteger$3(candidate.width) || !positiveSafeInteger$3(candidate.height) || !positiveSafeInteger$3(candidate.bytes) || candidate.bytes > 50331648 || typeof candidate.name !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(candidate.name) || typeof candidate.sha256 !== "string" || !/^[0-9a-f]{64}$/u.test(candidate.sha256)) return void 0;
|
|
5317
|
-
return {
|
|
5318
|
-
assetId: candidate.assetId,
|
|
5319
|
-
mediaType: candidate.mediaType,
|
|
5320
|
-
width: candidate.width,
|
|
5321
|
-
height: candidate.height,
|
|
5322
|
-
bytes: candidate.bytes,
|
|
5323
|
-
name: candidate.name,
|
|
5324
|
-
sha256: candidate.sha256
|
|
5325
|
-
};
|
|
5326
|
-
}
|
|
5327
|
-
function imageInputObject(value) {
|
|
5328
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
5329
|
-
}
|
|
5330
|
-
function positive(value) {
|
|
5331
|
-
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
5332
|
-
}
|
|
5333
|
-
function identifier(value) {
|
|
5334
|
-
return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9:._-]{0,255}$/u.test(value);
|
|
5335
|
-
}
|
|
5336
|
-
function only(value, keys) {
|
|
5337
|
-
return Object.keys(value).every((key) => keys.includes(key));
|
|
5338
|
-
}
|
|
5339
|
-
/** Copy the exact published host reference vocabulary, including normalization metadata. */
|
|
5340
|
-
function decodeImageInputAttachment(value) {
|
|
5341
|
-
const ref = imageInputObject(value);
|
|
5342
|
-
if (ref === void 0 || !only(ref, [
|
|
5343
|
-
"attachmentId",
|
|
5344
|
-
"mediaType",
|
|
5345
|
-
"width",
|
|
5346
|
-
"height",
|
|
5347
|
-
"bytes",
|
|
5348
|
-
"name",
|
|
5349
|
-
"originalDimensions"
|
|
5350
|
-
]) || !identifier(ref.attachmentId) || ![
|
|
5351
|
-
"image/png",
|
|
5352
|
-
"image/jpeg",
|
|
5353
|
-
"image/webp"
|
|
5354
|
-
].includes(String(ref.mediaType)) || !positive(ref.width) || !positive(ref.height) || !positive(ref.bytes) || ref.name !== void 0 && (typeof ref.name !== "string" || ref.name.length < 1 || ref.name.length > 512)) return void 0;
|
|
5355
|
-
const dimensions = ref.originalDimensions === void 0 ? void 0 : imageInputObject(ref.originalDimensions);
|
|
5356
|
-
if (ref.originalDimensions !== void 0 && (dimensions === void 0 || !only(dimensions, ["width", "height"]) || !positive(dimensions.width) || !positive(dimensions.height))) return void 0;
|
|
5357
|
-
return {
|
|
5358
|
-
attachmentId: ref.attachmentId,
|
|
5359
|
-
mediaType: ref.mediaType,
|
|
5360
|
-
width: ref.width,
|
|
5361
|
-
height: ref.height,
|
|
5362
|
-
bytes: ref.bytes,
|
|
5363
|
-
...ref.name === void 0 ? {} : { name: ref.name },
|
|
5364
|
-
...dimensions === void 0 ? {} : { originalDimensions: {
|
|
5365
|
-
width: dimensions.width,
|
|
5366
|
-
height: dimensions.height
|
|
5367
|
-
} }
|
|
5368
|
-
};
|
|
5369
|
-
}
|
|
5370
|
-
/** Exactly one selector; a guessed ID or caller-provided metadata is not an authorization proof. */
|
|
5371
|
-
function decodeImageInputRef(value) {
|
|
5372
|
-
const ref = imageInputObject(value);
|
|
5373
|
-
if (ref === void 0) return void 0;
|
|
5374
|
-
if (typeof ref.assetId === "string" && OPENAI_CODEX_IMAGE_ASSET_ID_PATTERN.test(ref.assetId) && only(ref, ["assetId"])) return { assetId: ref.assetId };
|
|
5375
|
-
const preview = ref.usePreview === true ? { usePreview: true } : {};
|
|
5376
|
-
if (ref.usePreview !== void 0 && ref.usePreview !== true) return void 0;
|
|
5377
|
-
if (identifier(ref.attachmentId) && only(ref, ["attachmentId", "usePreview"])) return {
|
|
5378
|
-
attachmentId: ref.attachmentId,
|
|
5379
|
-
...preview
|
|
5380
|
-
};
|
|
5381
|
-
const attachment = decodeImageInputAttachment(ref.attachment);
|
|
5382
|
-
if (attachment !== void 0 && only(ref, ["attachment", "usePreview"])) return {
|
|
5383
|
-
attachment,
|
|
5384
|
-
...preview
|
|
5385
|
-
};
|
|
5386
|
-
}
|
|
5387
|
-
function decodeImageEditSources(value) {
|
|
5388
|
-
const candidate = imageInputObject(value);
|
|
5389
|
-
if (candidate === void 0 || !only(candidate, ["target", "references"])) return void 0;
|
|
5390
|
-
const target = decodeImageInputRef(candidate.target);
|
|
5391
|
-
if (target === void 0 || !Array.isArray(candidate.references) || candidate.references.length >= 5) return void 0;
|
|
5392
|
-
const references = [];
|
|
5393
|
-
for (const item of candidate.references) {
|
|
5394
|
-
const ref = imageInputObject(item);
|
|
5395
|
-
if (ref === void 0 || !only(ref, ["image", "purpose"]) || typeof ref.purpose !== "string" || ref.purpose.trim().length === 0 || ref.purpose.length > 512) return void 0;
|
|
5396
|
-
const image = decodeImageInputRef(ref.image);
|
|
5397
|
-
if (image === void 0) return void 0;
|
|
5398
|
-
references.push({
|
|
5399
|
-
image,
|
|
5400
|
-
purpose: ref.purpose.trim()
|
|
5401
|
-
});
|
|
5402
|
-
}
|
|
5403
|
-
return {
|
|
5404
|
-
target,
|
|
5405
|
-
references
|
|
5406
|
-
};
|
|
5407
|
-
}
|
|
5408
|
-
/** Preserve prompt-only calls; edit intent can never degrade to generation on invalid inputs. */
|
|
5409
|
-
function decodeImageToolRequest(value) {
|
|
5410
|
-
const request = imageInputObject(value);
|
|
5411
|
-
if (request === void 0 || typeof request.prompt !== "string") return void 0;
|
|
5412
|
-
const prompt = request.prompt.trim();
|
|
5413
|
-
if (prompt.length < 1 || prompt.length > 32e3) return void 0;
|
|
5414
|
-
if ((request.operation === void 0 || request.operation === "generate") && only(request, ["prompt", "operation"])) return {
|
|
5415
|
-
operation: "generate",
|
|
5416
|
-
prompt
|
|
5417
|
-
};
|
|
5418
|
-
if (request.operation !== "edit" || !only(request, [
|
|
5419
|
-
"operation",
|
|
5420
|
-
"prompt",
|
|
5421
|
-
"target",
|
|
5422
|
-
"references"
|
|
5423
|
-
])) return void 0;
|
|
5424
|
-
const edit = decodeImageEditSources({
|
|
5425
|
-
target: request.target,
|
|
5426
|
-
references: request.references === void 0 ? [] : request.references
|
|
5427
|
-
});
|
|
5428
|
-
return edit === void 0 ? void 0 : {
|
|
5429
|
-
operation: "edit",
|
|
5430
|
-
prompt,
|
|
5431
|
-
edit
|
|
5432
|
-
};
|
|
5433
|
-
}
|
|
5434
|
-
const IMAGE_INPUT_SCHEMA = {
|
|
5435
|
-
type: "object",
|
|
5436
|
-
additionalProperties: false,
|
|
5437
|
-
description: "Select exactly one: assetId for an original result, attachmentId from this session, or a complete attachment reference. For wording like first/second image, copy the stable attachmentId from the model-visible handle line adjacent to that request image. usePreview=true is only for an explicitly chosen lower-resolution preview.",
|
|
5438
|
-
properties: {
|
|
5439
|
-
assetId: { type: "string" },
|
|
5440
|
-
attachmentId: { type: "string" },
|
|
5441
|
-
attachment: {
|
|
5442
|
-
type: "object",
|
|
5443
|
-
additionalProperties: false,
|
|
5444
|
-
properties: {
|
|
5445
|
-
attachmentId: {
|
|
5446
|
-
type: "string",
|
|
5447
|
-
required: true
|
|
5448
|
-
},
|
|
5449
|
-
mediaType: {
|
|
5450
|
-
type: "string",
|
|
5451
|
-
required: true,
|
|
5452
|
-
enum: [
|
|
5453
|
-
"image/png",
|
|
5454
|
-
"image/jpeg",
|
|
5455
|
-
"image/webp"
|
|
5456
|
-
]
|
|
5457
|
-
},
|
|
5458
|
-
width: {
|
|
5459
|
-
type: "integer",
|
|
5460
|
-
required: true
|
|
5461
|
-
},
|
|
5462
|
-
height: {
|
|
5463
|
-
type: "integer",
|
|
5464
|
-
required: true
|
|
5465
|
-
},
|
|
5466
|
-
bytes: {
|
|
5467
|
-
type: "integer",
|
|
5468
|
-
required: true
|
|
5469
|
-
},
|
|
5470
|
-
name: { type: "string" },
|
|
5471
|
-
originalDimensions: {
|
|
5472
|
-
type: "object",
|
|
5473
|
-
additionalProperties: false,
|
|
5474
|
-
properties: {
|
|
5475
|
-
width: {
|
|
5476
|
-
type: "integer",
|
|
5477
|
-
required: true
|
|
5478
|
-
},
|
|
5479
|
-
height: {
|
|
5480
|
-
type: "integer",
|
|
5481
|
-
required: true
|
|
5482
|
-
}
|
|
5483
|
-
}
|
|
5484
|
-
}
|
|
5485
|
-
}
|
|
5486
|
-
},
|
|
5487
|
-
usePreview: { type: "boolean" }
|
|
5488
|
-
}
|
|
5489
|
-
};
|
|
5490
|
-
const IMAGE_REFERENCES_SCHEMA = {
|
|
5491
|
-
type: "array",
|
|
5492
|
-
description: "Reference images only, kept in the same order the user specified; never place the edit target here.",
|
|
5493
|
-
items: {
|
|
5494
|
-
type: "object",
|
|
5495
|
-
additionalProperties: false,
|
|
5496
|
-
properties: {
|
|
5497
|
-
image: {
|
|
5498
|
-
...IMAGE_INPUT_SCHEMA,
|
|
5499
|
-
required: true
|
|
5500
|
-
},
|
|
5501
|
-
purpose: {
|
|
5502
|
-
type: "string",
|
|
5503
|
-
required: true,
|
|
5504
|
-
description: "What to borrow, such as colors or texture, without replacing the target."
|
|
5505
|
-
}
|
|
5506
|
-
}
|
|
5507
|
-
}
|
|
5508
|
-
};
|
|
5509
|
-
const IMAGE_EDIT_SOURCES_SCHEMA = {
|
|
5510
|
-
type: "object",
|
|
5511
|
-
additionalProperties: false,
|
|
5512
|
-
properties: {
|
|
5513
|
-
target: {
|
|
5514
|
-
...IMAGE_INPUT_SCHEMA,
|
|
5515
|
-
required: true
|
|
5516
|
-
},
|
|
5517
|
-
references: {
|
|
5518
|
-
...IMAGE_REFERENCES_SCHEMA,
|
|
5519
|
-
required: true
|
|
5520
|
-
}
|
|
5521
|
-
}
|
|
5522
|
-
};
|
|
5523
|
-
//#endregion
|
|
5524
5526
|
//#region src/image-presentation.ts
|
|
5525
5527
|
/** Stable metadata marker for generated image result views. */
|
|
5526
5528
|
const IMAGE_PRESENTATION_KIND = "codex-connect-images";
|
|
@@ -5659,7 +5661,8 @@ function sessionImageInventory(session) {
|
|
|
5659
5661
|
const result = {
|
|
5660
5662
|
attachments: /* @__PURE__ */ new Map(),
|
|
5661
5663
|
results: /* @__PURE__ */ new Map(),
|
|
5662
|
-
originals: /* @__PURE__ */ new Map()
|
|
5664
|
+
originals: /* @__PURE__ */ new Map(),
|
|
5665
|
+
uploads: /* @__PURE__ */ new Map()
|
|
5663
5666
|
};
|
|
5664
5667
|
const addRef = (value) => {
|
|
5665
5668
|
const ref = decodeImageInputAttachment(value);
|
|
@@ -5670,12 +5673,18 @@ function sessionImageInventory(session) {
|
|
|
5670
5673
|
result.attachments.set(id, occurrences);
|
|
5671
5674
|
return ref;
|
|
5672
5675
|
};
|
|
5673
|
-
const add = (content) => {
|
|
5676
|
+
const add = (content, userUpload = false) => {
|
|
5674
5677
|
if (!Array.isArray(content)) return;
|
|
5675
5678
|
for (const block of content) {
|
|
5676
5679
|
const candidate = imageInputObject(block);
|
|
5677
5680
|
if (candidate?.type !== "image") continue;
|
|
5678
|
-
addRef(candidate.attachment);
|
|
5681
|
+
const ref = addRef(candidate.attachment);
|
|
5682
|
+
if (userUpload && ref !== void 0) {
|
|
5683
|
+
const id = String(ref.attachmentId);
|
|
5684
|
+
const occurrences = result.uploads.get(id) ?? /* @__PURE__ */ new Map();
|
|
5685
|
+
occurrences.set(JSON.stringify(ref), ref);
|
|
5686
|
+
result.uploads.set(id, occurrences);
|
|
5687
|
+
}
|
|
5679
5688
|
}
|
|
5680
5689
|
};
|
|
5681
5690
|
for (const event of session.snapshotEvents()) {
|
|
@@ -5699,7 +5708,10 @@ function sessionImageInventory(session) {
|
|
|
5699
5708
|
continue;
|
|
5700
5709
|
}
|
|
5701
5710
|
if (event.type === "agent/inbox/spliced") {
|
|
5702
|
-
if (Array.isArray(data?.inserted)) for (const message of data.inserted)
|
|
5711
|
+
if (Array.isArray(data?.inserted)) for (const message of data.inserted) {
|
|
5712
|
+
const inserted = imageInputObject(message);
|
|
5713
|
+
add(inserted?.content, imageInputObject(inserted?.source)?.kind === "user");
|
|
5714
|
+
}
|
|
5703
5715
|
continue;
|
|
5704
5716
|
}
|
|
5705
5717
|
if (event.type === "compaction/summary") {
|
|
@@ -5708,7 +5720,7 @@ function sessionImageInventory(session) {
|
|
|
5708
5720
|
continue;
|
|
5709
5721
|
}
|
|
5710
5722
|
const message = deriveEventMessage(event);
|
|
5711
|
-
if (message !== null) add(message.content);
|
|
5723
|
+
if (message !== null) add(message.content, event.type === "user/message" && message.source.kind === "user");
|
|
5712
5724
|
}
|
|
5713
5725
|
return result;
|
|
5714
5726
|
}
|
|
@@ -5766,7 +5778,7 @@ function registerOpenAICodexOriginalImageRoute(ctx, trustedOrigins, assets) {
|
|
|
5766
5778
|
}
|
|
5767
5779
|
//#endregion
|
|
5768
5780
|
//#region src/version.ts
|
|
5769
|
-
const CODEX_CONNECT_VERSION = "0.1.0-alpha.4.
|
|
5781
|
+
const CODEX_CONNECT_VERSION = "0.1.0-alpha.4.49";
|
|
5770
5782
|
//#endregion
|
|
5771
5783
|
//#region src/fast-mode-defaults.ts
|
|
5772
5784
|
/**
|
|
@@ -5876,10 +5888,85 @@ function decodeStrictBase64(value) {
|
|
|
5876
5888
|
return decoded.byteLength === expected ? new Uint8Array(decoded) : void 0;
|
|
5877
5889
|
}
|
|
5878
5890
|
//#endregion
|
|
5891
|
+
//#region src/image-error-contract.ts
|
|
5892
|
+
/** Node-free, fixed public image failures. Unknown provider/host text is never rendered. */
|
|
5893
|
+
const IMAGE_INPUT_FAILURE_REASONS = [
|
|
5894
|
+
"shorten the instructions or reference descriptions.",
|
|
5895
|
+
"requires valid, bounded image selections.",
|
|
5896
|
+
"requires the current session and its image history.",
|
|
5897
|
+
"requires complete host image limits.",
|
|
5898
|
+
"too many inputs for this deployment.",
|
|
5899
|
+
"is unavailable in this session. Select or attach the image again.",
|
|
5900
|
+
"is unavailable or does not match a reference in this session. Select or attach the image again.",
|
|
5901
|
+
"identifies both an upload and a generated result. Select the uploaded attachment explicitly or choose an exact original image.",
|
|
5902
|
+
"matches several original results. Select one exact original image.",
|
|
5903
|
+
"only a preview is available. Explicitly choose that preview or attach an original.",
|
|
5904
|
+
"has unsupported attachment metadata.",
|
|
5905
|
+
"exceeds this deployment's image limits or uses an unsupported format.",
|
|
5906
|
+
"exceeds this deployment's total input limit.",
|
|
5907
|
+
"the original is unavailable or failed integrity checks; no preview was substituted.",
|
|
5908
|
+
"the stored bytes do not match the image reference.",
|
|
5909
|
+
"cannot be read or validated. No image request was sent.",
|
|
5910
|
+
"is required."
|
|
5911
|
+
];
|
|
5912
|
+
function imageInputFailureMessage(label, reason) {
|
|
5913
|
+
return `${label}: ${reason}`;
|
|
5914
|
+
}
|
|
5915
|
+
const TRANSPORT_MESSAGES = {
|
|
5916
|
+
OPENAI_CODEX_SIGNED_OUT: "Sign in to OpenAI Codex before generating images.",
|
|
5917
|
+
OPENAI_CODEX_REAUTH_REQUIRED: "Renew OpenAI Codex authorization before generating images.",
|
|
5918
|
+
OPENAI_CODEX_RATE_LIMITED: "Image generation is temporarily unavailable. Try again later.",
|
|
5919
|
+
OPENAI_CODEX_TIMEOUT: "Image generation timed out. The request may still be processing.",
|
|
5920
|
+
OPENAI_CODEX_CANCELED: "Image generation was canceled. The request may still be processing.",
|
|
5921
|
+
OPENAI_CODEX_NETWORK_ERROR: "The image generation request lost its network connection. The request may still be processing.",
|
|
5922
|
+
OPENAI_CODEX_UPSTREAM_REJECTED: "The image generation request was rejected.",
|
|
5923
|
+
OPENAI_CODEX_UPSTREAM_UNAVAILABLE: "Image generation is temporarily unavailable.",
|
|
5924
|
+
OPENAI_CODEX_RESPONSE_TOO_LARGE: "The image generation response exceeded the safe size limit.",
|
|
5925
|
+
OPENAI_CODEX_MALFORMED_RESPONSE: "The image generation response was unreadable."
|
|
5926
|
+
};
|
|
5927
|
+
const UNKNOWN_TRANSPORT_MESSAGE = "Image generation failed without exposing private response details.";
|
|
5928
|
+
function imageTransportErrorMessage(code) {
|
|
5929
|
+
return typeof code === "string" && Object.hasOwn(TRANSPORT_MESSAGES, code) ? TRANSPORT_MESSAGES[code] : UNKNOWN_TRANSPORT_MESSAGE;
|
|
5930
|
+
}
|
|
5931
|
+
const failures = /* @__PURE__ */ new Map();
|
|
5932
|
+
function register(message, retryable, recovery) {
|
|
5933
|
+
for (const prefix of ["", "Error: "]) {
|
|
5934
|
+
const text = prefix + message;
|
|
5935
|
+
failures.set(text, {
|
|
5936
|
+
message: text,
|
|
5937
|
+
retryable,
|
|
5938
|
+
...recovery === void 0 ? {} : { recovery }
|
|
5939
|
+
});
|
|
5940
|
+
}
|
|
5941
|
+
}
|
|
5942
|
+
for (const label of [
|
|
5943
|
+
"Edit instructions",
|
|
5944
|
+
"Image editing",
|
|
5945
|
+
"Image batch",
|
|
5946
|
+
"Target image",
|
|
5947
|
+
"Reference image 1",
|
|
5948
|
+
"Reference image 2",
|
|
5949
|
+
"Reference image 3",
|
|
5950
|
+
"Reference image 4"
|
|
5951
|
+
]) for (const reason of IMAGE_INPUT_FAILURE_REASONS) register(imageInputFailureMessage(label, reason), false, "input");
|
|
5952
|
+
for (const [code, message] of Object.entries(TRANSPORT_MESSAGES)) {
|
|
5953
|
+
const account = code === "OPENAI_CODEX_SIGNED_OUT" || code === "OPENAI_CODEX_REAUTH_REQUIRED";
|
|
5954
|
+
register(message, !account, account ? "account" : void 0);
|
|
5955
|
+
}
|
|
5956
|
+
register(UNKNOWN_TRANSPORT_MESSAGE, true);
|
|
5957
|
+
register("Invalid image request. Editing requires operation=edit, one explicit target and valid references; no generation was attempted.", false, "input");
|
|
5958
|
+
register("This Codex Connect transport does not support editing. No generation was attempted.", false, "input");
|
|
5959
|
+
register("The Codex Connect image transport is unavailable.", false, "input");
|
|
5960
|
+
for (const message of [
|
|
5961
|
+
"The generated original images could not be saved.",
|
|
5962
|
+
"The generated images could not be saved; no attachment references were returned.",
|
|
5963
|
+
"The image stores returned an incomplete image batch."
|
|
5964
|
+
]) register(message, false, "storage");
|
|
5965
|
+
//#endregion
|
|
5879
5966
|
//#region src/image-inputs.ts
|
|
5880
5967
|
var ImageInputError = class extends Error {};
|
|
5881
5968
|
function fail$1(label, reason) {
|
|
5882
|
-
throw new ImageInputError(
|
|
5969
|
+
throw new ImageInputError(imageInputFailureMessage(label, reason));
|
|
5883
5970
|
}
|
|
5884
5971
|
/** Includes no input IDs or raw metadata in error messages. */
|
|
5885
5972
|
function promptForImageEdit(prompt, sources) {
|
|
@@ -5906,7 +5993,7 @@ async function resolveImageEditInputs(ctx, assets, sources, exec) {
|
|
|
5906
5993
|
const inputs = [sources.target, ...sources.references.map((ref) => ref.image)];
|
|
5907
5994
|
if (inputs.length > Math.min(5, limits.maxImagesPerMessage)) fail$1("Image batch", "too many inputs for this deployment.");
|
|
5908
5995
|
const candidates = inputs.map((source, index) => {
|
|
5909
|
-
const label = index === 0 ? "Target image" : `Reference image ${
|
|
5996
|
+
const label = index === 0 ? "Target image" : `Reference image ${index}`;
|
|
5910
5997
|
if ("assetId" in source) {
|
|
5911
5998
|
const ref = inventory.originals.get(source.assetId);
|
|
5912
5999
|
if (ref === void 0) fail$1(label, "is unavailable in this session. Select or attach the image again.");
|
|
@@ -5921,7 +6008,10 @@ async function resolveImageEditInputs(ctx, assets, sources, exec) {
|
|
|
5921
6008
|
const selectorKey = "attachment" in source ? JSON.stringify(source.attachment) : void 0;
|
|
5922
6009
|
const ref = selectorKey === void 0 ? occurrences?.values().next().value : occurrences?.get(selectorKey);
|
|
5923
6010
|
if (ref === void 0) fail$1(label, "is unavailable or does not match a reference in this session. Select or attach the image again.");
|
|
5924
|
-
const
|
|
6011
|
+
const uploads = inventory.uploads.get(id);
|
|
6012
|
+
const allResults = [...inventory.results.get(id)?.values() ?? []];
|
|
6013
|
+
if (selectorKey === void 0 && source.usePreview !== true && uploads !== void 0 && allResults.length > 0) fail$1(label, "identifies both an upload and a generated result. Select the uploaded attachment explicitly or choose an exact original image.");
|
|
6014
|
+
const results = selectorKey !== void 0 && uploads?.has(selectorKey) === true ? [] : allResults.filter((result) => selectorKey === void 0 || JSON.stringify(result.preview) === selectorKey);
|
|
5925
6015
|
const result = results[0];
|
|
5926
6016
|
if (result !== void 0 && source.usePreview !== true) {
|
|
5927
6017
|
if (new Set(results.map((item) => item.original?.assetId)).size > 1) fail$1(label, "matches several original results. Select one exact original image.");
|
|
@@ -6003,19 +6093,7 @@ function failure(message) {
|
|
|
6003
6093
|
}
|
|
6004
6094
|
/** Convert transport failures to fixed, secret-free user text. */
|
|
6005
6095
|
function fixedTransportMessage(error) {
|
|
6006
|
-
|
|
6007
|
-
case "OPENAI_CODEX_SIGNED_OUT": return "Sign in to OpenAI Codex before generating images.";
|
|
6008
|
-
case "OPENAI_CODEX_REAUTH_REQUIRED": return "Renew OpenAI Codex authorization before generating images.";
|
|
6009
|
-
case "OPENAI_CODEX_RATE_LIMITED": return "Image generation is temporarily unavailable. Try again later.";
|
|
6010
|
-
case "OPENAI_CODEX_TIMEOUT": return `Image generation timed out. ${CANCELED_REQUEST_NOTE}`;
|
|
6011
|
-
case "OPENAI_CODEX_CANCELED": return `Image generation was canceled. ${CANCELED_REQUEST_NOTE}`;
|
|
6012
|
-
case "OPENAI_CODEX_NETWORK_ERROR": return `The image generation request lost its network connection. ${CANCELED_REQUEST_NOTE}`;
|
|
6013
|
-
case "OPENAI_CODEX_UPSTREAM_REJECTED": return "The image generation request was rejected.";
|
|
6014
|
-
case "OPENAI_CODEX_UPSTREAM_UNAVAILABLE": return "Image generation is temporarily unavailable.";
|
|
6015
|
-
case "OPENAI_CODEX_RESPONSE_TOO_LARGE": return "The image generation response exceeded the safe size limit.";
|
|
6016
|
-
case "OPENAI_CODEX_MALFORMED_RESPONSE": return "The image generation response was unreadable.";
|
|
6017
|
-
default: return "Image generation failed without exposing private response details.";
|
|
6018
|
-
}
|
|
6096
|
+
return imageTransportErrorMessage(typeof error === "object" && error !== null && "code" in error ? error.code : void 0);
|
|
6019
6097
|
}
|
|
6020
6098
|
function extension(mediaType) {
|
|
6021
6099
|
return mediaType === "image/jpeg" ? "jpg" : mediaType.slice(6);
|
|
@@ -6187,7 +6265,7 @@ function imageGenerateTool(ctx, assets) {
|
|
|
6187
6265
|
const inFlight = /* @__PURE__ */ new Map();
|
|
6188
6266
|
return defineTool({
|
|
6189
6267
|
name: IMAGE_GENERATE_TOOL_NAME,
|
|
6190
|
-
description: "Generate a new image, or edit an explicitly selected session image. For edits use operation=edit and target; optional ordered references have separate purposes. When image editing is enabled, Codex Connect places a model-visible handle line immediately after each request image, numbered in that message and containing its stable attachmentId. When the user
|
|
6268
|
+
description: "Generate a new image, or edit an explicitly selected session image. For edits use operation=edit and target; optional ordered references have separate purposes. When image editing is enabled, Codex Connect places a model-visible handle line immediately after each request image, numbered in that message and containing its stable attachmentId. When the user edits an uploaded copy (including first/second attached image), copy the complete attachment reference from the adjacent handle line. An attachmentId shared by an upload and a generated result is ambiguous; ask rather than selecting an older original. For older generated originals use exact assetId handles from the conversation. Never guess or use global recent images; never swap target and reference. Ask when the target is ambiguous. An unavailable edit target must not become text-only generation. Results preserve originals and can be edited again; output size and style are service-controlled.",
|
|
6191
6269
|
parameters: {
|
|
6192
6270
|
prompt: {
|
|
6193
6271
|
type: "string",
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-codex-connect",
|
|
3
3
|
"displayName": "Codex Connect",
|
|
4
4
|
"description": "ChatGPT OAuth and Codex models for DeepSeek Harness.",
|
|
5
|
-
"version": "0.1.0-alpha.4.
|
|
5
|
+
"version": "0.1.0-alpha.4.49",
|
|
6
6
|
"author": "Frank Song",
|
|
7
7
|
"contributors": [
|
|
8
8
|
"Yan-Zero (original dsh-codex author)"
|