@tomflow/chatloop-extension 0.3.44 → 0.3.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  `extension/loop/resources.js` 在既有 Worker 内维护持久资源索引,不引入第二浏览器驱动。正式 Action 同时最多 3 页,已登记执行 Chat 同时最多 2 页(Owner 与 Handoff successor);新建前拒绝超限。已存在的普通 Chat、未知发送、BLOCKED 或带草稿页面不自动关闭。只对精确登记且测试 projectId 为 `cl-intent-e2e-*` 的 DONE Chat 执行空草稿、非激活、URL 未变化的 TTL 回收。用户真实任务的 Chat 不会自动删除;其配额满时安全拒绝新建,需用户确认归属后清理。机器只读 Action 最多 3 分钟后有界回收;写入 Action 仅凭匹配终态与 token 回收。资源创建/关闭/峰值/拒绝写入同一 `chat-loop.resources.v1`,Acceptance Audit 读取该记录;未知收据不补发。`ACTION_RESULT_TIMEOUT_UNVERIFIED` 为安全 BLOCKED,不是自动重试。
6
6
 
7
- **失败 Start 诊断(本地 0.3.44)**:首轮发送前若新 Chat 主页未就绪,Worker 保持 BLOCKED/START_SEND_UNVERIFIED;新增仅审计字段 `lastStartFailureCode` 记录安全白名单里的未就绪原因,`popup.html?audit=1` 的失败页探针只提供 DOM 就绪状态和控件存在布尔值,不读草稿/正文/密钥。它不证明页面可自动绕过挑战,也不能授权重发或清理未确认草稿。
7
+ **失败 Start 诊断(本地 0.3.45)**:首轮发送前若新 Chat 主页未就绪,Worker 保持 BLOCKED/START_SEND_UNVERIFIED;新增仅审计字段 `lastStartFailureCode` 记录安全白名单里的未就绪原因,`popup.html?audit=1` 的失败页探针只提供 DOM 就绪状态和控件存在布尔值,不读草稿/正文/密钥。它不证明页面可自动绕过挑战,也不能授权重发或清理未确认草稿。
8
8
 
9
9
  **手动入口限额**:Popup 的 Clean 点击也必须经 Worker 同一 Action 配额准入;开发验收 New Test 一次最多保留一个已登记测试/首页,不能从旁路无限创建标签。
10
10
 
@@ -45,3 +45,7 @@ Run: chatloop-extension extension <command> --help
45
45
  Clean 只清空输入框,不发送,不更改 Owner;必须指定精确标签页 ID 且验证目标。Chrome 已安装扩展不随 npm 包自动安装。本地源码与已发布 npm 版本可能不同,真实结果请看 [CURRENT](../../context/CURRENT.md)。
46
46
 
47
47
  详细接口和安全边界统一见 [Extension 产品文档](../../docs/extension.md)。
48
+
49
+ **新页准备超时策略(0.3.45)**:Start 新 Chat 编辑器只读等待约 218 秒,Handoff 新 Chat 只读等待约 234 秒,均保持一次新建/一次发送且不跳过 ChatGPT 网页验证。Start CLI 最多等待 310 秒,MCP Tools 转发最多 330 秒;Worker 对 Start/Handoff 的未确认资源等待 330 秒,其它 Action 维持 180 秒。窗口到期仍无确定回执时保留 BLOCKED,禁止自动重发。
50
+
51
+ **0.3.46 Chrome pendingUrl 修复**:Worker 创建正式 Action 时,以自己刚发起的受控 Extension URL 与 Chrome 返回的数值 tabId 登记资源,不能依赖 `tabs.create` 立即返回最终 `tab.url`(它可能仅有 `pendingUrl`)。Action 自身仍需验证真实 URL、Owner、token,任何未确认发送都不得重试;代码回归覆盖过渡 tab.url 缺失但单次 Action 正常创建。
package/bin/cli.mjs CHANGED
@@ -68,7 +68,7 @@ async function executeAction(action,intent) {
68
68
  ? action+'.html':action.slice(5)+'.html';
69
69
  const url='chrome-extension://'+config.extensionId+'/'+page+'?requestId='+req.id;
70
70
  openAction(url);
71
- const until=Date.now()+(action==='start'?105000:27000);
71
+ const until=Date.now()+(action==='start'?310000:27000);
72
72
  while(Date.now()<until){
73
73
  const result=readResult(req.id);
74
74
  if(result){
@@ -90,7 +90,7 @@ async function verifyOldChat(target, summary, mode = "EXPLICIT") {
90
90
  return execution.result.snapshot || summary;
91
91
  }
92
92
  async function waitForNewChat(tabId, allowKnownTestDraftCleanup = false) {
93
- for (let attempt = 0; attempt < 120; attempt++) {
93
+ for (let attempt = 0; attempt < 520; attempt++) {
94
94
  const tab = await chrome.tabs.get(tabId);
95
95
  if (tab.url?.startsWith("https://chatgpt.com/")) {
96
96
  try {
@@ -13,7 +13,7 @@ async function waitForHomeUrl(id){
13
13
  throw Error('START_HOME_URL_UNVERIFIED');
14
14
  }
15
15
  async function newChatReady(id){
16
- for(let i=0;i<85;i++){
16
+ for(let i=0;i<520;i++){
17
17
  const tab=await chrome.tabs.get(id).catch(()=>null);
18
18
  if(tab?.url==='https://chatgpt.com/'){
19
19
  const [found]=await chrome.scripting.executeScript({target:{tabId:id},func:()=>{
@@ -27,7 +27,7 @@ async function newChatReady(id){
27
27
  }}).catch(()=>[]);
28
28
  if(found?.result===true)return;
29
29
  // A newly opened ChatGPT home may hydrate slowly; never fail at 6 seconds.
30
- // Exhaust the bounded 35-second readiness window without sending.
30
+ // Security interstitials may outlast 2 minutes; wait up to ~218 seconds without sending.
31
31
  }
32
32
  await pause(420);
33
33
  }
@@ -46,7 +46,16 @@ async function createBoundedAction(options) {
46
46
  const quota=await resources.admit(await readRun(),{kind:'action'});
47
47
  if (!quota.ok) throw Error(quota.code);
48
48
  const tab=await chrome.tabs.create(options);
49
- if (!await resources.registerAction(tab)) throw Error('ACTION_RESOURCE_UNVERIFIED');
49
+ // MV3 tabs.create may return a tab with pendingUrl but no committed url.
50
+ // Register the exact Extension URL WE requested, not an about:blank
51
+ // transitional snapshot. The Action still checks its own actual source,
52
+ // token and Owner before any browser write.
53
+ if (!Number.isSafeInteger(tab?.id)||tab.id<=0
54
+ ||typeof options?.url!=='string'
55
+ ||!options.url.startsWith(chrome.runtime.getURL('')))
56
+ throw Error('ACTION_CREATED_ID_UNVERIFIED');
57
+ if (!await resources.registerAction({id:tab.id,url:options.url}))
58
+ throw Error('ACTION_RESOURCE_UNVERIFIED');
50
59
  return tab;
51
60
  }
52
61
  const pathOf = url => {
@@ -287,7 +296,8 @@ async function expireStaleAction() {
287
296
  const run=await readRun();
288
297
  if(!['STARTING','RESERVED','PENDING'].includes(run?.phase)
289
298
  || !Number.isSafeInteger(run.actionPendingAt)
290
- || Date.now()-run.actionPendingAt<180000) return;
299
+ || Date.now()-run.actionPendingAt<((run.action==='START'||run.action==='HANDOFF')
300
+ ?330000:180000)) return;
291
301
  // No action may be recreated or re-sent on a missing receipt. Keep the Chat.
292
302
  await saveRun({...run,phase:'BLOCKED',reason:'ACTION_RESULT_TIMEOUT_UNVERIFIED'});
293
303
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Chat Loop Extension",
4
- "version": "0.3.44",
4
+ "version": "0.3.46",
5
5
  "description": "Chat Loop browser companion: Eye actions, Turn observer, Continue and Handoff Actions",
6
6
  "permissions": [
7
7
  "activeTab",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomflow/chatloop-extension",
3
- "version": "0.3.44",
3
+ "version": "0.3.46",
4
4
  "type": "module",
5
5
  "description": "Chat Loop Extension package: nine formal Action pages and its own native CLI bridge",
6
6
  "bin": {