@synaplink/orqlaude 0.3.3 → 0.5.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.
- package/README.md +45 -2
- package/dist/__tests__/state.test.js +1 -1
- package/dist/__tests__/userio.test.d.ts +1 -0
- package/dist/__tests__/userio.test.js +101 -0
- package/dist/__tests__/userio.test.js.map +1 -0
- package/dist/__tests__/v05.test.d.ts +1 -0
- package/dist/__tests__/v05.test.js +80 -0
- package/dist/__tests__/v05.test.js.map +1 -0
- package/dist/cli.js +65 -42
- package/dist/cli.js.map +1 -1
- package/dist/lib/agnet.d.ts +26 -0
- package/dist/lib/agnet.js +94 -0
- package/dist/lib/agnet.js.map +1 -0
- package/dist/lib/state.d.ts +95 -1
- package/dist/lib/state.js +26 -4
- package/dist/lib/state.js.map +1 -1
- package/dist/lib/style.d.ts +42 -0
- package/dist/lib/style.js +96 -0
- package/dist/lib/style.js.map +1 -0
- package/dist/server.js +3 -1
- package/dist/server.js.map +1 -1
- package/dist/telegram/api.d.ts +40 -0
- package/dist/telegram/api.js +70 -2
- package/dist/telegram/api.js.map +1 -1
- package/dist/telegram/bot.js +6 -1
- package/dist/telegram/bot.js.map +1 -1
- package/dist/telegram/commands.d.ts +5 -1
- package/dist/telegram/commands.js +107 -6
- package/dist/telegram/commands.js.map +1 -1
- package/dist/telegram/notifier.d.ts +3 -11
- package/dist/telegram/notifier.js +304 -25
- package/dist/telegram/notifier.js.map +1 -1
- package/dist/tools/ping.js +1 -1
- package/dist/tools/planning.js +8 -0
- package/dist/tools/planning.js.map +1 -1
- package/dist/tools/userio.d.ts +4 -0
- package/dist/tools/userio.js +194 -0
- package/dist/tools/userio.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agnet — the orqlaude term for a spawned worker (a portmanteau-cousin of
|
|
3
|
+
* "agent", matching the orqlaude / Claude naming aesthetic).
|
|
4
|
+
*
|
|
5
|
+
* Each task in a plan gets a stable, human-friendly Agnet name like
|
|
6
|
+
* "Agnet Zenith" or "Agnet Verdant". The name is:
|
|
7
|
+
* • deterministic per task_id (so the same task always gets the same
|
|
8
|
+
* name across MCP restarts);
|
|
9
|
+
* • unique within a plan (we linear-probe to avoid collisions);
|
|
10
|
+
* • picked from a curated list of ~32 single-word designations chosen for
|
|
11
|
+
* readability in chat surfaces.
|
|
12
|
+
*
|
|
13
|
+
* Names are stored on the Task at create_plan time and surfaced in:
|
|
14
|
+
* • CLI output (`orqlaude status` / `list`)
|
|
15
|
+
* • Telegram notifications (notifier prefixes events with "Agnet Zenith")
|
|
16
|
+
* • Tool responses (so primary Claude can refer to them by name in chat)
|
|
17
|
+
*/
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
19
|
+
/** Curated single-word designations. Add freely; just don't shorten this list
|
|
20
|
+
* below 8 or so or collision avoidance starts to bite. */
|
|
21
|
+
const NAMES = [
|
|
22
|
+
"Aegis",
|
|
23
|
+
"Argent",
|
|
24
|
+
"Azure",
|
|
25
|
+
"Cipher",
|
|
26
|
+
"Cobalt",
|
|
27
|
+
"Crimson",
|
|
28
|
+
"Drift",
|
|
29
|
+
"Ember",
|
|
30
|
+
"Glyph",
|
|
31
|
+
"Halcyon",
|
|
32
|
+
"Helix",
|
|
33
|
+
"Indigo",
|
|
34
|
+
"Juno",
|
|
35
|
+
"Kestrel",
|
|
36
|
+
"Lumen",
|
|
37
|
+
"Onyx",
|
|
38
|
+
"Pyrite",
|
|
39
|
+
"Quartz",
|
|
40
|
+
"Quill",
|
|
41
|
+
"Raven",
|
|
42
|
+
"Sable",
|
|
43
|
+
"Sage",
|
|
44
|
+
"Solstice",
|
|
45
|
+
"Spire",
|
|
46
|
+
"Tempest",
|
|
47
|
+
"Umbral",
|
|
48
|
+
"Velvet",
|
|
49
|
+
"Verdant",
|
|
50
|
+
"Vortex",
|
|
51
|
+
"Wraith",
|
|
52
|
+
"Yarrow",
|
|
53
|
+
"Zenith",
|
|
54
|
+
"Zephyr",
|
|
55
|
+
];
|
|
56
|
+
/** Stable per-id name selection. Salt with a small constant so two callers
|
|
57
|
+
* with the same id but different salts could disambiguate (not used today
|
|
58
|
+
* but reserved for review-fleet → parent-fleet name distinction). */
|
|
59
|
+
function hashIndex(seed, mod, salt = "") {
|
|
60
|
+
const h = createHash("sha256").update(`${salt}:${seed}`).digest();
|
|
61
|
+
return h.readUInt32BE(0) % mod;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Pick an Agnet name for a task, avoiding any name in `taken`. If all 32
|
|
65
|
+
* names are taken (huge fleet), append a numeric suffix.
|
|
66
|
+
*/
|
|
67
|
+
export function pickAgnetName(taskId, taken) {
|
|
68
|
+
for (let salt = 0; salt < NAMES.length; salt++) {
|
|
69
|
+
const candidate = NAMES[hashIndex(taskId, NAMES.length, String(salt))];
|
|
70
|
+
if (!taken.has(candidate))
|
|
71
|
+
return candidate;
|
|
72
|
+
}
|
|
73
|
+
// Pathological collision: append index.
|
|
74
|
+
let i = 2;
|
|
75
|
+
while (true) {
|
|
76
|
+
const candidate = `${NAMES[hashIndex(taskId, NAMES.length, `n${i}`)]}-${i}`;
|
|
77
|
+
if (!taken.has(candidate))
|
|
78
|
+
return candidate;
|
|
79
|
+
i++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** Format an Agnet for user-facing display: "Agnet Zenith". */
|
|
83
|
+
export function agnetLabel(name) {
|
|
84
|
+
if (!name)
|
|
85
|
+
return "Agnet";
|
|
86
|
+
return `Agnet ${name}`;
|
|
87
|
+
}
|
|
88
|
+
/** Two-letter monogram for compact CLI rendering: "Agnet Zenith" → "Ze". */
|
|
89
|
+
export function agnetMonogram(name) {
|
|
90
|
+
if (!name)
|
|
91
|
+
return "??";
|
|
92
|
+
return name.slice(0, 2);
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=agnet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agnet.js","sourceRoot":"","sources":["../../src/lib/agnet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;2DAC2D;AAC3D,MAAM,KAAK,GAAG;IACZ,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,OAAO;IACP,OAAO;IACP,OAAO;IACP,SAAS;IACT,OAAO;IACP,QAAQ;IACR,MAAM;IACN,SAAS;IACT,OAAO;IACP,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;IACN,UAAU;IACV,OAAO;IACP,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;CACT,CAAC;AAEF;;sEAEsE;AACtE,SAAS,SAAS,CAAC,IAAY,EAAE,GAAW,EAAE,IAAI,GAAG,EAAE;IACrD,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IAClE,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,KAAkB;IAC9D,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC9C,CAAC;IACD,wCAAwC;IACxC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,SAAS,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5E,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5C,CAAC,EAAE,CAAC;IACN,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,UAAU,CAAC,IAAwB;IACjD,IAAI,CAAC,IAAI;QAAE,OAAO,OAAO,CAAC;IAC1B,OAAO,SAAS,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,aAAa,CAAC,IAAwB;IACpD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1B,CAAC"}
|
package/dist/lib/state.d.ts
CHANGED
|
@@ -27,6 +27,9 @@ export interface Task {
|
|
|
27
27
|
branchHint?: string;
|
|
28
28
|
status: TaskStatus;
|
|
29
29
|
spawnedSessionId?: string;
|
|
30
|
+
/** v0.5+: Human-friendly Agnet designation (e.g. "Zenith"). Used in CLI
|
|
31
|
+
* output and Telegram notifications. Stable per task_id. */
|
|
32
|
+
agnetName?: string;
|
|
30
33
|
/** Optional per-task token budget hint. If set, status() surfaces a soft
|
|
31
34
|
* warning when usage exceeds 70% of this value, separate from the
|
|
32
35
|
* plan-wide hard cap. */
|
|
@@ -77,6 +80,84 @@ export interface FileClaim {
|
|
|
77
80
|
reason?: string;
|
|
78
81
|
claimedAt: number;
|
|
79
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Outbound message from primary Claude to the user. Pushed to Telegram by
|
|
85
|
+
* the notifier on its next tick. Lives on the plan so it can be filtered by
|
|
86
|
+
* which fleet it belongs to.
|
|
87
|
+
*/
|
|
88
|
+
export interface UserNotification {
|
|
89
|
+
id: string;
|
|
90
|
+
taskId?: string;
|
|
91
|
+
text: string;
|
|
92
|
+
urgency: "low" | "normal" | "high";
|
|
93
|
+
createdAt: number;
|
|
94
|
+
delivered: boolean;
|
|
95
|
+
deliveredAt?: number;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* v0.5+: Streamed message from primary Claude to user. A stream is a long-
|
|
99
|
+
* running message that gets *edited in place* as new chunks arrive — the
|
|
100
|
+
* Telegram-shaped equivalent of a streamed assistant reply.
|
|
101
|
+
*
|
|
102
|
+
* Lifecycle:
|
|
103
|
+
* 1. stream_to_user_start writes the initial record + first content.
|
|
104
|
+
* Notifier sends the message and records telegramMessageId.
|
|
105
|
+
* 2. stream_to_user_append adds a chunk to `content`. Notifier edits the
|
|
106
|
+
* Telegram message on its next tick (throttled to ~1 edit/1.5s by
|
|
107
|
+
* Telegram rate limits).
|
|
108
|
+
* 3. stream_to_user_end finalizes. Notifier does a final edit with an
|
|
109
|
+
* "✓ complete" marker.
|
|
110
|
+
*/
|
|
111
|
+
export interface UserStream {
|
|
112
|
+
id: string;
|
|
113
|
+
shortId: string;
|
|
114
|
+
taskId?: string;
|
|
115
|
+
/** Title shown in bold at the top of the message (e.g. "Agnet Verdant"). */
|
|
116
|
+
title: string;
|
|
117
|
+
/** Full accumulated content. */
|
|
118
|
+
content: string;
|
|
119
|
+
status: "active" | "ended";
|
|
120
|
+
createdAt: number;
|
|
121
|
+
endedAt?: number;
|
|
122
|
+
/** v0.5.1+: deterministic non-zero integer for Telegram's sendMessageDraft.
|
|
123
|
+
* Derived from the stream UUID so it's stable across restarts. */
|
|
124
|
+
draftId?: number;
|
|
125
|
+
/** v0.5.1+: which transport path is active.
|
|
126
|
+
* "draft" → sendMessageDraft for each update, sendMessage to persist on end.
|
|
127
|
+
* "edit" → fallback: sendMessage once + editMessageText for updates (v0.5 default). */
|
|
128
|
+
transport?: "draft" | "edit";
|
|
129
|
+
/** Per-chat persistence so the notifier knows which message to edit (edit path) or persist (draft path). */
|
|
130
|
+
telegramChatId?: number;
|
|
131
|
+
telegramMessageId?: number;
|
|
132
|
+
/** v0.5.1+: whether the stream's final persisted message has been sent. */
|
|
133
|
+
finalSent?: boolean;
|
|
134
|
+
/** Last delivered content snapshot (so notifier knows what to send / edit). */
|
|
135
|
+
lastDeliveredContent?: string;
|
|
136
|
+
lastEditedAt?: number;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Outbound question from primary Claude to the user, with an awaited
|
|
140
|
+
* response. The notifier pushes to Telegram (with an inline keyboard if
|
|
141
|
+
* `options` is set). The bot writes the user's choice/text back here on
|
|
142
|
+
* callback_query. Primary Claude polls via `poll_user_response`.
|
|
143
|
+
*/
|
|
144
|
+
export interface UserResponseRequest {
|
|
145
|
+
id: string;
|
|
146
|
+
shortId: string;
|
|
147
|
+
taskId?: string;
|
|
148
|
+
prompt: string;
|
|
149
|
+
options?: string[];
|
|
150
|
+
createdAt: number;
|
|
151
|
+
timeoutAt: number;
|
|
152
|
+
delivered: boolean;
|
|
153
|
+
deliveredAt?: number;
|
|
154
|
+
/** Telegram message_id of the question, so the bot can edit it on response. */
|
|
155
|
+
telegramMessageId?: number;
|
|
156
|
+
telegramChatId?: number;
|
|
157
|
+
response?: string;
|
|
158
|
+
respondedAt?: number;
|
|
159
|
+
cancelled?: boolean;
|
|
160
|
+
}
|
|
80
161
|
export interface Plan {
|
|
81
162
|
id: string;
|
|
82
163
|
createdAt: number;
|
|
@@ -97,10 +178,15 @@ export interface Plan {
|
|
|
97
178
|
notes: Note[];
|
|
98
179
|
messages: Message[];
|
|
99
180
|
claims: FileClaim[];
|
|
181
|
+
/** v0.4+: outbound notifications / questions from primary Claude to user. */
|
|
182
|
+
userNotifications: UserNotification[];
|
|
183
|
+
userResponseRequests: UserResponseRequest[];
|
|
184
|
+
/** v0.5+: streaming-message records (edit-in-place Telegram messages). */
|
|
185
|
+
userStreams: UserStream[];
|
|
100
186
|
reviewPlanId?: string;
|
|
101
187
|
}
|
|
102
188
|
export interface State {
|
|
103
|
-
schemaVersion:
|
|
189
|
+
schemaVersion: 3;
|
|
104
190
|
plans: Record<string, Plan>;
|
|
105
191
|
}
|
|
106
192
|
export declare class StateStore {
|
|
@@ -128,6 +214,14 @@ export declare class StateStore {
|
|
|
128
214
|
private persist;
|
|
129
215
|
}
|
|
130
216
|
export declare function newPlan(rootTask: string, budgetCapTokens: number, tasksInput: Array<Omit<Task, "id" | "status">>): Plan;
|
|
217
|
+
export declare function findUserStream(state: State, streamId: string): {
|
|
218
|
+
plan: Plan;
|
|
219
|
+
stream: UserStream;
|
|
220
|
+
} | undefined;
|
|
221
|
+
export declare function findUserResponseRequest(state: State, requestId: string): {
|
|
222
|
+
plan: Plan;
|
|
223
|
+
req: UserResponseRequest;
|
|
224
|
+
} | undefined;
|
|
131
225
|
export declare function findPlan(state: State, planId: string): Plan;
|
|
132
226
|
export declare function findTask(plan: Plan, taskId: string): Task;
|
|
133
227
|
export declare function findTaskBySession(plan: Plan, sessionId: string): Task | undefined;
|
package/dist/lib/state.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
|
-
const EMPTY_STATE = { schemaVersion:
|
|
4
|
+
const EMPTY_STATE = { schemaVersion: 3, plans: {} };
|
|
5
5
|
const LOCK_TIMEOUT_MS = 5_000;
|
|
6
6
|
const LOCK_RETRY_BASE_MS = 30;
|
|
7
7
|
export class StateStore {
|
|
@@ -143,12 +143,12 @@ function isProcessAlive(pid) {
|
|
|
143
143
|
function sleep(ms) {
|
|
144
144
|
return new Promise((res) => setTimeout(res, ms));
|
|
145
145
|
}
|
|
146
|
-
/** Forward-compatible migration from earlier schemas. */
|
|
146
|
+
/** Forward-compatible migration from earlier schemas. v1 → v3 in one pass. */
|
|
147
147
|
function migrate(input) {
|
|
148
148
|
const v = input.schemaVersion ?? 1;
|
|
149
|
-
if (v ===
|
|
149
|
+
if (v === 3 && input.plans)
|
|
150
150
|
return input;
|
|
151
|
-
const out = { schemaVersion:
|
|
151
|
+
const out = { schemaVersion: 3, plans: {} };
|
|
152
152
|
for (const [id, plan] of Object.entries(input.plans ?? {})) {
|
|
153
153
|
const p = plan;
|
|
154
154
|
out.plans[id] = {
|
|
@@ -159,6 +159,9 @@ function migrate(input) {
|
|
|
159
159
|
notes: p.notes ?? [],
|
|
160
160
|
messages: p.messages ?? [],
|
|
161
161
|
claims: p.claims ?? [],
|
|
162
|
+
userNotifications: p.userNotifications ?? [],
|
|
163
|
+
userResponseRequests: p.userResponseRequests ?? [],
|
|
164
|
+
userStreams: p.userStreams ?? [],
|
|
162
165
|
};
|
|
163
166
|
}
|
|
164
167
|
return out;
|
|
@@ -181,8 +184,27 @@ export function newPlan(rootTask, budgetCapTokens, tasksInput) {
|
|
|
181
184
|
notes: [],
|
|
182
185
|
messages: [],
|
|
183
186
|
claims: [],
|
|
187
|
+
userNotifications: [],
|
|
188
|
+
userResponseRequests: [],
|
|
189
|
+
userStreams: [],
|
|
184
190
|
};
|
|
185
191
|
}
|
|
192
|
+
export function findUserStream(state, streamId) {
|
|
193
|
+
for (const plan of Object.values(state.plans)) {
|
|
194
|
+
const stream = plan.userStreams.find((s) => s.id === streamId || s.shortId === streamId);
|
|
195
|
+
if (stream)
|
|
196
|
+
return { plan, stream };
|
|
197
|
+
}
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
export function findUserResponseRequest(state, requestId) {
|
|
201
|
+
for (const plan of Object.values(state.plans)) {
|
|
202
|
+
const req = plan.userResponseRequests.find((r) => r.id === requestId || r.shortId === requestId);
|
|
203
|
+
if (req)
|
|
204
|
+
return { plan, req };
|
|
205
|
+
}
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
186
208
|
export function findPlan(state, planId) {
|
|
187
209
|
const plan = state.plans[planId];
|
|
188
210
|
if (!plan)
|
package/dist/lib/state.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/lib/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/lib/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic-palette terminal styling. Uses ANSI 24-bit truecolor escapes so
|
|
3
|
+
* the rendered colors match the brand exactly when the terminal supports it.
|
|
4
|
+
*
|
|
5
|
+
* Brand colors (from Anthropic's public design):
|
|
6
|
+
* • Claude Coral #DA7756 — the signature warm orange. Primary brand.
|
|
7
|
+
* • Cream #F5F4EE — soft off-white. Secondary text / surfaces.
|
|
8
|
+
* • Crimson #BB5944 — deeper terracotta. Accent / hover.
|
|
9
|
+
* • Charcoal #2A2926 — near-black with brown warmth. Body text.
|
|
10
|
+
* • Dim Sand #B9B6AB — muted tan. Captions / disabled.
|
|
11
|
+
*
|
|
12
|
+
* Color is automatically disabled when:
|
|
13
|
+
* • stdout is not a TTY (piped output)
|
|
14
|
+
* • NO_COLOR env var is set (https://no-color.org/)
|
|
15
|
+
* • TERM is "dumb"
|
|
16
|
+
*
|
|
17
|
+
* Use `style.claude("text")` rather than concatenating escape codes directly,
|
|
18
|
+
* so a consumer reading orqlaude's output to a file gets clean text.
|
|
19
|
+
*/
|
|
20
|
+
export declare const style: {
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
/** Claude coral — primary brand color. Use for headings + accents. */
|
|
23
|
+
coral: (s: string) => string;
|
|
24
|
+
/** Cream — soft off-white. Use for secondary emphasis. */
|
|
25
|
+
cream: (s: string) => string;
|
|
26
|
+
/** Crimson — deeper terracotta. Use for warnings, accents. */
|
|
27
|
+
crimson: (s: string) => string;
|
|
28
|
+
/** Charcoal — near-black warm. Use for body text. */
|
|
29
|
+
charcoal: (s: string) => string;
|
|
30
|
+
/** Sand — muted tan. Use for captions, disabled. */
|
|
31
|
+
sand: (s: string) => string;
|
|
32
|
+
/** Coral background — for the orqlaude header banner. */
|
|
33
|
+
coralBg: (s: string) => string;
|
|
34
|
+
bold: (s: string) => string;
|
|
35
|
+
dim: (s: string) => string;
|
|
36
|
+
italic: (s: string) => string;
|
|
37
|
+
underline: (s: string) => string;
|
|
38
|
+
};
|
|
39
|
+
/** Status-keyed color: maps task/plan status strings to the brand palette. */
|
|
40
|
+
export declare function styleStatus(status: string): (s: string) => string;
|
|
41
|
+
/** orqlaude header banner. Shown at the top of `orqlaude` CLI invocations. */
|
|
42
|
+
export declare function banner(): string;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic-palette terminal styling. Uses ANSI 24-bit truecolor escapes so
|
|
3
|
+
* the rendered colors match the brand exactly when the terminal supports it.
|
|
4
|
+
*
|
|
5
|
+
* Brand colors (from Anthropic's public design):
|
|
6
|
+
* • Claude Coral #DA7756 — the signature warm orange. Primary brand.
|
|
7
|
+
* • Cream #F5F4EE — soft off-white. Secondary text / surfaces.
|
|
8
|
+
* • Crimson #BB5944 — deeper terracotta. Accent / hover.
|
|
9
|
+
* • Charcoal #2A2926 — near-black with brown warmth. Body text.
|
|
10
|
+
* • Dim Sand #B9B6AB — muted tan. Captions / disabled.
|
|
11
|
+
*
|
|
12
|
+
* Color is automatically disabled when:
|
|
13
|
+
* • stdout is not a TTY (piped output)
|
|
14
|
+
* • NO_COLOR env var is set (https://no-color.org/)
|
|
15
|
+
* • TERM is "dumb"
|
|
16
|
+
*
|
|
17
|
+
* Use `style.claude("text")` rather than concatenating escape codes directly,
|
|
18
|
+
* so a consumer reading orqlaude's output to a file gets clean text.
|
|
19
|
+
*/
|
|
20
|
+
const NO_COLOR = !!process.env.NO_COLOR;
|
|
21
|
+
const TERM_DUMB = process.env.TERM === "dumb";
|
|
22
|
+
const FORCE_COLOR = process.env.FORCE_COLOR && process.env.FORCE_COLOR !== "0";
|
|
23
|
+
const ENABLED = FORCE_COLOR || (!NO_COLOR && !TERM_DUMB && process.stdout.isTTY);
|
|
24
|
+
function fg(r, g, b) {
|
|
25
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
26
|
+
}
|
|
27
|
+
function bg(r, g, b) {
|
|
28
|
+
return `\x1b[48;2;${r};${g};${b}m`;
|
|
29
|
+
}
|
|
30
|
+
const RESET = "\x1b[0m";
|
|
31
|
+
const BOLD = "\x1b[1m";
|
|
32
|
+
const DIM = "\x1b[2m";
|
|
33
|
+
const ITALIC = "\x1b[3m";
|
|
34
|
+
const UNDERLINE = "\x1b[4m";
|
|
35
|
+
const FG_CORAL = fg(0xda, 0x77, 0x56);
|
|
36
|
+
const FG_CREAM = fg(0xf5, 0xf4, 0xee);
|
|
37
|
+
const FG_CRIMSON = fg(0xbb, 0x59, 0x44);
|
|
38
|
+
const FG_CHARCOAL = fg(0x2a, 0x29, 0x26);
|
|
39
|
+
const FG_SAND = fg(0xb9, 0xb6, 0xab);
|
|
40
|
+
const BG_CORAL = bg(0xda, 0x77, 0x56);
|
|
41
|
+
function wrap(prefix, text) {
|
|
42
|
+
if (!ENABLED)
|
|
43
|
+
return text;
|
|
44
|
+
return `${prefix}${text}${RESET}`;
|
|
45
|
+
}
|
|
46
|
+
export const style = {
|
|
47
|
+
enabled: ENABLED,
|
|
48
|
+
/** Claude coral — primary brand color. Use for headings + accents. */
|
|
49
|
+
coral: (s) => wrap(FG_CORAL, s),
|
|
50
|
+
/** Cream — soft off-white. Use for secondary emphasis. */
|
|
51
|
+
cream: (s) => wrap(FG_CREAM, s),
|
|
52
|
+
/** Crimson — deeper terracotta. Use for warnings, accents. */
|
|
53
|
+
crimson: (s) => wrap(FG_CRIMSON, s),
|
|
54
|
+
/** Charcoal — near-black warm. Use for body text. */
|
|
55
|
+
charcoal: (s) => wrap(FG_CHARCOAL, s),
|
|
56
|
+
/** Sand — muted tan. Use for captions, disabled. */
|
|
57
|
+
sand: (s) => wrap(FG_SAND, s),
|
|
58
|
+
/** Coral background — for the orqlaude header banner. */
|
|
59
|
+
coralBg: (s) => wrap(`${BG_CORAL}${fg(0x2a, 0x29, 0x26)}`, s),
|
|
60
|
+
bold: (s) => wrap(BOLD, s),
|
|
61
|
+
dim: (s) => wrap(DIM, s),
|
|
62
|
+
italic: (s) => wrap(ITALIC, s),
|
|
63
|
+
underline: (s) => wrap(UNDERLINE, s),
|
|
64
|
+
};
|
|
65
|
+
/** Status-keyed color: maps task/plan status strings to the brand palette. */
|
|
66
|
+
export function styleStatus(status) {
|
|
67
|
+
switch (status) {
|
|
68
|
+
case "draft":
|
|
69
|
+
case "estimating":
|
|
70
|
+
case "pending":
|
|
71
|
+
return style.sand;
|
|
72
|
+
case "awaiting_approval":
|
|
73
|
+
case "approved":
|
|
74
|
+
case "dispatching":
|
|
75
|
+
return style.cream;
|
|
76
|
+
case "running":
|
|
77
|
+
case "dispatched":
|
|
78
|
+
return style.coral;
|
|
79
|
+
case "done":
|
|
80
|
+
case "collected":
|
|
81
|
+
return (s) => style.bold(style.coral(s));
|
|
82
|
+
case "failed":
|
|
83
|
+
case "cancelled":
|
|
84
|
+
case "cancelled_overbudget":
|
|
85
|
+
return style.crimson;
|
|
86
|
+
default:
|
|
87
|
+
return (s) => s;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** orqlaude header banner. Shown at the top of `orqlaude` CLI invocations. */
|
|
91
|
+
export function banner() {
|
|
92
|
+
if (!ENABLED)
|
|
93
|
+
return "orqlaude";
|
|
94
|
+
return style.coral("◆ ") + style.bold(style.coral("orqlaude")) + style.sand(" — multi-agent orchestrator for Claude Code");
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=style.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.js","sourceRoot":"","sources":["../../src/lib/style.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -10,6 +10,7 @@ import { registerDispatch } from "./tools/dispatch.js";
|
|
|
10
10
|
import { registerBroker } from "./tools/broker.js";
|
|
11
11
|
import { registerLifecycle } from "./tools/lifecycle.js";
|
|
12
12
|
import { registerReview } from "./tools/review.js";
|
|
13
|
+
import { registerUserIo } from "./tools/userio.js";
|
|
13
14
|
/**
|
|
14
15
|
* orqlaude — multi-agent orchestrator for Claude Code.
|
|
15
16
|
*
|
|
@@ -22,7 +23,7 @@ const store = new StateStore(stateDir);
|
|
|
22
23
|
const audit = new AuditLog(stateDir);
|
|
23
24
|
const server = new McpServer({
|
|
24
25
|
name: "orqlaude",
|
|
25
|
-
version: "0.
|
|
26
|
+
version: "0.5.1",
|
|
26
27
|
});
|
|
27
28
|
registerPing(server);
|
|
28
29
|
registerPlanning(server, store, audit);
|
|
@@ -30,6 +31,7 @@ registerDispatch(server, store, audit);
|
|
|
30
31
|
registerBroker(server, store, audit);
|
|
31
32
|
registerLifecycle(server, store, audit);
|
|
32
33
|
registerReview(server, store, audit);
|
|
34
|
+
registerUserIo(server, store, audit);
|
|
33
35
|
const transport = new StdioServerTransport();
|
|
34
36
|
await server.connect(transport);
|
|
35
37
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,wBAAwB,EAAE,CAAC;AAC5D,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;AACvC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAErC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,YAAY,CAAC,MAAM,CAAC,CAAC;AACrB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACvC,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACvC,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACrC,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACxC,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAErC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,wBAAwB,EAAE,CAAC;AAC5D,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;AACvC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAErC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,YAAY,CAAC,MAAM,CAAC,CAAC;AACrB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACvC,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACvC,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACrC,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACxC,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACrC,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAErC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
package/dist/telegram/api.d.ts
CHANGED
|
@@ -24,9 +24,20 @@ export interface TelegramMessage {
|
|
|
24
24
|
date: number;
|
|
25
25
|
text?: string;
|
|
26
26
|
}
|
|
27
|
+
export interface TelegramCallbackQuery {
|
|
28
|
+
id: string;
|
|
29
|
+
from: TelegramUser;
|
|
30
|
+
data?: string;
|
|
31
|
+
message?: TelegramMessage;
|
|
32
|
+
}
|
|
27
33
|
export interface TelegramUpdate {
|
|
28
34
|
update_id: number;
|
|
29
35
|
message?: TelegramMessage;
|
|
36
|
+
callback_query?: TelegramCallbackQuery;
|
|
37
|
+
}
|
|
38
|
+
export interface InlineKeyboardButton {
|
|
39
|
+
text: string;
|
|
40
|
+
callback_data: string;
|
|
30
41
|
}
|
|
31
42
|
export declare class TelegramApi {
|
|
32
43
|
private readonly token;
|
|
@@ -36,6 +47,35 @@ export declare class TelegramApi {
|
|
|
36
47
|
getUpdates(offset: number, timeoutSec?: number): Promise<TelegramUpdate[]>;
|
|
37
48
|
sendMessage(chatId: number, text: string, opts?: {
|
|
38
49
|
parseMode?: "Markdown" | "HTML";
|
|
50
|
+
inlineKeyboard?: InlineKeyboardButton[][];
|
|
51
|
+
}): Promise<{
|
|
52
|
+
message_id: number;
|
|
53
|
+
}>;
|
|
54
|
+
/** Acknowledge a callback_query so the Telegram client stops the spinner. */
|
|
55
|
+
answerCallbackQuery(callbackQueryId: string, text?: string): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Stream a partial draft message. Telegram animates updates that share the
|
|
58
|
+
* same `draft_id`, and the draft is ephemeral (~30s) — so when the stream
|
|
59
|
+
* is complete, follow up with a real `sendMessage` to persist the final
|
|
60
|
+
* content in the chat.
|
|
61
|
+
*
|
|
62
|
+
* Returns `{ ok: true }` on success, or `{ ok: false, status, body }` so
|
|
63
|
+
* callers can fall back to `editMessageText` on older Bot API servers that
|
|
64
|
+
* don't yet support drafts.
|
|
65
|
+
*/
|
|
66
|
+
sendMessageDraft(chatId: number, draftId: number, text: string, opts?: {
|
|
67
|
+
parseMode?: "Markdown" | "HTML";
|
|
68
|
+
messageThreadId?: number;
|
|
69
|
+
}): Promise<{
|
|
70
|
+
ok: true;
|
|
71
|
+
} | {
|
|
72
|
+
ok: false;
|
|
73
|
+
status: number;
|
|
74
|
+
body: string;
|
|
75
|
+
}>;
|
|
76
|
+
/** Edit a previously-sent message — used to mark questions as answered. */
|
|
77
|
+
editMessageText(chatId: number, messageId: number, text: string, opts?: {
|
|
78
|
+
parseMode?: "Markdown" | "HTML";
|
|
39
79
|
}): Promise<void>;
|
|
40
80
|
/** Verify the token works by hitting getMe. Returns the bot's username. */
|
|
41
81
|
getMe(): Promise<{
|
package/dist/telegram/api.js
CHANGED
|
@@ -30,19 +30,87 @@ export class TelegramApi {
|
|
|
30
30
|
return body.result;
|
|
31
31
|
}
|
|
32
32
|
async sendMessage(chatId, text, opts = {}) {
|
|
33
|
+
const body = {
|
|
34
|
+
chat_id: chatId,
|
|
35
|
+
text,
|
|
36
|
+
parse_mode: opts.parseMode,
|
|
37
|
+
disable_web_page_preview: true,
|
|
38
|
+
};
|
|
39
|
+
if (opts.inlineKeyboard) {
|
|
40
|
+
body.reply_markup = { inline_keyboard: opts.inlineKeyboard };
|
|
41
|
+
}
|
|
33
42
|
const res = await fetch(this.endpoint("sendMessage"), {
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: { "content-type": "application/json" },
|
|
45
|
+
body: JSON.stringify(body),
|
|
46
|
+
});
|
|
47
|
+
if (!res.ok) {
|
|
48
|
+
const text = await res.text();
|
|
49
|
+
throw new Error(`sendMessage ${res.status}: ${text}`);
|
|
50
|
+
}
|
|
51
|
+
const parsed = (await res.json());
|
|
52
|
+
return { message_id: parsed.result.message_id };
|
|
53
|
+
}
|
|
54
|
+
/** Acknowledge a callback_query so the Telegram client stops the spinner. */
|
|
55
|
+
async answerCallbackQuery(callbackQueryId, text) {
|
|
56
|
+
const res = await fetch(this.endpoint("answerCallbackQuery"), {
|
|
57
|
+
method: "POST",
|
|
58
|
+
headers: { "content-type": "application/json" },
|
|
59
|
+
body: JSON.stringify({ callback_query_id: callbackQueryId, text }),
|
|
60
|
+
});
|
|
61
|
+
if (!res.ok) {
|
|
62
|
+
// Non-fatal: log but don't throw. Telegram will eventually time out the
|
|
63
|
+
// spinner on the client side.
|
|
64
|
+
process.stderr.write(`[orqlaude tg] answerCallbackQuery ${res.status}: ${await res.text()}\n`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Stream a partial draft message. Telegram animates updates that share the
|
|
69
|
+
* same `draft_id`, and the draft is ephemeral (~30s) — so when the stream
|
|
70
|
+
* is complete, follow up with a real `sendMessage` to persist the final
|
|
71
|
+
* content in the chat.
|
|
72
|
+
*
|
|
73
|
+
* Returns `{ ok: true }` on success, or `{ ok: false, status, body }` so
|
|
74
|
+
* callers can fall back to `editMessageText` on older Bot API servers that
|
|
75
|
+
* don't yet support drafts.
|
|
76
|
+
*/
|
|
77
|
+
async sendMessageDraft(chatId, draftId, text, opts = {}) {
|
|
78
|
+
if (!Number.isInteger(draftId) || draftId === 0) {
|
|
79
|
+
throw new Error("draftId must be a non-zero integer");
|
|
80
|
+
}
|
|
81
|
+
const body = {
|
|
82
|
+
chat_id: chatId,
|
|
83
|
+
draft_id: draftId,
|
|
84
|
+
text,
|
|
85
|
+
parse_mode: opts.parseMode,
|
|
86
|
+
};
|
|
87
|
+
if (opts.messageThreadId !== undefined)
|
|
88
|
+
body.message_thread_id = opts.messageThreadId;
|
|
89
|
+
const res = await fetch(this.endpoint("sendMessageDraft"), {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers: { "content-type": "application/json" },
|
|
92
|
+
body: JSON.stringify(body),
|
|
93
|
+
});
|
|
94
|
+
if (!res.ok) {
|
|
95
|
+
return { ok: false, status: res.status, body: await res.text() };
|
|
96
|
+
}
|
|
97
|
+
return { ok: true };
|
|
98
|
+
}
|
|
99
|
+
/** Edit a previously-sent message — used to mark questions as answered. */
|
|
100
|
+
async editMessageText(chatId, messageId, text, opts = {}) {
|
|
101
|
+
const res = await fetch(this.endpoint("editMessageText"), {
|
|
34
102
|
method: "POST",
|
|
35
103
|
headers: { "content-type": "application/json" },
|
|
36
104
|
body: JSON.stringify({
|
|
37
105
|
chat_id: chatId,
|
|
106
|
+
message_id: messageId,
|
|
38
107
|
text,
|
|
39
108
|
parse_mode: opts.parseMode,
|
|
40
109
|
disable_web_page_preview: true,
|
|
41
110
|
}),
|
|
42
111
|
});
|
|
43
112
|
if (!res.ok) {
|
|
44
|
-
|
|
45
|
-
throw new Error(`sendMessage ${res.status}: ${body}`);
|
|
113
|
+
process.stderr.write(`[orqlaude tg] editMessageText ${res.status}: ${await res.text()}\n`);
|
|
46
114
|
}
|
|
47
115
|
}
|
|
48
116
|
/** Verify the token works by hitting getMe. Returns the bot's username. */
|