@mogragsigma/dsh-dual-host-plugin 0.33.4 → 2.0.1

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.
Files changed (99) hide show
  1. package/README.md +70 -99
  2. package/bundle/README.md +70 -99
  3. package/bundle/SETUP.md +87 -0
  4. package/bundle/approval-chat.js +2 -2
  5. package/bundle/approval-feishu.js +4 -1
  6. package/bundle/approval-ledger.js +30 -13
  7. package/bundle/approval-workbench.js +2 -0
  8. package/bundle/artifact-media.js +2 -2
  9. package/bundle/compatibility.json +43 -3
  10. package/bundle/configuration-v2.json +15 -0
  11. package/bundle/delivery-state.js +2 -0
  12. package/bundle/development-gate.js +2 -0
  13. package/bundle/distribution-lock.json +2 -2
  14. package/bundle/gateway-maintenance.js +1 -0
  15. package/bundle/global-rules/AGENTS.md +24 -20
  16. package/bundle/index.js +135 -25
  17. package/bundle/intervention-state.js +1 -1
  18. package/bundle/link-contract.js +9 -4
  19. package/bundle/managed-closeout.js +45 -0
  20. package/bundle/managed-cloud-policy.js +19 -0
  21. package/bundle/managed-command.js +71 -0
  22. package/bundle/managed-development-contract.js +43 -0
  23. package/bundle/managed-development.js +86 -0
  24. package/bundle/managed-endpoint.js +282 -0
  25. package/bundle/managed-execution.js +207 -0
  26. package/bundle/managed-policy.js +20 -0
  27. package/bundle/managed-runtime.js +186 -0
  28. package/bundle/managed-search.js +57 -0
  29. package/bundle/managed-tools.js +17 -0
  30. package/bundle/managed-triggers.js +85 -0
  31. package/bundle/native-context.js +4 -2
  32. package/bundle/native-entry.js +6 -2
  33. package/bundle/native-human-context.js +29 -0
  34. package/bundle/native-model-choice.js +12 -0
  35. package/bundle/native-rules/continuity.md +13 -0
  36. package/bundle/native-rules/execution.md +36 -0
  37. package/bundle/native-tools.js +52 -19
  38. package/bundle/notification-artifacts.js +26 -10
  39. package/bundle/notification-endpoint.js +1 -1
  40. package/bundle/notification-feishu.js +2 -2
  41. package/bundle/notification-media-endpoint.js +4 -3
  42. package/bundle/notification-observations.js +45 -0
  43. package/bundle/onboarding-cloud-package.js +1 -1
  44. package/bundle/onboarding-cloud.js +1 -1
  45. package/bundle/onboarding-file-contract.js +3 -2
  46. package/bundle/onboarding-file-transfer.js +4 -4
  47. package/bundle/onboarding-native-probe.js +1 -1
  48. package/bundle/onboarding-runtime-activation.js +1 -1
  49. package/bundle/onboarding-runtime-extension.js +2 -2
  50. package/bundle/package-lock.json +2 -2
  51. package/bundle/package.json +6 -4
  52. package/bundle/peer-file-review.js +1 -1
  53. package/bundle/peer-files.js +8 -4
  54. package/bundle/recovery.js +1 -1
  55. package/bundle/repository-gitee.js +12 -0
  56. package/bundle/repository-managed.js +1 -0
  57. package/bundle/runtime-im-lock.json +3409 -2849
  58. package/bundle/runtime-im-package.json +5 -5
  59. package/bundle/runtime-lock.json +3409 -2849
  60. package/bundle/runtime-package.json +5 -5
  61. package/bundle/schedule-ledger.js +35 -0
  62. package/bundle/search-contract.js +11 -1
  63. package/bundle/skills/task-approval/SKILL.md +20 -1
  64. package/bundle/skills/task-development/SKILL.md +30 -13
  65. package/bundle/skills/task-direct-link/SKILL.md +39 -13
  66. package/bundle/skills/task-file-transfer/SKILL.md +2 -2
  67. package/bundle/skills/task-notify/SKILL.md +2 -0
  68. package/bundle/skills/task-repository/SKILL.md +10 -1
  69. package/bundle/skills/task-research/SKILL.md +17 -2
  70. package/bundle/source-assessment.js +38 -0
  71. package/bundle/source-gitee.js +52 -0
  72. package/bundle/source-intake.js +137 -0
  73. package/bundle/source-policy-envelope.js +29 -0
  74. package/bundle/source-routing-tools.js +12 -0
  75. package/bundle/source-routing.js +218 -0
  76. package/bundle/source-search.js +2 -1
  77. package/bundle/store.js +6 -5
  78. package/bundle/task-artifacts.js +51 -12
  79. package/bundle/task-board.js +8 -4
  80. package/bundle/task-catalog.js +4 -3
  81. package/bundle/task-context.js +2 -2
  82. package/bundle/task-continuity-tools.js +14 -0
  83. package/bundle/task-continuity.js +248 -0
  84. package/bundle/task-envelope.js +31 -20
  85. package/bundle/task-notifications.js +6 -2
  86. package/bundle/task-observer-model.js +25 -0
  87. package/bundle/task-observer.js +120 -0
  88. package/bundle/task-results.js +1 -1
  89. package/bundle/task-scheduler.js +3 -3
  90. package/bundle/task-trigger-time.js +17 -12
  91. package/bundle/task-triggers.js +5 -30
  92. package/bundle/task-worker.js +10 -2
  93. package/bundle/task-workflows.js +2 -1
  94. package/bundle/workbench-client.js +165 -30
  95. package/bundle/workbench-decisions.js +22 -5
  96. package/bundle/workbench-host.js +5 -3
  97. package/bundle/worker-tools.js +8 -1
  98. package/compatibility.json +43 -3
  99. package/package.json +3 -3
@@ -1,11 +1,14 @@
1
1
  import fs from 'node:fs';
2
2
  import {join} from 'node:path';
3
3
  import {FileRoot,fileHash,fileName,sourceFile} from './peer-file-fs.js';
4
- export const FILE_CHUNK=48*1024,FILE_MAX=2*1024*1024;
4
+ export const FILE_CHUNK=48*1024,FILE_MAX=32*1024*1024,FILE_CONFIG_MAX=512*1024*1024;
5
+ // FILE_MAX is the fresh-install default, not a universal transfer-size promise.
6
+ // Preserve an existing implicit limit; expanding a persisted scope remains explicit.
5
7
  const other=r=>r==='local'?'cloud':'local',jid=x=>typeof x==='string'&&/^file-[a-f0-9]{64}$/.test(x),task=x=>typeof x==='string'&&/^task-[a-f0-9-]{36}$/.test(x);
6
8
  const json=JSON.stringify,fail=c=>{throw Error('PEER_FILE_'+c);};
7
9
  const same=(a,b)=>json(a)===json(b);
8
10
  export function fileMetadata(a,namespace,origin,max){
11
+ if(Number.isSafeInteger(a?.size)&&a.size>max)fail('TOO_LARGE');
9
12
  const keys=['v','namespace','id','task_id','from','to','name','size','sha256','created_at'];
10
13
  if(!a||typeof a!=='object'||Object.keys(a).some(k=>!keys.includes(k))||a.v!==1||a.namespace!==namespace||!jid(a.id)||!task(a.task_id)||a.from!==origin||a.to!==other(origin)||!Number.isSafeInteger(a.size)||a.size<0||a.size>max||!(/^[a-f0-9]{64}$/.test(a.sha256??''))||!Number.isSafeInteger(a.created_at)||a.created_at<0)fail('METADATA_INVALID');
11
14
  fileName(a.name);return Object.fromEntries(keys.map(k=>[k,a[k]]));
@@ -15,9 +18,10 @@ function decode(s){if(typeof s!=='string'||s.length>FILE_CHUNK*4/3||!s.length)fa
15
18
  export class PeerFiles {
16
19
  constructor(g,c){
17
20
  if(!c||c.enabled!==true||Object.keys(c).some(k=>!['enabled','sendRoots','receiveRoot','maxBytes'].includes(k))||!Array.isArray(c.sendRoots)||!c.sendRoots.length||c.sendRoots.length>8)fail('CONFIG_INVALID');
18
- this.g=g;this.db=g.db;this.role=g.c.role;this.namespace=g.c.namespace;this.max=c.maxBytes??FILE_MAX;
21
+ this.g=g;this.db=g.db;this.role=g.c.role;this.namespace=g.c.namespace;const retained=this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='peer_file_owner'").get()?this.db.prepare('SELECT config FROM peer_file_owner WHERE id=1').get():null;
22
+ this.max=c.maxBytes??(retained?JSON.parse(retained.config).max:FILE_MAX);
19
23
  if(!['local','cloud'].includes(this.role)||typeof this.namespace!=='string'||!this.namespace||this.namespace.length>128)fail('CONFIG_INVALID');
20
- if(!Number.isSafeInteger(this.max)||this.max<1||this.max>FILE_MAX)fail('CONFIG_INVALID');
24
+ if(!Number.isSafeInteger(this.max)||this.max<1||this.max>FILE_CONFIG_MAX)fail('CONFIG_INVALID');
21
25
  this.roots=c.sendRoots.map(p=>new FileRoot(p));this.receive=new FileRoot(c.receiveRoot);
22
26
  const dir=join(g.c.stateDir,'peer-files');fs.mkdirSync(dir,{recursive:true,mode:0o700});this.spool=new FileRoot(dir);
23
27
  this.db.exec(`CREATE TABLE IF NOT EXISTS peer_file_owner(id INTEGER PRIMARY KEY,config TEXT NOT NULL);
@@ -149,7 +153,7 @@ export class PeerFiles {
149
153
  const out=this.db.prepare('SELECT * FROM peer_file_out').all().filter(r=>JSON.parse(r.meta).task_id===task_id).map(r=>this.receipt(r));
150
154
  const incoming=this.db.prepare('SELECT * FROM peer_file_in').all().filter(r=>JSON.parse(r.meta).task_id===task_id).map(r=>{
151
155
  const m=JSON.parse(r.meta);let availability='not_received';
152
- if(r.state==='received'){try{const b=this.receive.read([m.task_id,m.id,m.name],FILE_MAX);availability=b.length===m.size&&fileHash(b)===m.sha256?'available':'changed';}catch{availability='missing_or_unsafe';}}
156
+ if(r.state==='received'){try{const b=this.receive.read([m.task_id,m.id,m.name],m.size);availability=b.length===m.size&&fileHash(b)===m.sha256?'available':'changed';}catch(e){availability=e.message==='PEER_FILE_TOO_LARGE'?'changed':'missing_or_unsafe';}}
153
157
  return {...this.receipt(r),path:r.path,availability,checked_at:this.g.now()};
154
158
  });return {host:this.role,sent:out,received:incoming,grants_execution:false};
155
159
  }
@@ -3,7 +3,7 @@ import {randomUUID} from 'node:crypto';
3
3
  export const permanentErrors=new Set(['INGRESS_ID_CONFLICT','TASK_CONTENT_CONFLICT','INVALID_TASK_ENVELOPE','INVALID_TASK_TITLE','INVALID_CONTEXT_SOURCE','CONTEXT_ORIGIN_MISMATCH','REFERENCE_NOT_IN_USER_CONTEXT','UNSUPPORTED_REFERENCE','CONTEXT_LIMIT','INVALID_INGRESS','INVALID_GOAL','INVALID_SUBMISSION','AUTH_DENIED','METHOD_DENIED']);
4
4
  export function safeError(e){const s=e?.message;return permanentErrors.has(s)?s:['DELIVERY_TIMEOUT','SEND_TIMEOUT'].includes(s)?s:'TRANSIENT_FAILURE';}
5
5
  export function bounded(p,ms,code){let t;return Promise.race([p,new Promise((_,reject)=>{t=setTimeout(()=>reject(Error(code)),ms);})]).finally(()=>clearTimeout(t));}
6
- export function tx(db,fn){db.exec('BEGIN IMMEDIATE');try{const r=fn();db.exec('COMMIT');return r;}catch(e){db.exec('ROLLBACK');throw e;}}
6
+ export function tx(db,fn){db.exec('BEGIN IMMEDIATE');try{const r=fn();db.exec('COMMIT');return r;}catch(e){try{db.exec('ROLLBACK');}catch{}throw e;}}
7
7
  export function migrateRecovery(db){
8
8
  tx(db,()=>{
9
9
  for(const table of ['submissions','receipts','notices']){
@@ -54,6 +54,18 @@ export class GiteeReadOnly {
54
54
  if(!Number.isSafeInteger(meta.id)||meta.id<=0||typeof meta.full_name!=='string'||typeof meta.private!=='boolean'||repositoryURL('https://gitee.com/'+meta.full_name).url!==r.url)throw Error('REPOSITORY_IDENTITY_MISMATCH');
55
55
  return {provider:'gitee',repository_id:meta.id,url:r.url,private:meta.private};
56
56
  }
57
+ async issue(snapshot,number){
58
+ const r=repositoryURL(snapshot.url);
59
+ if(!Number.isSafeInteger(snapshot.repository_id)||snapshot.repository_id<=0||typeof number!=='string'||!/^I[A-Z0-9]{1,20}$/.test(number))throw Error('REPOSITORY_ISSUE_INVALID');
60
+ if((await this.identity(r.url)).repository_id!==snapshot.repository_id)throw Error('REPOSITORY_IDENTITY_MISMATCH');
61
+ const item=await this.get(`/repos/${encodeURIComponent(r.owner)}/${encodeURIComponent(r.repo)}/issues/${number}`,131072);
62
+ const at=Date.parse(item.updated_at),url=r.url+'/issues/'+number;item.body??='';
63
+ if(!Number.isSafeInteger(item.id)||item.id<=0||item.number!==number||item.html_url!==url||!Number.isSafeInteger(at)||at<0||
64
+ !['open','progressing','closed','rejected'].includes(item.state)||typeof item.title!=='string'||typeof item.body!=='string'||
65
+ Buffer.byteLength(item.title+'\n'+item.body)>65536||!Number.isSafeInteger(item.user?.id)||item.user.id<=0)throw Error('REPOSITORY_ISSUE_RESPONSE_INVALID');
66
+ return {id:item.id,number,state:item.state,updated_at:at,title:item.title,body:item.body,url,
67
+ actor:{id:String(item.user.id),kind:item.user.type==='User'?'human':item.user.type==='Bot'?'bot':'unknown'}};
68
+ }
57
69
  async commit(snapshot,expected){
58
70
  const r=repositoryURL(snapshot.url),path=`/repos/${encodeURIComponent(r.owner)}/${encodeURIComponent(r.repo)}`;
59
71
  if(!/^[a-f0-9]{40}$/.test(snapshot.base_sha??'')||![expected?.tree_oid,expected?.parent_oid].every(x=>/^[a-f0-9]{40}$/.test(x??'')))throw Error('ARTIFACT_PROVIDER_COMMIT_INVALID');
@@ -43,4 +43,5 @@ export class ManagedGiteeReadOnly {
43
43
  identity(...a){return this.read('identity',a);}
44
44
  file(...a){return this.read('file',a);}
45
45
  commit(...a){return this.read('commit',a);}
46
+ issue(...a){return this.read('issue',a);}
46
47
  }