chatroom-cli 1.12.0 → 1.13.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/dist/index.js +1082 -588
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2167,7 +2167,7 @@ function getVersion() {
|
|
|
2167
2167
|
}
|
|
2168
2168
|
var init_version = () => {};
|
|
2169
2169
|
|
|
2170
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
2170
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/common/index.js
|
|
2171
2171
|
function parseArgs(args) {
|
|
2172
2172
|
if (args === undefined) {
|
|
2173
2173
|
return {};
|
|
@@ -2203,10 +2203,10 @@ function isSimpleObject(value) {
|
|
|
2203
2203
|
return isObject && isSimple;
|
|
2204
2204
|
}
|
|
2205
2205
|
|
|
2206
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
2207
|
-
var version = "1.
|
|
2206
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/index.js
|
|
2207
|
+
var version = "1.34.0";
|
|
2208
2208
|
|
|
2209
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
2209
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/values/base64.js
|
|
2210
2210
|
var exports_base64 = {};
|
|
2211
2211
|
__export(exports_base64, {
|
|
2212
2212
|
toByteArray: () => toByteArray,
|
|
@@ -2306,7 +2306,7 @@ var init_base64 = __esm(() => {
|
|
|
2306
2306
|
revLookup[95] = 63;
|
|
2307
2307
|
});
|
|
2308
2308
|
|
|
2309
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
2309
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/values/value.js
|
|
2310
2310
|
function isSpecial(n) {
|
|
2311
2311
|
return Number.isNaN(n) || !Number.isFinite(n) || Object.is(n, -0);
|
|
2312
2312
|
}
|
|
@@ -2547,7 +2547,7 @@ var init_value = __esm(() => {
|
|
|
2547
2547
|
base64ToBigInt = DataView.prototype.getBigInt64 ? modernBase64ToBigInt : slowBase64ToBigInt;
|
|
2548
2548
|
});
|
|
2549
2549
|
|
|
2550
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
2550
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/values/errors.js
|
|
2551
2551
|
var __defProp2, __defNormalProp = (obj, key, value) => (key in obj) ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value, __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value), _a, _b, IDENTIFYING_FIELD, ConvexError;
|
|
2552
2552
|
var init_errors = __esm(() => {
|
|
2553
2553
|
init_value();
|
|
@@ -2564,14 +2564,14 @@ var init_errors = __esm(() => {
|
|
|
2564
2564
|
};
|
|
2565
2565
|
});
|
|
2566
2566
|
|
|
2567
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
2567
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/values/index.js
|
|
2568
2568
|
var init_values = __esm(() => {
|
|
2569
2569
|
init_value();
|
|
2570
2570
|
init_base64();
|
|
2571
2571
|
init_errors();
|
|
2572
2572
|
});
|
|
2573
2573
|
|
|
2574
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
2574
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/logging.js
|
|
2575
2575
|
function prefix_for_source(source) {
|
|
2576
2576
|
switch (source) {
|
|
2577
2577
|
case "query":
|
|
@@ -2691,7 +2691,7 @@ var init_logging = __esm(() => {
|
|
|
2691
2691
|
__defProp3 = Object.defineProperty;
|
|
2692
2692
|
});
|
|
2693
2693
|
|
|
2694
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
2694
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/udf_path_utils.js
|
|
2695
2695
|
function canonicalizeUdfPath(udfPath) {
|
|
2696
2696
|
const pieces = udfPath.split(":");
|
|
2697
2697
|
let moduleName;
|
|
@@ -2731,7 +2731,7 @@ var init_udf_path_utils = __esm(() => {
|
|
|
2731
2731
|
init_values();
|
|
2732
2732
|
});
|
|
2733
2733
|
|
|
2734
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
2734
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/local_state.js
|
|
2735
2735
|
class LocalSyncState {
|
|
2736
2736
|
constructor() {
|
|
2737
2737
|
__publicField3(this, "nextQueryId");
|
|
@@ -2922,7 +2922,7 @@ class LocalSyncState {
|
|
|
2922
2922
|
queryJournal(queryToken) {
|
|
2923
2923
|
return this.querySet.get(queryToken)?.journal;
|
|
2924
2924
|
}
|
|
2925
|
-
restart(
|
|
2925
|
+
restart() {
|
|
2926
2926
|
this.unpause();
|
|
2927
2927
|
this.outstandingQueriesOlderThanRestart.clear();
|
|
2928
2928
|
const modifications = [];
|
|
@@ -2936,9 +2936,7 @@ class LocalSyncState {
|
|
|
2936
2936
|
componentPath: localQuery.componentPath
|
|
2937
2937
|
};
|
|
2938
2938
|
modifications.push(add);
|
|
2939
|
-
|
|
2940
|
-
this.outstandingQueriesOlderThanRestart.add(localQuery.id);
|
|
2941
|
-
}
|
|
2939
|
+
this.outstandingQueriesOlderThanRestart.add(localQuery.id);
|
|
2942
2940
|
}
|
|
2943
2941
|
this.querySetVersion = 1;
|
|
2944
2942
|
const querySet = {
|
|
@@ -3022,7 +3020,7 @@ var init_local_state = __esm(() => {
|
|
|
3022
3020
|
__defProp4 = Object.defineProperty;
|
|
3023
3021
|
});
|
|
3024
3022
|
|
|
3025
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
3023
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/request_manager.js
|
|
3026
3024
|
class RequestManager {
|
|
3027
3025
|
constructor(logger, markConnectionStateDirty) {
|
|
3028
3026
|
this.logger = logger;
|
|
@@ -3207,13 +3205,13 @@ var init_request_manager = __esm(() => {
|
|
|
3207
3205
|
__defProp5 = Object.defineProperty;
|
|
3208
3206
|
});
|
|
3209
3207
|
|
|
3210
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
3208
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/server/functionName.js
|
|
3211
3209
|
var functionName;
|
|
3212
3210
|
var init_functionName = __esm(() => {
|
|
3213
3211
|
functionName = Symbol.for("functionName");
|
|
3214
3212
|
});
|
|
3215
3213
|
|
|
3216
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
3214
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/server/components/paths.js
|
|
3217
3215
|
function extractReferencePath(reference) {
|
|
3218
3216
|
return reference[toReferencePath] ?? null;
|
|
3219
3217
|
}
|
|
@@ -3245,7 +3243,7 @@ var init_paths = __esm(() => {
|
|
|
3245
3243
|
toReferencePath = Symbol.for("toReferencePath");
|
|
3246
3244
|
});
|
|
3247
3245
|
|
|
3248
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
3246
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/server/api.js
|
|
3249
3247
|
function getFunctionName(functionReference) {
|
|
3250
3248
|
const address = getFunctionAddress(functionReference);
|
|
3251
3249
|
if (address.name === undefined) {
|
|
@@ -3298,7 +3296,7 @@ var init_api = __esm(() => {
|
|
|
3298
3296
|
anyApi = createApi();
|
|
3299
3297
|
});
|
|
3300
3298
|
|
|
3301
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
3299
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/optimistic_updates_impl.js
|
|
3302
3300
|
class OptimisticLocalStoreImpl {
|
|
3303
3301
|
constructor(queryResults) {
|
|
3304
3302
|
__publicField5(this, "queryResults");
|
|
@@ -3437,7 +3435,7 @@ var init_optimistic_updates_impl = __esm(() => {
|
|
|
3437
3435
|
__defProp6 = Object.defineProperty;
|
|
3438
3436
|
});
|
|
3439
3437
|
|
|
3440
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
3438
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/vendor/long.js
|
|
3441
3439
|
class Long {
|
|
3442
3440
|
constructor(low, high) {
|
|
3443
3441
|
__publicField6(this, "low");
|
|
@@ -3515,7 +3513,7 @@ var init_long = __esm(() => {
|
|
|
3515
3513
|
MAX_UNSIGNED_VALUE = new Long(4294967295 | 0, 4294967295 | 0);
|
|
3516
3514
|
});
|
|
3517
3515
|
|
|
3518
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
3516
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/remote_query_set.js
|
|
3519
3517
|
class RemoteQuerySet {
|
|
3520
3518
|
constructor(queryPath, logger) {
|
|
3521
3519
|
__publicField7(this, "version");
|
|
@@ -3591,7 +3589,7 @@ var init_remote_query_set = __esm(() => {
|
|
|
3591
3589
|
__defProp8 = Object.defineProperty;
|
|
3592
3590
|
});
|
|
3593
3591
|
|
|
3594
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
3592
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/protocol.js
|
|
3595
3593
|
function u64ToLong(encoded) {
|
|
3596
3594
|
const integerBytes = exports_base64.toByteArray(encoded);
|
|
3597
3595
|
return Long.fromBytesLE(Array.from(integerBytes));
|
|
@@ -3661,7 +3659,7 @@ var init_protocol = __esm(() => {
|
|
|
3661
3659
|
init_long();
|
|
3662
3660
|
});
|
|
3663
3661
|
|
|
3664
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
3662
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/web_socket_manager.js
|
|
3665
3663
|
function monotonicMillis() {
|
|
3666
3664
|
if (firstTime === undefined) {
|
|
3667
3665
|
firstTime = Date.now();
|
|
@@ -3699,6 +3697,9 @@ class WebSocketManager {
|
|
|
3699
3697
|
__publicField8(this, "retries");
|
|
3700
3698
|
__publicField8(this, "serverInactivityThreshold");
|
|
3701
3699
|
__publicField8(this, "reconnectDueToServerInactivityTimeout");
|
|
3700
|
+
__publicField8(this, "scheduledReconnect", null);
|
|
3701
|
+
__publicField8(this, "networkOnlineHandler", null);
|
|
3702
|
+
__publicField8(this, "pendingNetworkRecoveryInfo", null);
|
|
3702
3703
|
__publicField8(this, "uri");
|
|
3703
3704
|
__publicField8(this, "onOpen");
|
|
3704
3705
|
__publicField8(this, "onResume");
|
|
@@ -3711,7 +3712,7 @@ class WebSocketManager {
|
|
|
3711
3712
|
this.connectionCount = 0;
|
|
3712
3713
|
this.lastCloseReason = "InitialConnect";
|
|
3713
3714
|
this.defaultInitialBackoff = 1000;
|
|
3714
|
-
this.maxBackoff =
|
|
3715
|
+
this.maxBackoff = 64000;
|
|
3715
3716
|
this.retries = 0;
|
|
3716
3717
|
this.serverInactivityThreshold = 60000;
|
|
3717
3718
|
this.reconnectDueToServerInactivityTimeout = null;
|
|
@@ -3721,6 +3722,7 @@ class WebSocketManager {
|
|
|
3721
3722
|
this.onMessage = callbacks.onMessage;
|
|
3722
3723
|
this.onServerDisconnectError = callbacks.onServerDisconnectError;
|
|
3723
3724
|
this.logger = logger;
|
|
3725
|
+
this.setupNetworkListener();
|
|
3724
3726
|
this.connect();
|
|
3725
3727
|
}
|
|
3726
3728
|
setSocketState(state) {
|
|
@@ -3728,6 +3730,27 @@ class WebSocketManager {
|
|
|
3728
3730
|
this._logVerbose(`socket state changed: ${this.socket.state}, paused: ${"paused" in this.socket ? this.socket.paused : undefined}`);
|
|
3729
3731
|
this.markConnectionStateDirty();
|
|
3730
3732
|
}
|
|
3733
|
+
setupNetworkListener() {
|
|
3734
|
+
if (typeof window === "undefined" || typeof window.addEventListener !== "function") {
|
|
3735
|
+
return;
|
|
3736
|
+
}
|
|
3737
|
+
if (this.networkOnlineHandler !== null) {
|
|
3738
|
+
return;
|
|
3739
|
+
}
|
|
3740
|
+
this.networkOnlineHandler = () => {
|
|
3741
|
+
this._logVerbose("network online event detected");
|
|
3742
|
+
this.tryReconnectImmediately();
|
|
3743
|
+
};
|
|
3744
|
+
window.addEventListener("online", this.networkOnlineHandler);
|
|
3745
|
+
this._logVerbose("network online event listener registered");
|
|
3746
|
+
}
|
|
3747
|
+
cleanupNetworkListener() {
|
|
3748
|
+
if (this.networkOnlineHandler && typeof window !== "undefined" && typeof window.removeEventListener === "function") {
|
|
3749
|
+
window.removeEventListener("online", this.networkOnlineHandler);
|
|
3750
|
+
this.networkOnlineHandler = null;
|
|
3751
|
+
this._logVerbose("network online event listener removed");
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3731
3754
|
assembleTransition(chunk) {
|
|
3732
3755
|
if (chunk.partNumber < 0 || chunk.partNumber >= chunk.totalParts || chunk.totalParts === 0 || this.transitionChunkBuffer && (this.transitionChunkBuffer.totalParts !== chunk.totalParts || this.transitionChunkBuffer.transitionId !== chunk.transitionId)) {
|
|
3733
3756
|
this.transitionChunkBuffer = null;
|
|
@@ -3800,6 +3823,16 @@ class WebSocketManager {
|
|
|
3800
3823
|
}
|
|
3801
3824
|
this.connectionCount += 1;
|
|
3802
3825
|
this.lastCloseReason = null;
|
|
3826
|
+
if (this.pendingNetworkRecoveryInfo !== null) {
|
|
3827
|
+
const { timeSavedMs } = this.pendingNetworkRecoveryInfo;
|
|
3828
|
+
this.pendingNetworkRecoveryInfo = null;
|
|
3829
|
+
this.sendMessage({
|
|
3830
|
+
type: "Event",
|
|
3831
|
+
eventType: "NetworkRecoveryReconnect",
|
|
3832
|
+
event: { timeSavedMs }
|
|
3833
|
+
});
|
|
3834
|
+
this.logger.log(`Network recovery reconnect saved ~${Math.round(timeSavedMs / 1000)}s of waiting`);
|
|
3835
|
+
}
|
|
3803
3836
|
};
|
|
3804
3837
|
ws.onerror = (error) => {
|
|
3805
3838
|
this.transitionChunkBuffer = null;
|
|
@@ -3901,11 +3934,26 @@ class WebSocketManager {
|
|
|
3901
3934
|
}, this.serverInactivityThreshold);
|
|
3902
3935
|
}
|
|
3903
3936
|
scheduleReconnect(reason) {
|
|
3937
|
+
if (this.scheduledReconnect) {
|
|
3938
|
+
clearTimeout(this.scheduledReconnect.timeout);
|
|
3939
|
+
this.scheduledReconnect = null;
|
|
3940
|
+
}
|
|
3904
3941
|
this.socket = { state: "disconnected" };
|
|
3905
3942
|
const backoff = this.nextBackoff(reason);
|
|
3906
3943
|
this.markConnectionStateDirty();
|
|
3907
3944
|
this.logger.log(`Attempting reconnect in ${Math.round(backoff)}ms`);
|
|
3908
|
-
|
|
3945
|
+
const scheduledAt = monotonicMillis();
|
|
3946
|
+
const timeoutId = setTimeout(() => {
|
|
3947
|
+
if (this.scheduledReconnect?.timeout === timeoutId) {
|
|
3948
|
+
this.scheduledReconnect = null;
|
|
3949
|
+
this.connect();
|
|
3950
|
+
}
|
|
3951
|
+
}, backoff);
|
|
3952
|
+
this.scheduledReconnect = {
|
|
3953
|
+
timeout: timeoutId,
|
|
3954
|
+
scheduledAt,
|
|
3955
|
+
backoffMs: backoff
|
|
3956
|
+
};
|
|
3909
3957
|
}
|
|
3910
3958
|
closeAndReconnect(closeReason) {
|
|
3911
3959
|
this._logVerbose(`begin closeAndReconnect with reason ${closeReason}`);
|
|
@@ -3973,6 +4021,11 @@ class WebSocketManager {
|
|
|
3973
4021
|
if (this.reconnectDueToServerInactivityTimeout) {
|
|
3974
4022
|
clearTimeout(this.reconnectDueToServerInactivityTimeout);
|
|
3975
4023
|
}
|
|
4024
|
+
if (this.scheduledReconnect) {
|
|
4025
|
+
clearTimeout(this.scheduledReconnect.timeout);
|
|
4026
|
+
this.scheduledReconnect = null;
|
|
4027
|
+
}
|
|
4028
|
+
this.cleanupNetworkListener();
|
|
3976
4029
|
switch (this.socket.state) {
|
|
3977
4030
|
case "terminated":
|
|
3978
4031
|
case "stopped":
|
|
@@ -3997,6 +4050,7 @@ class WebSocketManager {
|
|
|
3997
4050
|
case "stopped":
|
|
3998
4051
|
case "disconnected":
|
|
3999
4052
|
case "ready": {
|
|
4053
|
+
this.cleanupNetworkListener();
|
|
4000
4054
|
const result = this.close();
|
|
4001
4055
|
this.socket = { state: "stopped" };
|
|
4002
4056
|
return result;
|
|
@@ -4021,6 +4075,7 @@ class WebSocketManager {
|
|
|
4021
4075
|
this.socket;
|
|
4022
4076
|
}
|
|
4023
4077
|
}
|
|
4078
|
+
this.setupNetworkListener();
|
|
4024
4079
|
this.connect();
|
|
4025
4080
|
}
|
|
4026
4081
|
pause() {
|
|
@@ -4040,6 +4095,25 @@ class WebSocketManager {
|
|
|
4040
4095
|
}
|
|
4041
4096
|
}
|
|
4042
4097
|
}
|
|
4098
|
+
tryReconnectImmediately() {
|
|
4099
|
+
this._logVerbose("tryReconnectImmediately called");
|
|
4100
|
+
if (this.socket.state !== "disconnected") {
|
|
4101
|
+
this._logVerbose(`tryReconnectImmediately called but socket state is ${this.socket.state}, no action taken`);
|
|
4102
|
+
return;
|
|
4103
|
+
}
|
|
4104
|
+
let timeSavedMs = null;
|
|
4105
|
+
if (this.scheduledReconnect) {
|
|
4106
|
+
const elapsed = monotonicMillis() - this.scheduledReconnect.scheduledAt;
|
|
4107
|
+
timeSavedMs = Math.max(0, this.scheduledReconnect.backoffMs - elapsed);
|
|
4108
|
+
this._logVerbose(`would have waited ${Math.round(timeSavedMs)}ms more (backoff was ${Math.round(this.scheduledReconnect.backoffMs)}ms, elapsed ${Math.round(elapsed)}ms)`);
|
|
4109
|
+
clearTimeout(this.scheduledReconnect.timeout);
|
|
4110
|
+
this.scheduledReconnect = null;
|
|
4111
|
+
this._logVerbose("canceled scheduled reconnect");
|
|
4112
|
+
}
|
|
4113
|
+
this.logger.log("Network recovery detected, reconnecting immediately");
|
|
4114
|
+
this.pendingNetworkRecoveryInfo = timeSavedMs !== null ? { timeSavedMs } : null;
|
|
4115
|
+
this.connect();
|
|
4116
|
+
}
|
|
4043
4117
|
resume() {
|
|
4044
4118
|
switch (this.socket.state) {
|
|
4045
4119
|
case "connecting":
|
|
@@ -4130,13 +4204,17 @@ var init_web_socket_manager = __esm(() => {
|
|
|
4130
4204
|
VectorIndexesUnavailable: { timeout: 1000 },
|
|
4131
4205
|
SearchIndexesUnavailable: { timeout: 1000 },
|
|
4132
4206
|
TableSummariesUnavailable: { timeout: 1000 },
|
|
4207
|
+
ServiceUnavailable: { timeout: 3000 },
|
|
4208
|
+
WorkerOverloaded: { timeout: 3000 },
|
|
4209
|
+
IsolateNotClean: { timeout: 3000 },
|
|
4210
|
+
InitialPermitTimeoutError: { timeout: 3000 },
|
|
4133
4211
|
VectorIndexTooLarge: { timeout: 3000 },
|
|
4134
4212
|
SearchIndexTooLarge: { timeout: 3000 },
|
|
4135
4213
|
TooManyWritesInTimePeriod: { timeout: 3000 }
|
|
4136
4214
|
};
|
|
4137
4215
|
});
|
|
4138
4216
|
|
|
4139
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
4217
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/session.js
|
|
4140
4218
|
function newSessionId() {
|
|
4141
4219
|
return uuidv4();
|
|
4142
4220
|
}
|
|
@@ -4147,7 +4225,7 @@ function uuidv4() {
|
|
|
4147
4225
|
});
|
|
4148
4226
|
}
|
|
4149
4227
|
|
|
4150
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
4228
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/vendor/jwt-decode/index.js
|
|
4151
4229
|
function b64DecodeUnicode(str) {
|
|
4152
4230
|
return decodeURIComponent(atob(str).replace(/(.)/g, (_m, p) => {
|
|
4153
4231
|
let code2 = p.charCodeAt(0).toString(16).toUpperCase();
|
|
@@ -4206,7 +4284,7 @@ var init_jwt_decode = __esm(() => {
|
|
|
4206
4284
|
InvalidTokenError.prototype.name = "InvalidTokenError";
|
|
4207
4285
|
});
|
|
4208
4286
|
|
|
4209
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
4287
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/authentication_manager.js
|
|
4210
4288
|
class AuthenticationManager {
|
|
4211
4289
|
constructor(syncState, callbacks, config) {
|
|
4212
4290
|
__publicField9(this, "authState", { state: "noAuth" });
|
|
@@ -4470,7 +4548,7 @@ var init_authentication_manager = __esm(() => {
|
|
|
4470
4548
|
MAXIMUM_REFRESH_DELAY = 20 * 24 * 60 * 60 * 1000;
|
|
4471
4549
|
});
|
|
4472
4550
|
|
|
4473
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
4551
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/metrics.js
|
|
4474
4552
|
function mark(name, sessionId) {
|
|
4475
4553
|
const detail = { sessionId };
|
|
4476
4554
|
if (typeof performance === "undefined" || !performance.mark)
|
|
@@ -4505,7 +4583,7 @@ var init_metrics = __esm(() => {
|
|
|
4505
4583
|
];
|
|
4506
4584
|
});
|
|
4507
4585
|
|
|
4508
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
4586
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/client.js
|
|
4509
4587
|
class BaseConvexClient {
|
|
4510
4588
|
constructor(address, onTransition, options) {
|
|
4511
4589
|
__publicField10(this, "address");
|
|
@@ -4549,7 +4627,7 @@ class BaseConvexClient {
|
|
|
4549
4627
|
validateDeploymentUrl(address);
|
|
4550
4628
|
}
|
|
4551
4629
|
options = { ...options };
|
|
4552
|
-
const authRefreshTokenLeewaySeconds = options.authRefreshTokenLeewaySeconds ??
|
|
4630
|
+
const authRefreshTokenLeewaySeconds = options.authRefreshTokenLeewaySeconds ?? 10;
|
|
4553
4631
|
let webSocketConstructor = options.webSocketConstructor;
|
|
4554
4632
|
if (!webSocketConstructor && typeof WebSocket === "undefined") {
|
|
4555
4633
|
throw new Error("No WebSocket global variable defined! To use Convex in an environment without WebSocket try the HTTP client: https://docs.convex.dev/api/classes/browser.ConvexHttpClient");
|
|
@@ -4627,9 +4705,8 @@ class BaseConvexClient {
|
|
|
4627
4705
|
sessionId: this._sessionId,
|
|
4628
4706
|
maxObservedTimestamp: this.maxObservedTimestamp
|
|
4629
4707
|
});
|
|
4630
|
-
const oldRemoteQueryResults = new Set(this.remoteQuerySet.remoteQueryResults().keys());
|
|
4631
4708
|
this.remoteQuerySet = new RemoteQuerySet((queryId) => this.state.queryPath(queryId), this.logger);
|
|
4632
|
-
const [querySetModification, authModification] = this.state.restart(
|
|
4709
|
+
const [querySetModification, authModification] = this.state.restart();
|
|
4633
4710
|
if (authModification) {
|
|
4634
4711
|
this.webSocketManager.sendMessage(authModification);
|
|
4635
4712
|
}
|
|
@@ -4708,7 +4785,7 @@ class BaseConvexClient {
|
|
|
4708
4785
|
}
|
|
4709
4786
|
}
|
|
4710
4787
|
hasSyncedPastLastReconnect() {
|
|
4711
|
-
const hasSyncedPastLastReconnect = this.requestManager.hasSyncedPastLastReconnect()
|
|
4788
|
+
const hasSyncedPastLastReconnect = this.requestManager.hasSyncedPastLastReconnect() && this.state.hasSyncedPastLastReconnect();
|
|
4712
4789
|
return hasSyncedPastLastReconnect;
|
|
4713
4790
|
}
|
|
4714
4791
|
observedTimestamp(observedTs) {
|
|
@@ -5001,12 +5078,12 @@ var init_client = __esm(() => {
|
|
|
5001
5078
|
__defProp11 = Object.defineProperty;
|
|
5002
5079
|
});
|
|
5003
5080
|
|
|
5004
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
5081
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/index.js
|
|
5005
5082
|
var init_browser = __esm(() => {
|
|
5006
5083
|
init_client();
|
|
5007
5084
|
});
|
|
5008
5085
|
|
|
5009
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
5086
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/pagination.js
|
|
5010
5087
|
function asPaginationResult(value) {
|
|
5011
5088
|
if (typeof value !== "object" || value === null || !Array.isArray(value.page) || typeof value.isDone !== "boolean" || typeof value.continueCursor !== "string") {
|
|
5012
5089
|
throw new Error(`Not a valid paginated query result: ${value?.toString()}`);
|
|
@@ -5014,7 +5091,7 @@ function asPaginationResult(value) {
|
|
|
5014
5091
|
return value;
|
|
5015
5092
|
}
|
|
5016
5093
|
|
|
5017
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
5094
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/sync/paginated_query_client.js
|
|
5018
5095
|
class PaginatedQueryClient {
|
|
5019
5096
|
constructor(client, onTransition) {
|
|
5020
5097
|
this.client = client;
|
|
@@ -5293,7 +5370,7 @@ var init_paginated_query_client = __esm(() => {
|
|
|
5293
5370
|
__defProp12 = Object.defineProperty;
|
|
5294
5371
|
});
|
|
5295
5372
|
|
|
5296
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
5373
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/simple_client.js
|
|
5297
5374
|
function setDefaultWebSocketConstructor(ws) {
|
|
5298
5375
|
defaultWebSocketConstructor = ws;
|
|
5299
5376
|
}
|
|
@@ -5545,10 +5622,10 @@ var init_simple_client = __esm(() => {
|
|
|
5545
5622
|
__defProp13 = Object.defineProperty;
|
|
5546
5623
|
});
|
|
5547
5624
|
|
|
5548
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
5625
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/simple_client-node.js
|
|
5549
5626
|
import { createRequire as createRequire2 } from "module";
|
|
5550
5627
|
import { resolve as nodePathResolve } from "path";
|
|
5551
|
-
var __dirname = "/home/runner/work/chatroom/chatroom/node_modules/.pnpm/convex@1.
|
|
5628
|
+
var __dirname = "/home/runner/work/chatroom/chatroom/node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser", require2, __create2, __defProp14, __getOwnPropDesc, __getOwnPropNames2, __getProtoOf2, __hasOwnProp2, __require2, __commonJS2 = (cb, mod) => function __require22() {
|
|
5552
5629
|
return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
5553
5630
|
}, __copyProps = (to, from, except, desc) => {
|
|
5554
5631
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -8630,7 +8707,7 @@ var init_simple_client_node = __esm(() => {
|
|
|
8630
8707
|
setDefaultWebSocketConstructor(nodeWebSocket);
|
|
8631
8708
|
});
|
|
8632
8709
|
|
|
8633
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
8710
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/http_client.js
|
|
8634
8711
|
class ConvexHttpClient2 {
|
|
8635
8712
|
constructor(address, options) {
|
|
8636
8713
|
__publicField13(this, "address");
|
|
@@ -8950,7 +9027,7 @@ var init_http_client = __esm(() => {
|
|
|
8950
9027
|
__defProp15 = Object.defineProperty;
|
|
8951
9028
|
});
|
|
8952
9029
|
|
|
8953
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
9030
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/browser/index-node.js
|
|
8954
9031
|
var init_index_node = __esm(() => {
|
|
8955
9032
|
init_simple_client_node();
|
|
8956
9033
|
init_http_client();
|
|
@@ -9199,7 +9276,7 @@ var init_storage = __esm(() => {
|
|
|
9199
9276
|
CHATROOM_DIR = join2(homedir(), ".chatroom");
|
|
9200
9277
|
});
|
|
9201
9278
|
|
|
9202
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
9279
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/values/validators.js
|
|
9203
9280
|
function throwUndefinedValidatorError(context, fieldName) {
|
|
9204
9281
|
const fieldInfo = fieldName !== undefined ? ` for field "${fieldName}"` : "";
|
|
9205
9282
|
throw new Error(`A validator is undefined${fieldInfo} in ${context}. This is often caused by circular imports. See ${UNDEFINED_VALIDATOR_ERROR_URL} for details.`);
|
|
@@ -9534,7 +9611,7 @@ var init_validators = __esm(() => {
|
|
|
9534
9611
|
};
|
|
9535
9612
|
});
|
|
9536
9613
|
|
|
9537
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
9614
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/values/validator.js
|
|
9538
9615
|
var v2;
|
|
9539
9616
|
var init_validator = __esm(() => {
|
|
9540
9617
|
init_validators();
|
|
@@ -9603,7 +9680,7 @@ var init_validator = __esm(() => {
|
|
|
9603
9680
|
};
|
|
9604
9681
|
});
|
|
9605
9682
|
|
|
9606
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
9683
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/server/pagination.js
|
|
9607
9684
|
var paginationOptsValidator;
|
|
9608
9685
|
var init_pagination = __esm(() => {
|
|
9609
9686
|
init_validator();
|
|
@@ -9617,10 +9694,10 @@ var init_pagination = __esm(() => {
|
|
|
9617
9694
|
});
|
|
9618
9695
|
});
|
|
9619
9696
|
|
|
9620
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
9697
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/server/search_filter_builder.js
|
|
9621
9698
|
var init_search_filter_builder = () => {};
|
|
9622
9699
|
|
|
9623
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
9700
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/server/components/index.js
|
|
9624
9701
|
function createChildComponents(root, pathParts) {
|
|
9625
9702
|
const handler = {
|
|
9626
9703
|
get(_, prop) {
|
|
@@ -9645,7 +9722,7 @@ var init_components = __esm(() => {
|
|
|
9645
9722
|
init_paths();
|
|
9646
9723
|
});
|
|
9647
9724
|
|
|
9648
|
-
// ../../node_modules/.pnpm/convex@1.
|
|
9725
|
+
// ../../node_modules/.pnpm/convex@1.34.0_react@19.2.3/node_modules/convex/dist/esm/server/index.js
|
|
9649
9726
|
var init_server = __esm(() => {
|
|
9650
9727
|
init_api();
|
|
9651
9728
|
init_components();
|
|
@@ -10257,7 +10334,12 @@ ${options.prompt}` : options.prompt;
|
|
|
10257
10334
|
cwd: options.workingDir,
|
|
10258
10335
|
stdio: ["pipe", "pipe", "pipe"],
|
|
10259
10336
|
shell: false,
|
|
10260
|
-
detached: true
|
|
10337
|
+
detached: true,
|
|
10338
|
+
env: {
|
|
10339
|
+
...process.env,
|
|
10340
|
+
GIT_EDITOR: "true",
|
|
10341
|
+
GIT_SEQUENCE_EDITOR: "true"
|
|
10342
|
+
}
|
|
10261
10343
|
});
|
|
10262
10344
|
childProcess.stdin?.write(fullPrompt);
|
|
10263
10345
|
childProcess.stdin?.end();
|
|
@@ -10458,7 +10540,12 @@ var init_pi_agent_service = __esm(() => {
|
|
|
10458
10540
|
cwd: options.workingDir,
|
|
10459
10541
|
stdio: ["pipe", "pipe", "pipe"],
|
|
10460
10542
|
shell: false,
|
|
10461
|
-
detached: true
|
|
10543
|
+
detached: true,
|
|
10544
|
+
env: {
|
|
10545
|
+
...process.env,
|
|
10546
|
+
GIT_EDITOR: "true",
|
|
10547
|
+
GIT_SEQUENCE_EDITOR: "true"
|
|
10548
|
+
}
|
|
10462
10549
|
});
|
|
10463
10550
|
childProcess.stdin?.write(JSON.stringify({ type: "prompt", message: prompt }) + `
|
|
10464
10551
|
`);
|
|
@@ -10755,7 +10842,11 @@ ${options.prompt}` : options.prompt;
|
|
|
10755
10842
|
stdio: ["pipe", "pipe", "pipe"],
|
|
10756
10843
|
shell: false,
|
|
10757
10844
|
detached: true,
|
|
10758
|
-
env: {
|
|
10845
|
+
env: {
|
|
10846
|
+
...process.env,
|
|
10847
|
+
GIT_EDITOR: "true",
|
|
10848
|
+
GIT_SEQUENCE_EDITOR: "true"
|
|
10849
|
+
}
|
|
10759
10850
|
});
|
|
10760
10851
|
childProcess.stdin?.write(fullPrompt);
|
|
10761
10852
|
childProcess.stdin?.end();
|
|
@@ -10884,6 +10975,99 @@ var init_registry = __esm(() => {
|
|
|
10884
10975
|
registry = new Map;
|
|
10885
10976
|
});
|
|
10886
10977
|
|
|
10978
|
+
// src/infrastructure/services/remote-agents/claude/claude-code-agent-service.ts
|
|
10979
|
+
var CLAUDE_COMMAND = "claude", DEFAULT_MAX_TURNS = 200, ClaudeCodeAgentService;
|
|
10980
|
+
var init_claude_code_agent_service = __esm(() => {
|
|
10981
|
+
init_base_cli_agent_service();
|
|
10982
|
+
ClaudeCodeAgentService = class ClaudeCodeAgentService extends BaseCLIAgentService {
|
|
10983
|
+
id = "claude";
|
|
10984
|
+
displayName = "Claude Code";
|
|
10985
|
+
command = CLAUDE_COMMAND;
|
|
10986
|
+
constructor(deps) {
|
|
10987
|
+
super(deps);
|
|
10988
|
+
}
|
|
10989
|
+
isInstalled() {
|
|
10990
|
+
return this.checkInstalled(CLAUDE_COMMAND);
|
|
10991
|
+
}
|
|
10992
|
+
getVersion() {
|
|
10993
|
+
return this.checkVersion(CLAUDE_COMMAND);
|
|
10994
|
+
}
|
|
10995
|
+
async listModels() {
|
|
10996
|
+
return [
|
|
10997
|
+
"claude-sonnet-4-20250514",
|
|
10998
|
+
"claude-opus-4-20250514"
|
|
10999
|
+
];
|
|
11000
|
+
}
|
|
11001
|
+
async spawn(options) {
|
|
11002
|
+
const { systemPrompt, model, prompt } = options;
|
|
11003
|
+
const args = ["-p"];
|
|
11004
|
+
args.push("--max-turns", String(DEFAULT_MAX_TURNS));
|
|
11005
|
+
if (model) {
|
|
11006
|
+
args.push("--model", model);
|
|
11007
|
+
}
|
|
11008
|
+
if (systemPrompt) {
|
|
11009
|
+
args.push("--system-prompt", systemPrompt);
|
|
11010
|
+
}
|
|
11011
|
+
args.push(prompt);
|
|
11012
|
+
const childProcess = this.deps.spawn(CLAUDE_COMMAND, args, {
|
|
11013
|
+
cwd: options.workingDir,
|
|
11014
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
11015
|
+
shell: false,
|
|
11016
|
+
detached: true,
|
|
11017
|
+
env: {
|
|
11018
|
+
...process.env,
|
|
11019
|
+
GIT_EDITOR: "true",
|
|
11020
|
+
GIT_SEQUENCE_EDITOR: "true"
|
|
11021
|
+
}
|
|
11022
|
+
});
|
|
11023
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
11024
|
+
if (childProcess.killed || childProcess.exitCode !== null) {
|
|
11025
|
+
throw new Error(`Agent process exited immediately (exit code: ${childProcess.exitCode})`);
|
|
11026
|
+
}
|
|
11027
|
+
if (!childProcess.pid) {
|
|
11028
|
+
throw new Error("Agent process started but has no PID");
|
|
11029
|
+
}
|
|
11030
|
+
const pid = childProcess.pid;
|
|
11031
|
+
const context = options.context;
|
|
11032
|
+
const entry = this.registerProcess(pid, context);
|
|
11033
|
+
const outputCallbacks = [];
|
|
11034
|
+
if (childProcess.stdout) {
|
|
11035
|
+
childProcess.stdout.pipe(process.stdout, { end: false });
|
|
11036
|
+
childProcess.stdout.on("data", () => {
|
|
11037
|
+
entry.lastOutputAt = Date.now();
|
|
11038
|
+
for (const cb of outputCallbacks)
|
|
11039
|
+
cb();
|
|
11040
|
+
});
|
|
11041
|
+
}
|
|
11042
|
+
if (childProcess.stderr) {
|
|
11043
|
+
childProcess.stderr.pipe(process.stderr, { end: false });
|
|
11044
|
+
childProcess.stderr.on("data", () => {
|
|
11045
|
+
entry.lastOutputAt = Date.now();
|
|
11046
|
+
for (const cb of outputCallbacks)
|
|
11047
|
+
cb();
|
|
11048
|
+
});
|
|
11049
|
+
}
|
|
11050
|
+
return {
|
|
11051
|
+
pid,
|
|
11052
|
+
onExit: (cb) => {
|
|
11053
|
+
childProcess.on("exit", (code2, signal) => {
|
|
11054
|
+
this.deleteProcess(pid);
|
|
11055
|
+
cb({ code: code2, signal, context });
|
|
11056
|
+
});
|
|
11057
|
+
},
|
|
11058
|
+
onOutput: (cb) => {
|
|
11059
|
+
outputCallbacks.push(cb);
|
|
11060
|
+
}
|
|
11061
|
+
};
|
|
11062
|
+
}
|
|
11063
|
+
};
|
|
11064
|
+
});
|
|
11065
|
+
|
|
11066
|
+
// src/infrastructure/services/remote-agents/claude/index.ts
|
|
11067
|
+
var init_claude = __esm(() => {
|
|
11068
|
+
init_claude_code_agent_service();
|
|
11069
|
+
});
|
|
11070
|
+
|
|
10887
11071
|
// src/infrastructure/services/remote-agents/init-registry.ts
|
|
10888
11072
|
function initHarnessRegistry() {
|
|
10889
11073
|
if (initialized)
|
|
@@ -10891,10 +11075,12 @@ function initHarnessRegistry() {
|
|
|
10891
11075
|
registerHarness(new OpenCodeAgentService);
|
|
10892
11076
|
registerHarness(new PiAgentService);
|
|
10893
11077
|
registerHarness(new CursorAgentService);
|
|
11078
|
+
registerHarness(new ClaudeCodeAgentService);
|
|
10894
11079
|
initialized = true;
|
|
10895
11080
|
}
|
|
10896
11081
|
var initialized = false;
|
|
10897
11082
|
var init_init_registry = __esm(() => {
|
|
11083
|
+
init_claude();
|
|
10898
11084
|
init_cursor();
|
|
10899
11085
|
init_opencode();
|
|
10900
11086
|
init_pi();
|
|
@@ -11595,30 +11781,6 @@ var init_new_feature = () => {};
|
|
|
11595
11781
|
var init_classification = __esm(() => {
|
|
11596
11782
|
init_new_feature();
|
|
11597
11783
|
});
|
|
11598
|
-
|
|
11599
|
-
// ../../services/backend/prompts/cli/task-started/command.ts
|
|
11600
|
-
function taskStartedCommand(params) {
|
|
11601
|
-
const prefix = params.cliEnvPrefix || "";
|
|
11602
|
-
const chatroomId = params.chatroomId || "<chatroom-id>";
|
|
11603
|
-
const role = params.role || "<role>";
|
|
11604
|
-
const taskId = params.taskId || "<task-id>";
|
|
11605
|
-
const classification = params.classification || "<question|new_feature|follow_up>";
|
|
11606
|
-
const baseCmd = `${prefix}chatroom task-started --chatroom-id="${chatroomId}" --role="${role}" --task-id="${taskId}" --origin-message-classification=${classification}`;
|
|
11607
|
-
if (params.classification === "new_feature" || classification === "new_feature") {
|
|
11608
|
-
const title = params.title || "[Feature title]";
|
|
11609
|
-
const description = params.description || "[Feature description]";
|
|
11610
|
-
const techSpecs = params.techSpecs || "[Technical specifications]";
|
|
11611
|
-
return `${baseCmd} << 'EOF'
|
|
11612
|
-
---TITLE---
|
|
11613
|
-
${title}
|
|
11614
|
-
---DESCRIPTION---
|
|
11615
|
-
${description}
|
|
11616
|
-
---TECH_SPECS---
|
|
11617
|
-
${techSpecs}
|
|
11618
|
-
EOF`;
|
|
11619
|
-
}
|
|
11620
|
-
return baseCmd;
|
|
11621
|
-
}
|
|
11622
11784
|
// ../../services/backend/prompts/cli/task-started/main-prompt.ts
|
|
11623
11785
|
var init_main_prompt = () => {};
|
|
11624
11786
|
|
|
@@ -12085,10 +12247,10 @@ var init_get_next_task = __esm(() => {
|
|
|
12085
12247
|
init_session();
|
|
12086
12248
|
});
|
|
12087
12249
|
|
|
12088
|
-
// src/commands/
|
|
12089
|
-
var
|
|
12090
|
-
__export(
|
|
12091
|
-
|
|
12250
|
+
// src/commands/classify/index.ts
|
|
12251
|
+
var exports_classify = {};
|
|
12252
|
+
__export(exports_classify, {
|
|
12253
|
+
classify: () => classify
|
|
12092
12254
|
});
|
|
12093
12255
|
async function createDefaultDeps7() {
|
|
12094
12256
|
const client2 = await getConvexClient();
|
|
@@ -12104,9 +12266,9 @@ async function createDefaultDeps7() {
|
|
|
12104
12266
|
}
|
|
12105
12267
|
};
|
|
12106
12268
|
}
|
|
12107
|
-
async function
|
|
12269
|
+
async function classify(chatroomId, options, deps) {
|
|
12108
12270
|
const d = deps ?? await createDefaultDeps7();
|
|
12109
|
-
const { role, originMessageClassification, rawStdin, taskId
|
|
12271
|
+
const { role, originMessageClassification, rawStdin, taskId } = options;
|
|
12110
12272
|
const convexUrl = d.session.getConvexUrl();
|
|
12111
12273
|
const cliEnvPrefix = getCliEnvPrefix(convexUrl);
|
|
12112
12274
|
const sessionId = d.session.getSessionId();
|
|
@@ -12121,7 +12283,7 @@ async function taskStarted(chatroomId, options, deps) {
|
|
|
12121
12283
|
}
|
|
12122
12284
|
console.error(`
|
|
12123
12285
|
To use a different environment, set CHATROOM_CONVEX_URL:`);
|
|
12124
|
-
console.error(` CHATROOM_CONVEX_URL=${otherUrls[0]} chatroom
|
|
12286
|
+
console.error(` CHATROOM_CONVEX_URL=${otherUrls[0]} chatroom classify ...`);
|
|
12125
12287
|
console.error(`
|
|
12126
12288
|
Or to authenticate for the current environment:`);
|
|
12127
12289
|
}
|
|
@@ -12132,28 +12294,24 @@ async function taskStarted(chatroomId, options, deps) {
|
|
|
12132
12294
|
console.error(`❌ Invalid chatroom ID format: ID must be 20-40 characters (got ${chatroomId?.length || 0})`);
|
|
12133
12295
|
process.exit(1);
|
|
12134
12296
|
}
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12138
|
-
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
|
|
12142
|
-
taskId: "<task-id>",
|
|
12143
|
-
classification: "question",
|
|
12144
|
-
cliEnvPrefix
|
|
12145
|
-
})}`);
|
|
12146
|
-
console.error("");
|
|
12147
|
-
console.error(" For handoff recipients (receiving from other agents):");
|
|
12148
|
-
console.error(` ${cliEnvPrefix}chatroom task-started --chatroom-id=${chatroomId} --role=${role} --task-id=<task-id> --no-classify`);
|
|
12297
|
+
const chatroom = await d.backend.query(api.chatrooms.get, {
|
|
12298
|
+
sessionId,
|
|
12299
|
+
chatroomId
|
|
12300
|
+
});
|
|
12301
|
+
if (!chatroom) {
|
|
12302
|
+
console.error(`❌ Chatroom not found: ${chatroomId}`);
|
|
12303
|
+
console.error(` Verify the chatroom ID is correct and you have access.`);
|
|
12149
12304
|
process.exit(1);
|
|
12150
12305
|
}
|
|
12151
|
-
|
|
12152
|
-
|
|
12153
|
-
console.error(
|
|
12306
|
+
const entryPoint = chatroom?.teamEntryPoint ?? chatroom?.teamRoles?.[0];
|
|
12307
|
+
if (entryPoint && role.toLowerCase() !== entryPoint.toLowerCase()) {
|
|
12308
|
+
console.error(`❌ \`classify\` is only available to the entry point role (${entryPoint}). Your role is ${role}.`);
|
|
12309
|
+
console.error("");
|
|
12310
|
+
console.error(" Entry point roles receive user messages and must classify them.");
|
|
12311
|
+
console.error(" Other roles receive handoffs — use `task read` to mark in_progress.");
|
|
12154
12312
|
process.exit(1);
|
|
12155
12313
|
}
|
|
12156
|
-
if (
|
|
12314
|
+
if (originMessageClassification === "new_feature") {
|
|
12157
12315
|
if (!rawStdin || rawStdin.trim().length === 0) {
|
|
12158
12316
|
console.error(`❌ new_feature classification requires stdin with feature metadata`);
|
|
12159
12317
|
console.error(" Provide structured stdin with TITLE, DESCRIPTION, and TECH_SPECS");
|
|
@@ -12164,7 +12322,7 @@ Feature title
|
|
|
12164
12322
|
---DESCRIPTION---
|
|
12165
12323
|
What this feature does
|
|
12166
12324
|
---TECH_SPECS---
|
|
12167
|
-
How to implement it' | ${
|
|
12325
|
+
How to implement it' | ${classifyCommand({
|
|
12168
12326
|
chatroomId,
|
|
12169
12327
|
role,
|
|
12170
12328
|
taskId: "<task-id>",
|
|
@@ -12174,10 +12332,9 @@ How to implement it' | ${taskStartedCommand({
|
|
|
12174
12332
|
process.exit(1);
|
|
12175
12333
|
}
|
|
12176
12334
|
}
|
|
12177
|
-
let targetTask = null;
|
|
12178
12335
|
if (!taskId) {
|
|
12179
|
-
console.error(`❌ --task-id is required for
|
|
12180
|
-
console.error(` Usage: ${
|
|
12336
|
+
console.error(`❌ --task-id is required for classify`);
|
|
12337
|
+
console.error(` Usage: ${classifyCommand({
|
|
12181
12338
|
chatroomId: "<chatroomId>",
|
|
12182
12339
|
role: "<role>",
|
|
12183
12340
|
taskId: "<task-id>",
|
|
@@ -12186,7 +12343,7 @@ How to implement it' | ${taskStartedCommand({
|
|
|
12186
12343
|
})}`);
|
|
12187
12344
|
process.exit(1);
|
|
12188
12345
|
}
|
|
12189
|
-
targetTask = await d.backend.query(api.tasks.getTask, {
|
|
12346
|
+
const targetTask = await d.backend.query(api.tasks.getTask, {
|
|
12190
12347
|
sessionId,
|
|
12191
12348
|
chatroomId,
|
|
12192
12349
|
taskId
|
|
@@ -12196,26 +12353,6 @@ How to implement it' | ${taskStartedCommand({
|
|
|
12196
12353
|
console.error(` Verify the task ID is correct and you have access to this chatroom`);
|
|
12197
12354
|
process.exit(1);
|
|
12198
12355
|
}
|
|
12199
|
-
try {
|
|
12200
|
-
await d.backend.mutation(api.tasks.startTask, {
|
|
12201
|
-
sessionId,
|
|
12202
|
-
chatroomId,
|
|
12203
|
-
role,
|
|
12204
|
-
taskId
|
|
12205
|
-
});
|
|
12206
|
-
} catch (error) {
|
|
12207
|
-
const err = error;
|
|
12208
|
-
console.error(`❌ Failed to start task`);
|
|
12209
|
-
console.error(` Error: ${err.message}`);
|
|
12210
|
-
process.exit(1);
|
|
12211
|
-
}
|
|
12212
|
-
if (noClassify) {
|
|
12213
|
-
console.log(`✅ Task started`);
|
|
12214
|
-
console.log(` Task: ${targetTask.content}`);
|
|
12215
|
-
console.log(`
|
|
12216
|
-
\uD83D\uDCA1 Task is now in progress. Begin your work.`);
|
|
12217
|
-
return;
|
|
12218
|
-
}
|
|
12219
12356
|
try {
|
|
12220
12357
|
const result = await d.backend.mutation(api.messages.taskStarted, {
|
|
12221
12358
|
sessionId,
|
|
@@ -12252,227 +12389,65 @@ How to implement it' | ${taskStartedCommand({
|
|
|
12252
12389
|
process.exit(1);
|
|
12253
12390
|
}
|
|
12254
12391
|
}
|
|
12255
|
-
var
|
|
12392
|
+
var init_classify = __esm(() => {
|
|
12256
12393
|
init_env();
|
|
12257
12394
|
init_api3();
|
|
12258
12395
|
init_storage();
|
|
12259
12396
|
init_client2();
|
|
12260
12397
|
});
|
|
12261
12398
|
|
|
12262
|
-
// src/
|
|
12263
|
-
var
|
|
12264
|
-
__export(
|
|
12265
|
-
|
|
12399
|
+
// src/utils/serialization/decode/index.ts
|
|
12400
|
+
var exports_decode = {};
|
|
12401
|
+
__export(exports_decode, {
|
|
12402
|
+
formatDecodeError: () => formatDecodeError,
|
|
12403
|
+
detectDelimiterCollisions: () => detectDelimiterCollisions,
|
|
12404
|
+
decode: () => decode
|
|
12266
12405
|
});
|
|
12267
|
-
|
|
12268
|
-
const
|
|
12269
|
-
|
|
12270
|
-
|
|
12271
|
-
|
|
12272
|
-
|
|
12273
|
-
}
|
|
12274
|
-
|
|
12275
|
-
|
|
12276
|
-
getConvexUrl,
|
|
12277
|
-
getOtherSessionUrls
|
|
12278
|
-
}
|
|
12279
|
-
};
|
|
12406
|
+
function decode(input, options = {}) {
|
|
12407
|
+
const { singleParam, expectedParams, requiredParams } = options;
|
|
12408
|
+
if (singleParam) {
|
|
12409
|
+
const trimmed = input.trim();
|
|
12410
|
+
const singleParamDelimiter = `---${singleParam.toUpperCase()}---`;
|
|
12411
|
+
const stripped = trimmed.startsWith(singleParamDelimiter) ? trimmed.slice(singleParamDelimiter.length).trim() : trimmed;
|
|
12412
|
+
return { [singleParam]: stripped };
|
|
12413
|
+
}
|
|
12414
|
+
return decodeMultiParam(input, expectedParams, requiredParams);
|
|
12280
12415
|
}
|
|
12281
|
-
|
|
12282
|
-
const
|
|
12283
|
-
|
|
12284
|
-
const
|
|
12285
|
-
const
|
|
12286
|
-
const
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
|
|
12290
|
-
|
|
12291
|
-
|
|
12292
|
-
|
|
12293
|
-
|
|
12294
|
-
|
|
12416
|
+
function decodeMultiParam(input, expectedParams, requiredParams) {
|
|
12417
|
+
const lines = input.split(`
|
|
12418
|
+
`);
|
|
12419
|
+
const result = {};
|
|
12420
|
+
const seenParams = new Set;
|
|
12421
|
+
const delimiterPattern = /^---([A-Z_]+)---$/;
|
|
12422
|
+
let currentParam = null;
|
|
12423
|
+
let currentContent = [];
|
|
12424
|
+
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
12425
|
+
const line = lines[i2];
|
|
12426
|
+
const match = line.match(delimiterPattern);
|
|
12427
|
+
if (match) {
|
|
12428
|
+
const paramName = match[1];
|
|
12429
|
+
if (currentParam !== null) {
|
|
12430
|
+
const content = currentContent.join(`
|
|
12431
|
+
`).trim();
|
|
12432
|
+
result[currentParam] = content;
|
|
12295
12433
|
}
|
|
12296
|
-
|
|
12297
|
-
|
|
12298
|
-
|
|
12299
|
-
|
|
12300
|
-
|
|
12301
|
-
|
|
12302
|
-
|
|
12303
|
-
|
|
12304
|
-
|
|
12305
|
-
|
|
12306
|
-
|
|
12307
|
-
|
|
12308
|
-
|
|
12309
|
-
|
|
12310
|
-
|
|
12311
|
-
|
|
12312
|
-
|
|
12313
|
-
if (!chatroom) {
|
|
12314
|
-
console.error(`❌ Chatroom not found: ${chatroomId}`);
|
|
12315
|
-
console.error(` Verify the chatroom ID is correct and you have access.`);
|
|
12316
|
-
process.exit(1);
|
|
12317
|
-
}
|
|
12318
|
-
const entryPoint = chatroom?.teamEntryPoint ?? chatroom?.teamRoles?.[0];
|
|
12319
|
-
if (entryPoint && role.toLowerCase() !== entryPoint.toLowerCase()) {
|
|
12320
|
-
console.error(`❌ \`classify\` is only available to the entry point role (${entryPoint}). Your role is ${role}.`);
|
|
12321
|
-
console.error("");
|
|
12322
|
-
console.error(" Entry point roles receive user messages and must classify them.");
|
|
12323
|
-
console.error(" Other roles receive handoffs — use `task read` to mark in_progress.");
|
|
12324
|
-
process.exit(1);
|
|
12325
|
-
}
|
|
12326
|
-
if (originMessageClassification === "new_feature") {
|
|
12327
|
-
if (!rawStdin || rawStdin.trim().length === 0) {
|
|
12328
|
-
console.error(`❌ new_feature classification requires stdin with feature metadata`);
|
|
12329
|
-
console.error(" Provide structured stdin with TITLE, DESCRIPTION, and TECH_SPECS");
|
|
12330
|
-
console.error("");
|
|
12331
|
-
console.error(" Example:");
|
|
12332
|
-
console.error(` echo '---TITLE---
|
|
12333
|
-
Feature title
|
|
12334
|
-
---DESCRIPTION---
|
|
12335
|
-
What this feature does
|
|
12336
|
-
---TECH_SPECS---
|
|
12337
|
-
How to implement it' | ${classifyCommand({
|
|
12338
|
-
chatroomId,
|
|
12339
|
-
role,
|
|
12340
|
-
taskId: "<task-id>",
|
|
12341
|
-
classification: "new_feature",
|
|
12342
|
-
cliEnvPrefix
|
|
12343
|
-
})}`);
|
|
12344
|
-
process.exit(1);
|
|
12345
|
-
}
|
|
12346
|
-
}
|
|
12347
|
-
if (!taskId) {
|
|
12348
|
-
console.error(`❌ --task-id is required for classify`);
|
|
12349
|
-
console.error(` Usage: ${classifyCommand({
|
|
12350
|
-
chatroomId: "<chatroomId>",
|
|
12351
|
-
role: "<role>",
|
|
12352
|
-
taskId: "<task-id>",
|
|
12353
|
-
classification: "question",
|
|
12354
|
-
cliEnvPrefix
|
|
12355
|
-
})}`);
|
|
12356
|
-
process.exit(1);
|
|
12357
|
-
}
|
|
12358
|
-
const targetTask = await d.backend.query(api.tasks.getTask, {
|
|
12359
|
-
sessionId,
|
|
12360
|
-
chatroomId,
|
|
12361
|
-
taskId
|
|
12362
|
-
});
|
|
12363
|
-
if (!targetTask) {
|
|
12364
|
-
console.error(`❌ Task with ID "${taskId}" not found in this chatroom`);
|
|
12365
|
-
console.error(` Verify the task ID is correct and you have access to this chatroom`);
|
|
12366
|
-
process.exit(1);
|
|
12367
|
-
}
|
|
12368
|
-
try {
|
|
12369
|
-
await d.backend.mutation(api.tasks.startTask, {
|
|
12370
|
-
sessionId,
|
|
12371
|
-
chatroomId,
|
|
12372
|
-
role,
|
|
12373
|
-
taskId
|
|
12374
|
-
});
|
|
12375
|
-
} catch (error) {
|
|
12376
|
-
const err = error;
|
|
12377
|
-
console.error(`❌ Failed to start task`);
|
|
12378
|
-
console.error(` Error: ${err.message}`);
|
|
12379
|
-
process.exit(1);
|
|
12380
|
-
}
|
|
12381
|
-
try {
|
|
12382
|
-
const result = await d.backend.mutation(api.messages.taskStarted, {
|
|
12383
|
-
sessionId,
|
|
12384
|
-
chatroomId,
|
|
12385
|
-
role,
|
|
12386
|
-
taskId,
|
|
12387
|
-
originMessageClassification,
|
|
12388
|
-
convexUrl: d.session.getConvexUrl(),
|
|
12389
|
-
...rawStdin && { rawStdin }
|
|
12390
|
-
});
|
|
12391
|
-
console.log(`✅ Task acknowledged and classified`);
|
|
12392
|
-
console.log(` Classification: ${originMessageClassification}`);
|
|
12393
|
-
console.log(` Task: ${targetTask.content}`);
|
|
12394
|
-
if (result.reminder) {
|
|
12395
|
-
console.log(`
|
|
12396
|
-
\uD83D\uDCA1 ${result.reminder}`);
|
|
12397
|
-
}
|
|
12398
|
-
} catch (error) {
|
|
12399
|
-
const err = error;
|
|
12400
|
-
console.error(`❌ Failed to acknowledge task`);
|
|
12401
|
-
console.error(` Error: ${err.message}`);
|
|
12402
|
-
if ("stack" in err && err.stack) {
|
|
12403
|
-
const stackLines = err.stack.split(`
|
|
12404
|
-
`).slice(0, 5);
|
|
12405
|
-
console.error(` Stack trace:`);
|
|
12406
|
-
stackLines.forEach((line) => console.error(` ${line}`));
|
|
12407
|
-
}
|
|
12408
|
-
if (typeof error === "object" && error !== null && "data" in error) {
|
|
12409
|
-
const errData = error.data;
|
|
12410
|
-
if (errData) {
|
|
12411
|
-
console.error(` Server details:`, JSON.stringify(errData, null, 2));
|
|
12412
|
-
}
|
|
12413
|
-
}
|
|
12414
|
-
process.exit(1);
|
|
12415
|
-
}
|
|
12416
|
-
}
|
|
12417
|
-
var init_classify = __esm(() => {
|
|
12418
|
-
init_env();
|
|
12419
|
-
init_api3();
|
|
12420
|
-
init_storage();
|
|
12421
|
-
init_client2();
|
|
12422
|
-
});
|
|
12423
|
-
|
|
12424
|
-
// src/utils/serialization/decode/index.ts
|
|
12425
|
-
var exports_decode = {};
|
|
12426
|
-
__export(exports_decode, {
|
|
12427
|
-
formatDecodeError: () => formatDecodeError,
|
|
12428
|
-
detectDelimiterCollisions: () => detectDelimiterCollisions,
|
|
12429
|
-
decode: () => decode
|
|
12430
|
-
});
|
|
12431
|
-
function decode(input, options = {}) {
|
|
12432
|
-
const { singleParam, expectedParams, requiredParams } = options;
|
|
12433
|
-
if (singleParam) {
|
|
12434
|
-
const trimmed = input.trim();
|
|
12435
|
-
const singleParamDelimiter = `---${singleParam.toUpperCase()}---`;
|
|
12436
|
-
const stripped = trimmed.startsWith(singleParamDelimiter) ? trimmed.slice(singleParamDelimiter.length).trim() : trimmed;
|
|
12437
|
-
return { [singleParam]: stripped };
|
|
12438
|
-
}
|
|
12439
|
-
return decodeMultiParam(input, expectedParams, requiredParams);
|
|
12440
|
-
}
|
|
12441
|
-
function decodeMultiParam(input, expectedParams, requiredParams) {
|
|
12442
|
-
const lines = input.split(`
|
|
12443
|
-
`);
|
|
12444
|
-
const result = {};
|
|
12445
|
-
const seenParams = new Set;
|
|
12446
|
-
const delimiterPattern = /^---([A-Z_]+)---$/;
|
|
12447
|
-
let currentParam = null;
|
|
12448
|
-
let currentContent = [];
|
|
12449
|
-
for (let i2 = 0;i2 < lines.length; i2++) {
|
|
12450
|
-
const line = lines[i2];
|
|
12451
|
-
const match = line.match(delimiterPattern);
|
|
12452
|
-
if (match) {
|
|
12453
|
-
const paramName = match[1];
|
|
12454
|
-
if (currentParam !== null) {
|
|
12455
|
-
const content = currentContent.join(`
|
|
12456
|
-
`).trim();
|
|
12457
|
-
result[currentParam] = content;
|
|
12458
|
-
}
|
|
12459
|
-
if (expectedParams && !expectedParams.includes(paramName)) {
|
|
12460
|
-
throw createDecodeError("UNKNOWN_PARAM", `Unknown parameter '${paramName}'. Expected one of: ${expectedParams.join(", ")}`, i2 + 1, paramName);
|
|
12461
|
-
}
|
|
12462
|
-
if (seenParams.has(paramName)) {
|
|
12463
|
-
throw createDecodeError("DUPLICATE_PARAM", `Duplicate parameter '${paramName}' found at line ${i2 + 1}`, i2 + 1, paramName);
|
|
12464
|
-
}
|
|
12465
|
-
seenParams.add(paramName);
|
|
12466
|
-
currentParam = paramName;
|
|
12467
|
-
currentContent = [];
|
|
12468
|
-
} else {
|
|
12469
|
-
if (currentParam === null) {
|
|
12470
|
-
if (line.trim().length > 0) {
|
|
12471
|
-
throw createDecodeError("INVALID_FORMAT", `Content found before first parameter delimiter at line ${i2 + 1}. Expected format: ---PARAM_NAME---`, i2 + 1);
|
|
12472
|
-
}
|
|
12473
|
-
continue;
|
|
12474
|
-
}
|
|
12475
|
-
currentContent.push(line);
|
|
12434
|
+
if (expectedParams && !expectedParams.includes(paramName)) {
|
|
12435
|
+
throw createDecodeError("UNKNOWN_PARAM", `Unknown parameter '${paramName}'. Expected one of: ${expectedParams.join(", ")}`, i2 + 1, paramName);
|
|
12436
|
+
}
|
|
12437
|
+
if (seenParams.has(paramName)) {
|
|
12438
|
+
throw createDecodeError("DUPLICATE_PARAM", `Duplicate parameter '${paramName}' found at line ${i2 + 1}`, i2 + 1, paramName);
|
|
12439
|
+
}
|
|
12440
|
+
seenParams.add(paramName);
|
|
12441
|
+
currentParam = paramName;
|
|
12442
|
+
currentContent = [];
|
|
12443
|
+
} else {
|
|
12444
|
+
if (currentParam === null) {
|
|
12445
|
+
if (line.trim().length > 0) {
|
|
12446
|
+
throw createDecodeError("INVALID_FORMAT", `Content found before first parameter delimiter at line ${i2 + 1}. Expected format: ---PARAM_NAME---`, i2 + 1);
|
|
12447
|
+
}
|
|
12448
|
+
continue;
|
|
12449
|
+
}
|
|
12450
|
+
currentContent.push(line);
|
|
12476
12451
|
}
|
|
12477
12452
|
}
|
|
12478
12453
|
if (currentParam !== null) {
|
|
@@ -12561,7 +12536,7 @@ var exports_handoff = {};
|
|
|
12561
12536
|
__export(exports_handoff, {
|
|
12562
12537
|
handoff: () => handoff
|
|
12563
12538
|
});
|
|
12564
|
-
async function
|
|
12539
|
+
async function createDefaultDeps8() {
|
|
12565
12540
|
const client2 = await getConvexClient();
|
|
12566
12541
|
return {
|
|
12567
12542
|
backend: {
|
|
@@ -12576,7 +12551,7 @@ async function createDefaultDeps9() {
|
|
|
12576
12551
|
};
|
|
12577
12552
|
}
|
|
12578
12553
|
async function handoff(chatroomId, options, deps) {
|
|
12579
|
-
const d = deps ?? await
|
|
12554
|
+
const d = deps ?? await createDefaultDeps8();
|
|
12580
12555
|
const { role, message, nextRole, attachedArtifactIds = [] } = options;
|
|
12581
12556
|
const sessionId = d.session.getSessionId();
|
|
12582
12557
|
if (!sessionId) {
|
|
@@ -12710,7 +12685,7 @@ var exports_report_progress = {};
|
|
|
12710
12685
|
__export(exports_report_progress, {
|
|
12711
12686
|
reportProgress: () => reportProgress
|
|
12712
12687
|
});
|
|
12713
|
-
async function
|
|
12688
|
+
async function createDefaultDeps9() {
|
|
12714
12689
|
const client2 = await getConvexClient();
|
|
12715
12690
|
return {
|
|
12716
12691
|
backend: {
|
|
@@ -12725,7 +12700,7 @@ async function createDefaultDeps10() {
|
|
|
12725
12700
|
};
|
|
12726
12701
|
}
|
|
12727
12702
|
async function reportProgress(chatroomId, options, deps) {
|
|
12728
|
-
const d = deps ?? await
|
|
12703
|
+
const d = deps ?? await createDefaultDeps9();
|
|
12729
12704
|
const { role, message } = options;
|
|
12730
12705
|
const sessionId = d.session.getSessionId();
|
|
12731
12706
|
if (!sessionId) {
|
|
@@ -12824,7 +12799,7 @@ __export(exports_backlog, {
|
|
|
12824
12799
|
});
|
|
12825
12800
|
import { createHash } from "node:crypto";
|
|
12826
12801
|
import * as nodePath from "node:path";
|
|
12827
|
-
async function
|
|
12802
|
+
async function createDefaultDeps10() {
|
|
12828
12803
|
const client2 = await getConvexClient();
|
|
12829
12804
|
const fs = await import("node:fs/promises");
|
|
12830
12805
|
return {
|
|
@@ -12859,7 +12834,7 @@ function validateChatroomId(chatroomId) {
|
|
|
12859
12834
|
}
|
|
12860
12835
|
}
|
|
12861
12836
|
async function listBacklog(chatroomId, options, deps) {
|
|
12862
|
-
const d = deps ?? await
|
|
12837
|
+
const d = deps ?? await createDefaultDeps10();
|
|
12863
12838
|
const sessionId = requireAuth2(d);
|
|
12864
12839
|
validateChatroomId(chatroomId);
|
|
12865
12840
|
const limit = options.limit ?? 100;
|
|
@@ -12918,7 +12893,7 @@ async function listBacklog(chatroomId, options, deps) {
|
|
|
12918
12893
|
}
|
|
12919
12894
|
}
|
|
12920
12895
|
async function addBacklog(chatroomId, options, deps) {
|
|
12921
|
-
const d = deps ?? await
|
|
12896
|
+
const d = deps ?? await createDefaultDeps10();
|
|
12922
12897
|
const sessionId = requireAuth2(d);
|
|
12923
12898
|
validateChatroomId(chatroomId);
|
|
12924
12899
|
if (!options.content || options.content.trim().length === 0) {
|
|
@@ -12945,7 +12920,7 @@ async function addBacklog(chatroomId, options, deps) {
|
|
|
12945
12920
|
}
|
|
12946
12921
|
}
|
|
12947
12922
|
async function completeBacklog(chatroomId, options, deps) {
|
|
12948
|
-
const d = deps ?? await
|
|
12923
|
+
const d = deps ?? await createDefaultDeps10();
|
|
12949
12924
|
const sessionId = requireAuth2(d);
|
|
12950
12925
|
validateChatroomId(chatroomId);
|
|
12951
12926
|
if (!options.backlogItemId || options.backlogItemId.trim().length === 0) {
|
|
@@ -12979,7 +12954,7 @@ async function completeBacklog(chatroomId, options, deps) {
|
|
|
12979
12954
|
}
|
|
12980
12955
|
}
|
|
12981
12956
|
async function reopenBacklog(chatroomId, options, deps) {
|
|
12982
|
-
const d = deps ?? await
|
|
12957
|
+
const d = deps ?? await createDefaultDeps10();
|
|
12983
12958
|
const sessionId = requireAuth2(d);
|
|
12984
12959
|
validateChatroomId(chatroomId);
|
|
12985
12960
|
if (!options.backlogItemId || options.backlogItemId.trim().length === 0) {
|
|
@@ -13006,7 +12981,7 @@ async function reopenBacklog(chatroomId, options, deps) {
|
|
|
13006
12981
|
}
|
|
13007
12982
|
}
|
|
13008
12983
|
async function patchBacklog(chatroomId, options, deps) {
|
|
13009
|
-
const d = deps ?? await
|
|
12984
|
+
const d = deps ?? await createDefaultDeps10();
|
|
13010
12985
|
const sessionId = requireAuth2(d);
|
|
13011
12986
|
validateChatroomId(chatroomId);
|
|
13012
12987
|
if (!options.backlogItemId || options.backlogItemId.trim().length === 0) {
|
|
@@ -13068,7 +13043,7 @@ async function patchBacklog(chatroomId, options, deps) {
|
|
|
13068
13043
|
}
|
|
13069
13044
|
}
|
|
13070
13045
|
async function scoreBacklog(chatroomId, options, deps) {
|
|
13071
|
-
const d = deps ?? await
|
|
13046
|
+
const d = deps ?? await createDefaultDeps10();
|
|
13072
13047
|
const sessionId = requireAuth2(d);
|
|
13073
13048
|
validateChatroomId(chatroomId);
|
|
13074
13049
|
if (!options.backlogItemId || options.backlogItemId.trim().length === 0) {
|
|
@@ -13131,7 +13106,7 @@ async function scoreBacklog(chatroomId, options, deps) {
|
|
|
13131
13106
|
}
|
|
13132
13107
|
}
|
|
13133
13108
|
async function markForReviewBacklog(chatroomId, options, deps) {
|
|
13134
|
-
const d = deps ?? await
|
|
13109
|
+
const d = deps ?? await createDefaultDeps10();
|
|
13135
13110
|
const sessionId = requireAuth2(d);
|
|
13136
13111
|
validateChatroomId(chatroomId);
|
|
13137
13112
|
if (!options.backlogItemId || options.backlogItemId.trim().length === 0) {
|
|
@@ -13158,7 +13133,7 @@ async function markForReviewBacklog(chatroomId, options, deps) {
|
|
|
13158
13133
|
}
|
|
13159
13134
|
}
|
|
13160
13135
|
async function historyBacklog(chatroomId, options, deps) {
|
|
13161
|
-
const d = deps ?? await
|
|
13136
|
+
const d = deps ?? await createDefaultDeps10();
|
|
13162
13137
|
const sessionId = requireAuth2(d);
|
|
13163
13138
|
validateChatroomId(chatroomId);
|
|
13164
13139
|
const now = Date.now();
|
|
@@ -13253,7 +13228,7 @@ async function historyBacklog(chatroomId, options, deps) {
|
|
|
13253
13228
|
}
|
|
13254
13229
|
}
|
|
13255
13230
|
async function closeBacklog(chatroomId, options, deps) {
|
|
13256
|
-
const d = deps ?? await
|
|
13231
|
+
const d = deps ?? await createDefaultDeps10();
|
|
13257
13232
|
const sessionId = requireAuth2(d);
|
|
13258
13233
|
validateChatroomId(chatroomId);
|
|
13259
13234
|
if (!options.backlogItemId || options.backlogItemId.trim().length === 0) {
|
|
@@ -13279,176 +13254,600 @@ async function closeBacklog(chatroomId, options, deps) {
|
|
|
13279
13254
|
console.log(` Reason: ${options.reason}`);
|
|
13280
13255
|
console.log("");
|
|
13281
13256
|
} catch (error) {
|
|
13282
|
-
console.error(`❌ Failed to close backlog item: ${error.message}`);
|
|
13257
|
+
console.error(`❌ Failed to close backlog item: ${error.message}`);
|
|
13258
|
+
process.exit(1);
|
|
13259
|
+
return;
|
|
13260
|
+
}
|
|
13261
|
+
}
|
|
13262
|
+
function getStatusEmoji(status) {
|
|
13263
|
+
switch (status) {
|
|
13264
|
+
case "pending":
|
|
13265
|
+
return "\uD83D\uDFE2";
|
|
13266
|
+
case "acknowledged":
|
|
13267
|
+
return "\uD83D\uDCEC";
|
|
13268
|
+
case "in_progress":
|
|
13269
|
+
return "\uD83D\uDD35";
|
|
13270
|
+
case "backlog":
|
|
13271
|
+
return "⚪";
|
|
13272
|
+
case "completed":
|
|
13273
|
+
return "✅";
|
|
13274
|
+
case "pending_user_review":
|
|
13275
|
+
return "\uD83D\uDC40";
|
|
13276
|
+
case "closed":
|
|
13277
|
+
return "\uD83D\uDD12";
|
|
13278
|
+
default:
|
|
13279
|
+
return "⚫";
|
|
13280
|
+
}
|
|
13281
|
+
}
|
|
13282
|
+
function computeContentHash(content) {
|
|
13283
|
+
return createHash("sha256").update(content).digest("hex");
|
|
13284
|
+
}
|
|
13285
|
+
async function exportBacklog(chatroomId, options, deps) {
|
|
13286
|
+
const d = deps ?? await createDefaultDeps10();
|
|
13287
|
+
const sessionId = requireAuth2(d);
|
|
13288
|
+
validateChatroomId(chatroomId);
|
|
13289
|
+
if (!d.fs) {
|
|
13290
|
+
console.error("❌ File system operations not available");
|
|
13291
|
+
process.exit(1);
|
|
13292
|
+
return;
|
|
13293
|
+
}
|
|
13294
|
+
try {
|
|
13295
|
+
const backlogItems = await d.backend.query(api.backlog.listBacklogItems, {
|
|
13296
|
+
sessionId,
|
|
13297
|
+
chatroomId,
|
|
13298
|
+
statusFilter: "backlog"
|
|
13299
|
+
});
|
|
13300
|
+
const exportData = {
|
|
13301
|
+
exportedAt: Date.now(),
|
|
13302
|
+
chatroomId,
|
|
13303
|
+
items: backlogItems.map((item) => {
|
|
13304
|
+
const exportItem = {
|
|
13305
|
+
contentHash: computeContentHash(item.content),
|
|
13306
|
+
content: item.content,
|
|
13307
|
+
status: item.status,
|
|
13308
|
+
createdBy: item.createdBy ?? "unknown",
|
|
13309
|
+
createdAt: item.createdAt
|
|
13310
|
+
};
|
|
13311
|
+
if (item.complexity)
|
|
13312
|
+
exportItem.complexity = item.complexity;
|
|
13313
|
+
if (item.value)
|
|
13314
|
+
exportItem.value = item.value;
|
|
13315
|
+
if (item.priority !== undefined)
|
|
13316
|
+
exportItem.priority = item.priority;
|
|
13317
|
+
return exportItem;
|
|
13318
|
+
})
|
|
13319
|
+
};
|
|
13320
|
+
const exportDir = options.path ?? nodePath.join(process.cwd(), DEFAULT_EXPORT_DIR);
|
|
13321
|
+
await d.fs.mkdir(exportDir, { recursive: true });
|
|
13322
|
+
const filePath = nodePath.join(exportDir, BACKLOG_EXPORT_FILENAME);
|
|
13323
|
+
await d.fs.writeFile(filePath, JSON.stringify(exportData, null, 2));
|
|
13324
|
+
console.log("");
|
|
13325
|
+
console.log(`✅ Exported ${exportData.items.length} backlog item(s)`);
|
|
13326
|
+
console.log(` File: ${filePath}`);
|
|
13327
|
+
console.log("");
|
|
13328
|
+
} catch (error) {
|
|
13329
|
+
console.error(`❌ Failed to export backlog items: ${error.message}`);
|
|
13330
|
+
process.exit(1);
|
|
13331
|
+
return;
|
|
13332
|
+
}
|
|
13333
|
+
}
|
|
13334
|
+
async function importBacklog(chatroomId, options, deps) {
|
|
13335
|
+
const d = deps ?? await createDefaultDeps10();
|
|
13336
|
+
const sessionId = requireAuth2(d);
|
|
13337
|
+
validateChatroomId(chatroomId);
|
|
13338
|
+
if (!d.fs) {
|
|
13339
|
+
console.error("❌ File system operations not available");
|
|
13340
|
+
process.exit(1);
|
|
13341
|
+
return;
|
|
13342
|
+
}
|
|
13343
|
+
try {
|
|
13344
|
+
const importDir = options.path ?? nodePath.join(process.cwd(), DEFAULT_EXPORT_DIR);
|
|
13345
|
+
const filePath = nodePath.join(importDir, BACKLOG_EXPORT_FILENAME);
|
|
13346
|
+
const raw = await d.fs.readFile(filePath, "utf-8");
|
|
13347
|
+
const exportData = JSON.parse(raw);
|
|
13348
|
+
const ageMs = Date.now() - exportData.exportedAt;
|
|
13349
|
+
if (ageMs > STALENESS_THRESHOLD_MS) {
|
|
13350
|
+
const ageDays = Math.floor(ageMs / 86400000);
|
|
13351
|
+
console.log(`⚠️ This export is ${ageDays} days old and may be stale.`);
|
|
13352
|
+
}
|
|
13353
|
+
const existingItems = await d.backend.query(api.backlog.listBacklogItems, {
|
|
13354
|
+
sessionId,
|
|
13355
|
+
chatroomId,
|
|
13356
|
+
statusFilter: "backlog"
|
|
13357
|
+
});
|
|
13358
|
+
const existingHashes = new Set(existingItems.map((item) => computeContentHash(item.content)));
|
|
13359
|
+
let imported = 0;
|
|
13360
|
+
let skipped = 0;
|
|
13361
|
+
for (const item of exportData.items) {
|
|
13362
|
+
const hash = computeContentHash(item.content);
|
|
13363
|
+
if (existingHashes.has(hash)) {
|
|
13364
|
+
skipped++;
|
|
13365
|
+
continue;
|
|
13366
|
+
}
|
|
13367
|
+
await d.backend.mutation(api.backlog.createBacklogItem, {
|
|
13368
|
+
sessionId,
|
|
13369
|
+
chatroomId,
|
|
13370
|
+
content: item.content,
|
|
13371
|
+
createdBy: item.createdBy,
|
|
13372
|
+
priority: item.priority,
|
|
13373
|
+
complexity: item.complexity,
|
|
13374
|
+
value: item.value
|
|
13375
|
+
});
|
|
13376
|
+
existingHashes.add(hash);
|
|
13377
|
+
imported++;
|
|
13378
|
+
}
|
|
13379
|
+
console.log("");
|
|
13380
|
+
console.log(`✅ Import complete`);
|
|
13381
|
+
console.log(` Total items in file: ${exportData.items.length}`);
|
|
13382
|
+
console.log(` Imported: ${imported}`);
|
|
13383
|
+
console.log(` Skipped (duplicate): ${skipped}`);
|
|
13384
|
+
console.log("");
|
|
13385
|
+
} catch (error) {
|
|
13386
|
+
console.error(`❌ Failed to import backlog items: ${error.message}`);
|
|
13387
|
+
process.exit(1);
|
|
13388
|
+
return;
|
|
13389
|
+
}
|
|
13390
|
+
}
|
|
13391
|
+
var BACKLOG_EXPORT_FILENAME = "backlog-export.json", STALENESS_THRESHOLD_MS, DEFAULT_EXPORT_DIR = ".chatroom/exports";
|
|
13392
|
+
var init_backlog = __esm(() => {
|
|
13393
|
+
init_api3();
|
|
13394
|
+
init_storage();
|
|
13395
|
+
init_client2();
|
|
13396
|
+
STALENESS_THRESHOLD_MS = 7 * 24 * 60 * 60 * 1000;
|
|
13397
|
+
});
|
|
13398
|
+
|
|
13399
|
+
// src/utils/file-content.ts
|
|
13400
|
+
var exports_file_content = {};
|
|
13401
|
+
__export(exports_file_content, {
|
|
13402
|
+
resolveContent: () => resolveContent,
|
|
13403
|
+
readFileContent: () => readFileContent
|
|
13404
|
+
});
|
|
13405
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
13406
|
+
import { resolve } from "path";
|
|
13407
|
+
function readFileContent(filePath, optionName) {
|
|
13408
|
+
const absolutePath = resolve(process.cwd(), filePath);
|
|
13409
|
+
try {
|
|
13410
|
+
return readFileSync5(absolutePath, "utf-8");
|
|
13411
|
+
} catch (err) {
|
|
13412
|
+
const nodeErr = err;
|
|
13413
|
+
throw new Error(`Cannot read file for --${optionName}: ${absolutePath}
|
|
13414
|
+
` + `Reason: ${nodeErr.message}`);
|
|
13415
|
+
}
|
|
13416
|
+
}
|
|
13417
|
+
function resolveContent(content, filePath, optionName) {
|
|
13418
|
+
if (content && filePath) {
|
|
13419
|
+
throw new Error(`Cannot specify both --${optionName} and --${optionName}-file`);
|
|
13420
|
+
}
|
|
13421
|
+
if (filePath) {
|
|
13422
|
+
return readFileContent(filePath, `${optionName}-file`);
|
|
13423
|
+
}
|
|
13424
|
+
return content;
|
|
13425
|
+
}
|
|
13426
|
+
var init_file_content = () => {};
|
|
13427
|
+
|
|
13428
|
+
// src/commands/workflow/index.ts
|
|
13429
|
+
var exports_workflow = {};
|
|
13430
|
+
__export(exports_workflow, {
|
|
13431
|
+
specifyWorkflowStep: () => specifyWorkflowStep,
|
|
13432
|
+
parseSections: () => parseSections,
|
|
13433
|
+
getWorkflowStatus: () => getWorkflowStatus,
|
|
13434
|
+
exitWorkflow: () => exitWorkflow,
|
|
13435
|
+
executeWorkflow: () => executeWorkflow,
|
|
13436
|
+
createWorkflow: () => createWorkflow,
|
|
13437
|
+
completeStep: () => completeStep,
|
|
13438
|
+
cancelStep: () => cancelStep
|
|
13439
|
+
});
|
|
13440
|
+
async function createDefaultDeps11() {
|
|
13441
|
+
const client2 = await getConvexClient();
|
|
13442
|
+
return {
|
|
13443
|
+
backend: {
|
|
13444
|
+
mutation: (endpoint, args) => client2.mutation(endpoint, args),
|
|
13445
|
+
query: (endpoint, args) => client2.query(endpoint, args)
|
|
13446
|
+
},
|
|
13447
|
+
session: {
|
|
13448
|
+
getSessionId,
|
|
13449
|
+
getConvexUrl,
|
|
13450
|
+
getOtherSessionUrls
|
|
13451
|
+
}
|
|
13452
|
+
};
|
|
13453
|
+
}
|
|
13454
|
+
function requireAuth3(d) {
|
|
13455
|
+
const sessionId = d.session.getSessionId();
|
|
13456
|
+
if (!sessionId) {
|
|
13457
|
+
console.error(`❌ Not authenticated. Please run: chatroom auth login`);
|
|
13458
|
+
process.exit(1);
|
|
13459
|
+
}
|
|
13460
|
+
return sessionId;
|
|
13461
|
+
}
|
|
13462
|
+
function validateChatroomId2(chatroomId) {
|
|
13463
|
+
if (!chatroomId || typeof chatroomId !== "string" || chatroomId.length < 20 || chatroomId.length > 40) {
|
|
13464
|
+
console.error(`❌ Invalid chatroom ID format: ID must be 20-40 characters (got ${chatroomId?.length || 0})`);
|
|
13465
|
+
process.exit(1);
|
|
13466
|
+
}
|
|
13467
|
+
}
|
|
13468
|
+
function parseSections(input, requiredSections, optionalSections) {
|
|
13469
|
+
const allSections = [...requiredSections, ...optionalSections];
|
|
13470
|
+
const result = new Map;
|
|
13471
|
+
const markerPattern = allSections.map((s) => `---${s}---`).join("|");
|
|
13472
|
+
const regex = new RegExp(`(${markerPattern})`, "g");
|
|
13473
|
+
const markers = [];
|
|
13474
|
+
let match;
|
|
13475
|
+
while ((match = regex.exec(input)) !== null) {
|
|
13476
|
+
const sectionName = match[1].replace(/^---/, "").replace(/---$/, "");
|
|
13477
|
+
markers.push({ section: sectionName, index: match.index + match[0].length, matchStart: match.index });
|
|
13478
|
+
}
|
|
13479
|
+
for (let i2 = 0;i2 < markers.length; i2++) {
|
|
13480
|
+
const start = markers[i2].index;
|
|
13481
|
+
const end = i2 + 1 < markers.length ? markers[i2 + 1].matchStart : input.length;
|
|
13482
|
+
const content = input.substring(start, end).trim();
|
|
13483
|
+
result.set(markers[i2].section, content);
|
|
13484
|
+
}
|
|
13485
|
+
for (const section of requiredSections) {
|
|
13486
|
+
if (!result.has(section) || !result.get(section)) {
|
|
13487
|
+
console.error(`❌ Missing required section: ---${section}---`);
|
|
13488
|
+
console.error("");
|
|
13489
|
+
console.error("Expected format:");
|
|
13490
|
+
for (const s of allSections) {
|
|
13491
|
+
const isRequired = requiredSections.includes(s);
|
|
13492
|
+
console.error(` ---${s}---`);
|
|
13493
|
+
console.error(` [${s.toLowerCase()} content here${isRequired ? " (required)" : " (optional)"}]`);
|
|
13494
|
+
}
|
|
13495
|
+
process.exit(1);
|
|
13496
|
+
}
|
|
13497
|
+
}
|
|
13498
|
+
return result;
|
|
13499
|
+
}
|
|
13500
|
+
function getStepStatusEmoji(status) {
|
|
13501
|
+
switch (status) {
|
|
13502
|
+
case "pending":
|
|
13503
|
+
return "⏳";
|
|
13504
|
+
case "in_progress":
|
|
13505
|
+
return "\uD83D\uDD35";
|
|
13506
|
+
case "completed":
|
|
13507
|
+
return "✅";
|
|
13508
|
+
case "cancelled":
|
|
13509
|
+
return "❌";
|
|
13510
|
+
default:
|
|
13511
|
+
return "⚫";
|
|
13512
|
+
}
|
|
13513
|
+
}
|
|
13514
|
+
function getWorkflowStatusEmoji(status) {
|
|
13515
|
+
switch (status) {
|
|
13516
|
+
case "draft":
|
|
13517
|
+
return "\uD83D\uDCDD";
|
|
13518
|
+
case "active":
|
|
13519
|
+
return "▶️";
|
|
13520
|
+
case "completed":
|
|
13521
|
+
return "✅";
|
|
13522
|
+
case "cancelled":
|
|
13523
|
+
return "❌";
|
|
13524
|
+
default:
|
|
13525
|
+
return "⚫";
|
|
13526
|
+
}
|
|
13527
|
+
}
|
|
13528
|
+
async function createWorkflow(chatroomId, options, deps) {
|
|
13529
|
+
const d = deps ?? await createDefaultDeps11();
|
|
13530
|
+
const sessionId = requireAuth3(d);
|
|
13531
|
+
validateChatroomId2(chatroomId);
|
|
13532
|
+
let stepsData;
|
|
13533
|
+
try {
|
|
13534
|
+
stepsData = JSON.parse(options.stdinContent);
|
|
13535
|
+
} catch {
|
|
13536
|
+
console.error("❌ Invalid JSON input. Expected format:");
|
|
13537
|
+
console.error(' { "steps": [{ "stepKey": "...", "description": "...", "dependsOn": [...], "order": N }] }');
|
|
13538
|
+
process.exit(1);
|
|
13539
|
+
return;
|
|
13540
|
+
}
|
|
13541
|
+
if (!stepsData.steps || !Array.isArray(stepsData.steps)) {
|
|
13542
|
+
console.error('❌ JSON must contain a "steps" array');
|
|
13543
|
+
process.exit(1);
|
|
13544
|
+
return;
|
|
13545
|
+
}
|
|
13546
|
+
if (stepsData.steps.length === 0) {
|
|
13547
|
+
console.error("❌ Workflow must have at least one step");
|
|
13548
|
+
process.exit(1);
|
|
13549
|
+
return;
|
|
13550
|
+
}
|
|
13551
|
+
const ALLOWED_STEP_FIELDS = new Set(["stepKey", "description", "dependsOn", "order"]);
|
|
13552
|
+
for (let i2 = 0;i2 < stepsData.steps.length; i2++) {
|
|
13553
|
+
const step = stepsData.steps[i2];
|
|
13554
|
+
const stepLabel = step.stepKey ? `"${step.stepKey}"` : `at index ${i2}`;
|
|
13555
|
+
if (!step.stepKey || typeof step.stepKey !== "string") {
|
|
13556
|
+
console.error(`❌ Step ${stepLabel} must have a "stepKey" (string)`);
|
|
13557
|
+
console.error(" All steps require: stepKey, description, dependsOn, order");
|
|
13558
|
+
process.exit(1);
|
|
13559
|
+
return;
|
|
13560
|
+
}
|
|
13561
|
+
if (!step.description || typeof step.description !== "string") {
|
|
13562
|
+
console.error(`❌ Step ${stepLabel} must have a "description" (string)`);
|
|
13563
|
+
console.error(" All steps require: stepKey, description, dependsOn, order");
|
|
13564
|
+
process.exit(1);
|
|
13565
|
+
return;
|
|
13566
|
+
}
|
|
13567
|
+
if (!Array.isArray(step.dependsOn)) {
|
|
13568
|
+
console.error(`❌ Step ${stepLabel} must have a "dependsOn" (array of strings)`);
|
|
13569
|
+
console.error(" All steps require: stepKey, description, dependsOn, order");
|
|
13570
|
+
process.exit(1);
|
|
13571
|
+
return;
|
|
13572
|
+
}
|
|
13573
|
+
if (typeof step.order !== "number") {
|
|
13574
|
+
console.error(`❌ Step ${stepLabel} must have an "order" (number)`);
|
|
13575
|
+
console.error(" All steps require: stepKey, description, dependsOn, order");
|
|
13576
|
+
process.exit(1);
|
|
13577
|
+
return;
|
|
13578
|
+
}
|
|
13579
|
+
const extraFields = Object.keys(step).filter((k) => !ALLOWED_STEP_FIELDS.has(k));
|
|
13580
|
+
if (extraFields.length > 0) {
|
|
13581
|
+
console.error(`⚠️ Stripped unknown fields from step "${step.stepKey}": ${extraFields.join(", ")}`);
|
|
13582
|
+
}
|
|
13583
|
+
}
|
|
13584
|
+
const cleanSteps = stepsData.steps.map((step) => ({
|
|
13585
|
+
stepKey: step.stepKey,
|
|
13586
|
+
description: step.description,
|
|
13587
|
+
dependsOn: step.dependsOn,
|
|
13588
|
+
order: step.order
|
|
13589
|
+
}));
|
|
13590
|
+
try {
|
|
13591
|
+
const result = await d.backend.mutation(api.workflows.createWorkflow, {
|
|
13592
|
+
sessionId,
|
|
13593
|
+
chatroomId,
|
|
13594
|
+
workflowKey: options.workflowKey,
|
|
13595
|
+
steps: cleanSteps,
|
|
13596
|
+
createdBy: options.role
|
|
13597
|
+
});
|
|
13598
|
+
console.log("");
|
|
13599
|
+
console.log("✅ Workflow created");
|
|
13600
|
+
console.log(` Key: ${options.workflowKey}`);
|
|
13601
|
+
console.log(` Workflow ID: ${result.workflowId}`);
|
|
13602
|
+
console.log(` Steps: ${cleanSteps.length}`);
|
|
13603
|
+
console.log(` Status: draft`);
|
|
13604
|
+
console.log("");
|
|
13605
|
+
} catch (error) {
|
|
13606
|
+
console.error(`❌ Failed to create workflow: ${error.message}`);
|
|
13607
|
+
process.exit(1);
|
|
13608
|
+
return;
|
|
13609
|
+
}
|
|
13610
|
+
}
|
|
13611
|
+
async function specifyWorkflowStep(chatroomId, options, deps) {
|
|
13612
|
+
const d = deps ?? await createDefaultDeps11();
|
|
13613
|
+
const sessionId = requireAuth3(d);
|
|
13614
|
+
validateChatroomId2(chatroomId);
|
|
13615
|
+
const sections = parseSections(options.stdinContent, ["GOAL", "REQUIREMENTS"], ["WARNINGS"]);
|
|
13616
|
+
const goal = sections.get("GOAL");
|
|
13617
|
+
const requirements = sections.get("REQUIREMENTS");
|
|
13618
|
+
const warnings = sections.get("WARNINGS") || undefined;
|
|
13619
|
+
try {
|
|
13620
|
+
await d.backend.mutation(api.workflows.specifyStep, {
|
|
13621
|
+
sessionId,
|
|
13622
|
+
chatroomId,
|
|
13623
|
+
workflowKey: options.workflowKey,
|
|
13624
|
+
stepKey: options.stepKey,
|
|
13625
|
+
assigneeRole: options.assigneeRole,
|
|
13626
|
+
goal,
|
|
13627
|
+
requirements,
|
|
13628
|
+
warnings
|
|
13629
|
+
});
|
|
13630
|
+
console.log("");
|
|
13631
|
+
console.log("✅ Step specified");
|
|
13632
|
+
console.log(` Workflow: ${options.workflowKey}`);
|
|
13633
|
+
console.log(` Step: ${options.stepKey}`);
|
|
13634
|
+
console.log(` Assignee: ${options.assigneeRole}`);
|
|
13635
|
+
console.log("");
|
|
13636
|
+
} catch (error) {
|
|
13637
|
+
console.error(`❌ Failed to specify step: ${error.message}`);
|
|
13638
|
+
process.exit(1);
|
|
13639
|
+
return;
|
|
13640
|
+
}
|
|
13641
|
+
}
|
|
13642
|
+
async function executeWorkflow(chatroomId, options, deps) {
|
|
13643
|
+
const d = deps ?? await createDefaultDeps11();
|
|
13644
|
+
const sessionId = requireAuth3(d);
|
|
13645
|
+
validateChatroomId2(chatroomId);
|
|
13646
|
+
try {
|
|
13647
|
+
await d.backend.mutation(api.workflows.executeWorkflow, {
|
|
13648
|
+
sessionId,
|
|
13649
|
+
chatroomId,
|
|
13650
|
+
workflowKey: options.workflowKey
|
|
13651
|
+
});
|
|
13652
|
+
console.log("");
|
|
13653
|
+
console.log("✅ Workflow activated");
|
|
13654
|
+
console.log(` Key: ${options.workflowKey}`);
|
|
13655
|
+
console.log(` Status: active`);
|
|
13656
|
+
console.log("");
|
|
13657
|
+
console.log("\uD83D\uDCA1 Root steps (no dependencies) are now in_progress.");
|
|
13658
|
+
console.log("");
|
|
13659
|
+
} catch (error) {
|
|
13660
|
+
console.error(`❌ Failed to execute workflow: ${error.message}`);
|
|
13661
|
+
process.exit(1);
|
|
13662
|
+
return;
|
|
13663
|
+
}
|
|
13664
|
+
}
|
|
13665
|
+
async function getWorkflowStatus(chatroomId, options, deps) {
|
|
13666
|
+
const d = deps ?? await createDefaultDeps11();
|
|
13667
|
+
const sessionId = requireAuth3(d);
|
|
13668
|
+
validateChatroomId2(chatroomId);
|
|
13669
|
+
try {
|
|
13670
|
+
const result = await d.backend.query(api.workflows.getWorkflowStatus, {
|
|
13671
|
+
sessionId,
|
|
13672
|
+
chatroomId,
|
|
13673
|
+
workflowKey: options.workflowKey
|
|
13674
|
+
});
|
|
13675
|
+
const wf = result.workflow;
|
|
13676
|
+
console.log("");
|
|
13677
|
+
console.log("══════════════════════════════════════════════════");
|
|
13678
|
+
console.log(`${getWorkflowStatusEmoji(wf.status)} WORKFLOW: ${wf.workflowKey}`);
|
|
13679
|
+
console.log("══════════════════════════════════════════════════");
|
|
13680
|
+
console.log(`Status: ${wf.status.toUpperCase()}`);
|
|
13681
|
+
console.log(`Created by: ${wf.createdBy}`);
|
|
13682
|
+
const createdDate = new Date(wf.createdAt).toLocaleString("en-US", {
|
|
13683
|
+
month: "short",
|
|
13684
|
+
day: "numeric",
|
|
13685
|
+
hour: "2-digit",
|
|
13686
|
+
minute: "2-digit",
|
|
13687
|
+
hour12: false
|
|
13688
|
+
});
|
|
13689
|
+
console.log(`Created: ${createdDate}`);
|
|
13690
|
+
if (wf.completedAt) {
|
|
13691
|
+
const completedDate = new Date(wf.completedAt).toLocaleString("en-US", {
|
|
13692
|
+
month: "short",
|
|
13693
|
+
day: "numeric",
|
|
13694
|
+
hour: "2-digit",
|
|
13695
|
+
minute: "2-digit",
|
|
13696
|
+
hour12: false
|
|
13697
|
+
});
|
|
13698
|
+
console.log(`Completed: ${completedDate}`);
|
|
13699
|
+
}
|
|
13700
|
+
if (wf.cancelledAt) {
|
|
13701
|
+
const cancelledDate = new Date(wf.cancelledAt).toLocaleString("en-US", {
|
|
13702
|
+
month: "short",
|
|
13703
|
+
day: "numeric",
|
|
13704
|
+
hour: "2-digit",
|
|
13705
|
+
minute: "2-digit",
|
|
13706
|
+
hour12: false
|
|
13707
|
+
});
|
|
13708
|
+
console.log(`Cancelled: ${cancelledDate}`);
|
|
13709
|
+
if (wf.cancelReason) {
|
|
13710
|
+
console.log(`Reason: ${wf.cancelReason}`);
|
|
13711
|
+
}
|
|
13712
|
+
}
|
|
13713
|
+
console.log("");
|
|
13714
|
+
console.log("──────────────────────────────────────────────────");
|
|
13715
|
+
console.log("\uD83D\uDCCB STEPS");
|
|
13716
|
+
console.log("──────────────────────────────────────────────────");
|
|
13717
|
+
if (result.steps.length === 0) {
|
|
13718
|
+
console.log("No steps.");
|
|
13719
|
+
} else {
|
|
13720
|
+
for (const step of result.steps) {
|
|
13721
|
+
const emoji = getStepStatusEmoji(step.status);
|
|
13722
|
+
console.log(`${emoji} [${step.status.toUpperCase()}] ${step.stepKey}: ${step.description}`);
|
|
13723
|
+
const details = [];
|
|
13724
|
+
if (step.assigneeRole)
|
|
13725
|
+
details.push(`assignee=${step.assigneeRole}`);
|
|
13726
|
+
if (step.dependsOn.length > 0)
|
|
13727
|
+
details.push(`depends_on=[${step.dependsOn.join(", ")}]`);
|
|
13728
|
+
details.push(`order=${step.order}`);
|
|
13729
|
+
console.log(` ${details.join(" | ")}`);
|
|
13730
|
+
if (step.specification) {
|
|
13731
|
+
const spec = step.specification;
|
|
13732
|
+
if (spec.goal) {
|
|
13733
|
+
console.log(` \uD83D\uDCCE Goal: ${spec.goal}`);
|
|
13734
|
+
}
|
|
13735
|
+
if (spec.requirements) {
|
|
13736
|
+
console.log(` \uD83D\uDCCE Requirements: ${spec.requirements}`);
|
|
13737
|
+
}
|
|
13738
|
+
if (spec.warnings) {
|
|
13739
|
+
console.log(` ⚠️ Warnings: ${spec.warnings}`);
|
|
13740
|
+
}
|
|
13741
|
+
}
|
|
13742
|
+
if (step.cancelReason) {
|
|
13743
|
+
console.log(` Cancel reason: ${step.cancelReason}`);
|
|
13744
|
+
}
|
|
13745
|
+
console.log("");
|
|
13746
|
+
}
|
|
13747
|
+
}
|
|
13748
|
+
if (result.availableNextSteps.length > 0) {
|
|
13749
|
+
console.log("──────────────────────────────────────────────────");
|
|
13750
|
+
console.log("\uD83D\uDD1C AVAILABLE NEXT STEPS");
|
|
13751
|
+
console.log("──────────────────────────────────────────────────");
|
|
13752
|
+
for (const stepKey of result.availableNextSteps) {
|
|
13753
|
+
const step = result.steps.find((s) => s.stepKey === stepKey);
|
|
13754
|
+
if (step) {
|
|
13755
|
+
console.log(` → ${stepKey}: ${step.description}`);
|
|
13756
|
+
}
|
|
13757
|
+
}
|
|
13758
|
+
console.log("");
|
|
13759
|
+
}
|
|
13760
|
+
console.log("══════════════════════════════════════════════════");
|
|
13761
|
+
console.log("");
|
|
13762
|
+
} catch (error) {
|
|
13763
|
+
console.error(`❌ Failed to get workflow status: ${error.message}`);
|
|
13764
|
+
process.exit(1);
|
|
13765
|
+
return;
|
|
13766
|
+
}
|
|
13767
|
+
}
|
|
13768
|
+
async function completeStep(chatroomId, options, deps) {
|
|
13769
|
+
const d = deps ?? await createDefaultDeps11();
|
|
13770
|
+
const sessionId = requireAuth3(d);
|
|
13771
|
+
validateChatroomId2(chatroomId);
|
|
13772
|
+
try {
|
|
13773
|
+
await d.backend.mutation(api.workflows.completeStep, {
|
|
13774
|
+
sessionId,
|
|
13775
|
+
chatroomId,
|
|
13776
|
+
workflowKey: options.workflowKey,
|
|
13777
|
+
stepKey: options.stepKey
|
|
13778
|
+
});
|
|
13779
|
+
console.log("");
|
|
13780
|
+
console.log("✅ Step completed");
|
|
13781
|
+
console.log(` Workflow: ${options.workflowKey}`);
|
|
13782
|
+
console.log(` Step: ${options.stepKey}`);
|
|
13783
|
+
console.log("");
|
|
13784
|
+
} catch (error) {
|
|
13785
|
+
console.error(`❌ Failed to complete step: ${error.message}`);
|
|
13283
13786
|
process.exit(1);
|
|
13284
13787
|
return;
|
|
13285
13788
|
}
|
|
13286
13789
|
}
|
|
13287
|
-
function
|
|
13288
|
-
switch (status) {
|
|
13289
|
-
case "pending":
|
|
13290
|
-
return "\uD83D\uDFE2";
|
|
13291
|
-
case "acknowledged":
|
|
13292
|
-
return "\uD83D\uDCEC";
|
|
13293
|
-
case "in_progress":
|
|
13294
|
-
return "\uD83D\uDD35";
|
|
13295
|
-
case "backlog":
|
|
13296
|
-
return "⚪";
|
|
13297
|
-
case "completed":
|
|
13298
|
-
return "✅";
|
|
13299
|
-
case "pending_user_review":
|
|
13300
|
-
return "\uD83D\uDC40";
|
|
13301
|
-
case "closed":
|
|
13302
|
-
return "\uD83D\uDD12";
|
|
13303
|
-
default:
|
|
13304
|
-
return "⚫";
|
|
13305
|
-
}
|
|
13306
|
-
}
|
|
13307
|
-
function computeContentHash(content) {
|
|
13308
|
-
return createHash("sha256").update(content).digest("hex");
|
|
13309
|
-
}
|
|
13310
|
-
async function exportBacklog(chatroomId, options, deps) {
|
|
13790
|
+
async function cancelStep(chatroomId, options, deps) {
|
|
13311
13791
|
const d = deps ?? await createDefaultDeps11();
|
|
13312
|
-
const sessionId =
|
|
13313
|
-
|
|
13314
|
-
if (!
|
|
13315
|
-
console.error("❌
|
|
13792
|
+
const sessionId = requireAuth3(d);
|
|
13793
|
+
validateChatroomId2(chatroomId);
|
|
13794
|
+
if (!options.reason || options.reason.trim().length === 0) {
|
|
13795
|
+
console.error("❌ Reason is required when cancelling a step");
|
|
13316
13796
|
process.exit(1);
|
|
13317
13797
|
return;
|
|
13318
13798
|
}
|
|
13319
13799
|
try {
|
|
13320
|
-
|
|
13800
|
+
await d.backend.mutation(api.workflows.cancelStep, {
|
|
13321
13801
|
sessionId,
|
|
13322
13802
|
chatroomId,
|
|
13323
|
-
|
|
13803
|
+
workflowKey: options.workflowKey,
|
|
13804
|
+
stepKey: options.stepKey,
|
|
13805
|
+
reason: options.reason.trim()
|
|
13324
13806
|
});
|
|
13325
|
-
const exportData = {
|
|
13326
|
-
exportedAt: Date.now(),
|
|
13327
|
-
chatroomId,
|
|
13328
|
-
items: backlogItems.map((item) => {
|
|
13329
|
-
const exportItem = {
|
|
13330
|
-
contentHash: computeContentHash(item.content),
|
|
13331
|
-
content: item.content,
|
|
13332
|
-
status: item.status,
|
|
13333
|
-
createdBy: item.createdBy ?? "unknown",
|
|
13334
|
-
createdAt: item.createdAt
|
|
13335
|
-
};
|
|
13336
|
-
if (item.complexity)
|
|
13337
|
-
exportItem.complexity = item.complexity;
|
|
13338
|
-
if (item.value)
|
|
13339
|
-
exportItem.value = item.value;
|
|
13340
|
-
if (item.priority !== undefined)
|
|
13341
|
-
exportItem.priority = item.priority;
|
|
13342
|
-
return exportItem;
|
|
13343
|
-
})
|
|
13344
|
-
};
|
|
13345
|
-
const exportDir = options.path ?? nodePath.join(process.cwd(), DEFAULT_EXPORT_DIR);
|
|
13346
|
-
await d.fs.mkdir(exportDir, { recursive: true });
|
|
13347
|
-
const filePath = nodePath.join(exportDir, BACKLOG_EXPORT_FILENAME);
|
|
13348
|
-
await d.fs.writeFile(filePath, JSON.stringify(exportData, null, 2));
|
|
13349
13807
|
console.log("");
|
|
13350
|
-
console.log(
|
|
13351
|
-
console.log(`
|
|
13808
|
+
console.log("❌ Step cancelled");
|
|
13809
|
+
console.log(` Workflow: ${options.workflowKey}`);
|
|
13810
|
+
console.log(` Step: ${options.stepKey}`);
|
|
13811
|
+
console.log(` Reason: ${options.reason.trim()}`);
|
|
13352
13812
|
console.log("");
|
|
13353
13813
|
} catch (error) {
|
|
13354
|
-
console.error(`❌ Failed to
|
|
13814
|
+
console.error(`❌ Failed to cancel step: ${error.message}`);
|
|
13355
13815
|
process.exit(1);
|
|
13356
13816
|
return;
|
|
13357
13817
|
}
|
|
13358
13818
|
}
|
|
13359
|
-
async function
|
|
13819
|
+
async function exitWorkflow(chatroomId, options, deps) {
|
|
13360
13820
|
const d = deps ?? await createDefaultDeps11();
|
|
13361
|
-
const sessionId =
|
|
13362
|
-
|
|
13363
|
-
if (!
|
|
13364
|
-
console.error("❌
|
|
13821
|
+
const sessionId = requireAuth3(d);
|
|
13822
|
+
validateChatroomId2(chatroomId);
|
|
13823
|
+
if (!options.reason || options.reason.trim().length === 0) {
|
|
13824
|
+
console.error("❌ Reason is required when exiting a workflow");
|
|
13365
13825
|
process.exit(1);
|
|
13366
13826
|
return;
|
|
13367
13827
|
}
|
|
13368
13828
|
try {
|
|
13369
|
-
|
|
13370
|
-
const filePath = nodePath.join(importDir, BACKLOG_EXPORT_FILENAME);
|
|
13371
|
-
const raw = await d.fs.readFile(filePath, "utf-8");
|
|
13372
|
-
const exportData = JSON.parse(raw);
|
|
13373
|
-
const ageMs = Date.now() - exportData.exportedAt;
|
|
13374
|
-
if (ageMs > STALENESS_THRESHOLD_MS) {
|
|
13375
|
-
const ageDays = Math.floor(ageMs / 86400000);
|
|
13376
|
-
console.log(`⚠️ This export is ${ageDays} days old and may be stale.`);
|
|
13377
|
-
}
|
|
13378
|
-
const existingItems = await d.backend.query(api.backlog.listBacklogItems, {
|
|
13829
|
+
await d.backend.mutation(api.workflows.exitWorkflow, {
|
|
13379
13830
|
sessionId,
|
|
13380
13831
|
chatroomId,
|
|
13381
|
-
|
|
13832
|
+
workflowKey: options.workflowKey,
|
|
13833
|
+
reason: options.reason.trim()
|
|
13382
13834
|
});
|
|
13383
|
-
const existingHashes = new Set(existingItems.map((item) => computeContentHash(item.content)));
|
|
13384
|
-
let imported = 0;
|
|
13385
|
-
let skipped = 0;
|
|
13386
|
-
for (const item of exportData.items) {
|
|
13387
|
-
const hash = computeContentHash(item.content);
|
|
13388
|
-
if (existingHashes.has(hash)) {
|
|
13389
|
-
skipped++;
|
|
13390
|
-
continue;
|
|
13391
|
-
}
|
|
13392
|
-
await d.backend.mutation(api.backlog.createBacklogItem, {
|
|
13393
|
-
sessionId,
|
|
13394
|
-
chatroomId,
|
|
13395
|
-
content: item.content,
|
|
13396
|
-
createdBy: item.createdBy,
|
|
13397
|
-
priority: item.priority,
|
|
13398
|
-
complexity: item.complexity,
|
|
13399
|
-
value: item.value
|
|
13400
|
-
});
|
|
13401
|
-
existingHashes.add(hash);
|
|
13402
|
-
imported++;
|
|
13403
|
-
}
|
|
13404
13835
|
console.log("");
|
|
13405
|
-
console.log(
|
|
13406
|
-
console.log(`
|
|
13407
|
-
console.log(`
|
|
13408
|
-
console.log(` Skipped (duplicate): ${skipped}`);
|
|
13836
|
+
console.log("❌ Workflow exited (cancelled)");
|
|
13837
|
+
console.log(` Key: ${options.workflowKey}`);
|
|
13838
|
+
console.log(` Reason: ${options.reason.trim()}`);
|
|
13409
13839
|
console.log("");
|
|
13410
13840
|
} catch (error) {
|
|
13411
|
-
console.error(`❌ Failed to
|
|
13841
|
+
console.error(`❌ Failed to exit workflow: ${error.message}`);
|
|
13412
13842
|
process.exit(1);
|
|
13413
13843
|
return;
|
|
13414
13844
|
}
|
|
13415
13845
|
}
|
|
13416
|
-
var
|
|
13417
|
-
var init_backlog = __esm(() => {
|
|
13846
|
+
var init_workflow = __esm(() => {
|
|
13418
13847
|
init_api3();
|
|
13419
13848
|
init_storage();
|
|
13420
13849
|
init_client2();
|
|
13421
|
-
STALENESS_THRESHOLD_MS = 7 * 24 * 60 * 60 * 1000;
|
|
13422
|
-
});
|
|
13423
|
-
|
|
13424
|
-
// src/utils/file-content.ts
|
|
13425
|
-
var exports_file_content = {};
|
|
13426
|
-
__export(exports_file_content, {
|
|
13427
|
-
resolveContent: () => resolveContent,
|
|
13428
|
-
readFileContent: () => readFileContent
|
|
13429
13850
|
});
|
|
13430
|
-
import { readFileSync as readFileSync5 } from "fs";
|
|
13431
|
-
import { resolve } from "path";
|
|
13432
|
-
function readFileContent(filePath, optionName) {
|
|
13433
|
-
const absolutePath = resolve(process.cwd(), filePath);
|
|
13434
|
-
try {
|
|
13435
|
-
return readFileSync5(absolutePath, "utf-8");
|
|
13436
|
-
} catch (err) {
|
|
13437
|
-
const nodeErr = err;
|
|
13438
|
-
throw new Error(`Cannot read file for --${optionName}: ${absolutePath}
|
|
13439
|
-
` + `Reason: ${nodeErr.message}`);
|
|
13440
|
-
}
|
|
13441
|
-
}
|
|
13442
|
-
function resolveContent(content, filePath, optionName) {
|
|
13443
|
-
if (content && filePath) {
|
|
13444
|
-
throw new Error(`Cannot specify both --${optionName} and --${optionName}-file`);
|
|
13445
|
-
}
|
|
13446
|
-
if (filePath) {
|
|
13447
|
-
return readFileContent(filePath, `${optionName}-file`);
|
|
13448
|
-
}
|
|
13449
|
-
return content;
|
|
13450
|
-
}
|
|
13451
|
-
var init_file_content = () => {};
|
|
13452
13851
|
|
|
13453
13852
|
// src/commands/task/read/index.ts
|
|
13454
13853
|
var exports_read = {};
|
|
@@ -13582,7 +13981,7 @@ async function createDefaultDeps13() {
|
|
|
13582
13981
|
}
|
|
13583
13982
|
};
|
|
13584
13983
|
}
|
|
13585
|
-
function
|
|
13984
|
+
function requireAuth4(d) {
|
|
13586
13985
|
const sessionId = d.session.getSessionId();
|
|
13587
13986
|
if (!sessionId) {
|
|
13588
13987
|
console.error(`❌ Not authenticated. Please run: chatroom auth login`);
|
|
@@ -13592,7 +13991,7 @@ function requireAuth3(d) {
|
|
|
13592
13991
|
}
|
|
13593
13992
|
async function listSkills(chatroomId, options, deps) {
|
|
13594
13993
|
const d = deps ?? await createDefaultDeps13();
|
|
13595
|
-
const sessionId =
|
|
13994
|
+
const sessionId = requireAuth4(d);
|
|
13596
13995
|
try {
|
|
13597
13996
|
const skills = await d.backend.query(api.skills.list, {
|
|
13598
13997
|
sessionId,
|
|
@@ -13620,7 +14019,7 @@ async function listSkills(chatroomId, options, deps) {
|
|
|
13620
14019
|
}
|
|
13621
14020
|
async function activateSkill(chatroomId, skillId, options, deps) {
|
|
13622
14021
|
const d = deps ?? await createDefaultDeps13();
|
|
13623
|
-
const sessionId =
|
|
14022
|
+
const sessionId = requireAuth4(d);
|
|
13624
14023
|
try {
|
|
13625
14024
|
const convexUrl = d.session.getConvexUrl();
|
|
13626
14025
|
const result = await d.backend.mutation(api.skills.activate, {
|
|
@@ -14456,6 +14855,15 @@ async function onRequestStartAgent(ctx, event) {
|
|
|
14456
14855
|
});
|
|
14457
14856
|
if (!result.success) {
|
|
14458
14857
|
console.log(`[daemon] Agent start rejected for role=${event.role}: ${result.error ?? "unknown"}`);
|
|
14858
|
+
ctx.deps.backend.mutation(api.machines.emitAgentStartFailed, {
|
|
14859
|
+
sessionId: ctx.sessionId,
|
|
14860
|
+
machineId: ctx.machineId,
|
|
14861
|
+
chatroomId: event.chatroomId,
|
|
14862
|
+
role: event.role,
|
|
14863
|
+
error: result.error ?? "unknown"
|
|
14864
|
+
}).catch((err) => {
|
|
14865
|
+
console.log(` ⚠️ Failed to emit startFailed event: ${err.message}`);
|
|
14866
|
+
});
|
|
14459
14867
|
} else {
|
|
14460
14868
|
ctx.deps.backend.mutation(api.workspaces.registerWorkspace, {
|
|
14461
14869
|
sessionId: ctx.sessionId,
|
|
@@ -15482,6 +15890,19 @@ class AgentProcessManager {
|
|
|
15482
15890
|
const key = agentKey2(opts.chatroomId, opts.role);
|
|
15483
15891
|
const slot = this.slots.get(key);
|
|
15484
15892
|
if (!slot || slot.state === "idle") {
|
|
15893
|
+
this.deps.backend.mutation(api.machines.recordAgentExited, {
|
|
15894
|
+
sessionId: this.deps.sessionId,
|
|
15895
|
+
machineId: this.deps.machineId,
|
|
15896
|
+
chatroomId: opts.chatroomId,
|
|
15897
|
+
role: opts.role,
|
|
15898
|
+
pid: 0,
|
|
15899
|
+
stopReason: opts.reason,
|
|
15900
|
+
exitCode: undefined,
|
|
15901
|
+
signal: undefined,
|
|
15902
|
+
agentHarness: undefined
|
|
15903
|
+
}).catch((err) => {
|
|
15904
|
+
console.log(` ⚠️ Failed to record agent exit (idle cleanup): ${err.message}`);
|
|
15905
|
+
});
|
|
15485
15906
|
return { success: true };
|
|
15486
15907
|
}
|
|
15487
15908
|
if (slot.state === "stopping" && slot.pendingOperation) {
|
|
@@ -15539,7 +15960,7 @@ class AgentProcessManager {
|
|
|
15539
15960
|
for (const service of this.deps.agentServices.values()) {
|
|
15540
15961
|
service.untrack(opts.pid);
|
|
15541
15962
|
}
|
|
15542
|
-
const isIntentionalStop = stopReason === "user.stop" || stopReason === "platform.team_switch";
|
|
15963
|
+
const isIntentionalStop = stopReason === "user.stop" || stopReason === "platform.team_switch" || stopReason === "daemon.shutdown";
|
|
15543
15964
|
const isDaemonRespawn = stopReason === "daemon.respawn";
|
|
15544
15965
|
if (isIntentionalStop) {
|
|
15545
15966
|
this.deps.crashLoop.clear(opts.chatroomId, opts.role);
|
|
@@ -15934,11 +16355,12 @@ async function connectDaemon(client2, sessionId, machineId, convexUrl) {
|
|
|
15934
16355
|
} catch (error) {
|
|
15935
16356
|
if (isNetworkError(error)) {
|
|
15936
16357
|
formatConnectivityError(error, convexUrl);
|
|
16358
|
+
throw error;
|
|
15937
16359
|
} else {
|
|
15938
16360
|
console.error(`❌ Failed to update daemon status: ${error.message}`);
|
|
16361
|
+
releaseLock();
|
|
16362
|
+
process.exit(1);
|
|
15939
16363
|
}
|
|
15940
|
-
releaseLock();
|
|
15941
|
-
process.exit(1);
|
|
15942
16364
|
}
|
|
15943
16365
|
}
|
|
15944
16366
|
function logStartup(ctx, availableModels) {
|
|
@@ -15968,45 +16390,59 @@ async function initDaemon() {
|
|
|
15968
16390
|
const sessionId = validateAuthentication(convexUrl);
|
|
15969
16391
|
const client2 = await getConvexClient();
|
|
15970
16392
|
const typedSessionId = sessionId;
|
|
15971
|
-
|
|
15972
|
-
|
|
15973
|
-
|
|
15974
|
-
|
|
15975
|
-
|
|
15976
|
-
|
|
15977
|
-
|
|
15978
|
-
|
|
15979
|
-
|
|
15980
|
-
|
|
15981
|
-
|
|
15982
|
-
|
|
15983
|
-
|
|
15984
|
-
|
|
15985
|
-
|
|
15986
|
-
|
|
15987
|
-
|
|
15988
|
-
|
|
15989
|
-
|
|
15990
|
-
|
|
15991
|
-
|
|
15992
|
-
|
|
15993
|
-
|
|
15994
|
-
|
|
15995
|
-
|
|
15996
|
-
|
|
15997
|
-
|
|
15998
|
-
|
|
15999
|
-
|
|
16000
|
-
|
|
16001
|
-
|
|
16002
|
-
|
|
16003
|
-
|
|
16004
|
-
|
|
16005
|
-
|
|
16006
|
-
|
|
16007
|
-
|
|
16008
|
-
|
|
16393
|
+
while (true) {
|
|
16394
|
+
try {
|
|
16395
|
+
await validateSession(client2, typedSessionId, convexUrl);
|
|
16396
|
+
const config3 = setupMachine();
|
|
16397
|
+
const { machineId } = config3;
|
|
16398
|
+
initHarnessRegistry();
|
|
16399
|
+
const agentServices = new Map(getAllHarnesses().map((s) => [s.id, s]));
|
|
16400
|
+
const availableModels = await registerCapabilities(client2, typedSessionId, config3, agentServices);
|
|
16401
|
+
await connectDaemon(client2, typedSessionId, machineId, convexUrl);
|
|
16402
|
+
const deps = createDefaultDeps19();
|
|
16403
|
+
deps.backend.mutation = (endpoint, args) => client2.mutation(endpoint, args);
|
|
16404
|
+
deps.backend.query = (endpoint, args) => client2.query(endpoint, args);
|
|
16405
|
+
deps.agentProcessManager = new AgentProcessManager({
|
|
16406
|
+
agentServices,
|
|
16407
|
+
backend: deps.backend,
|
|
16408
|
+
sessionId: typedSessionId,
|
|
16409
|
+
machineId,
|
|
16410
|
+
processes: deps.processes,
|
|
16411
|
+
clock: deps.clock,
|
|
16412
|
+
fs: deps.fs,
|
|
16413
|
+
persistence: deps.machine,
|
|
16414
|
+
spawning: deps.spawning,
|
|
16415
|
+
crashLoop: new CrashLoopTracker,
|
|
16416
|
+
convexUrl
|
|
16417
|
+
});
|
|
16418
|
+
const events = new DaemonEventBus;
|
|
16419
|
+
const ctx = {
|
|
16420
|
+
client: client2,
|
|
16421
|
+
sessionId: typedSessionId,
|
|
16422
|
+
machineId,
|
|
16423
|
+
config: config3,
|
|
16424
|
+
deps,
|
|
16425
|
+
events,
|
|
16426
|
+
agentServices,
|
|
16427
|
+
lastPushedGitState: new Map
|
|
16428
|
+
};
|
|
16429
|
+
registerEventListeners(ctx);
|
|
16430
|
+
logStartup(ctx, availableModels);
|
|
16431
|
+
await recoverState(ctx);
|
|
16432
|
+
return ctx;
|
|
16433
|
+
} catch (error) {
|
|
16434
|
+
if (isNetworkError(error)) {
|
|
16435
|
+
console.log(`
|
|
16436
|
+
Retrying in ${CONNECTION_RETRY_INTERVAL_MS / 1000}s...
|
|
16437
|
+
`);
|
|
16438
|
+
await new Promise((resolve2) => setTimeout(resolve2, CONNECTION_RETRY_INTERVAL_MS));
|
|
16439
|
+
} else {
|
|
16440
|
+
throw error;
|
|
16441
|
+
}
|
|
16442
|
+
}
|
|
16443
|
+
}
|
|
16009
16444
|
}
|
|
16445
|
+
var CONNECTION_RETRY_INTERVAL_MS = 1000;
|
|
16010
16446
|
var init_init2 = __esm(() => {
|
|
16011
16447
|
init_state_recovery();
|
|
16012
16448
|
init_api3();
|
|
@@ -16033,7 +16469,7 @@ async function onDaemonShutdown(ctx) {
|
|
|
16033
16469
|
await ctx.deps.agentProcessManager.stop({
|
|
16034
16470
|
chatroomId,
|
|
16035
16471
|
role,
|
|
16036
|
-
reason: "
|
|
16472
|
+
reason: "daemon.shutdown"
|
|
16037
16473
|
});
|
|
16038
16474
|
console.log(` Stopped ${role} (PID ${slot.pid})`);
|
|
16039
16475
|
} catch (e) {
|
|
@@ -16775,8 +17211,8 @@ async function maybeRequireAuth() {
|
|
|
16775
17211
|
console.log("⚠️ Skipping authentication (--skip-auth flag)");
|
|
16776
17212
|
return;
|
|
16777
17213
|
}
|
|
16778
|
-
const { requireAuth:
|
|
16779
|
-
await
|
|
17214
|
+
const { requireAuth: requireAuth5 } = await Promise.resolve().then(() => (init_middleware(), exports_middleware));
|
|
17215
|
+
await requireAuth5();
|
|
16780
17216
|
}
|
|
16781
17217
|
var authCommand = program2.command("auth").description("Manage CLI authentication");
|
|
16782
17218
|
authCommand.command("login").description("Authenticate the CLI via browser").option("-f, --force", "Re-authenticate even if already logged in").action(async (options) => {
|
|
@@ -16818,56 +17254,6 @@ program2.command("get-next-task").description("Join a chatroom and get the next
|
|
|
16818
17254
|
role: options.role
|
|
16819
17255
|
});
|
|
16820
17256
|
});
|
|
16821
|
-
program2.command("task-started").description("[LEGACY] Acknowledge a task and optionally classify the user message. Use classify instead for entry-point roles.").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").option("--origin-message-classification <type>", "Original message classification: question, new_feature, or follow_up (for entry point roles)").option("--no-classify", "Skip classification (for handoff recipients - classification already done by entry point)").requiredOption("--task-id <taskId>", "Task ID to acknowledge").action(async (options) => {
|
|
16822
|
-
console.error("⚠️ DEPRECATED: task-started is legacy. Use chatroom classify for entry-point roles.");
|
|
16823
|
-
await maybeRequireAuth();
|
|
16824
|
-
const skipClassification = options.classify === false;
|
|
16825
|
-
if (!skipClassification && !options.originMessageClassification) {
|
|
16826
|
-
console.error(`❌ Either --no-classify or --origin-message-classification is required`);
|
|
16827
|
-
console.error("");
|
|
16828
|
-
console.error(" For entry point roles (receiving user messages):");
|
|
16829
|
-
console.error(" Use --origin-message-classification=<type>");
|
|
16830
|
-
console.error("");
|
|
16831
|
-
console.error(" For handoff recipients (receiving from other agents):");
|
|
16832
|
-
console.error(" Use --no-classify");
|
|
16833
|
-
process.exit(1);
|
|
16834
|
-
}
|
|
16835
|
-
if (skipClassification && options.originMessageClassification) {
|
|
16836
|
-
console.error(`❌ Cannot use both --no-classify and --origin-message-classification`);
|
|
16837
|
-
console.error(" Use --no-classify for handoffs, or --origin-message-classification for user messages");
|
|
16838
|
-
process.exit(1);
|
|
16839
|
-
}
|
|
16840
|
-
if (options.originMessageClassification) {
|
|
16841
|
-
const validClassifications = ["question", "new_feature", "follow_up"];
|
|
16842
|
-
if (!validClassifications.includes(options.originMessageClassification)) {
|
|
16843
|
-
console.error(`❌ Invalid classification: ${options.originMessageClassification}. Must be one of: ${validClassifications.join(", ")}`);
|
|
16844
|
-
process.exit(1);
|
|
16845
|
-
}
|
|
16846
|
-
}
|
|
16847
|
-
let rawStdin;
|
|
16848
|
-
if (options.originMessageClassification === "new_feature") {
|
|
16849
|
-
const stdinContent = await readStdin();
|
|
16850
|
-
if (!stdinContent.trim()) {
|
|
16851
|
-
console.error(`❌ Stdin is empty. For new_feature classification, provide:
|
|
16852
|
-
---TITLE---
|
|
16853
|
-
[title]
|
|
16854
|
-
---DESCRIPTION---
|
|
16855
|
-
[description]
|
|
16856
|
-
---TECH_SPECS---
|
|
16857
|
-
[specs]`);
|
|
16858
|
-
process.exit(1);
|
|
16859
|
-
}
|
|
16860
|
-
rawStdin = stdinContent;
|
|
16861
|
-
}
|
|
16862
|
-
const { taskStarted: taskStarted2 } = await Promise.resolve().then(() => (init_task_started2(), exports_task_started2));
|
|
16863
|
-
await taskStarted2(options.chatroomId, {
|
|
16864
|
-
role: options.role,
|
|
16865
|
-
originMessageClassification: options.originMessageClassification,
|
|
16866
|
-
taskId: options.taskId,
|
|
16867
|
-
rawStdin,
|
|
16868
|
-
noClassify: skipClassification
|
|
16869
|
-
});
|
|
16870
|
-
});
|
|
16871
17257
|
program2.command("classify").description("Classify a task's origin message (entry-point role only).").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role (must be entry-point role)").requiredOption("--task-id <taskId>", "Task ID to acknowledge").requiredOption("--origin-message-classification <type>", "Original message classification: question, new_feature, or follow_up").action(async (options) => {
|
|
16872
17258
|
await maybeRequireAuth();
|
|
16873
17259
|
const validClassifications = ["question", "new_feature", "follow_up"];
|
|
@@ -16964,18 +17350,28 @@ backlogCommand.command("list").description("List backlog items").requiredOption(
|
|
|
16964
17350
|
filter: options.filter
|
|
16965
17351
|
});
|
|
16966
17352
|
});
|
|
16967
|
-
backlogCommand.command("add").description("Add a backlog item").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role (creator)").
|
|
17353
|
+
backlogCommand.command("add").description("Add a backlog item").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role (creator)").option("--content-file <path>", "Path to file containing task content (or use stdin/heredoc)").action(async (options) => {
|
|
16968
17354
|
await maybeRequireAuth();
|
|
16969
|
-
const { readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_file_content(), exports_file_content));
|
|
16970
17355
|
let content;
|
|
16971
|
-
|
|
16972
|
-
|
|
16973
|
-
|
|
16974
|
-
|
|
16975
|
-
|
|
17356
|
+
if (options.contentFile) {
|
|
17357
|
+
const { readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_file_content(), exports_file_content));
|
|
17358
|
+
try {
|
|
17359
|
+
content = readFileContent2(options.contentFile, "content-file");
|
|
17360
|
+
} catch (err) {
|
|
17361
|
+
console.error(`❌ ${err.message}`);
|
|
17362
|
+
process.exit(1);
|
|
17363
|
+
}
|
|
17364
|
+
} else {
|
|
17365
|
+
const stdinContent = await readStdin();
|
|
17366
|
+
content = stdinContent;
|
|
16976
17367
|
}
|
|
16977
17368
|
if (!content || content.trim().length === 0) {
|
|
16978
|
-
console.error("❌ Content file
|
|
17369
|
+
console.error("❌ Content is empty. Provide content via --content-file or stdin (heredoc).");
|
|
17370
|
+
console.error("");
|
|
17371
|
+
console.error(" Example with heredoc:");
|
|
17372
|
+
console.error(" chatroom backlog add --chatroom-id=<id> --role=<role> << 'EOF'");
|
|
17373
|
+
console.error(" Your backlog item content here");
|
|
17374
|
+
console.error(" EOF");
|
|
16979
17375
|
process.exit(1);
|
|
16980
17376
|
}
|
|
16981
17377
|
const { addBacklog: addBacklog2 } = await Promise.resolve().then(() => (init_backlog(), exports_backlog));
|
|
@@ -17026,6 +17422,104 @@ backlogCommand.command("import").description("Import backlog items from a JSON e
|
|
|
17026
17422
|
const { importBacklog: importBacklog2 } = await Promise.resolve().then(() => (init_backlog(), exports_backlog));
|
|
17027
17423
|
await importBacklog2(options.chatroomId, { role: options.role, path: options.path });
|
|
17028
17424
|
});
|
|
17425
|
+
var workflowCommand = program2.command("workflow").description("Manage structured workflows");
|
|
17426
|
+
workflowCommand.command("create").description("Create a new workflow with steps (reads JSON from stdin)").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role (creator)").requiredOption("--workflow-key <key>", "Unique workflow key").action(async (options) => {
|
|
17427
|
+
await maybeRequireAuth();
|
|
17428
|
+
const stdinContent = await readStdin();
|
|
17429
|
+
if (!stdinContent || stdinContent.trim().length === 0) {
|
|
17430
|
+
console.error("❌ JSON input is required via stdin.");
|
|
17431
|
+
console.error("");
|
|
17432
|
+
console.error(" Example:");
|
|
17433
|
+
console.error(" chatroom workflow create --chatroom-id=<id> --role=<role> --workflow-key=<key> << 'EOF'");
|
|
17434
|
+
console.error(' { "steps": [{ "stepKey": "step1", "description": "First step", "dependsOn": [], "order": 1 }] }');
|
|
17435
|
+
console.error(" EOF");
|
|
17436
|
+
process.exit(1);
|
|
17437
|
+
}
|
|
17438
|
+
const { createWorkflow: createWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
|
|
17439
|
+
await createWorkflow2(options.chatroomId, {
|
|
17440
|
+
role: options.role,
|
|
17441
|
+
workflowKey: options.workflowKey,
|
|
17442
|
+
stdinContent
|
|
17443
|
+
});
|
|
17444
|
+
});
|
|
17445
|
+
workflowCommand.command("specify").description("Specify a workflow step with goal, requirements, and optional warnings").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--workflow-key <key>", "Workflow key").requiredOption("--step-key <stepKey>", "Step key to specify").requiredOption("--assignee-role <assigneeRole>", "Role to assign the step to").action(async (options) => {
|
|
17446
|
+
await maybeRequireAuth();
|
|
17447
|
+
const stdinContent = await readStdin();
|
|
17448
|
+
if (!stdinContent || stdinContent.trim().length === 0) {
|
|
17449
|
+
console.error("❌ Step specification is required via stdin.");
|
|
17450
|
+
console.error("");
|
|
17451
|
+
console.error(" Example:");
|
|
17452
|
+
console.error(" chatroom workflow specify --chatroom-id=<id> --role=<role> --workflow-key=<key> --step-key=<step> --assignee-role=<role> << 'EOF'");
|
|
17453
|
+
console.error(" ---GOAL---");
|
|
17454
|
+
console.error(" Your goal here");
|
|
17455
|
+
console.error(" ---REQUIREMENTS---");
|
|
17456
|
+
console.error(" Your requirements here");
|
|
17457
|
+
console.error(" ---WARNINGS---");
|
|
17458
|
+
console.error(" Optional warnings here");
|
|
17459
|
+
console.error(" EOF");
|
|
17460
|
+
process.exit(1);
|
|
17461
|
+
}
|
|
17462
|
+
const { specifyWorkflowStep: specifyWorkflowStep2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
|
|
17463
|
+
await specifyWorkflowStep2(options.chatroomId, {
|
|
17464
|
+
role: options.role,
|
|
17465
|
+
workflowKey: options.workflowKey,
|
|
17466
|
+
stepKey: options.stepKey,
|
|
17467
|
+
assigneeRole: options.assigneeRole,
|
|
17468
|
+
stdinContent
|
|
17469
|
+
});
|
|
17470
|
+
});
|
|
17471
|
+
workflowCommand.command("execute").description("Activate a draft workflow (transitions to active, starts root steps)").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--workflow-key <key>", "Workflow key to execute").action(async (options) => {
|
|
17472
|
+
await maybeRequireAuth();
|
|
17473
|
+
const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
|
|
17474
|
+
await executeWorkflow2(options.chatroomId, {
|
|
17475
|
+
role: options.role,
|
|
17476
|
+
workflowKey: options.workflowKey
|
|
17477
|
+
});
|
|
17478
|
+
});
|
|
17479
|
+
workflowCommand.command("status").description("View the full status of a workflow including all steps").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--workflow-key <key>", "Workflow key").action(async (options) => {
|
|
17480
|
+
await maybeRequireAuth();
|
|
17481
|
+
const { getWorkflowStatus: getWorkflowStatus2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
|
|
17482
|
+
await getWorkflowStatus2(options.chatroomId, {
|
|
17483
|
+
role: options.role,
|
|
17484
|
+
workflowKey: options.workflowKey
|
|
17485
|
+
});
|
|
17486
|
+
});
|
|
17487
|
+
workflowCommand.command("step-complete").description("Mark a workflow step as completed").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--workflow-key <key>", "Workflow key").requiredOption("--step-key <stepKey>", "Step key to mark as complete").action(async (options) => {
|
|
17488
|
+
await maybeRequireAuth();
|
|
17489
|
+
const { completeStep: completeStep2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
|
|
17490
|
+
await completeStep2(options.chatroomId, {
|
|
17491
|
+
role: options.role,
|
|
17492
|
+
workflowKey: options.workflowKey,
|
|
17493
|
+
stepKey: options.stepKey
|
|
17494
|
+
});
|
|
17495
|
+
});
|
|
17496
|
+
workflowCommand.command("step-cancel").description("Cancel a workflow step with a reason").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--workflow-key <key>", "Workflow key").requiredOption("--step-key <stepKey>", "Step key to cancel").requiredOption("--reason <text>", "Reason for cancellation (required)").action(async (options) => {
|
|
17497
|
+
await maybeRequireAuth();
|
|
17498
|
+
if (!options.reason || options.reason.trim().length === 0) {
|
|
17499
|
+
console.error("❌ --reason is required and cannot be empty");
|
|
17500
|
+
process.exit(1);
|
|
17501
|
+
}
|
|
17502
|
+
const { cancelStep: cancelStep2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
|
|
17503
|
+
await cancelStep2(options.chatroomId, {
|
|
17504
|
+
role: options.role,
|
|
17505
|
+
workflowKey: options.workflowKey,
|
|
17506
|
+
stepKey: options.stepKey,
|
|
17507
|
+
reason: options.reason
|
|
17508
|
+
});
|
|
17509
|
+
});
|
|
17510
|
+
workflowCommand.command("exit").description("Exit (cancel) an entire workflow with a reason").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--workflow-key <key>", "Workflow key to exit").requiredOption("--reason <text>", "Reason for exiting the workflow (required)").action(async (options) => {
|
|
17511
|
+
await maybeRequireAuth();
|
|
17512
|
+
if (!options.reason || options.reason.trim().length === 0) {
|
|
17513
|
+
console.error("❌ --reason is required and cannot be empty");
|
|
17514
|
+
process.exit(1);
|
|
17515
|
+
}
|
|
17516
|
+
const { exitWorkflow: exitWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
|
|
17517
|
+
await exitWorkflow2(options.chatroomId, {
|
|
17518
|
+
role: options.role,
|
|
17519
|
+
workflowKey: options.workflowKey,
|
|
17520
|
+
reason: options.reason
|
|
17521
|
+
});
|
|
17522
|
+
});
|
|
17029
17523
|
var taskCommand = program2.command("task").description("Manage tasks");
|
|
17030
17524
|
taskCommand.command("read").description("Read a task and mark it as in_progress").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role in the chatroom").requiredOption("--task-id <taskId>", "Task ID to read").action(async (options) => {
|
|
17031
17525
|
await maybeRequireAuth();
|