|
|
@@ -86,17 +86,17 @@ namespace ClankerSaddle.Api {
|
|
|
break;
|
|
|
|
|
|
case "comment":
|
|
|
- string body_text = get_string_or(data, "body", get_string_or(data, "text", ""));
|
|
|
+ string body_text = EntryJson.get_string_or(data, "body", EntryJson.get_string_or(data, "text", ""));
|
|
|
yield tasks.add_comment(task_id, "agent", body_text);
|
|
|
yield tasks.log_session_entry(task_id, "comment", "saddle comment", body_text);
|
|
|
break;
|
|
|
|
|
|
case "block":
|
|
|
var block = yield tasks.add_block(task_id,
|
|
|
- get_string_or(data, "question", ""),
|
|
|
- get_string_or(data, "type", "question"),
|
|
|
- string_options(data),
|
|
|
- get_string_or(data, "body", null));
|
|
|
+ EntryJson.get_string_or(data, "question", ""),
|
|
|
+ EntryJson.get_string_or(data, "type", "question"),
|
|
|
+ EntryJson.string_array_member(data, "options", "block options"),
|
|
|
+ EntryJson.get_string_or(data, "body", null));
|
|
|
yield tasks.log_session_entry(task_id, "block",
|
|
|
@"block: $(block.question)", block.body);
|
|
|
var block_response = new Json.Object();
|
|
|
@@ -114,33 +114,33 @@ namespace ClankerSaddle.Api {
|
|
|
@"The '$(type)' update type is gone (plan 12) — use the task callbacks / the goal's plan flow");
|
|
|
|
|
|
case "progress":
|
|
|
- string summary = get_string_or(data, "summary",
|
|
|
- get_string_or(data, "text", ""));
|
|
|
+ string summary = EntryJson.get_string_or(data, "summary",
|
|
|
+ EntryJson.get_string_or(data, "text", ""));
|
|
|
yield tasks.add_progress(task_id, summary);
|
|
|
yield tasks.log_session_entry(task_id, "progress", "saddle progress-update", summary);
|
|
|
break;
|
|
|
|
|
|
case "review":
|
|
|
- string review_summary = get_string_or(data, "summary", "");
|
|
|
+ string review_summary = EntryJson.get_string_or(data, "summary", "");
|
|
|
var review_block = yield tasks.request_review(task_id, review_summary);
|
|
|
yield tasks.log_session_entry(task_id, "review", "saddle review", review_summary);
|
|
|
break;
|
|
|
|
|
|
case "done":
|
|
|
yield tasks.complete_task(task_id,
|
|
|
- get_string_or(data, "summary", null),
|
|
|
- get_string_or(data, "working_branch", null), "done");
|
|
|
+ EntryJson.get_string_or(data, "summary", null),
|
|
|
+ EntryJson.get_string_or(data, "working_branch", null), "done");
|
|
|
break;
|
|
|
|
|
|
case "failed":
|
|
|
- string failure = get_string_or(data, "summary",
|
|
|
- get_string_or(data, "text", ""));
|
|
|
+ string failure = EntryJson.get_string_or(data, "summary",
|
|
|
+ EntryJson.get_string_or(data, "text", ""));
|
|
|
yield tasks.fail_task(task_id, failure.length > 0 ? failure : null);
|
|
|
yield tasks.log_session_entry(task_id, "failed", "saddle failure", failure);
|
|
|
break;
|
|
|
|
|
|
case "status":
|
|
|
- string state = get_string_or(data, "state", "");
|
|
|
+ string state = EntryJson.get_string_or(data, "state", "");
|
|
|
if (state == "working" || state == "blocked") {
|
|
|
yield tasks.set_status(task_id, state);
|
|
|
}
|
|
|
@@ -157,17 +157,17 @@ namespace ClankerSaddle.Api {
|
|
|
private async void store_output(int64 session_id, Json.Object entry) throws Error {
|
|
|
var command = new SessionCommand() {
|
|
|
session_id = session_id,
|
|
|
- command_text = get_string_or(entry, "command", ""),
|
|
|
- output_text = get_string_or(entry, "output", null),
|
|
|
+ command_text = EntryJson.get_string_or(entry, "command", ""),
|
|
|
+ output_text = EntryJson.get_string_or(entry, "output", null),
|
|
|
exit_code = entry.has_member("exit_code")
|
|
|
&& entry.get_member("exit_code").get_value_type() == typeof(int64)
|
|
|
? entry.get_int_member("exit_code") : 0,
|
|
|
- entry_type = get_string_or(entry, "type", "command"),
|
|
|
- piped_input = get_string_or(entry, "input", null) != null
|
|
|
- && get_string_or(entry, "input", "").length > 0
|
|
|
- ? get_string_or(entry, "input", null) : null,
|
|
|
- started_at = parse_iso(entry, "started_at"),
|
|
|
- completed_at = parse_iso(entry, "completed_at"),
|
|
|
+ entry_type = EntryJson.get_string_or(entry, "type", "command"),
|
|
|
+ piped_input = EntryJson.get_string_or(entry, "input", null) != null
|
|
|
+ && EntryJson.get_string_or(entry, "input", "").length > 0
|
|
|
+ ? EntryJson.get_string_or(entry, "input", null) : null,
|
|
|
+ started_at = EntryJson.parse_iso(entry, "started_at"),
|
|
|
+ completed_at = EntryJson.parse_iso(entry, "completed_at"),
|
|
|
duration_ms = entry.has_member("duration_ms")
|
|
|
&& entry.get_member("duration_ms").get_value_type() == typeof(int64)
|
|
|
? entry.get_int_member("duration_ms") : 0
|
|
|
@@ -175,46 +175,6 @@ namespace ClankerSaddle.Api {
|
|
|
yield db.insert_async<SessionCommand>(command);
|
|
|
}
|
|
|
|
|
|
- /** The `options` member as a string array (native or JSON-encoded). */
|
|
|
- private static string[] string_options(Json.Object data) {
|
|
|
- if (!data.has_member("options")) {
|
|
|
- return new string[0];
|
|
|
- }
|
|
|
- var member = data.get_member("options");
|
|
|
- if (member.get_node_type() == Json.NodeType.ARRAY) {
|
|
|
- var values = new Vector<string>();
|
|
|
- foreach (var element in member.get_array().get_elements()) {
|
|
|
- if (element.get_node_type() == Json.NodeType.VALUE
|
|
|
- && element.get_string() != null) {
|
|
|
- values.add(element.get_string());
|
|
|
- }
|
|
|
- }
|
|
|
- return values.to_array();
|
|
|
- }
|
|
|
- string raw = get_string_or(data, "options", "");
|
|
|
- if (raw.length == 0) {
|
|
|
- return new string[0];
|
|
|
- }
|
|
|
- try {
|
|
|
- var parser = new Json.Parser();
|
|
|
- parser.load_from_data(raw);
|
|
|
- var root = parser.get_root();
|
|
|
- if (root != null && root.get_node_type() == Json.NodeType.ARRAY) {
|
|
|
- var values = new Vector<string>();
|
|
|
- foreach (var element in root.get_array().get_elements()) {
|
|
|
- if (element.get_node_type() == Json.NodeType.VALUE
|
|
|
- && element.get_string() != null) {
|
|
|
- values.add(element.get_string());
|
|
|
- }
|
|
|
- }
|
|
|
- return values.to_array();
|
|
|
- }
|
|
|
- } catch (Error e) {
|
|
|
- warning("[ClankerSaddle] Ignoring malformed block options: %s", e.message);
|
|
|
- }
|
|
|
- return new string[0];
|
|
|
- }
|
|
|
-
|
|
|
private async int64 task_id_for_session(int64 session_id) throws Error {
|
|
|
var session = yield db.query<ClankerSaddle.Data.Session>()
|
|
|
.where(Invercargill.Expressions.expr("id == $0",
|
|
|
@@ -278,23 +238,6 @@ namespace ClankerSaddle.Api {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- internal static string get_string_or(Json.Object obj, string name, string? fallback) {
|
|
|
- if (obj.has_member(name) && obj.get_member(name).get_string() != null) {
|
|
|
- return obj.get_string_member(name);
|
|
|
- }
|
|
|
- return fallback;
|
|
|
- }
|
|
|
-
|
|
|
- internal static DateTime? parse_iso(Json.Object obj, string name) {
|
|
|
- if (!obj.has_member(name)) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- var value = obj.get_member(name);
|
|
|
- if (value.get_node_type() != Json.NodeType.VALUE || value.get_string() == null) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- return new DateTime.from_iso8601(value.get_string(), new TimeZone.utc());
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -560,8 +503,8 @@ namespace ClankerSaddle.Api {
|
|
|
return SaddleUpdateEndpoint.json_error(400, e.message);
|
|
|
}
|
|
|
|
|
|
- string project_name = SaddleUpdateEndpoint.get_string_or(body, "project", "");
|
|
|
- string note_body = SaddleUpdateEndpoint.get_string_or(body, "body", "");
|
|
|
+ string project_name = EntryJson.get_string_or(body, "project", "");
|
|
|
+ string note_body = EntryJson.get_string_or(body, "body", "");
|
|
|
int64 task_id = body.has_member("task_id")
|
|
|
&& body.get_member("task_id").get_value_type() == typeof(int64)
|
|
|
? body.get_int_member("task_id") : 0;
|
|
|
@@ -671,8 +614,8 @@ namespace ClankerSaddle.Api {
|
|
|
&& body.get_member("session_id").get_value_type() == typeof(int64)
|
|
|
? body.get_int_member("session_id") : 0;
|
|
|
int64 goal_id = yield goal_scope_of(saddle, session_id);
|
|
|
- string title = SaddleUpdateEndpoint.get_string_or(body, "title", "");
|
|
|
- string mandate = SaddleUpdateEndpoint.get_string_or(body, "mandate", "");
|
|
|
+ string title = EntryJson.get_string_or(body, "title", "");
|
|
|
+ string mandate = EntryJson.get_string_or(body, "mandate", "");
|
|
|
if (title.length == 0) {
|
|
|
return SaddleUpdateEndpoint.json_error(400, "A title is required");
|
|
|
}
|
|
|
@@ -680,7 +623,7 @@ namespace ClankerSaddle.Api {
|
|
|
return SaddleUpdateEndpoint.json_error(400,
|
|
|
"A mandate is required (heredoc body of `task create`)");
|
|
|
}
|
|
|
- string mode = SaddleUpdateEndpoint.get_string_or(body, "mode", "implement");
|
|
|
+ string mode = EntryJson.get_string_or(body, "mode", "implement");
|
|
|
bool mode_valid = false;
|
|
|
foreach (string candidate in TASK_MODES) {
|
|
|
if (mode == candidate) {
|
|
|
@@ -1107,14 +1050,14 @@ namespace ClankerSaddle.Api {
|
|
|
@"No session $(session_id) exists on saddle $(((!)saddle).id)");
|
|
|
}
|
|
|
|
|
|
- string state = SaddleUpdateEndpoint.get_string_or(body, "state", "");
|
|
|
+ string state = EntryJson.get_string_or(body, "state", "");
|
|
|
if (state.length == 0) {
|
|
|
return SaddleUpdateEndpoint.json_error(400, "A state is required");
|
|
|
}
|
|
|
Json.Object? block = body.has_member("block")
|
|
|
&& body.get_member("block").get_node_type() == Json.NodeType.OBJECT
|
|
|
? body.get_object_member("block") : null;
|
|
|
- string? summary = SaddleUpdateEndpoint.get_string_or(body, "summary", null);
|
|
|
+ string? summary = EntryJson.get_string_or(body, "summary", null);
|
|
|
|
|
|
poll_state.note_push(session_id);
|
|
|
try {
|