@alook/cli 0.0.12 → 0.0.14

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 CHANGED
@@ -14040,6 +14040,9 @@ var CreateConversationRequestSchema = exports_external.object({
14040
14040
  var CreateMessageRequestSchema = exports_external.object({
14041
14041
  content: exports_external.string().min(1, "content is required")
14042
14042
  });
14043
+ var CreateBufferedMessageRequestSchema = exports_external.object({
14044
+ content: exports_external.string().min(1, "content is required")
14045
+ });
14043
14046
  var EmailAttachmentSchema = exports_external.object({
14044
14047
  key: exports_external.string().min(1),
14045
14048
  filename: exports_external.string().min(1),
@@ -14115,6 +14118,9 @@ var TestEmailConnectionSchema = exports_external.object({
14115
14118
  smtpPassword: exports_external.string().min(1),
14116
14119
  smtpTls: exports_external.number().int().min(0).max(2).default(1)
14117
14120
  });
14121
+ var UpdateMemberRequestSchema = exports_external.object({
14122
+ global_instruction: exports_external.string().max(50000).trim()
14123
+ });
14118
14124
  var CreateWorkspaceRequestSchema = exports_external.object({
14119
14125
  name: exports_external.string().min(1, "name is required"),
14120
14126
  slug: exports_external.string().min(1, "slug is required")
@@ -15547,6 +15553,7 @@ var member = sqliteTable("member", {
15547
15553
  workspaceId: text("workspace_id").notNull().references(() => workspace.id, { onDelete: "cascade" }),
15548
15554
  userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
15549
15555
  role: text("role").notNull().default("member"),
15556
+ globalInstruction: text("global_instruction").notNull().default(""),
15550
15557
  createdAt: text("created_at").notNull().$defaultFn(() => new Date().toISOString())
15551
15558
  }, (t) => [unique("member_workspace_user").on(t.workspaceId, t.userId)]);
15552
15559
  var machine = sqliteTable("machine", {
@@ -15626,8 +15633,11 @@ var message = sqliteTable("message", {
15626
15633
  content: text("content").notNull().default(""),
15627
15634
  taskId: text("task_id"),
15628
15635
  attachmentIds: text("attachment_ids"),
15636
+ status: text("status").notNull().default("active"),
15629
15637
  createdAt: text("created_at").notNull().$defaultFn(() => new Date().toISOString())
15630
- });
15638
+ }, (t) => [
15639
+ index("idx_message_conversation_status").on(t.conversationId, t.status)
15640
+ ]);
15631
15641
  var agentTaskQueue = sqliteTable("agent_task_queue", {
15632
15642
  id: text("id").primaryKey().$defaultFn(() => nanoid3()),
15633
15643
  agentId: text("agent_id").notNull(),
@@ -15649,6 +15659,7 @@ var agentTaskQueue = sqliteTable("agent_task_queue", {
15649
15659
  error: text("error")
15650
15660
  }, (t) => [
15651
15661
  index("idx_task_queue_pending").on(t.agentId, t.status).where(sql`status IN ('queued', 'dispatched')`),
15662
+ index("idx_task_queue_workspace_active").on(t.workspaceId, t.status, t.agentId).where(sql`status IN ('queued', 'dispatched', 'running')`),
15652
15663
  foreignKey({
15653
15664
  columns: [t.agentId, t.workspaceId],
15654
15665
  foreignColumns: [agent.id, agent.workspaceId]
@@ -16745,7 +16756,7 @@ import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, readFileSync
16745
16756
  import { basename, join as join5 } from "path";
16746
16757
  import PostalMime from "postal-mime";
16747
16758
  var VALID_STATUSES = ["unread", "read", "archived"];
16748
- var EMAIL_DIR = "/tmp/alook-emails";
16759
+ var EMAIL_BASE = "/tmp/alook-emails";
16749
16760
  var MIME_BY_EXT = {
16750
16761
  ".pdf": "application/pdf",
16751
16762
  ".png": "image/png",
@@ -16795,13 +16806,14 @@ function resolveClientOpts(command, opts) {
16795
16806
  }
16796
16807
  function emailCommand() {
16797
16808
  const cmd = new Command5("email").description("Manage agent emails");
16798
- cmd.command("pull").description("Download and parse emails to /tmp/alook-emails/").requiredOption("--agent_id <id>", "Agent ID").option("--status <status>", "Filter by status (unread, read, archived)").option("--workspace <id>", "Workspace ID").option("--json", "Output as JSON instead of files").action(async (opts, command) => {
16809
+ cmd.command("pull").description("Download and parse emails to /tmp/alook-emails/{workspaceId}/{agentId}/").requiredOption("--agent_id <id>", "Agent ID").option("--status <status>", "Filter by status (unread, read, archived)").option("--workspace <id>", "Workspace ID").option("--json", "Output as JSON instead of files").action(async (opts, command) => {
16799
16810
  const { serverUrl, token, workspaceId } = resolveClientOpts(command, { workspace: opts.workspace, agentId: opts.agent_id });
16800
16811
  const client = new APIClient(serverUrl, token, workspaceId);
16801
16812
  if (opts.status && !VALID_STATUSES.includes(opts.status)) {
16802
16813
  console.error(`Error: invalid status "${opts.status}", must be one of: ${VALID_STATUSES.join(", ")}`);
16803
16814
  process.exit(1);
16804
16815
  }
16816
+ const emailDir_base = join5(EMAIL_BASE, workspaceId, opts.agent_id);
16805
16817
  try {
16806
16818
  let query = `/api/email?agentId=${opts.agent_id}`;
16807
16819
  if (opts.status)
@@ -16815,10 +16827,10 @@ function emailCommand() {
16815
16827
  printJSON(emails2);
16816
16828
  return;
16817
16829
  }
16818
- mkdirSync5(EMAIL_DIR, { recursive: true });
16830
+ mkdirSync5(emailDir_base, { recursive: true });
16819
16831
  const downloadedPaths = [];
16820
16832
  for (const email3 of emails2) {
16821
- const emailDir = join5(EMAIL_DIR, email3.id);
16833
+ const emailDir = join5(emailDir_base, email3.id);
16822
16834
  mkdirSync5(emailDir, { recursive: true });
16823
16835
  const metadata = {
16824
16836
  id: email3.id,
@@ -16882,7 +16894,7 @@ function emailCommand() {
16882
16894
  }
16883
16895
  }
16884
16896
  }
16885
- console.log(`Downloaded ${emails2.length} email${emails2.length === 1 ? "" : "s"} to ${EMAIL_DIR}/`);
16897
+ console.log(`Downloaded ${emails2.length} email${emails2.length === 1 ? "" : "s"} to ${emailDir_base}/`);
16886
16898
  for (const p of downloadedPaths) {
16887
16899
  console.log(` ${p}`);
16888
16900
  }
@@ -13757,6 +13757,9 @@ var CreateConversationRequestSchema = exports_external.object({
13757
13757
  var CreateMessageRequestSchema = exports_external.object({
13758
13758
  content: exports_external.string().min(1, "content is required")
13759
13759
  });
13760
+ var CreateBufferedMessageRequestSchema = exports_external.object({
13761
+ content: exports_external.string().min(1, "content is required")
13762
+ });
13760
13763
  var EmailAttachmentSchema = exports_external.object({
13761
13764
  key: exports_external.string().min(1),
13762
13765
  filename: exports_external.string().min(1),
@@ -13832,6 +13835,9 @@ var TestEmailConnectionSchema = exports_external.object({
13832
13835
  smtpPassword: exports_external.string().min(1),
13833
13836
  smtpTls: exports_external.number().int().min(0).max(2).default(1)
13834
13837
  });
13838
+ var UpdateMemberRequestSchema = exports_external.object({
13839
+ global_instruction: exports_external.string().max(50000).trim()
13840
+ });
13835
13841
  var CreateWorkspaceRequestSchema = exports_external.object({
13836
13842
  name: exports_external.string().min(1, "name is required"),
13837
13843
  slug: exports_external.string().min(1, "slug is required")
@@ -15264,6 +15270,7 @@ var member = sqliteTable("member", {
15264
15270
  workspaceId: text("workspace_id").notNull().references(() => workspace.id, { onDelete: "cascade" }),
15265
15271
  userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
15266
15272
  role: text("role").notNull().default("member"),
15273
+ globalInstruction: text("global_instruction").notNull().default(""),
15267
15274
  createdAt: text("created_at").notNull().$defaultFn(() => new Date().toISOString())
15268
15275
  }, (t) => [unique("member_workspace_user").on(t.workspaceId, t.userId)]);
15269
15276
  var machine = sqliteTable("machine", {
@@ -15343,8 +15350,11 @@ var message = sqliteTable("message", {
15343
15350
  content: text("content").notNull().default(""),
15344
15351
  taskId: text("task_id"),
15345
15352
  attachmentIds: text("attachment_ids"),
15353
+ status: text("status").notNull().default("active"),
15346
15354
  createdAt: text("created_at").notNull().$defaultFn(() => new Date().toISOString())
15347
- });
15355
+ }, (t) => [
15356
+ index("idx_message_conversation_status").on(t.conversationId, t.status)
15357
+ ]);
15348
15358
  var agentTaskQueue = sqliteTable("agent_task_queue", {
15349
15359
  id: text("id").primaryKey().$defaultFn(() => nanoid3()),
15350
15360
  agentId: text("agent_id").notNull(),
@@ -15366,6 +15376,7 @@ var agentTaskQueue = sqliteTable("agent_task_queue", {
15366
15376
  error: text("error")
15367
15377
  }, (t) => [
15368
15378
  index("idx_task_queue_pending").on(t.agentId, t.status).where(sql`status IN ('queued', 'dispatched')`),
15379
+ index("idx_task_queue_workspace_active").on(t.workspaceId, t.status, t.agentId).where(sql`status IN ('queued', 'dispatched', 'running')`),
15369
15380
  foreignKey({
15370
15381
  columns: [t.agentId, t.workspaceId],
15371
15382
  foreignColumns: [agent.id, agent.workspaceId]
@@ -16589,30 +16600,30 @@ ${task.agent?.userEmail ? `Your owner's email address is '${task.agent.userEmail
16589
16600
 
16590
16601
  ### Emails
16591
16602
  ---
16592
- Run 'npx @alook/cli pull --agent_id ${task.agentId} --status unread' to download unread emails to '/tmp/alook-emails/'.
16593
- Each email is saved to '/tmp/alook-emails/<emailId>/' with:
16603
+ Run 'npx @alook/cli email pull --agent_id ${task.agentId} --workspace ${task.workspaceId} --status unread' to download unread emails to '/tmp/alook-emails/${task.workspaceId}/${task.agentId}/'.
16604
+ Each email is saved to '/tmp/alook-emails/${task.workspaceId}/${task.agentId}/<emailId>/' with:
16594
16605
  - 'metadata.json' — sender, recipient, subject, date, status, message_id, in_reply_to, references
16595
16606
  - 'body.txt' — plain text body
16596
16607
  - 'body.html' — HTML body (if available)
16597
16608
  - 'attachments/' — extracted attachment files (if any)
16598
16609
  ---
16599
16610
  Before starting to process an email, mark it as read:
16600
- - Run 'npx @alook/cli set --agent_id ${task.agentId} --email_id <EMAIL_ID> --status read'
16611
+ - Run 'npx @alook/cli email set --agent_id ${task.agentId} --workspace ${task.workspaceId} --email_id <EMAIL_ID> --status read'
16601
16612
  ---
16602
16613
 
16603
16614
  #### Sending a new email
16604
16615
  Write the HTML body to a file first, then send it. The body is forwarded as-is (HTML).
16605
- - Run 'npx @alook/cli email send --agent_id ${task.agentId} --to <ADDRESS> --subject "<SUBJECT>" --body-file <PATH_TO_HTML>'
16616
+ - Run 'npx @alook/cli email send --agent_id ${task.agentId} --workspace ${task.workspaceId} --to <ADDRESS> --subject "<SUBJECT>" --body-file <PATH_TO_HTML>'
16606
16617
  - To send from a specific mailbox, add '--from <YOUR_EMAIL_ADDRESS>'. Without '--from', the default Alook address is used.
16607
16618
  - Attach files with '--attachment <PATH>' — repeat the flag for multiple attachments. Each file is uploaded before sending.
16608
- - Example: 'npx @alook/cli email send --agent_id ${task.agentId} --to foo@bar.com --subject "Weekly report" --body-file /tmp/body.html --from alice@company.com --attachment /tmp/report.pdf'
16619
+ - Example: 'npx @alook/cli email send --agent_id ${task.agentId} --workspace ${task.workspaceId} --to foo@bar.com --subject "Weekly report" --body-file /tmp/body.html --from alice@company.com --attachment /tmp/report.pdf'
16609
16620
 
16610
16621
  #### Replying to an email
16611
16622
  To reply to an email, add '--in-reply-to <EMAIL_ID>' to the send command. This sets the correct email threading headers so the recipient's email client groups the reply into the same conversation thread.
16612
16623
  - Use 'Re: <original subject>' as the subject.
16613
16624
  - Quote the original email body in your reply (wrap it in a blockquote).
16614
16625
  - The <EMAIL_ID> is the Alook email id from metadata.json (not the message_id header).
16615
- - Example: 'npx @alook/cli email send --agent_id ${task.agentId} --to sender@example.com --subject "Re: Bug report" --body-file /tmp/reply.html --in-reply-to <EMAIL_ID>'
16626
+ - Example: 'npx @alook/cli email send --agent_id ${task.agentId} --workspace ${task.workspaceId} --to sender@example.com --subject "Re: Bug report" --body-file /tmp/reply.html --in-reply-to <EMAIL_ID>'
16616
16627
  ---
16617
16628
  `;
16618
16629
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alook/cli",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Alook CLI — register and run always-on AI coding agents.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/alookai/alook#readme",