@tomflow/chatloop-tools 0.4.14 → 0.4.15

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.
@@ -17,6 +17,10 @@ export const extensionTools=[
17
17
  extensionTool('clean','Clear composer text in one exact verified ChatGPT tab; never sends.',false,
18
18
  {tabId:{type:'integer',minimum:1}},['tabId']),
19
19
  extensionTool('reload','Request reload of Chat Loop Extension; final health is unverified.',false),
20
+ extensionTool('status','Read the unique current Mac Chrome Web Chat Owner; never starts or sends.',true),
21
+ extensionTool('start','After confirmed intent and preflight, ask Extension to start one unique Web Chat; fails if any task owns it.',false,
22
+ {projectId:{type:'string',minLength:1,maxLength:128},prompt:{type:'string',minLength:1,maxLength:4000},confirmed:{const:true}},
23
+ ['projectId','prompt','confirmed']),
20
24
  extensionTool('continue','Submit next-turn text with turnToken and nextPrompt; alternatively query its final status with turnToken and intentId. Only the Extension can send after Turn completion.',false,
21
25
  {turnToken:{type:'string'},nextPrompt:{type:'string',minLength:1,maxLength:4000},
22
26
  intentId:{type:'string',pattern:'^[a-f0-9]{32}$'},lookup:{type:'boolean'}},['turnToken']),
@@ -40,6 +44,8 @@ const commands={
40
44
  chat_dom:['extension','chat','dom'],
41
45
  chat_screenshot:['extension','chat','screenshot'],
42
46
  reload:['extension','reload'],
47
+ status:['extension','status'],
48
+ start:['extension','start'],
43
49
  clean:['extension','clean'],
44
50
  continue:['extension','continue'],
45
51
  handoff:['extension','handoff']
@@ -48,13 +54,19 @@ const fail=code=>({isError:true,content:[{type:'text',text:code}]});
48
54
  export async function forwardExtensionAction(name,args={}) {
49
55
  const invocation=extensionInvocation(name);
50
56
  if(!invocation||!args||typeof args!=='object'||Array.isArray(args))return fail('INVALID_ARGUMENT');
51
- const control=['continue','handoff'].includes(name);
57
+ const control=['continue','handoff','start'].includes(name);
52
58
  if(name==='clean'){
53
59
  if(Object.keys(args).length!==1||!Number.isSafeInteger(args.tabId)||args.tabId<1)
54
60
  return fail('INVALID_ARGUMENT');
55
61
  invocation.args.push(String(args.tabId));
56
62
  }else if(!control && Object.keys(args).length)return fail('INVALID_ARGUMENT');
57
- if(control){
63
+ if(name==='start'){
64
+ if(Object.keys(args).some(k=>!['projectId','prompt','confirmed'].includes(k))
65
+ ||!(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/).test(args.projectId||'')
66
+ ||typeof args.prompt!=='string'||!args.prompt.trim()||args.prompt.length>4000
67
+ ||args.confirmed!==true)return fail('INVALID_ARGUMENT');
68
+ }
69
+ if(control&&name!=='start'){
58
70
  const query=Object.hasOwn(args,'intentId')||args.lookup===true;
59
71
  if(typeof args.turnToken!=='string' || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(args.turnToken)
60
72
  || Object.keys(args).some(k=>k!=='turnToken' && (query?
@@ -77,7 +89,7 @@ export async function forwardExtensionAction(name,args={}) {
77
89
  cwd:tmpdir(),windowsHide:true,env:process.env});
78
90
  let stdout='',finished=false;
79
91
  const settle=x=>{if(finished)return;finished=true;clearTimeout(timer);resolve(x);};
80
- const timer=setTimeout(()=>{child.kill('SIGTERM');settle(fail('RESULT_TIMEOUT'));},90000);
92
+ const timer=setTimeout(()=>{child.kill('SIGTERM');settle(fail('RESULT_TIMEOUT'));},name==='start'?125000:90000);
81
93
  if(control)child.stdin.end(JSON.stringify(args));
82
94
  child.stdout.on('data',b=>{
83
95
  stdout+=b.toString();
@@ -102,6 +114,16 @@ export function formatExtensionResult(name,response) {
102
114
  return {content:[{type:'text',text:'ACCEPTED_UNVERIFIED: Extension reload requested; healthy restart not confirmed.'}]};
103
115
  if(response?.status!=='OK'||response.action!==name||typeof response.path!=='string')
104
116
  return fail('INVALID_EXTENSION_RESULT');
117
+ if(['start','status'].includes(name)){
118
+ try{
119
+ const proof=JSON.parse(response.content);
120
+ if(name==='start'){
121
+ if(proof.status!=='OK'||!proof.sessionId||!proof.activeChatId||!proof.activeChatUrl)
122
+ return fail('START_RESULT_UNVERIFIED');
123
+ }else if(!['OK','UNVERIFIED'].includes(proof.status))return fail('STATUS_RESULT_UNVERIFIED');
124
+ return {content:[{type:'text',text:JSON.stringify(proof)}]};
125
+ }catch{return fail('INVALID_SESSION_RESULT');}
126
+ }
105
127
  if(['continue','handoff'].includes(name)){
106
128
  try {
107
129
  const proof=JSON.parse(response.content);
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.4.14",
6
+ "version": "0.4.15",
7
7
  "type": "module",
8
8
  "description": "Chat Loop local tools: MCP gateway, isolated bundled tunnel-client and unified CLI",
9
9
  "bin": {