@xeno-corporation/xeno-agent-sdk 0.5.1 → 0.6.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.
@@ -26,8 +26,11 @@ interface AgentRunRecord {
26
26
  statusReason?: string;
27
27
  blockedReason?: string;
28
28
  model: string;
29
+ effort?: "low" | "medium" | "high" | "xhigh" | "max";
29
30
  agent?: AgentRunAgentDefinitionRef;
30
31
  permissionMode: "default" | "plan" | "acceptEdits" | "auto" | "dontAsk" | "bypassPermissions";
32
+ createdByCliVersion?: string;
33
+ createdBySdkVersion?: string;
31
34
  createdAt: string;
32
35
  updatedAt: string;
33
36
  startedAt?: string;
@@ -45,7 +48,10 @@ interface AgentRunRecord {
45
48
  exitCode?: number | null;
46
49
  git?: {
47
50
  root?: string;
51
+ originBranch?: string;
52
+ originCommit?: string;
48
53
  branch?: string;
54
+ baseRef?: string;
49
55
  commit?: string;
50
56
  worktree?: string;
51
57
  };
@@ -70,10 +76,12 @@ interface AgentRunCreateInput {
70
76
  prompt: string;
71
77
  cwd: string;
72
78
  model: string;
79
+ effort?: AgentRunRecord["effort"];
73
80
  agent?: AgentRunAgentDefinitionRef;
74
81
  permissionMode: AgentRunRecord["permissionMode"];
75
82
  title?: string;
76
83
  pinned?: boolean;
84
+ git?: AgentRunRecord["git"];
77
85
  cliVersion?: string;
78
86
  sdkVersion?: string;
79
87
  }
@@ -91,6 +99,7 @@ declare class AgentRunStore {
91
99
  pid: number;
92
100
  workerVersion?: string;
93
101
  model?: string;
102
+ effort?: AgentRunRecord["effort"];
94
103
  }): AgentRunRecord | null;
95
104
  markCompleted(runId: string, input: {
96
105
  status: AgentRunStatus;
@@ -109,5 +118,21 @@ declare class AgentRunStore {
109
118
  private update;
110
119
  private write;
111
120
  private recordPath;
121
+ private runDir;
112
122
  }
113
- export { type AgentRunAgentDefinitionRef, type AgentRunCreateInput, type AgentRunEvent, type AgentRunListOptions, type AgentRunRecord, type AgentRunStatus, AgentRunStore, type AgentRunUsage, createAgentRunId, getAgentRunDir, getAgentRunStoreDir };
123
+ interface ControlPlaneLockRecord {
124
+ schemaVersion: 1;
125
+ name: string;
126
+ pid: number;
127
+ hostname: string;
128
+ processStartedAt: string;
129
+ version: string;
130
+ acquiredAt: string;
131
+ updatedAt: string;
132
+ }
133
+ interface ControlPlaneLockHandle {
134
+ record: ControlPlaneLockRecord;
135
+ release: () => void;
136
+ }
137
+ declare function acquireControlPlaneLock(path: string, name: string, version: string): ControlPlaneLockHandle;
138
+ export { type AgentRunAgentDefinitionRef, type AgentRunCreateInput, type AgentRunEvent, type AgentRunListOptions, type AgentRunRecord, type AgentRunStatus, AgentRunStore, type AgentRunUsage, type ControlPlaneLockHandle, type ControlPlaneLockRecord, acquireControlPlaneLock, createAgentRunId, getAgentRunDir, getAgentRunStoreDir };
@@ -1,3 +1,4 @@
1
- import{randomUUID as y}from"crypto";import{appendFileSync as S,existsSync as A,mkdirSync as d,readFileSync as f,readdirSync as P,renameSync as k,rmSync as D,writeFileSync as c}from"fs";import{homedir as E}from"os";import{basename as _,dirname as h,join as o,resolve as x}from"path";var m=1,O=o(E(),".xeno-agent"),N=o(process.env.XENO_AGENT_HOME??O,"daemon"),R=o(N,"runs");function i(){return new Date().toISOString()}function b(r=new Date){return r.toISOString().replace(/[^0-9]/g,"").slice(0,14)}function v(r){return r.replace(/[^A-Za-z0-9_.-]/g,"_").slice(0,80)}function l(r){return x(r)}function C(r){return v(Buffer.from(l(r)).toString("base64url"))}function V(){return{input:0,output:0,total:0}}function g(r){try{return JSON.parse(f(r,"utf8"))}catch{return null}}function T(r,t){d(h(r),{recursive:!0});let e=`${r}.${process.pid}.${Date.now()}.tmp`;c(e,JSON.stringify(t,null,2)+`
2
- `,"utf8"),k(e,r)}function I(r){if(!r||r<=0)return!1;try{return process.kill(r,0),!0}catch{return!1}}function U(r){return r==="completed"||r==="failed"||r==="cancelled"||r==="interrupted"}function F(r,t){return r.pinned!==t.pinned?r.pinned?-1:1:Date.parse(t.updatedAt)-Date.parse(r.updatedAt)}function z(){return R}function B(r){return o(R,r)}function M(r=new Date){return`run_${b(r)}_${y().slice(0,8)}`}var p=class{constructor(t=R){this.runsDir=t;d(this.runsDir,{recursive:!0})}create(t){let e=M(),n=o(this.runsDir,e);d(n,{recursive:!0});let s=i(),a=o(n,"events.jsonl"),u={schemaVersion:m,runId:e,sessionId:e,rootRunId:e,cwd:l(t.cwd),workspaceId:C(t.cwd),prompt:t.prompt,...t.title?{title:t.title}:{},status:"starting",model:t.model,...t.agent?{agent:t.agent}:{},permissionMode:t.permissionMode,createdAt:s,updatedAt:s,lastActivityAt:s,pinned:!!t.pinned,attachedClients:0,...t.cliVersion?{cliVersion:t.cliVersion}:{},...t.sdkVersion?{sdkVersion:t.sdkVersion}:{},stdoutPath:o(n,"stdout.log"),stderrPath:o(n,"stderr.log"),eventsPath:a,usage:V(),children:[],tags:[]};return c(u.stdoutPath,"","utf8"),c(u.stderrPath,"","utf8"),c(u.eventsPath,"","utf8"),this.write(u),this.appendEvent(e,"run_created",{cwd:u.cwd,model:u.model,...u.agent?{agent:u.agent}:{},permissionMode:u.permissionMode,pinned:u.pinned}),u}get(t){let e=g(this.recordPath(t));return e?this.refreshRecordStatus(e):null}list(t={}){if(!A(this.runsDir))return[];let e=P(this.runsDir,{withFileTypes:!0}).filter(n=>n.isDirectory()).map(n=>this.get(n.name)).filter(n=>n!==null).filter(n=>t.all||!t.cwd||l(n.cwd)===l(t.cwd)).filter(n=>!t.status||t.status.includes(n.status)).sort(F);return typeof t.limit=="number"&&t.limit>0?e.slice(0,t.limit):e}markSpawned(t,e,n){return this.update(t,s=>({...s,status:"running",workerPid:e,...n?{workerVersion:n}:{},startedAt:s.startedAt??i(),lastActivityAt:i()}))}markStarted(t,e){return this.update(t,n=>({...n,status:"running",workerPid:e.pid,...e.workerVersion?{workerVersion:e.workerVersion}:{},...e.model?{model:e.model}:{},startedAt:n.startedAt??i(),lastActivityAt:i()}))}markCompleted(t,e){return this.update(t,n=>({...n,status:e.status,...e.statusReason?{statusReason:e.statusReason}:{},exitCode:e.exitCode??null,usage:e.usage??n.usage,endedAt:i(),lastActivityAt:i()}))}markCancelled(t,e){return this.update(t,n=>({...n,status:"cancelled",statusReason:e,endedAt:i(),lastActivityAt:i()}))}markPaused(t,e="Paused by user."){let n=this.update(t,s=>({...s,status:"paused",statusReason:e,lastActivityAt:i()}));return n&&this.appendEvent(t,"run_paused",{reason:e}),n}markResumed(t,e="Resumed by user."){let n=this.update(t,s=>{let a={...s,status:"running",statusReason:e,lastActivityAt:i()};return delete a.endedAt,delete a.exitCode,a});return n&&this.appendEvent(t,"run_resumed",{reason:e}),n}setPinned(t,e){let n=this.update(t,s=>({...s,pinned:e,lastActivityAt:i()}));return n&&this.appendEvent(t,e?"run_pinned":"run_unpinned",{pinned:e}),n}appendEvent(t,e,n={}){let s=g(this.recordPath(t)),a=s?.eventsPath??o(this.runsDir,t,"events.jsonl");d(h(a),{recursive:!0});let u={schemaVersion:m,runId:t,type:e,timestamp:i(),payload:n};S(a,JSON.stringify(u)+`
3
- `,"utf8"),s&&this.update(t,w=>({...w,lastActivityAt:u.timestamp}))}readEvents(t){let e=this.get(t);return!e||!A(e.eventsPath)?[]:f(e.eventsPath,"utf8").split(/\r?\n/).map(n=>n.trim()).filter(Boolean).map(n=>{try{return JSON.parse(n)}catch{return null}}).filter(n=>n!==null)}delete(t){D(o(this.runsDir,t),{recursive:!0,force:!0})}refreshRecordStatus(t){if(U(t.status))return t;if(t.workerPid&&!I(t.workerPid)){let e={...t,status:"failed",statusReason:"Worker process is no longer running and did not record a terminal status.",endedAt:t.endedAt??i(),updatedAt:i()};return this.write(e),e}return t}update(t,e){let n=g(this.recordPath(t));if(!n)return null;let s=e(n);return s.updatedAt=i(),this.write(s),s}write(t){T(this.recordPath(t.runId),t)}recordPath(t){return o(this.runsDir,v(_(t)),"run.json")}};export{p as AgentRunStore,M as createAgentRunId,B as getAgentRunDir,z as getAgentRunStoreDir};
1
+ import{randomUUID as J}from"crypto";import{appendFileSync as M,existsSync as y,mkdirSync as d,readFileSync as x,readdirSync as U,renameSync as z,rmSync as j,writeFileSync as l}from"fs";import{homedir as q}from"os";import{basename as P,dirname as L,join as u,resolve as B}from"path";var f="0.6.0";import{mkdirSync as O,readFileSync as V,rmSync as v,writeFileSync as _}from"fs";import{hostname as k}from"os";import{dirname as N}from"path";function b(){return new Date().toISOString()}function I(){return new Date(Date.now()-Math.floor(process.uptime()*1e3)).toISOString()}function w(r){try{return JSON.parse(V(r,"utf8"))}catch{return null}}function T(r){if(!r||r<=0)return!1;try{return process.kill(r,0),!0}catch{return!1}}function F(r){return r.hostname!==k()?!0:T(r.pid)}function h(r,t){O(N(r),{recursive:!0}),_(r,JSON.stringify(t,null,2)+`
2
+ `,{encoding:"utf8",flag:"wx"})}function $(r,t){let e=w(r);e?.pid!==t.pid||e.hostname!==t.hostname||v(r,{force:!0})}function S(r,t,e){let n=b(),s={schemaVersion:1,name:t,pid:process.pid,hostname:k(),processStartedAt:I(),version:e,acquiredAt:n,updatedAt:n};try{h(r,s)}catch(a){if(a.code!=="EEXIST")throw a;let c=w(r);if(c&&F(c))throw new Error(`${t} is already locked by PID ${c.pid} on ${c.hostname}.`);v(r,{force:!0}),h(r,s)}return{record:s,release:()=>{$(r,s)}}}var D=1,H=u(q(),".xeno-agent"),W=u(process.env.XENO_AGENT_HOME??H,"daemon"),A=u(W,"runs");function i(){return new Date().toISOString()}function G(r=new Date){return r.toISOString().replace(/[^0-9]/g,"").slice(0,14)}function R(r){return r.replace(/[^A-Za-z0-9_.-]/g,"_").slice(0,80)}function p(r){return B(r)}function g(r){return p(r).toLowerCase()}function C(r,t){let e=g(r),n=g(t);return e===n||e.startsWith(`${n}\\`)||e.startsWith(`${n}/`)}function K(r,t){return!!(g(r.cwd)===g(t)||r.git?.root&&C(t,r.git.root)||r.git?.worktree&&C(t,r.git.worktree))}function X(r){return R(Buffer.from(p(r)).toString("base64url"))}function Z(){return{input:0,output:0,total:0}}function m(r){try{return JSON.parse(x(r,"utf8"))}catch{return null}}function Q(r,t){d(L(r),{recursive:!0});let e=`${r}.${process.pid}.${Date.now()}.tmp`;l(e,JSON.stringify(t,null,2)+`
3
+ `,"utf8"),z(e,r)}function Y(r){if(!r||r<=0)return!1;try{return process.kill(r,0),!0}catch{return!1}}function tt(r){return r==="completed"||r==="failed"||r==="cancelled"||r==="interrupted"}function et(r,t){return r.pinned!==t.pinned?r.pinned?-1:1:Date.parse(t.updatedAt)-Date.parse(r.updatedAt)}function mt(){return A}function Rt(r){return u(A,r)}function rt(r=new Date){return`run_${G(r)}_${J().slice(0,8)}`}var E=class{constructor(t=A){this.runsDir=t;d(this.runsDir,{recursive:!0})}create(t){let e=rt(),n=u(this.runsDir,e);d(n,{recursive:!0});let s=i(),a=u(n,"events.jsonl"),o={schemaVersion:D,runId:e,sessionId:e,rootRunId:e,cwd:p(t.cwd),workspaceId:X(t.cwd),prompt:t.prompt,...t.title?{title:t.title}:{},status:"starting",model:t.model,...t.effort?{effort:t.effort}:{},...t.agent?{agent:t.agent}:{},...t.git?{git:t.git}:{},permissionMode:t.permissionMode,...t.cliVersion?{createdByCliVersion:t.cliVersion}:{},createdBySdkVersion:t.sdkVersion??f,createdAt:s,updatedAt:s,lastActivityAt:s,pinned:!!t.pinned,attachedClients:0,...t.cliVersion?{cliVersion:t.cliVersion}:{},...t.sdkVersion?{sdkVersion:t.sdkVersion}:{},stdoutPath:u(n,"stdout.log"),stderrPath:u(n,"stderr.log"),eventsPath:a,usage:Z(),children:[],tags:[]};return l(o.stdoutPath,"","utf8"),l(o.stderrPath,"","utf8"),l(o.eventsPath,"","utf8"),this.write(o),this.appendEvent(e,"run_created",{cwd:o.cwd,model:o.model,...o.agent?{agent:o.agent}:{},...o.git?{git:o.git}:{},permissionMode:o.permissionMode,pinned:o.pinned}),o}get(t){let e=m(this.recordPath(t));return e?this.refreshRecordStatus(e):null}list(t={}){if(!y(this.runsDir))return[];let e=U(this.runsDir,{withFileTypes:!0}).filter(n=>n.isDirectory()).map(n=>this.get(n.name)).filter(n=>n!==null).filter(n=>t.all||!t.cwd||K(n,t.cwd)).filter(n=>!t.status||t.status.includes(n.status)).sort(et);return typeof t.limit=="number"&&t.limit>0?e.slice(0,t.limit):e}markSpawned(t,e,n){return this.update(t,s=>({...s,status:"running",workerPid:e,...n?{workerVersion:n}:{},startedAt:s.startedAt??i(),lastActivityAt:i()}))}markStarted(t,e){return this.update(t,n=>({...n,status:"running",workerPid:e.pid,...e.workerVersion?{workerVersion:e.workerVersion}:{},...e.model?{model:e.model}:{},...e.effort?{effort:e.effort}:{},startedAt:n.startedAt??i(),lastActivityAt:i()}))}markCompleted(t,e){return this.update(t,n=>({...n,status:e.status,...e.statusReason?{statusReason:e.statusReason}:{},exitCode:e.exitCode??null,usage:e.usage??n.usage,endedAt:i(),lastActivityAt:i()}))}markCancelled(t,e){return this.update(t,n=>({...n,status:"cancelled",statusReason:e,endedAt:i(),lastActivityAt:i()}))}markPaused(t,e="Paused by user."){let n=this.update(t,s=>({...s,status:"paused",statusReason:e,lastActivityAt:i()}));return n&&this.appendEvent(t,"run_paused",{reason:e}),n}markResumed(t,e="Resumed by user."){let n=this.update(t,s=>{let a={...s,status:"running",statusReason:e,lastActivityAt:i()};return delete a.endedAt,delete a.exitCode,a});return n&&this.appendEvent(t,"run_resumed",{reason:e}),n}setPinned(t,e){let n=this.update(t,s=>({...s,pinned:e,lastActivityAt:i()}));return n&&this.appendEvent(t,e?"run_pinned":"run_unpinned",{pinned:e}),n}appendEvent(t,e,n={}){let s=m(this.recordPath(t)),a=s?.eventsPath??u(this.runsDir,t,"events.jsonl");d(L(a),{recursive:!0});let o={schemaVersion:D,runId:t,type:e,timestamp:i(),payload:n};M(a,JSON.stringify(o)+`
4
+ `,"utf8"),s&&this.update(t,c=>({...c,lastActivityAt:o.timestamp}))}readEvents(t){let e=this.get(t);return!e||!y(e.eventsPath)?[]:x(e.eventsPath,"utf8").split(/\r?\n/).map(n=>n.trim()).filter(Boolean).map(n=>{try{return JSON.parse(n)}catch{return null}}).filter(n=>n!==null)}delete(t){j(u(this.runsDir,t),{recursive:!0,force:!0})}refreshRecordStatus(t){if(tt(t.status))return t;if(t.workerPid&&!Y(t.workerPid)){let e={...t,status:"failed",statusReason:"Worker process is no longer running and did not record a terminal status.",endedAt:t.endedAt??i(),updatedAt:i()};return this.write(e),e}return t}update(t,e){let n=m(this.recordPath(t));if(!n)return null;let s=e(n);return s.updatedAt=i(),this.write(s),s}write(t){let e=S(u(this.runDir(t.runId),"run.lock"),`run:${t.runId}`,f);try{Q(this.recordPath(t.runId),t)}finally{e.release()}}recordPath(t){return u(this.runsDir,R(P(t)),"run.json")}runDir(t){return u(this.runsDir,R(P(t)))}};export{E as AgentRunStore,S as acquireControlPlaneLock,rt as createAgentRunId,Rt as getAgentRunDir,mt as getAgentRunStoreDir};
@@ -60,6 +60,7 @@ interface Message {
60
60
  }
61
61
  type PermissionDecision = "allow" | "ask" | "deny";
62
62
  type ExecutionMode = "agent" | "chatOnly";
63
+ type AgentEffortLevel = "low" | "medium" | "high" | "xhigh" | "max";
63
64
  interface PermissionRule {
64
65
  tool: string;
65
66
  pattern?: string;
@@ -349,9 +350,11 @@ type XenoRuntimeEvent = (XenoRuntimeEventBase & {
349
350
  type: "thread.started";
350
351
  cwd: string;
351
352
  model: string;
353
+ effort?: string;
352
354
  }) | (XenoRuntimeEventBase & {
353
355
  type: "turn.started";
354
356
  model: string;
357
+ effort?: string;
355
358
  promptPreview: string;
356
359
  }) | (XenoRuntimeEventBase & {
357
360
  type: "turn.completed";
@@ -772,6 +775,8 @@ interface AgentLoopConfig {
772
775
  baseURL: string;
773
776
  ollamaBaseURL?: string;
774
777
  model: string;
778
+ fallbackModels?: string[];
779
+ effort?: AgentEffortLevel;
775
780
  maxTokens: number;
776
781
  maxIterations: number;
777
782
  systemPrompt: string;
@@ -895,6 +900,8 @@ declare class AgentLoop {
895
900
  get lastRunTermination(): AgentRunTermination | null;
896
901
  get model(): string;
897
902
  set model(value: string);
903
+ get effort(): AgentEffortLevel | undefined;
904
+ set effort(value: AgentEffortLevel | undefined);
898
905
  get executionMode(): ExecutionMode;
899
906
  set executionMode(value: ExecutionMode);
900
907
  get systemPrompt(): string;