@enderfga/claw-orchestrator 3.7.1 → 4.0.0

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 (107) hide show
  1. package/README.md +19 -3
  2. package/dist/bin/cli.js +30 -7
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/src/autoloop/messages.d.ts +0 -2
  5. package/dist/src/autoloop/messages.js +0 -2
  6. package/dist/src/autoloop/messages.js.map +1 -1
  7. package/dist/src/autoloop/planner-tools.d.ts +3 -3
  8. package/dist/src/autoloop/planner-tools.js +3 -3
  9. package/dist/src/autoloop/runner.d.ts +1 -2
  10. package/dist/src/autoloop/runner.js +1 -2
  11. package/dist/src/autoloop/runner.js.map +1 -1
  12. package/dist/src/autoloop/types.d.ts +0 -2
  13. package/dist/src/autoloop/types.js +0 -2
  14. package/dist/src/autoloop/types.js.map +1 -1
  15. package/dist/src/council.js +1 -0
  16. package/dist/src/council.js.map +1 -1
  17. package/dist/src/dashboard/index.html +709 -8
  18. package/dist/src/embedded-server.js +172 -6
  19. package/dist/src/embedded-server.js.map +1 -1
  20. package/dist/src/index.js +222 -1
  21. package/dist/src/index.js.map +1 -1
  22. package/dist/src/session-manager.d.ts +82 -1
  23. package/dist/src/session-manager.js +262 -5
  24. package/dist/src/session-manager.js.map +1 -1
  25. package/dist/src/ultraapp/build-events.d.ts +46 -0
  26. package/dist/src/ultraapp/build-events.js +6 -0
  27. package/dist/src/ultraapp/build-events.js.map +1 -0
  28. package/dist/src/ultraapp/build.d.ts +39 -0
  29. package/dist/src/ultraapp/build.js +111 -0
  30. package/dist/src/ultraapp/build.js.map +1 -0
  31. package/dist/src/ultraapp/conventions.d.ts +8 -0
  32. package/dist/src/ultraapp/conventions.js +248 -0
  33. package/dist/src/ultraapp/conventions.js.map +1 -0
  34. package/dist/src/ultraapp/council-adapter.d.ts +49 -0
  35. package/dist/src/ultraapp/council-adapter.js +152 -0
  36. package/dist/src/ultraapp/council-adapter.js.map +1 -0
  37. package/dist/src/ultraapp/deploy.d.ts +45 -0
  38. package/dist/src/ultraapp/deploy.js +82 -0
  39. package/dist/src/ultraapp/deploy.js.map +1 -0
  40. package/dist/src/ultraapp/diff-apply.d.ts +15 -0
  41. package/dist/src/ultraapp/diff-apply.js +48 -0
  42. package/dist/src/ultraapp/diff-apply.js.map +1 -0
  43. package/dist/src/ultraapp/docker.d.ts +57 -0
  44. package/dist/src/ultraapp/docker.js +83 -0
  45. package/dist/src/ultraapp/docker.js.map +1 -0
  46. package/dist/src/ultraapp/feedback-classifier.d.ts +24 -0
  47. package/dist/src/ultraapp/feedback-classifier.js +85 -0
  48. package/dist/src/ultraapp/feedback-classifier.js.map +1 -0
  49. package/dist/src/ultraapp/files.d.ts +24 -0
  50. package/dist/src/ultraapp/files.js +79 -0
  51. package/dist/src/ultraapp/files.js.map +1 -0
  52. package/dist/src/ultraapp/fix-on-failure-session.d.ts +23 -0
  53. package/dist/src/ultraapp/fix-on-failure-session.js +48 -0
  54. package/dist/src/ultraapp/fix-on-failure-session.js.map +1 -0
  55. package/dist/src/ultraapp/fix-on-failure.d.ts +39 -0
  56. package/dist/src/ultraapp/fix-on-failure.js +69 -0
  57. package/dist/src/ultraapp/fix-on-failure.js.map +1 -0
  58. package/dist/src/ultraapp/host-strategy.d.ts +57 -0
  59. package/dist/src/ultraapp/host-strategy.js +205 -0
  60. package/dist/src/ultraapp/host-strategy.js.map +1 -0
  61. package/dist/src/ultraapp/interview-parser.d.ts +41 -0
  62. package/dist/src/ultraapp/interview-parser.js +83 -0
  63. package/dist/src/ultraapp/interview-parser.js.map +1 -0
  64. package/dist/src/ultraapp/interview-tools.d.ts +16 -0
  65. package/dist/src/ultraapp/interview-tools.js +36 -0
  66. package/dist/src/ultraapp/interview-tools.js.map +1 -0
  67. package/dist/src/ultraapp/json-patch.d.ts +6 -0
  68. package/dist/src/ultraapp/json-patch.js +78 -0
  69. package/dist/src/ultraapp/json-patch.js.map +1 -0
  70. package/dist/src/ultraapp/lifecycle.d.ts +38 -0
  71. package/dist/src/ultraapp/lifecycle.js +31 -0
  72. package/dist/src/ultraapp/lifecycle.js.map +1 -0
  73. package/dist/src/ultraapp/manager.d.ts +141 -0
  74. package/dist/src/ultraapp/manager.js +661 -0
  75. package/dist/src/ultraapp/manager.js.map +1 -0
  76. package/dist/src/ultraapp/narrator-prompt.d.ts +10 -0
  77. package/dist/src/ultraapp/narrator-prompt.js +54 -0
  78. package/dist/src/ultraapp/narrator-prompt.js.map +1 -0
  79. package/dist/src/ultraapp/narrator.d.ts +49 -0
  80. package/dist/src/ultraapp/narrator.js +83 -0
  81. package/dist/src/ultraapp/narrator.js.map +1 -0
  82. package/dist/src/ultraapp/patcher.d.ts +35 -0
  83. package/dist/src/ultraapp/patcher.js +159 -0
  84. package/dist/src/ultraapp/patcher.js.map +1 -0
  85. package/dist/src/ultraapp/router.d.ts +39 -0
  86. package/dist/src/ultraapp/router.js +139 -0
  87. package/dist/src/ultraapp/router.js.map +1 -0
  88. package/dist/src/ultraapp/spec-delta.d.ts +18 -0
  89. package/dist/src/ultraapp/spec-delta.js +35 -0
  90. package/dist/src/ultraapp/spec-delta.js.map +1 -0
  91. package/dist/src/ultraapp/spec.d.ts +82 -0
  92. package/dist/src/ultraapp/spec.js +125 -0
  93. package/dist/src/ultraapp/spec.js.map +1 -0
  94. package/dist/src/ultraapp/store.d.ts +67 -0
  95. package/dist/src/ultraapp/store.js +177 -0
  96. package/dist/src/ultraapp/store.js.map +1 -0
  97. package/dist/src/ultraapp/versions.d.ts +50 -0
  98. package/dist/src/ultraapp/versions.js +65 -0
  99. package/dist/src/ultraapp/versions.js.map +1 -0
  100. package/openclaw.plugin.json +15 -1
  101. package/package.json +3 -1
  102. package/skills/SKILL.md +2 -2
  103. package/skills/references/autoloop.md +1 -1
  104. package/skills/references/mcp.md +2 -2
  105. package/skills/references/tools.md +183 -0
  106. package/skills/references/ultraapp.md +203 -0
  107. package/skills/ultraapp/SKILL.md +112 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/ultraapp/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Spec-delta — focused mini-interview when the user's done-mode feedback
3
+ * implies an AppSpec change rather than a cosmetic patch.
4
+ *
5
+ * Reuses the existing interview engine wholesale: we only inject a bootstrap
6
+ * system message naming the slots in scope and flip the run's mode back to
7
+ * 'interview'. The user then answers as in v0.1, and on [INTERVIEW: COMPLETE]
8
+ * the existing build flow takes over (council rerun is wired in v0.5+ — for
9
+ * v0.5 the user clicks Start Build manually for the focused rerun).
10
+ */
11
+ import type { AppSpec } from './spec.js';
12
+ interface SpecDeltaManagerLike {
13
+ injectSystemMessage(runId: string, text: string): Promise<void>;
14
+ setModeForDelta(runId: string): Promise<void>;
15
+ }
16
+ export declare function composeDeltaBootstrap(spec: AppSpec, feedback: string): string;
17
+ export declare function startSpecDeltaInterview(manager: SpecDeltaManagerLike, runId: string, feedback: string, currentSpec: AppSpec): Promise<void>;
18
+ export {};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Spec-delta — focused mini-interview when the user's done-mode feedback
3
+ * implies an AppSpec change rather than a cosmetic patch.
4
+ *
5
+ * Reuses the existing interview engine wholesale: we only inject a bootstrap
6
+ * system message naming the slots in scope and flip the run's mode back to
7
+ * 'interview'. The user then answers as in v0.1, and on [INTERVIEW: COMPLETE]
8
+ * the existing build flow takes over (council rerun is wired in v0.5+ — for
9
+ * v0.5 the user clicks Start Build manually for the focused rerun).
10
+ */
11
+ export function composeDeltaBootstrap(spec, feedback) {
12
+ return `The user has a previously-deployed ultraapp with the AppSpec below. They've
13
+ just sent feedback that requires a spec change. Run a FOCUSED interview that
14
+ asks ONLY about the slots that need to change to honour the feedback. Do not
15
+ re-confirm slots that are unaffected.
16
+
17
+ When the focused interview is done, call check_completeness and emit
18
+ [INTERVIEW: COMPLETE] as usual. The user can then click Start Build to
19
+ trigger a delta-aware council rerun.
20
+
21
+ ## Existing AppSpec
22
+
23
+ \`\`\`json
24
+ ${JSON.stringify(spec, null, 2)}
25
+ \`\`\`
26
+
27
+ ## User feedback
28
+
29
+ ${feedback}`;
30
+ }
31
+ export async function startSpecDeltaInterview(manager, runId, feedback, currentSpec) {
32
+ await manager.injectSystemMessage(runId, composeDeltaBootstrap(currentSpec, feedback));
33
+ await manager.setModeForDelta(runId);
34
+ }
35
+ //# sourceMappingURL=spec-delta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-delta.js","sourceRoot":"","sources":["../../../src/ultraapp/spec-delta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,MAAM,UAAU,qBAAqB,CAAC,IAAa,EAAE,QAAgB;IACnE,OAAO;;;;;;;;;;;;EAYP,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;;;;;EAK7B,QAAQ,EAAE,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAA6B,EAC7B,KAAa,EACb,QAAgB,EAChB,WAAoB;IAEpB,MAAM,OAAO,CAAC,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvF,MAAM,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,82 @@
1
+ export interface AppSpec {
2
+ version: 1;
3
+ runId: string;
4
+ createdAt: string;
5
+ updatedAt: string;
6
+ meta: {
7
+ name: string;
8
+ title: string;
9
+ description: string;
10
+ };
11
+ inputs: AppSpecInput[];
12
+ outputs: AppSpecOutput[];
13
+ pipeline: {
14
+ steps: AppSpecStep[];
15
+ };
16
+ runtime: AppSpecRuntime;
17
+ ui: AppSpecUi;
18
+ }
19
+ export interface AppSpecInput {
20
+ name: string;
21
+ type: 'file' | 'files' | 'text' | 'enum' | 'number';
22
+ accept?: string;
23
+ required: boolean;
24
+ description: string;
25
+ examples?: Array<{
26
+ ref: string;
27
+ metadata?: Record<string, unknown>;
28
+ }>;
29
+ enumValues?: string[];
30
+ }
31
+ export interface AppSpecOutput {
32
+ name: string;
33
+ type: 'file' | 'text' | 'json' | 'image-gallery' | 'video';
34
+ description: string;
35
+ }
36
+ export interface AppSpecStep {
37
+ id: string;
38
+ description: string;
39
+ inputs: string[];
40
+ outputs: string[];
41
+ hints: {
42
+ likelyTools?: string[];
43
+ referenceCommand?: string;
44
+ referenceCode?: string;
45
+ notes?: string;
46
+ };
47
+ validates: {
48
+ outputType: string;
49
+ };
50
+ }
51
+ export interface AppSpecRuntime {
52
+ needsLLM: boolean;
53
+ llmProviders: Array<'anthropic' | 'openai' | 'google'>;
54
+ binaryDeps: string[];
55
+ estimatedRuntimeSec: number;
56
+ estimatedFileSizeMB: number;
57
+ }
58
+ export interface AppSpecUi {
59
+ layout: 'single-form' | 'wizard' | 'split-view';
60
+ showProgress: boolean;
61
+ accentColor?: string;
62
+ }
63
+ export declare function makeEmptySpec(runId: string): AppSpec;
64
+ /**
65
+ * Lax shape check for intermediate AppSpec writes during interview iteration.
66
+ * Catches obviously-broken state but tolerates partial pipelines, references
67
+ * to inputs not yet declared, etc. — Claude builds the spec incrementally and
68
+ * transient invalid states are expected. Strict cross-ref + DAG check happens
69
+ * at startBuild via {@link validateAppSpec}.
70
+ */
71
+ export declare function validateAppSpecShape(spec: AppSpec): void;
72
+ /**
73
+ * Strict validation: shape + every pipeline step's input refs must resolve to
74
+ * a declared input or a prior step + the pipeline DAG must be acyclic. Called
75
+ * at startBuild; do NOT call from writeSpec (that fires on every interview
76
+ * patch and Claude iterates incrementally).
77
+ */
78
+ export declare function validateAppSpec(spec: AppSpec): void;
79
+ export declare function isComplete(spec: AppSpec): {
80
+ ok: boolean;
81
+ missing: string[];
82
+ };
@@ -0,0 +1,125 @@
1
+ const NAME_RE = /^[a-z0-9][a-z0-9-]{2,31}$/;
2
+ export function makeEmptySpec(runId) {
3
+ const now = new Date().toISOString();
4
+ return {
5
+ version: 1,
6
+ runId,
7
+ createdAt: now,
8
+ updatedAt: now,
9
+ meta: { name: '', title: '', description: '' },
10
+ inputs: [],
11
+ outputs: [],
12
+ pipeline: { steps: [] },
13
+ runtime: {
14
+ needsLLM: false,
15
+ llmProviders: [],
16
+ binaryDeps: [],
17
+ estimatedRuntimeSec: 0,
18
+ estimatedFileSizeMB: 0,
19
+ },
20
+ ui: { layout: 'single-form', showProgress: false },
21
+ };
22
+ }
23
+ /**
24
+ * Lax shape check for intermediate AppSpec writes during interview iteration.
25
+ * Catches obviously-broken state but tolerates partial pipelines, references
26
+ * to inputs not yet declared, etc. — Claude builds the spec incrementally and
27
+ * transient invalid states are expected. Strict cross-ref + DAG check happens
28
+ * at startBuild via {@link validateAppSpec}.
29
+ */
30
+ export function validateAppSpecShape(spec) {
31
+ if (spec.version !== 1)
32
+ throw new Error('AppSpec.version must be 1');
33
+ if (typeof spec.runId !== 'string' || spec.runId.length === 0) {
34
+ throw new Error('AppSpec.runId required');
35
+ }
36
+ if (spec.meta.name && !NAME_RE.test(spec.meta.name)) {
37
+ throw new Error('AppSpec.meta.name must match [a-z0-9][a-z0-9-]{2,31}');
38
+ }
39
+ }
40
+ /**
41
+ * Strict validation: shape + every pipeline step's input refs must resolve to
42
+ * a declared input or a prior step + the pipeline DAG must be acyclic. Called
43
+ * at startBuild; do NOT call from writeSpec (that fires on every interview
44
+ * patch and Claude iterates incrementally).
45
+ */
46
+ export function validateAppSpec(spec) {
47
+ validateAppSpecShape(spec);
48
+ const stepIds = new Set(spec.pipeline.steps.map((s) => s.id));
49
+ const inputNames = new Set(spec.inputs.map((i) => i.name));
50
+ for (const step of spec.pipeline.steps) {
51
+ for (const ref of step.inputs) {
52
+ if (ref.startsWith('inputs.')) {
53
+ const k = ref.slice('inputs.'.length);
54
+ if (!inputNames.has(k)) {
55
+ throw new Error(`pipeline step '${step.id}': unknown ref '${ref}'`);
56
+ }
57
+ }
58
+ else {
59
+ const [stepId] = ref.split('.');
60
+ if (!stepIds.has(stepId)) {
61
+ throw new Error(`pipeline step '${step.id}': unknown ref '${ref}'`);
62
+ }
63
+ }
64
+ }
65
+ }
66
+ const incoming = new Map();
67
+ for (const s of spec.pipeline.steps)
68
+ incoming.set(s.id, new Set());
69
+ for (const s of spec.pipeline.steps) {
70
+ for (const ref of s.inputs) {
71
+ if (!ref.startsWith('inputs.')) {
72
+ const [src] = ref.split('.');
73
+ incoming.get(s.id).add(src);
74
+ }
75
+ }
76
+ }
77
+ const queue = [];
78
+ for (const s of spec.pipeline.steps) {
79
+ if (incoming.get(s.id).size === 0)
80
+ queue.push(s.id);
81
+ }
82
+ let visited = 0;
83
+ while (queue.length) {
84
+ const id = queue.shift();
85
+ visited++;
86
+ for (const s of spec.pipeline.steps) {
87
+ const deps = incoming.get(s.id);
88
+ if (deps.has(id)) {
89
+ deps.delete(id);
90
+ if (deps.size === 0)
91
+ queue.push(s.id);
92
+ }
93
+ }
94
+ }
95
+ if (visited !== spec.pipeline.steps.length)
96
+ throw new Error('pipeline has a cycle');
97
+ }
98
+ export function isComplete(spec) {
99
+ const missing = [];
100
+ if (!spec.meta.name)
101
+ missing.push('meta.name');
102
+ if (!spec.meta.title)
103
+ missing.push('meta.title');
104
+ if (!spec.meta.description)
105
+ missing.push('meta.description');
106
+ if (spec.inputs.length === 0) {
107
+ missing.push('inputs[0]');
108
+ }
109
+ else {
110
+ spec.inputs.forEach((inp, i) => {
111
+ if (!inp.name)
112
+ missing.push(`inputs[${i}].name`);
113
+ if (!inp.type)
114
+ missing.push(`inputs[${i}].type`);
115
+ if (!inp.description)
116
+ missing.push(`inputs[${i}].description`);
117
+ });
118
+ }
119
+ if (spec.outputs.length === 0)
120
+ missing.push('outputs[0]');
121
+ if (spec.pipeline.steps.length === 0)
122
+ missing.push('pipeline.steps[0]');
123
+ return { ok: missing.length === 0, missing };
124
+ }
125
+ //# sourceMappingURL=spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../../src/ultraapp/spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import { type AppSpec } from './spec.js';
2
+ export type RunMode = 'interview' | 'queued' | 'building' | 'build-complete' | 'deploying' | 'done' | 'failed' | 'cancelled';
3
+ export interface DeployInfo {
4
+ url: string;
5
+ port: number;
6
+ containerName: string;
7
+ imageTag: string;
8
+ }
9
+ export interface RunState {
10
+ runId: string;
11
+ mode: RunMode;
12
+ createdAt: string;
13
+ updatedAt: string;
14
+ failure?: string;
15
+ }
16
+ export interface RunSummary {
17
+ runId: string;
18
+ mode: RunMode;
19
+ title: string;
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ }
23
+ export interface ChatEntry {
24
+ role: 'assistant' | 'user' | 'system';
25
+ kind: 'question' | 'answer' | 'free' | 'narrator' | 'error';
26
+ text: string;
27
+ payload?: Record<string, unknown>;
28
+ ts?: string;
29
+ }
30
+ export interface SpecHistoryEntry {
31
+ ts: string;
32
+ source: 'interview' | 'manual-edit';
33
+ spec: AppSpec;
34
+ }
35
+ export declare class UltraappStore {
36
+ private readonly root;
37
+ constructor(root: string);
38
+ createRun(): Promise<string>;
39
+ listRuns(): Promise<RunSummary[]>;
40
+ readState(runId: string): Promise<RunState>;
41
+ setMode(runId: string, mode: RunMode, failure?: string): Promise<void>;
42
+ readSpec(runId: string): Promise<AppSpec>;
43
+ writeSpec(runId: string, spec: AppSpec, source?: SpecHistoryEntry['source']): Promise<void>;
44
+ readSpecHistory(runId: string): Promise<SpecHistoryEntry[]>;
45
+ appendChat(runId: string, entry: ChatEntry): Promise<void>;
46
+ readChat(runId: string): Promise<ChatEntry[]>;
47
+ examplesDir(runId: string): string;
48
+ worktreesDir(runId: string): string;
49
+ versionsDir(runId: string): string;
50
+ runDirAbsolute(runId: string): string;
51
+ recordBuildArtifact(runId: string, args: {
52
+ worktreePath: string;
53
+ version: string;
54
+ }): Promise<void>;
55
+ readArtifacts(runId: string): Promise<Array<{
56
+ version: string;
57
+ worktreePath: string;
58
+ builtAt: string;
59
+ deploy?: DeployInfo;
60
+ deployedAt?: string;
61
+ }>>;
62
+ recordDeploy(runId: string, version: string, deploy: DeployInfo): Promise<void>;
63
+ deleteRunFiles(runId: string): Promise<void>;
64
+ rootDir(): string;
65
+ private runDir;
66
+ }
67
+ export declare function defaultStoreRoot(): string;
@@ -0,0 +1,177 @@
1
+ import * as fs from 'node:fs';
2
+ import * as fsp from 'node:fs/promises';
3
+ import * as path from 'node:path';
4
+ import * as crypto from 'node:crypto';
5
+ import { makeEmptySpec, validateAppSpecShape } from './spec.js';
6
+ export class UltraappStore {
7
+ root;
8
+ constructor(root) {
9
+ this.root = root;
10
+ fs.mkdirSync(root, { recursive: true });
11
+ }
12
+ async createRun() {
13
+ const id = `ua-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
14
+ const dir = this.runDir(id);
15
+ await fsp.mkdir(dir, { recursive: true });
16
+ await fsp.mkdir(path.join(dir, 'examples'), { recursive: true });
17
+ const now = new Date().toISOString();
18
+ const state = { runId: id, mode: 'interview', createdAt: now, updatedAt: now };
19
+ await fsp.writeFile(path.join(dir, 'state.json'), JSON.stringify(state, null, 2));
20
+ const spec = makeEmptySpec(id);
21
+ await fsp.writeFile(path.join(dir, 'spec.json'), JSON.stringify(spec, null, 2));
22
+ return id;
23
+ }
24
+ async listRuns() {
25
+ let entries;
26
+ try {
27
+ entries = await fsp.readdir(this.root);
28
+ }
29
+ catch {
30
+ return [];
31
+ }
32
+ const out = [];
33
+ for (const e of entries) {
34
+ if (!e.startsWith('ua-'))
35
+ continue;
36
+ try {
37
+ const state = await this.readState(e);
38
+ const spec = await this.readSpec(e);
39
+ out.push({
40
+ runId: e,
41
+ mode: state.mode,
42
+ title: spec.meta.title || spec.meta.name || '(untitled)',
43
+ createdAt: state.createdAt,
44
+ updatedAt: state.updatedAt,
45
+ });
46
+ }
47
+ catch {
48
+ // skip malformed
49
+ }
50
+ }
51
+ out.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
52
+ return out;
53
+ }
54
+ async readState(runId) {
55
+ const raw = await fsp.readFile(path.join(this.runDir(runId), 'state.json'), 'utf8');
56
+ return JSON.parse(raw);
57
+ }
58
+ async setMode(runId, mode, failure) {
59
+ const state = await this.readState(runId);
60
+ state.mode = mode;
61
+ state.updatedAt = new Date().toISOString();
62
+ if (failure !== undefined)
63
+ state.failure = failure;
64
+ await fsp.writeFile(path.join(this.runDir(runId), 'state.json'), JSON.stringify(state, null, 2));
65
+ }
66
+ async readSpec(runId) {
67
+ const raw = await fsp.readFile(path.join(this.runDir(runId), 'spec.json'), 'utf8');
68
+ return JSON.parse(raw);
69
+ }
70
+ async writeSpec(runId, spec, source = 'interview') {
71
+ spec.updatedAt = new Date().toISOString();
72
+ // Lax shape-only check: cross-ref + DAG strict checks happen at startBuild,
73
+ // not on every interview patch. Claude iterates incrementally and transient
74
+ // invalid states (e.g., a step refs an input not yet declared) are normal.
75
+ validateAppSpecShape(spec);
76
+ const dir = this.runDir(runId);
77
+ await fsp.writeFile(path.join(dir, 'spec.json'), JSON.stringify(spec, null, 2));
78
+ const entry = { ts: spec.updatedAt, source, spec };
79
+ await fsp.appendFile(path.join(dir, 'spec.history.jsonl'), JSON.stringify(entry) + '\n');
80
+ const state = await this.readState(runId);
81
+ state.updatedAt = spec.updatedAt;
82
+ await fsp.writeFile(path.join(dir, 'state.json'), JSON.stringify(state, null, 2));
83
+ }
84
+ async readSpecHistory(runId) {
85
+ try {
86
+ const raw = await fsp.readFile(path.join(this.runDir(runId), 'spec.history.jsonl'), 'utf8');
87
+ return raw
88
+ .split('\n')
89
+ .filter((l) => l.length > 0)
90
+ .map((l) => JSON.parse(l));
91
+ }
92
+ catch {
93
+ return [];
94
+ }
95
+ }
96
+ async appendChat(runId, entry) {
97
+ const e = { ...entry, ts: entry.ts ?? new Date().toISOString() };
98
+ await fsp.appendFile(path.join(this.runDir(runId), 'chat.jsonl'), JSON.stringify(e) + '\n');
99
+ }
100
+ async readChat(runId) {
101
+ try {
102
+ const raw = await fsp.readFile(path.join(this.runDir(runId), 'chat.jsonl'), 'utf8');
103
+ return raw
104
+ .split('\n')
105
+ .filter((l) => l.length > 0)
106
+ .map((l) => JSON.parse(l));
107
+ }
108
+ catch {
109
+ return [];
110
+ }
111
+ }
112
+ examplesDir(runId) {
113
+ return path.join(this.runDir(runId), 'examples');
114
+ }
115
+ worktreesDir(runId) {
116
+ return path.join(this.runDir(runId), 'worktrees');
117
+ }
118
+ versionsDir(runId) {
119
+ return path.join(this.runDir(runId), 'versions');
120
+ }
121
+ runDirAbsolute(runId) {
122
+ return this.runDir(runId);
123
+ }
124
+ async recordBuildArtifact(runId, args) {
125
+ const dir = path.join(this.versionsDir(runId), args.version);
126
+ await fsp.mkdir(dir, { recursive: true });
127
+ await fsp.writeFile(path.join(dir, 'artifact.json'), JSON.stringify({ worktreePath: args.worktreePath, builtAt: new Date().toISOString() }, null, 2));
128
+ }
129
+ async readArtifacts(runId) {
130
+ try {
131
+ const versions = await fsp.readdir(this.versionsDir(runId));
132
+ const out = [];
133
+ for (const v of versions) {
134
+ try {
135
+ const a = JSON.parse(await fsp.readFile(path.join(this.versionsDir(runId), v, 'artifact.json'), 'utf8'));
136
+ out.push({
137
+ version: v,
138
+ worktreePath: a.worktreePath,
139
+ builtAt: a.builtAt,
140
+ deploy: a.deploy,
141
+ deployedAt: a.deployedAt,
142
+ });
143
+ }
144
+ catch {
145
+ /* skip */
146
+ }
147
+ }
148
+ return out.sort((a, b) => a.version.localeCompare(b.version));
149
+ }
150
+ catch {
151
+ return [];
152
+ }
153
+ }
154
+ async recordDeploy(runId, version, deploy) {
155
+ const file = path.join(this.versionsDir(runId), version, 'artifact.json');
156
+ const cur = JSON.parse(await fsp.readFile(file, 'utf8'));
157
+ cur.deploy = deploy;
158
+ cur.deployedAt = new Date().toISOString();
159
+ await fsp.writeFile(file, JSON.stringify(cur, null, 2));
160
+ }
161
+ async deleteRunFiles(runId) {
162
+ await fsp.rm(this.runDir(runId), { recursive: true, force: true });
163
+ }
164
+ rootDir() {
165
+ return this.root;
166
+ }
167
+ runDir(runId) {
168
+ if (!/^ua-[a-zA-Z0-9-]+$/.test(runId))
169
+ throw new Error(`bad runId: ${runId}`);
170
+ return path.join(this.root, runId);
171
+ }
172
+ }
173
+ export function defaultStoreRoot() {
174
+ const home = process.env.HOME ?? process.cwd();
175
+ return path.join(home, '.claw-orchestrator', 'ultraapps');
176
+ }
177
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/ultraapp/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Version snapshot + swap mechanics.
3
+ *
4
+ * Each successful patcher / spec-delta / structural-rerun bumps a version.
5
+ * Versions live under `<runDir>/versions/v1/`, `v2/`, ..., each with their
6
+ * own `artifact.json` carrying worktreePath + (optionally) deploy info.
7
+ *
8
+ * `swapVersion` atomically retargets the router: deregister current slug,
9
+ * stop current container, start new container, register slug to new port.
10
+ */
11
+ export interface DeployInfoLite {
12
+ url: string;
13
+ port: number;
14
+ containerName: string;
15
+ imageTag: string;
16
+ }
17
+ export interface VersionEntry {
18
+ version: string;
19
+ worktreePath: string;
20
+ builtAt: string;
21
+ source?: string;
22
+ deploy?: DeployInfoLite;
23
+ }
24
+ export declare function listVersions(versionsDir: string): VersionEntry[];
25
+ export declare function snapshotVersion(versionsDir: string, args: {
26
+ worktreePath: string;
27
+ source: string;
28
+ }): string;
29
+ export interface SwapArgs {
30
+ versionsDir: string;
31
+ fromVersion: string;
32
+ toVersion: string;
33
+ slug: string;
34
+ router: {
35
+ register: (slug: string, port: number) => void;
36
+ deregister: (slug: string) => void;
37
+ };
38
+ startContainer: (containerName: string) => Promise<{
39
+ ok: boolean;
40
+ error?: string;
41
+ }>;
42
+ stopContainer: (containerName: string) => Promise<{
43
+ ok: boolean;
44
+ error?: string;
45
+ }>;
46
+ }
47
+ export declare function swapVersion(args: SwapArgs): Promise<{
48
+ ok: boolean;
49
+ error?: string;
50
+ }>;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Version snapshot + swap mechanics.
3
+ *
4
+ * Each successful patcher / spec-delta / structural-rerun bumps a version.
5
+ * Versions live under `<runDir>/versions/v1/`, `v2/`, ..., each with their
6
+ * own `artifact.json` carrying worktreePath + (optionally) deploy info.
7
+ *
8
+ * `swapVersion` atomically retargets the router: deregister current slug,
9
+ * stop current container, start new container, register slug to new port.
10
+ */
11
+ import * as fs from 'node:fs';
12
+ import * as path from 'node:path';
13
+ export function listVersions(versionsDir) {
14
+ if (!fs.existsSync(versionsDir))
15
+ return [];
16
+ const out = [];
17
+ for (const v of fs.readdirSync(versionsDir)) {
18
+ try {
19
+ const a = JSON.parse(fs.readFileSync(path.join(versionsDir, v, 'artifact.json'), 'utf8'));
20
+ out.push({ version: v, ...a });
21
+ }
22
+ catch {
23
+ /* skip non-version dirs */
24
+ }
25
+ }
26
+ out.sort((a, b) => parseVersionNumber(a.version) - parseVersionNumber(b.version));
27
+ return out;
28
+ }
29
+ function parseVersionNumber(version) {
30
+ const m = /^v(\d+)$/.exec(version);
31
+ return m ? parseInt(m[1], 10) : Number.MAX_SAFE_INTEGER;
32
+ }
33
+ export function snapshotVersion(versionsDir, args) {
34
+ fs.mkdirSync(versionsDir, { recursive: true });
35
+ const existing = listVersions(versionsDir);
36
+ const next = `v${existing.length + 1}`;
37
+ const dir = path.join(versionsDir, next);
38
+ fs.mkdirSync(dir, { recursive: true });
39
+ fs.writeFileSync(path.join(dir, 'artifact.json'), JSON.stringify({
40
+ worktreePath: args.worktreePath,
41
+ builtAt: new Date().toISOString(),
42
+ source: args.source,
43
+ }, null, 2));
44
+ return next;
45
+ }
46
+ export async function swapVersion(args) {
47
+ const versions = listVersions(args.versionsDir);
48
+ const from = versions.find((v) => v.version === args.fromVersion);
49
+ const to = versions.find((v) => v.version === args.toVersion);
50
+ if (!to?.deploy) {
51
+ return { ok: false, error: `target version ${args.toVersion} has no deploy info` };
52
+ }
53
+ args.router.deregister(args.slug);
54
+ if (from?.deploy) {
55
+ await args.stopContainer(from.deploy.containerName).catch(() => {
56
+ /* best effort */
57
+ });
58
+ }
59
+ const r = await args.startContainer(to.deploy.containerName);
60
+ if (!r.ok)
61
+ return { ok: false, error: r.error };
62
+ args.router.register(args.slug, to.deploy.port);
63
+ return { ok: true };
64
+ }
65
+ //# sourceMappingURL=versions.js.map