@1medium/cli 1.8.0 → 1.9.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.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/src/api.js +96 -0
  3. package/src/index.js +261 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1medium/cli",
3
- "version": "1.8.0",
3
+ "version": "1.9.1",
4
4
  "description": "CLI and MCP server for 1Medium AI task management",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/api.js CHANGED
@@ -208,6 +208,91 @@ async function deleteProject(id) {
208
208
  return request("DELETE", `/projects/${id}`);
209
209
  }
210
210
 
211
+ // ============================================================================
212
+ // Script API
213
+ // ============================================================================
214
+
215
+ /**
216
+ * List scripts
217
+ */
218
+ async function listScripts(params = {}) {
219
+ return request("GET", "/scripts", null, params);
220
+ }
221
+
222
+ /**
223
+ * Get a single script
224
+ */
225
+ async function getScript(id) {
226
+ return request("GET", `/scripts/${id}`);
227
+ }
228
+
229
+ /**
230
+ * Push (create/update) a script
231
+ */
232
+ async function pushScript(payload) {
233
+ return request("POST", "/scripts/push", payload);
234
+ }
235
+
236
+ /**
237
+ * Deprecate a script
238
+ */
239
+ async function deprecateScript(id) {
240
+ return request("POST", `/scripts/${id}/deprecate`);
241
+ }
242
+
243
+ // ============================================================================
244
+ // Script Event API
245
+ // ============================================================================
246
+
247
+ /**
248
+ * List script events
249
+ */
250
+ async function listScriptEvents(params = {}) {
251
+ return request("GET", "/script-events", null, params);
252
+ }
253
+
254
+ /**
255
+ * Get a single script event
256
+ */
257
+ async function getScriptEvent(id) {
258
+ return request("GET", `/script-events/${id}`);
259
+ }
260
+
261
+ /**
262
+ * Create a script event
263
+ */
264
+ async function createScriptEvent(payload) {
265
+ return request("POST", "/script-events", payload);
266
+ }
267
+
268
+ /**
269
+ * Update a script event
270
+ */
271
+ async function updateScriptEvent(id, payload) {
272
+ return request("PUT", `/script-events/${id}`, payload);
273
+ }
274
+
275
+ /**
276
+ * Delete a script event
277
+ */
278
+ async function deleteScriptEvent(id) {
279
+ return request("DELETE", `/script-events/${id}`);
280
+ }
281
+
282
+ /**
283
+ * Pause a script event
284
+ */
285
+ async function pauseScriptEvent(id) {
286
+ return request("POST", `/script-events/${id}/pause`);
287
+ }
288
+
289
+ /**
290
+ * Resume a script event
291
+ */
292
+ async function resumeScriptEvent(id) {
293
+ return request("POST", `/script-events/${id}/resume`);
294
+ }
295
+
211
296
  module.exports = {
212
297
  whoami,
213
298
  createTask,
@@ -226,4 +311,15 @@ module.exports = {
226
311
  createProject,
227
312
  updateProject,
228
313
  deleteProject,
314
+ listScripts,
315
+ getScript,
316
+ pushScript,
317
+ deprecateScript,
318
+ listScriptEvents,
319
+ getScriptEvent,
320
+ createScriptEvent,
321
+ updateScriptEvent,
322
+ deleteScriptEvent,
323
+ pauseScriptEvent,
324
+ resumeScriptEvent,
229
325
  };
package/src/index.js CHANGED
@@ -714,6 +714,267 @@ program
714
714
  }
715
715
  });
716
716
 
717
+ // ============================================================================
718
+ // Script Commands
719
+ // ============================================================================
720
+
721
+ const scriptCmd = program.command("script").description("Manage scripts");
722
+
723
+ scriptCmd
724
+ .command("push <file>")
725
+ .description("Push a script from a local file")
726
+ .option("-n, --name <name>", "Script name (defaults to filename)")
727
+ .option("--trigger <trigger>", "Trigger type: onCreate, onUpdate, onTag, schedule", "schedule")
728
+ .option("-j, --json", "Output as JSON")
729
+ .action(async (file, options) => {
730
+ try {
731
+ const fs = require("fs");
732
+ const path = require("path");
733
+
734
+ if (!fs.existsSync(file)) {
735
+ console.error(chalk.red(`Error: File not found: ${file}`));
736
+ process.exit(1);
737
+ }
738
+
739
+ const code = fs.readFileSync(file, "utf-8");
740
+ const name = options.name || path.basename(file, path.extname(file));
741
+
742
+ // Extract metadata from header comments
743
+ const metadata = {};
744
+ const metaRegex = /\/\/\s*@(\w+)\s+(.*)/g;
745
+ let match;
746
+ while ((match = metaRegex.exec(code)) !== null) {
747
+ metadata[match[1]] = match[2].trim();
748
+ }
749
+
750
+ const payload = {
751
+ name,
752
+ code,
753
+ trigger: metadata.trigger || options.trigger,
754
+ };
755
+
756
+ const data = await api.pushScript(payload);
757
+
758
+ if (options.json) {
759
+ console.log(JSON.stringify(data, null, 2));
760
+ } else {
761
+ console.log(chalk.green("Script pushed:"));
762
+ console.log(` ID: ${data.script?.id || data.id}`);
763
+ console.log(` Name: ${name}`);
764
+ console.log(` Version: ${data.script?.version || data.version || 1}`);
765
+ }
766
+
767
+ // Auto-create schedule if metadata includes startDateTime
768
+ if (metadata.startDateTime) {
769
+ const eventPayload = {
770
+ ScriptId: data.script?.id || data.id,
771
+ title: metadata.title || name,
772
+ startDateTime: metadata.startDateTime,
773
+ timezone: metadata.tz || metadata.timezone || "UTC",
774
+ };
775
+ if (metadata.rrule) eventPayload.rrule = metadata.rrule;
776
+ if (metadata.endDateTime) eventPayload.endDateTime = metadata.endDateTime;
777
+
778
+ const eventData = await api.createScriptEvent(eventPayload);
779
+ console.log(chalk.green("\nSchedule created:"));
780
+ console.log(` Event ID: ${eventData.scriptEvent?.id || eventData.id}`);
781
+ console.log(` Starts: ${eventPayload.startDateTime}`);
782
+ if (eventPayload.rrule) {
783
+ console.log(` Recurs: ${eventPayload.rrule}`);
784
+ }
785
+ }
786
+ } catch (error) {
787
+ console.error(chalk.red(`Error: ${error.message}`));
788
+ if (error.details) {
789
+ error.details.forEach((d) => console.error(chalk.red(` - ${d}`)));
790
+ }
791
+ process.exit(1);
792
+ }
793
+ });
794
+
795
+ scriptCmd
796
+ .command("list")
797
+ .description("List your scripts")
798
+ .option("-j, --json", "Output as JSON")
799
+ .action(async (options) => {
800
+ try {
801
+ const data = await api.listScripts();
802
+ const scripts = data.scripts || data;
803
+
804
+ if (options.json) {
805
+ console.log(JSON.stringify(data, null, 2));
806
+ } else {
807
+ console.log(chalk.bold("\nScripts:\n"));
808
+ if (!scripts.length) {
809
+ console.log(" No scripts found.");
810
+ } else {
811
+ for (const script of scripts) {
812
+ const statusColor = script.status === "active" ? chalk.green : chalk.gray;
813
+ console.log(` ${statusColor(script.status)} ${script.name} (v${script.version || 1})`);
814
+ console.log(chalk.gray(` ID: ${script.id} Trigger: ${script.trigger}`));
815
+ }
816
+ }
817
+ console.log("");
818
+ }
819
+ } catch (error) {
820
+ console.error(chalk.red(`Error: ${error.message}`));
821
+ process.exit(1);
822
+ }
823
+ });
824
+
825
+ scriptCmd
826
+ .command("delete <id>")
827
+ .description("Deprecate a script (soft delete)")
828
+ .option("-j, --json", "Output as JSON")
829
+ .action(async (id, options) => {
830
+ try {
831
+ const data = await api.deprecateScript(id);
832
+
833
+ if (options.json) {
834
+ console.log(JSON.stringify(data, null, 2));
835
+ } else {
836
+ console.log(chalk.green(`Script deprecated: ${id}`));
837
+ }
838
+ } catch (error) {
839
+ console.error(chalk.red(`Error: ${error.message}`));
840
+ process.exit(1);
841
+ }
842
+ });
843
+
844
+ scriptCmd
845
+ .command("schedule <script-id>")
846
+ .description("Schedule a script as a calendar event")
847
+ .requiredOption("--start <datetime>", "Start date/time (ISO 8601)")
848
+ .option("--end <datetime>", "End date/time (ISO 8601)")
849
+ .option("--rrule <rrule>", "Recurrence rule (RFC 5545 RRULE)")
850
+ .option("--tz <timezone>", "Timezone (e.g., America/New_York)", "UTC")
851
+ .option("-t, --title <title>", "Event title")
852
+ .option("-j, --json", "Output as JSON")
853
+ .action(async (scriptId, options) => {
854
+ try {
855
+ const payload = {
856
+ ScriptId: scriptId,
857
+ title: options.title || `Script ${scriptId}`,
858
+ startDateTime: options.start,
859
+ timezone: options.tz,
860
+ };
861
+ if (options.end) payload.endDateTime = options.end;
862
+ if (options.rrule) payload.rrule = options.rrule;
863
+
864
+ const data = await api.createScriptEvent(payload);
865
+ const event = data.scriptEvent || data;
866
+
867
+ if (options.json) {
868
+ console.log(JSON.stringify(data, null, 2));
869
+ } else {
870
+ console.log(chalk.green("Script scheduled:"));
871
+ console.log(` Event ID: ${event.id}`);
872
+ console.log(` Title: ${event.title}`);
873
+ console.log(` Starts: ${event.startDateTime}`);
874
+ console.log(` Timezone: ${event.timezone}`);
875
+ if (event.rrule) {
876
+ console.log(` Recurs: ${event.rrule}`);
877
+ }
878
+ if (event.nextRunAt) {
879
+ console.log(` Next run: ${event.nextRunAt}`);
880
+ }
881
+ }
882
+ } catch (error) {
883
+ console.error(chalk.red(`Error: ${error.message}`));
884
+ if (error.details) {
885
+ error.details.forEach((d) => console.error(chalk.red(` - ${d}`)));
886
+ }
887
+ process.exit(1);
888
+ }
889
+ });
890
+
891
+ scriptCmd
892
+ .command("events")
893
+ .description("List scheduled script events")
894
+ .option("--start <date>", "Filter by start date (ISO 8601)")
895
+ .option("--end <date>", "Filter by end date (ISO 8601)")
896
+ .option("-j, --json", "Output as JSON")
897
+ .action(async (options) => {
898
+ try {
899
+ const params = {};
900
+ if (options.start) params.start = options.start;
901
+ if (options.end) params.end = options.end;
902
+
903
+ const data = await api.listScriptEvents(params);
904
+ const events = data.scriptEvents || data;
905
+
906
+ if (options.json) {
907
+ console.log(JSON.stringify(data, null, 2));
908
+ } else {
909
+ console.log(chalk.bold("\nScheduled Script Events:\n"));
910
+ if (!events.length) {
911
+ console.log(" No scheduled events found.");
912
+ } else {
913
+ for (const event of events) {
914
+ const statusColor =
915
+ event.status === "active" ? chalk.green :
916
+ event.status === "paused" ? chalk.yellow :
917
+ chalk.gray;
918
+ console.log(` ${statusColor(event.status)} ${event.title}`);
919
+ console.log(chalk.gray(` ID: ${event.id}`));
920
+ console.log(chalk.gray(` Start: ${event.startDateTime} TZ: ${event.timezone}`));
921
+ if (event.rrule) {
922
+ console.log(chalk.gray(` Recurs: ${event.rrule}`));
923
+ }
924
+ if (event.nextRunAt) {
925
+ console.log(chalk.gray(` Next run: ${event.nextRunAt}`));
926
+ }
927
+ if (event.Script) {
928
+ console.log(chalk.gray(` Script: ${event.Script.name} (${event.Script.id})`));
929
+ }
930
+ }
931
+ }
932
+ console.log("");
933
+ }
934
+ } catch (error) {
935
+ console.error(chalk.red(`Error: ${error.message}`));
936
+ process.exit(1);
937
+ }
938
+ });
939
+
940
+ scriptCmd
941
+ .command("pause <event-id>")
942
+ .description("Pause a scheduled script event")
943
+ .option("-j, --json", "Output as JSON")
944
+ .action(async (eventId, options) => {
945
+ try {
946
+ const data = await api.pauseScriptEvent(eventId);
947
+
948
+ if (options.json) {
949
+ console.log(JSON.stringify(data, null, 2));
950
+ } else {
951
+ console.log(chalk.green(`Script event paused: ${eventId}`));
952
+ }
953
+ } catch (error) {
954
+ console.error(chalk.red(`Error: ${error.message}`));
955
+ process.exit(1);
956
+ }
957
+ });
958
+
959
+ scriptCmd
960
+ .command("resume <event-id>")
961
+ .description("Resume a paused script event")
962
+ .option("-j, --json", "Output as JSON")
963
+ .action(async (eventId, options) => {
964
+ try {
965
+ const data = await api.resumeScriptEvent(eventId);
966
+
967
+ if (options.json) {
968
+ console.log(JSON.stringify(data, null, 2));
969
+ } else {
970
+ console.log(chalk.green(`Script event resumed: ${eventId}`));
971
+ }
972
+ } catch (error) {
973
+ console.error(chalk.red(`Error: ${error.message}`));
974
+ process.exit(1);
975
+ }
976
+ });
977
+
717
978
  // ============================================================================
718
979
  // Config Commands
719
980
  // ============================================================================