@zaclinley/dsh-mailharbor 0.24.0 → 0.25.0

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/lib/index.js CHANGED
@@ -2542,6 +2542,16 @@ var TASK_SYSTEM = `\u4F60\u662F\u4EFB\u52A1\u63D0\u53D6\u52A9\u624B\u3002\u4ECE\
2542
2542
  - \u622A\u6B62\u65F6\u95F4\u80FD\u786E\u5B9A\u624D\u586B\uFF0C\u5426\u5219\u7559\u7A7A
2543
2543
  - \u6CA1\u6709\u53EF\u6267\u884C\u4E8B\u9879\u65F6\u8F93\u51FA []
2544
2544
  - \u4E0D\u8981\u7F16\u9020\u90AE\u4EF6\u91CC\u6CA1\u6709\u7684\u4FE1\u606F`;
2545
+ var PROJECT_TASK_SYSTEM = `\u4F60\u662F\u9879\u76EE\u4EFB\u52A1\u62C6\u89E3\u52A9\u624B\u3002\u6839\u636E\u9879\u76EE\u8BB0\u5F55\u3001\u672A\u5B8C\u6210\u4EFB\u52A1\u548C\u90AE\u4EF6\u6458\u8981\uFF0C\u63D0\u51FA\u9700\u8981\u7528\u6237\u8DDF\u8FDB\u7684\u5177\u4F53\u4E8B\u9879\u3002
2546
+
2547
+ \u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u6570\u7EC4\uFF0C\u4E0D\u8981\u8F93\u51FA\u89E3\u91CA\u3001Markdown \u6216\u4EE3\u7801\u5757\u6807\u8BB0\u3002\u6BCF\u4E2A\u5143\u7D20\uFF1A
2548
+ {"title": "\u4EFB\u52A1\u6807\u9898\uFF08\u52A8\u8BCD\u5F00\u5934\uFF0C\u5C3D\u91CF\u5177\u4F53\uFF09", "due": "YYYY-MM-DD \u6216\u7A7A\u5B57\u7B26\u4E32", "priority": 0 \u5230 9 \u7684\u6574\u6570, "owner": "\u76F8\u5173\u8054\u7CFB\u4EBA\u6216\u7A7A\u5B57\u7B26\u4E32", "notes": "\u4E00\u53E5\u4F9D\u636E"}
2549
+
2550
+ \u89C4\u5219\uFF1A
2551
+ - \u53EA\u63D0\u51FA\u6750\u6599\u91CC\u660E\u786E\u8981\u6C42\u3001\u6216\u660E\u663E\u9700\u8981\u8DDF\u8FDB\u7684\u4E8B\u9879
2552
+ - \u4E0D\u8981\u91CD\u590D\u5DF2\u7ECF\u5B58\u5728\u7684\u4EFB\u52A1
2553
+ - \u622A\u6B62\u65F6\u95F4\u4E0D\u786E\u5B9A\u5C31\u7559\u7A7A
2554
+ - \u6CA1\u6709\u53EF\u6267\u884C\u4E8B\u9879\u65F6\u8F93\u51FA []`;
2545
2555
  var STYLE_SYSTEM = `\u4F60\u662F\u5199\u4F5C\u98CE\u683C\u5206\u6790\u5E08\u3002\u9605\u8BFB\u7528\u6237\u6700\u8FD1\u53D1\u51FA\u7684\u90AE\u4EF6\uFF0C\u7528\u7B80\u4F53\u4E2D\u6587\u5199\u4E00\u6BB5 150-300 \u5B57\u7684\u5199\u4F5C\u98CE\u683C\u6863\u6848\uFF0C\u8986\u76D6\uFF1A
2546
2556
  \u5E38\u7528\u79F0\u547C\u3001\u5F00\u5934\u65B9\u5F0F\u3001\u7ED3\u5C3E\u4E0E\u7F72\u540D\u3001\u8BED\u6C14\uFF08\u6B63\u5F0F/\u4EB2\u5207/\u76F4\u63A5\uFF09\u3001\u53E5\u5B50\u957F\u77ED\u3001\u5E38\u7528\u8868\u8FBE\u6216\u53E3\u5934\u7985\u3002
2547
2557
  \u53EA\u8F93\u51FA\u6863\u6848\u6B63\u6587\uFF0C\u4E0D\u8981\u8F93\u51FA\u6807\u9898\u3001\u5217\u8868\u7B26\u53F7\u6216\u5206\u6790\u8FC7\u7A0B\u3002`;
@@ -2752,6 +2762,11 @@ ${clip(item, 4e3)}`).join("\n\n");
2752
2762
  const text2 = await this.complete(TASK_SYSTEM, contextOf(message), signal);
2753
2763
  return parseTaskJson(text2);
2754
2764
  }
2765
+ /** Propose tasks for a project from its notes, open tasks and mail summary. */
2766
+ async proposeProjectTasks(context, signal) {
2767
+ const text2 = await this.complete(PROJECT_TASK_SYSTEM, clip(context, 3e4), signal);
2768
+ return parseTaskJson(text2);
2769
+ }
2755
2770
  /** Compose-body assistance: draft from points, polish, or shorten. */
2756
2771
  async compose(account, options, signal) {
2757
2772
  const style = this.style(account)?.profile ?? "";
@@ -3228,7 +3243,7 @@ ${conversation.trim()}
3228
3243
  }
3229
3244
 
3230
3245
  // src/host/version.ts
3231
- var VERSION = "0.24.0";
3246
+ var VERSION = "0.25.0";
3232
3247
 
3233
3248
  // src/host/api.ts
3234
3249
  init_smtp();
@@ -4101,6 +4116,32 @@ function buildRouter(runtime) {
4101
4116
  throw aiHttpError(error);
4102
4117
  }
4103
4118
  });
4119
+ router.post("/ai/propose/tasks", async ({ body }) => {
4120
+ const payload = await body();
4121
+ const account = accountFromPayload(runtime, payload);
4122
+ const projectId = typeof payload.projectId === "string" ? payload.projectId : "";
4123
+ const project = projectId === "" ? void 0 : runtime.projects().get(projectId);
4124
+ if (projectId !== "" && project === void 0) throw new HttpError(404, "\u9879\u76EE\u4E0D\u5B58\u5728");
4125
+ const notes = Array.isArray(payload.noteIds) ? payload.noteIds.map((id) => project?.notes.find((note) => note.id === id)).filter((note) => note !== void 0) : project?.notes.slice(0, 30) ?? [];
4126
+ const text2 = typeof payload.text === "string" ? payload.text : "";
4127
+ if (notes.length === 0 && text2.trim() === "") throw new HttpError(400, "\u6CA1\u6709\u53EF\u5206\u6790\u7684\u8BB0\u5F55");
4128
+ const tasks = project === void 0 ? [] : runtime.tasks().list({ accountId: account.id, projectId: project.id });
4129
+ const context = [
4130
+ project === void 0 ? "" : `\u9879\u76EE\uFF1A${project.name}\uFF08${project.status}\uFF09`,
4131
+ notes.length === 0 ? "" : `\u9879\u76EE\u8BB0\u5F55\uFF1A
4132
+ ${notes.map((note) => `- ${note.createdAt.slice(0, 10)} ${note.body}`).join("\n")}`,
4133
+ tasks.length === 0 ? "" : `\u5DF2\u6709\u4EFB\u52A1\uFF1A
4134
+ ${tasks.map((task) => `- ${task.title}`).join("\n")}`,
4135
+ text2.trim() === "" ? "" : `\u8865\u5145\u5185\u5BB9\uFF1A
4136
+ ${text2}`
4137
+ ].filter((line2) => line2 !== "").join("\n\n");
4138
+ try {
4139
+ const suggestions = await runtime.ai().proposeProjectTasks(context);
4140
+ return { suggestions };
4141
+ } catch (error) {
4142
+ throw aiHttpError(error);
4143
+ }
4144
+ });
4104
4145
  router.post("/projects/:id/attachment", async ({ params, body }) => {
4105
4146
  const payload = await body();
4106
4147
  const account = accountFromPayload(runtime, payload);
@@ -4262,6 +4303,37 @@ function buildRouter(runtime) {
4262
4303
  runtime.projects().addActivity(project.id, `\u5220\u9664\u91CC\u7A0B\u7891\u300C${milestone?.title ?? ""}\u300D`);
4263
4304
  return { project: projectView(runtime.projects().get(project.id) ?? updated) };
4264
4305
  });
4306
+ router.post("/projects/:id/session", async ({ params, body }) => {
4307
+ const payload = await body();
4308
+ const project = runtime.projects().get(String(params.id ?? ""));
4309
+ if (project === void 0) throw new HttpError(404, "\u9879\u76EE\u4E0D\u5B58\u5728");
4310
+ if (runtime.sessions === void 0) throw new HttpError(400, "\u5F53\u524D DSH \u7EC4\u5408\u6CA1\u6709\u4F1A\u8BDD\u670D\u52A1");
4311
+ const purpose = typeof payload.purpose === "string" ? payload.purpose : "";
4312
+ const sessionId = randomUUID3();
4313
+ const session = runtime.sessions.create(sessionId, { meta: { cwd: project.path } });
4314
+ const notes = project.notes.slice(0, 20).map((note) => `- ${note.createdAt.slice(0, 10)} ${note.body}`).join("\n");
4315
+ const accountId = project.accountIds[0];
4316
+ const tasks = accountId === void 0 ? [] : runtime.tasks().list({ accountId, projectId: project.id }).filter((task) => task.status !== "COMPLETED" && task.status !== "CANCELLED").map(
4317
+ (task) => `- [${task.status}] ${task.title}${task.waitingOn === "" ? "" : `\uFF08\u7B49\u5F85\uFF1A${task.waitingOn}\uFF09`}`
4318
+ ).join("\n");
4319
+ const context = [
4320
+ `\u9879\u76EE\uFF1A${project.name}\uFF08${project.status}\uFF09`,
4321
+ purpose === "" ? "" : `\u8FD9\u6B21\u4F1A\u8BDD\u7684\u76EE\u7684\uFF1A${purpose}`,
4322
+ notes === "" ? "" : `\u6700\u8FD1\u8BB0\u5F55\uFF1A
4323
+ ${notes}`,
4324
+ tasks === "" ? "" : `\u672A\u5B8C\u6210\u4EFB\u52A1\uFF1A
4325
+ ${tasks}`,
4326
+ "\u8BF7\u57FA\u4E8E\u4EE5\u4E0A\u4E0A\u4E0B\u6587\u534F\u52A9\u6574\u7406\u8D44\u6599\u6216\u5904\u7406\u6587\u4EF6\uFF1B\u9700\u8981\u521B\u5EFA\u4EFB\u52A1\u65F6\u5148\u7ED9\u51FA\u63D0\u8BAE\uFF0C\u7B49\u6211\u786E\u8BA4\u3002"
4327
+ ].filter((line2) => line2 !== "").join("\n\n");
4328
+ session.append(
4329
+ "user/message",
4330
+ { role: "user", content: [{ type: "text", text: context }], source: { kind: "user" } },
4331
+ { surfaceOp: "append" }
4332
+ );
4333
+ runtime.projects().update(project.id, { sessionIds: [...project.sessionIds, sessionId] });
4334
+ runtime.projects().addActivity(project.id, "\u521B\u5EFA\u9879\u76EE\u4F1A\u8BDD");
4335
+ return { sessionId, project: projectView(runtime.projects().get(project.id) ?? project) };
4336
+ });
4265
4337
  router.post("/projects/:id/notes", async ({ params, body }) => {
4266
4338
  const payload = await body();
4267
4339
  const project = runtime.projects().get(String(params.id ?? ""));