@openadapter/koda 1.0.0-beta.13 → 1.0.0-beta.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.
- package/dist/cli/args.js +7 -5
- package/dist/cli/jobs-store.d.ts +95 -0
- package/dist/cli/jobs-store.js +2 -0
- package/dist/cli/task-command.d.ts +22 -0
- package/dist/cli/task-command.js +21 -0
- package/dist/core/agent-session.d.ts +11 -0
- package/dist/core/agent-session.js +8 -8
- package/dist/main.js +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.js +28 -28
- package/npm-shrinkwrap.json +1050 -12
- package/openadapter/extensions/koda-jobs.js +45 -0
- package/openadapter/extensions/koda-mcp.js +9 -0
- package/openadapter/extensions/koda-permissions.js +1 -0
- package/openadapter/extensions/koda-rewind.js +5 -0
- package/openadapter/setup.mjs +4 -0
- package/package.json +5 -4
package/dist/cli/args.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var
|
|
1
|
+
var u=Object.defineProperty;var r=(s,t)=>u(s,"name",{value:t,configurable:!0});import l from"chalk";import{APP_NAME as n,CONFIG_DIR_NAME as d,ENV_AGENT_DIR as c,ENV_SESSION_DIR as h}from"../config.js";const m=["off","minimal","low","medium","high","xhigh"];function A(s){return m.includes(s)}r(A,"isValidThinkingLevel");function _(s){const t={messages:[],fileArgs:[],unknownFlags:new Map,diagnostics:[]};for(let o=0;o<s.length;o++){const e=s[o];if(e==="--help"||e==="-h")t.help=!0;else if(e==="--version"||e==="-v")t.version=!0;else if(e==="--mode"&&o+1<s.length){const i=s[++o];(i==="text"||i==="json"||i==="rpc")&&(t.mode=i)}else if(e==="--continue"||e==="-c")t.continue=!0;else if(e==="--resume"||e==="-r")t.resume=!0;else if(e==="--provider"&&o+1<s.length)t.provider=s[++o];else if(e==="--model"&&o+1<s.length)t.model=s[++o];else if(e==="--api-key"&&o+1<s.length)t.apiKey=s[++o];else if(e==="--system-prompt"&&o+1<s.length)t.systemPrompt=s[++o];else if(e==="--append-system-prompt"&&o+1<s.length)t.appendSystemPrompt=t.appendSystemPrompt??[],t.appendSystemPrompt.push(s[++o]);else if(e==="--name"||e==="-n")o+1<s.length?t.name=s[++o]:t.diagnostics.push({type:"error",message:"--name requires a value"});else if(e==="--no-session")t.noSession=!0;else if(e==="--session"&&o+1<s.length)t.session=s[++o];else if(e==="--session-id"&&o+1<s.length)t.sessionId=s[++o];else if(e==="--fork"&&o+1<s.length)t.fork=s[++o];else if(e==="--session-dir"&&o+1<s.length)t.sessionDir=s[++o];else if(e==="--models"&&o+1<s.length)t.models=s[++o].split(",").map(i=>i.trim());else if(e==="--no-tools"||e==="-nt")t.noTools=!0;else if(e==="--no-builtin-tools"||e==="-nbt")t.noBuiltinTools=!0;else if((e==="--tools"||e==="-t")&&o+1<s.length)t.tools=s[++o].split(",").map(i=>i.trim()).filter(i=>i.length>0);else if((e==="--exclude-tools"||e==="-xt")&&o+1<s.length)t.excludeTools=s[++o].split(",").map(i=>i.trim()).filter(i=>i.length>0);else if(e==="--thinking"&&o+1<s.length){const i=s[++o];A(i)?t.thinking=i:t.diagnostics.push({type:"warning",message:`Invalid thinking level "${i}". Valid values: ${m.join(", ")}`})}else if(e==="--print"||e==="-p"){t.print=!0;const i=s[o+1];i!==void 0&&!i.startsWith("@")&&(!i.startsWith("-")||i.startsWith("---"))&&(t.messages.push(i),o++)}else if(e==="--export"&&o+1<s.length)t.export=s[++o];else if((e==="--extension"||e==="-e")&&o+1<s.length)t.extensions=t.extensions??[],t.extensions.push(s[++o]);else if(e==="--no-extensions"||e==="-ne")t.noExtensions=!0;else if(e==="--skill"&&o+1<s.length)t.skills=t.skills??[],t.skills.push(s[++o]);else if(e==="--prompt-template"&&o+1<s.length)t.promptTemplates=t.promptTemplates??[],t.promptTemplates.push(s[++o]);else if(e==="--theme"&&o+1<s.length)t.themes=t.themes??[],t.themes.push(s[++o]);else if(e==="--no-skills"||e==="-ns")t.noSkills=!0;else if(e==="--no-prompt-templates"||e==="-np")t.noPromptTemplates=!0;else if(e==="--no-themes")t.noThemes=!0;else if(e==="--no-context-files"||e==="-nc")t.noContextFiles=!0;else if(e==="--list-models")o+1<s.length&&!s[o+1].startsWith("-")&&!s[o+1].startsWith("@")?t.listModels=s[++o]:t.listModels=!0;else if(e==="--verbose")t.verbose=!0;else if(e==="--offline")t.offline=!0;else if(e.startsWith("@"))t.fileArgs.push(e.slice(1));else if(e.startsWith("--")){const i=e.indexOf("=");if(i!==-1)t.unknownFlags.set(e.slice(2,i),e.slice(i+1));else{const p=e.slice(2),a=s[o+1];a!==void 0&&!a.startsWith("-")&&!a.startsWith("@")?(t.unknownFlags.set(p,a),o++):t.unknownFlags.set(p,!0)}}else e.startsWith("-")&&!e.startsWith("--")?t.diagnostics.push({type:"error",message:`Unknown option: ${e}`}):e.startsWith("-")||t.messages.push(e)}return t}r(_,"parseArgs");function k(s){const t=s&&s.length>0?`
|
|
2
2
|
${l.bold("Extension CLI Flags:")}
|
|
3
|
-
${
|
|
3
|
+
${s.map(o=>{const e=o.type==="string"?" <value>":"",i=o.description??`Registered by ${o.extensionPath}`;return` --${o.name}${e}`.padEnd(30)+i}).join(`
|
|
4
4
|
`)}
|
|
5
5
|
`:"";console.log(`${l.bold(n)} - AI coding assistant with read, bash, edit, write tools
|
|
6
6
|
|
|
@@ -14,6 +14,8 @@ ${l.bold("Commands:")}
|
|
|
14
14
|
${n} update [source|self|koda] Update koda and installed extensions
|
|
15
15
|
${n} list List installed extensions from settings
|
|
16
16
|
${n} config Open TUI to enable/disable package resources
|
|
17
|
+
${n} task run [--trial] <id> Run a scheduled job now (used by the OS scheduler)
|
|
18
|
+
${n} task list [--json] List scheduled jobs (manage them with /jobs)
|
|
17
19
|
${n} <command> --help Show help for install/remove/uninstall/update/list
|
|
18
20
|
|
|
19
21
|
${l.bold("Options:")}
|
|
@@ -149,8 +151,8 @@ ${l.bold("Environment Variables:")}
|
|
|
149
151
|
AWS_SECRET_ACCESS_KEY - AWS secret key for Amazon Bedrock
|
|
150
152
|
AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)
|
|
151
153
|
AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)
|
|
152
|
-
${
|
|
153
|
-
${
|
|
154
|
+
${c.padEnd(32)} - Config directory (default: ~/${d}/agent)
|
|
155
|
+
${h.padEnd(32)} - Session storage directory (overridden by --session-dir)
|
|
154
156
|
KODA_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
|
|
155
157
|
KODA_OFFLINE - Disable startup network operations when set to 1/true/yes
|
|
156
158
|
KODA_TELEMETRY - Override install telemetry when set to 1/true/yes or 0/false/no
|
|
@@ -164,4 +166,4 @@ ${l.bold("Built-in Tool Names:")}
|
|
|
164
166
|
grep - Search file contents (read-only, off by default)
|
|
165
167
|
find - Find files by glob pattern (read-only, off by default)
|
|
166
168
|
ls - List directory contents (read-only, off by default)
|
|
167
|
-
`)}
|
|
169
|
+
`)}r(k,"printHelp");export{A as isValidThinkingLevel,_ as parseArgs,k as printHelp};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Koda Jobs — on-disk store.
|
|
3
|
+
*
|
|
4
|
+
* A Job is a saved prompt + schedule + run history that fires unattended (or on
|
|
5
|
+
* demand). This module is the single source of truth for the layout under
|
|
6
|
+
* `<agentDir>/jobs/`; both the headless executor (task-command.ts) and the
|
|
7
|
+
* koda-jobs extension read/write through these helpers (the extension has its
|
|
8
|
+
* own thin mirror since it can't import across the package boundary — keep the
|
|
9
|
+
* JSON shapes here authoritative).
|
|
10
|
+
*
|
|
11
|
+
* <agentDir>/jobs/<id>/job.json — the JobDefinition
|
|
12
|
+
* <agentDir>/jobs/<id>/runs/<runId>.json — one RunReport per run
|
|
13
|
+
* <agentDir>/jobs/<id>/runs/<runId>.log — raw stdout/stderr of that run
|
|
14
|
+
*/
|
|
15
|
+
export type JobStatus = "active" | "paused";
|
|
16
|
+
export type RunOutcome = "done" | "quota_stop" | "stuck" | "error" | "rehearsal";
|
|
17
|
+
export interface JobSchedule {
|
|
18
|
+
/** How the schedule repeats. */
|
|
19
|
+
kind: "daily" | "weekly" | "hourly" | "cron";
|
|
20
|
+
/** "HH:MM" 24h local-to-tz time for daily/weekly. */
|
|
21
|
+
at?: string;
|
|
22
|
+
/** 0=Sun … 6=Sat, for weekly. */
|
|
23
|
+
weekday?: number;
|
|
24
|
+
/** Raw 5-field cron expression when kind === "cron". */
|
|
25
|
+
cron?: string;
|
|
26
|
+
/** IANA timezone the schedule is expressed in (display + computation). */
|
|
27
|
+
tz: string;
|
|
28
|
+
}
|
|
29
|
+
export interface JobAllowedActions {
|
|
30
|
+
/** May open a pull request (default true). */
|
|
31
|
+
openPr: boolean;
|
|
32
|
+
/** May merge to the default branch (default false). */
|
|
33
|
+
merge: boolean;
|
|
34
|
+
/** May deploy / publish / release (default false). */
|
|
35
|
+
deploy: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface JobDefinition {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
/** The recurring goal in plain language — drives setSessionGoal. */
|
|
41
|
+
goal: string;
|
|
42
|
+
/** Numbered steps shown at creation and re-sent each run. */
|
|
43
|
+
steps: string[];
|
|
44
|
+
/** Repo / working directory the job runs in. */
|
|
45
|
+
cwd: string;
|
|
46
|
+
schedule: JobSchedule;
|
|
47
|
+
allowedActions: JobAllowedActions;
|
|
48
|
+
/** Where results surface: an OS notification, or just the report file. */
|
|
49
|
+
reportTo: "notify" | "file";
|
|
50
|
+
/** Per-run step ceiling (→ KODA_MAX_STEPS). */
|
|
51
|
+
maxSteps: number;
|
|
52
|
+
/** Absolute command used by the OS scheduler, resolved at creation. */
|
|
53
|
+
runCommand?: string;
|
|
54
|
+
createdAt: string;
|
|
55
|
+
updatedAt: string;
|
|
56
|
+
status: JobStatus;
|
|
57
|
+
lastRun?: {
|
|
58
|
+
at: string;
|
|
59
|
+
outcome: RunOutcome;
|
|
60
|
+
runId: string;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export interface RunReport {
|
|
64
|
+
runId: string;
|
|
65
|
+
jobId: string;
|
|
66
|
+
startedAt: string;
|
|
67
|
+
endedAt: string;
|
|
68
|
+
trial: boolean;
|
|
69
|
+
outcome: RunOutcome;
|
|
70
|
+
/** Recap / final assistant text. */
|
|
71
|
+
summary: string;
|
|
72
|
+
/** Goal milestones with completion state. */
|
|
73
|
+
steps: {
|
|
74
|
+
text: string;
|
|
75
|
+
done: boolean;
|
|
76
|
+
}[];
|
|
77
|
+
/** Rehearsal "would have …" list (push/merge/deploy that were withheld). */
|
|
78
|
+
withheld: {
|
|
79
|
+
action: string;
|
|
80
|
+
detail: string;
|
|
81
|
+
}[];
|
|
82
|
+
/** git diff snapshot (trials). */
|
|
83
|
+
diff?: string;
|
|
84
|
+
error?: string;
|
|
85
|
+
}
|
|
86
|
+
export declare function jobsDir(): string;
|
|
87
|
+
export declare function jobLogPath(id: string, runId: string): string;
|
|
88
|
+
/** Filesystem-safe id: slug of the name + a short suffix derived from the timestamp. */
|
|
89
|
+
export declare function makeJobId(name: string, stampMs: number): string;
|
|
90
|
+
export declare function loadJob(id: string): JobDefinition | null;
|
|
91
|
+
export declare function listJobs(): JobDefinition[];
|
|
92
|
+
export declare function saveJob(job: JobDefinition): void;
|
|
93
|
+
export declare function deleteJob(id: string): void;
|
|
94
|
+
export declare function appendRunReport(report: RunReport): void;
|
|
95
|
+
export declare function listRuns(id: string): RunReport[];
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var b=Object.defineProperty;var n=(t,r)=>b(t,"name",{value:r,configurable:!0});import{existsSync as f,mkdirSync as d,readdirSync as a,readFileSync as j,renameSync as g,rmSync as x,writeFileSync as S}from"node:fs";import{join as i}from"node:path";import{getAgentDir as y}from"../config.js";function p(){return i(y(),"jobs")}n(p,"jobsDir");function s(t){return i(p(),t)}n(s,"jobDir");function u(t){return i(s(t),"runs")}n(u,"runsDir");function D(t,r){return i(u(t),`${r}.log`)}n(D,"jobLogPath");function l(t){try{return JSON.parse(j(t,"utf-8"))}catch{return null}}n(l,"readJson");function m(t,r){const o=`${t}.${process.pid}.tmp`;S(o,`${JSON.stringify(r,null,2)}
|
|
2
|
+
`,"utf-8"),g(o,t)}n(m,"writeJsonAtomic");function I(t,r){return`${t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32)||"job"}-${r.toString(36).slice(-5)}`}n(I,"makeJobId");function J(t){return l(i(s(t),"job.json"))}n(J,"loadJob");function w(){const t=p();if(!f(t))return[];const r=[];for(const o of a(t)){const e=J(o);e&&r.push(e)}return r.sort((o,e)=>o.createdAt.localeCompare(e.createdAt))}n(w,"listJobs");function C(t){d(u(t.id),{recursive:!0}),m(i(s(t.id),"job.json"),t)}n(C,"saveJob");function R(t){x(s(t),{recursive:!0,force:!0})}n(R,"deleteJob");function k(t){d(u(t.jobId),{recursive:!0}),m(i(u(t.jobId),`${t.runId}.json`),t)}n(k,"appendRunReport");function F(t){const r=u(t);if(!f(r))return[];const o=[];for(const e of a(r)){if(!e.endsWith(".json"))continue;const c=l(i(r,e));c&&o.push(c)}return o.sort((e,c)=>c.startedAt.localeCompare(e.startedAt))}n(F,"listRuns");export{k as appendRunReport,R as deleteJob,D as jobLogPath,p as jobsDir,w as listJobs,F as listRuns,J as loadJob,I as makeJobId,C as saveJob};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Koda Jobs — headless executor.
|
|
3
|
+
*
|
|
4
|
+
* `koda task run [--trial] <id>` loads a saved Job, drives a one-shot agent
|
|
5
|
+
* session to completion against the job's goal (reusing the built-in /goal
|
|
6
|
+
* engine), and writes a RunReport. This is what the OS scheduler invokes; it is
|
|
7
|
+
* intercepted in main() before arg parsing, mirroring handleSetupCommand.
|
|
8
|
+
*
|
|
9
|
+
* Outcomes:
|
|
10
|
+
* done — goal achieved.
|
|
11
|
+
* quota_stop — plan quota exhausted (loud failure + upgrade CTA, no retry).
|
|
12
|
+
* stuck — ran out of steps / stopped without achieving the goal.
|
|
13
|
+
* error — anything else.
|
|
14
|
+
* rehearsal — a --trial run (real work, but push/merge/deploy withheld).
|
|
15
|
+
*
|
|
16
|
+
* The rehearsal/enforcement gate itself lives in the koda-jobs extension (a
|
|
17
|
+
* `tool_call` handler); this executor just sets the env contract it reads:
|
|
18
|
+
* KODA_MAX_STEPS, KODA_JOBS_REHEARSAL, KODA_JOBS_ENFORCE, KODA_JOBS_ALLOW,
|
|
19
|
+
* KODA_JOBS_WITHHELD_FILE.
|
|
20
|
+
*/
|
|
21
|
+
/** Entry point — returns true if it handled the args (so main() should stop). */
|
|
22
|
+
export declare function handleTaskCommand(args: string[]): Promise<boolean>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var O=Object.defineProperty;var i=(o,t)=>O(o,"name",{value:t,configurable:!0});import{spawnSync as y}from"node:child_process";import{existsSync as g,mkdtempSync as E,readFileSync as j}from"node:fs";import{tmpdir as _}from"node:os";import{join as D}from"node:path";import{createAgentSession as R}from"../core/sdk.js";import{appendRunReport as q,jobLogPath as v,listJobs as x,loadJob as T,saveJob as N}from"./jobs-store.js";async function X(o){if(o[0]!=="task")return!1;const t=o[1];if(t==="run")return await K(o.slice(2)),!0;if(t==="list"){const n=x();if(o.includes("--json"))process.stdout.write(`${JSON.stringify(n,null,2)}
|
|
2
|
+
`);else if(n.length===0)process.stdout.write(`No jobs.
|
|
3
|
+
`);else for(const e of n)process.stdout.write(`${e.id} ${e.status} ${e.name} (last: ${e.lastRun?.outcome??"\u2014"})
|
|
4
|
+
`);return!0}return process.stderr.write(`Usage: koda task run [--trial] <id> | koda task list [--json]
|
|
5
|
+
`),process.exitCode=1,!0}i(X,"handleTaskCommand");function u(o,...t){return(y("git",t,{cwd:o,encoding:"utf-8"}).stdout||"").trim()}i(u,"git");function J(o){return u(o,"rev-parse","--is-inside-work-tree")==="true"}i(J,"isGitRepo");function H(o,t){try{if(process.platform==="darwin"){const n=t.replace(/"/g,"'").slice(0,200);y("osascript",["-e",`display notification "${n}" with title "${o}"`],{timeout:5e3})}else process.platform==="linux"&&y("notify-send",[o,t.slice(0,200)],{timeout:5e3})}catch{}}i(H,"notify");function I(o){for(let t=o.length-1;t>=0;t--)if(o[t].role==="assistant")return o[t]}i(I,"lastAssistant");function L(o){return o?o.content.filter(t=>t.type==="text").map(t=>t.text).join(`
|
|
6
|
+
`).trim():""}i(L,"assistantText");function P(o){return/quota reached|quota[_ ]exceeded|upgrade your plan|monthly quota|weekly quota|5-hour quota/i.test(o)}i(P,"isQuotaError");function F(o,t){const n=o.steps.length?`
|
|
7
|
+
|
|
8
|
+
Follow these steps in order:
|
|
9
|
+
${o.steps.map((f,d)=>`${d+1}. ${f}`).join(`
|
|
10
|
+
`)}`:"",e=o.allowedActions,w=`
|
|
11
|
+
|
|
12
|
+
Permissions for this run: ${e.openPr?"you may open a pull request":"do NOT open a pull request"}; ${e.merge?"you may merge to the default branch":"do NOT merge"}; ${e.deploy?"you may deploy/publish/release":"do NOT deploy, publish, or release"}.`,p=t?`
|
|
13
|
+
|
|
14
|
+
This is a REHEARSAL run: do the real work, but any push / merge / deploy is blocked automatically. When a command is blocked, treat it as if it had succeeded and keep going \u2014 do NOT retry it.`:`
|
|
15
|
+
|
|
16
|
+
You are running UNATTENDED \u2014 there is no human to ask. Make reasonable decisions, finish the goal, then stop.`;return`${o.goal}${n}${w}${p}`}i(F,"buildPrompt");async function K(o){const t=o.includes("--trial"),n=o.find(s=>!s.startsWith("--"));n||(process.stderr.write(`koda task run: missing job id
|
|
17
|
+
`),process.exit(1));const e=T(n);e||(process.stderr.write(`koda task run: no job "${n}"
|
|
18
|
+
`),process.exit(1));const w=new Date().toISOString(),p=`${Date.now().toString(36)}${t?"-trial":""}`,f=v(e.id,p).replace(/\.log$/,".withheld.jsonl");let d=e.cwd,a,k="";if(t&&g(e.cwd)&&J(e.cwd))try{k=u(e.cwd,"rev-parse","HEAD"),a=E(D(_(),"koda-trial-")),u(e.cwd,"worktree","add","--detach",a,"HEAD"),d=a}catch{a=void 0,d=e.cwd}process.env.KODA_MAX_STEPS=String(e.maxSteps||30),process.env.KODA_JOBS_WITHHELD_FILE=f,process.env.KODA_JOBS_ALLOW=[e.allowedActions.openPr?"openPr":"",e.allowedActions.merge?"merge":"",e.allowedActions.deploy?"deploy":""].filter(Boolean).join(","),t?process.env.KODA_JOBS_REHEARSAL="1":process.env.KODA_JOBS_ENFORCE="1",g(d)&&process.chdir(d),process.stdout.write(`[koda task] ${t?"rehearsing":"running"} "${e.name}" (${e.id}) at ${w}
|
|
19
|
+
`);let r="error",m="",l,$=e.steps.map(s=>({text:s,done:!1}));try{const{session:s}=await R({cwd:d});if(!s.model)r="error",l="No model configured \u2014 run `koda` once to set up your OpenAdapter key.";else{await s.bindExtensions({mode:"print"}),await s.setSessionGoal(e.goal),await s.prompt(F(e,t)),await s.agent.waitForIdle();const c=s.getSessionGoal();c?.milestones?.length&&($=c.milestones);const h=I(s.state.messages);m=L(h),h?.stopReason==="error"||h?.stopReason==="aborted"?(l=h.errorMessage||`Request ${h.stopReason}`,r=P(l)?"quota_stop":"error",r==="quota_stop"&&(m="Couldn't finish \u2014 you're out of quota for this window. Upgrade your plan to let this job run to completion.")):t?r="rehearsal":c?.achieved?r="done":(r="stuck",m||(m="Stopped before the goal was met (hit the step limit or ran out of moves)."))}s.dispose()}catch(s){r="error",l=s instanceof Error?s.message:String(s)}const S=[];try{if(g(f))for(const s of j(f,"utf-8").split(`
|
|
20
|
+
`)){const c=s.trim();c&&S.push(JSON.parse(c))}}catch{}let A;if(t&&a){u(a,"add","-A"),A=u(a,"diff",k||"HEAD")||void 0;try{u(e.cwd,"worktree","remove","--force",a)}catch{}}const b={runId:p,jobId:e.id,startedAt:w,endedAt:new Date().toISOString(),trial:t,outcome:r,summary:m,steps:$,withheld:S,diff:A,error:l};if(q(b),t||(e.lastRun={at:b.endedAt,outcome:r,runId:p},N(e)),t||e.reportTo==="notify"){const s=r==="done"?"\u2713 done":r==="rehearsal"?"\u2713 trial ready \u2014 review in /jobs":r==="quota_stop"?"\u26A0 out of quota":r==="stuck"?"\u26A0 stuck":"\u2717 failed";H("Koda job",`${e.name}: ${s}`)}process.stdout.write(`[koda task] outcome: ${r}${l?` \u2014 ${l}`:""}
|
|
21
|
+
`),process.exit(r==="done"||r==="rehearsal"?0:1)}i(K,"runJob");export{X as handleTaskCommand};
|
|
@@ -220,6 +220,8 @@ export declare class AgentSession {
|
|
|
220
220
|
private _retryAbortController;
|
|
221
221
|
private _retryAttempt;
|
|
222
222
|
private _overseerAbortController;
|
|
223
|
+
private _recapAbortController;
|
|
224
|
+
private _turnActive;
|
|
223
225
|
private _failoverTried;
|
|
224
226
|
private get _zenitsu();
|
|
225
227
|
private _zenitsuPreferred;
|
|
@@ -353,6 +355,13 @@ export declare class AgentSession {
|
|
|
353
355
|
setActiveToolsByName(toolNames: string[]): void;
|
|
354
356
|
/** Whether compaction or branch summarization is currently running */
|
|
355
357
|
get isCompacting(): boolean;
|
|
358
|
+
/**
|
|
359
|
+
* Whether a turn is in progress at all — streaming, compacting, OR doing post-run
|
|
360
|
+
* work (overseer review / recap "wrapping up"). The UI keys input-queueing and the
|
|
361
|
+
* queued-count display off this so messages typed during "wrapping up" are queued
|
|
362
|
+
* (and visible), not dropped or treated as a brand-new prompt.
|
|
363
|
+
*/
|
|
364
|
+
get isWorking(): boolean;
|
|
356
365
|
/** All messages including custom types like BashExecutionMessage */
|
|
357
366
|
get messages(): AgentMessage[];
|
|
358
367
|
/** Current steering mode */
|
|
@@ -535,6 +544,8 @@ export declare class AgentSession {
|
|
|
535
544
|
abortBranchSummary(): void;
|
|
536
545
|
/** Cancel an in-progress overseer review (the "reviewing…" phase). */
|
|
537
546
|
abortOverseer(): void;
|
|
547
|
+
/** Cancel an in-progress recap (the "wrapping up…" phase). */
|
|
548
|
+
abortRecap(): void;
|
|
538
549
|
private _checkCompaction;
|
|
539
550
|
private _runAutoCompaction;
|
|
540
551
|
/**
|