@minidoll/agentkit-dsh-plugin 0.1.1 → 0.1.3

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 (2) hide show
  1. package/dist/index.js +42 -63
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -170,46 +170,9 @@ function findProjectRoot(candidates, sessionCwd) {
170
170
  }
171
171
 
172
172
  // src/inject.ts
173
- import { randomUUID } from "node:crypto";
174
173
  import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "node:fs";
175
174
  import { join as join4 } from "node:path";
176
175
  var MAX_CONTEXT_BYTES = 900;
177
- var SOURCE_KIND = "agentkit-context";
178
- var factoryLoader = null;
179
- async function loadFactory() {
180
- factoryLoader ??= (async () => {
181
- try {
182
- const pkg = "@deepseek-ai/dsh-llm";
183
- const mod = await import(pkg);
184
- return typeof mod.createUserMessage === "function" ? mod.createUserMessage : null;
185
- } catch {
186
- return null;
187
- }
188
- })();
189
- return factoryLoader;
190
- }
191
- function handcraft(text) {
192
- return {
193
- role: "user",
194
- id: randomUUID(),
195
- content: [{ type: "text", text }],
196
- source: { kind: SOURCE_KIND }
197
- };
198
- }
199
- function assertUserMessage(value) {
200
- if (typeof value !== "object" || value === null) return false;
201
- const m = value;
202
- if (m.role !== "user") return false;
203
- if (typeof m.id !== "string" || m.id === "") return false;
204
- const src = m.source;
205
- if (src === void 0 || src.kind !== SOURCE_KIND) return false;
206
- const content = m.content;
207
- if (!Array.isArray(content) || content.length === 0) return false;
208
- return content.every((b) => {
209
- const blk = b;
210
- return blk.type === "text" && typeof blk.text === "string" && blk.text.length > 0;
211
- });
212
- }
213
176
  var INJECT_CONFIG_REL = ".agent/inject.json";
214
177
  function injectEnabled(root) {
215
178
  if (process.env.AGENTKIT_CONTEXT_INJECT === "1") return true;
@@ -225,19 +188,35 @@ function injectEnabled(root) {
225
188
  }
226
189
  var injected = /* @__PURE__ */ new Set();
227
190
  var PATH_RULES = [
228
- { pattern: /^contracts\//, hint: "\u5951\u7EA6\u53D8\u66F4\uFF1A\u5B9E\u73B0\u5FC5\u987B\u540C\u6B65\uFF08AGENTS \u94C1\u5F8B\uFF09\uFF0C\u5E76\u5728\u4EA4\u63A5\u5355\u58F0\u660E\u5951\u7EA6\u5F71\u54CD\u4E0E\u8BC1\u636E\u7EA7\u522B L1-L4" },
229
- { pattern: /^docs\/rules\//, hint: "\u89C4\u5219\u6587\u6863\uFF1A\u6539\u5B83\u7B49\u4E8E\u6539\u6240\u6709\u4EBA\u7684\u884C\u4E3A\u7EA6\u675F \u2014\u2014 \u5148\u786E\u8BA4\u4E0E protocol.yml / AGENTS.md \u4E0D\u51B2\u7A81" },
230
- { pattern: /^docs\/design\//, hint: '\u8BBE\u8BA1\u6587\u6863\uFF1A\u9700\u4E0E codemap \u91CC\u7684\u6A21\u5757\u5BF9\u5E94\uFF08M4 \u4F1A\u6821\u9A8C"\u6587\u6863\u63D0\u5230\u8BE5\u6A21\u5757"\uFF09' },
231
- { pattern: /^\.agent\/decisions\/\d{4}-/, hint: "ADR\uFF1Aaccepted \u7684\u6709\u7EA6\u675F\u529B \u2014\u2014 \u8981\u63A8\u7FFB\u5148\u5199\u65B0 ADR \u6807 superseded\uFF0C\u4E0D\u8981\u76F4\u63A5\u6539\u65E7\u7ED3\u8BBA" },
232
- { pattern: /^AGENTS\.md$/, hint: "AGENTS.md \u662F\u6D3E\u751F\u6587\u4EF6\uFF08\u7531 protocol.yml \u751F\u6210\uFF09\u2014\u2014 \u6539\u5B83\u8BF7\u6539 protocol.yml \u518D akit sync" }
191
+ {
192
+ pattern: /^contracts\//,
193
+ hint: "\u5951\u7EA6\u53D8\u66F4\uFF1A\u5B9E\u73B0\u5FC5\u987B\u540C\u6B65\uFF08AGENTS \u94C1\u5F8B\uFF09\uFF0C\u5E76\u5728\u4EA4\u63A5\u5355\u58F0\u660E\u5951\u7EA6\u5F71\u54CD\u4E0E\u8BC1\u636E\u7EA7\u522B L1-L4"
194
+ },
195
+ {
196
+ pattern: /^docs\/rules\//,
197
+ hint: "\u89C4\u5219\u6587\u6863\uFF1A\u6539\u5B83\u7B49\u4E8E\u6539\u6240\u6709\u4EBA\u7684\u884C\u4E3A\u7EA6\u675F \u2014\u2014 \u5148\u786E\u8BA4\u4E0E protocol.yml / AGENTS.md \u4E0D\u51B2\u7A81"
198
+ },
199
+ {
200
+ pattern: /^docs\/design\//,
201
+ hint: '\u8BBE\u8BA1\u6587\u6863\uFF1A\u9700\u4E0E codemap \u91CC\u7684\u6A21\u5757\u5BF9\u5E94\uFF08M4 \u4F1A\u6821\u9A8C"\u6587\u6863\u63D0\u5230\u8BE5\u6A21\u5757"\uFF09'
202
+ },
203
+ {
204
+ pattern: /^\.agent\/decisions\/\d{4}-/,
205
+ hint: "ADR\uFF1Aaccepted \u7684\u6709\u7EA6\u675F\u529B \u2014\u2014 \u8981\u63A8\u7FFB\u5148\u5199\u65B0 ADR \u6807 superseded\uFF0C\u4E0D\u8981\u76F4\u63A5\u6539\u65E7\u7ED3\u8BBA"
206
+ },
207
+ {
208
+ pattern: /^AGENTS\.md$/,
209
+ hint: "AGENTS.md \u662F\u6D3E\u751F\u6587\u4EF6\uFF08\u7531 protocol.yml \u751F\u6210\uFF09\u2014\u2014 \u6539\u5B83\u8BF7\u6539 protocol.yml \u518D akit sync"
210
+ }
233
211
  ];
234
212
  function buildInjectText(input) {
235
213
  const lines = [];
236
214
  const rels = [];
237
215
  if (input.filePath !== void 0 && input.filePath !== "") rels.push(input.filePath);
238
216
  for (const p of input.extraPaths ?? []) if (p !== "") rels.push(p);
217
+ const norm = (p) => String(p).replace(/\\/g, "/").replace(/^\.\//, "");
239
218
  for (const raw of rels) {
240
- const rel = String(raw).replace(/\\/g, "/").replace(/^\.\//, "");
219
+ const rel = norm(raw);
241
220
  for (const rule of PATH_RULES) {
242
221
  if (rule.pattern.test(rel)) {
243
222
  lines.push(`- \u7EAA\u5F8B\uFF1A${rule.hint}`);
@@ -247,12 +226,12 @@ function buildInjectText(input) {
247
226
  if (lines.length > 0) break;
248
227
  }
249
228
  for (const raw of rels) {
250
- const rel = String(raw).replace(/\\/g, "/").replace(/^\.\//, "");
229
+ const rel = norm(raw);
251
230
  try {
252
231
  const cm = join4(input.root, ".agent", "codemap.json");
253
232
  if (!existsSync4(cm)) break;
254
233
  const map = JSON.parse(readFileSync3(cm, "utf8"));
255
- const mod = (map.modules ?? []).find((m) => String(m.path ?? "").replace(/^\.\//, "") === rel);
234
+ const mod = (map.modules ?? []).find((m) => norm(m.path ?? "") === rel);
256
235
  if (mod !== void 0) {
257
236
  if (mod.purpose !== void 0 && mod.purpose !== "") lines.push(`- \u6A21\u5757\u804C\u8D23\uFF08codemap\uFF09\uFF1A${mod.purpose}`);
258
237
  if (mod.doc !== void 0 && mod.doc !== "") lines.push(`- \u8BBE\u8BA1\u6587\u6863\uFF1A${mod.doc}`);
@@ -287,16 +266,16 @@ function buildInjectText(input) {
287
266
  \u2026\uFF08\u5DF2\u622A\u65AD\uFF09`;
288
267
  return text;
289
268
  }
290
- async function buildAdditionalContexts(input) {
269
+ async function buildInjectBlock(input) {
291
270
  try {
292
271
  if (!injectEnabled(input.root)) {
293
272
  input.trace?.("inject skipped: disabled (no .agent/inject.json / env)");
294
- return { ok: false, reason: "inject disabled (no .agent/inject.json / env)" };
273
+ return { ok: false, reason: "inject disabled" };
295
274
  }
296
275
  const key = `${input.sessionId ?? ""}|${input.filePath ?? ""}`;
297
276
  if (injected.has(key)) {
298
277
  input.trace?.("inject skipped: already injected for this session+file");
299
- return { ok: false, reason: "already injected for this session+file" };
278
+ return { ok: false, reason: "already injected" };
300
279
  }
301
280
  const text = buildInjectText({
302
281
  root: input.root,
@@ -305,19 +284,16 @@ async function buildAdditionalContexts(input) {
305
284
  });
306
285
  if (text === null) {
307
286
  input.trace?.("inject skipped: nothing to inject for this path");
308
- return { ok: false, reason: "nothing to inject for this path" };
287
+ return { ok: false, reason: "nothing to inject" };
309
288
  }
310
- const factory = await loadFactory();
311
- const msg = factory !== null ? factory({ content: [{ type: "text", text }], source: { kind: SOURCE_KIND } }) : handcraft(text);
312
- if (!assertUserMessage(msg)) {
313
- input.trace?.(`inject rejected: shape check failed (${factory !== null ? "factory" : "handcraft"})`);
314
- return { ok: false, reason: "shape check failed" };
289
+ const block = { type: "text", text };
290
+ if (block.type !== "text" || typeof block.text !== "string" || block.text.length === 0) {
291
+ input.trace?.("inject rejected: bad text block");
292
+ return { ok: false, reason: "bad text block" };
315
293
  }
316
294
  injected.add(key);
317
- input.trace?.(
318
- `inject ok: ${String(text.length)}B via ${factory !== null ? "factory" : "handcraft"}`
319
- );
320
- return { ok: true, messages: [msg] };
295
+ input.trace?.(`inject ok: ${String(text.length)}B as tool-result content block`);
296
+ return { ok: true, block };
321
297
  } catch (err) {
322
298
  input.trace?.(`inject skipped: ${err.message}`);
323
299
  return { ok: false, reason: err.message };
@@ -508,13 +484,13 @@ function createProjectHooksPlugin(ctx) {
508
484
  });
509
485
  const filePath = inside[0];
510
486
  const sessionId = exec.agent?.session?.id ?? null;
511
- const r = await buildAdditionalContexts({
487
+ const r = await buildInjectBlock({
512
488
  root,
513
489
  ...filePath !== void 0 ? { filePath } : {},
514
490
  ...sessionId !== null ? { sessionId } : {},
515
491
  trace: (line) => trace(process.env.DSH_HOME ?? join6(homedir(), ".dsh"), line)
516
492
  });
517
- return r.ok && r.messages !== void 0 ? r.messages : null;
493
+ return r.ok ? r : null;
518
494
  } catch (err) {
519
495
  trace(
520
496
  process.env.DSH_HOME ?? join6(homedir(), ".dsh"),
@@ -523,12 +499,15 @@ function createProjectHooksPlugin(ctx) {
523
499
  return null;
524
500
  }
525
501
  };
526
- const handle = async (event, exec) => {
502
+ const handle = async (event, exec, result) => {
527
503
  try {
528
504
  const decision = await runHooks(event, exec);
529
505
  if (event === "PostToolUse" && decision.kind === "allow") {
530
506
  const injected2 = await tryInjectContext(exec);
531
- if (injected2 !== null) return { kind: "accept", additionalContexts: injected2 };
507
+ if (injected2 !== null && injected2.block !== void 0) {
508
+ const original = Array.isArray(result?.content) ? result.content.filter((b) => typeof b === "object" && b !== null) : [];
509
+ return { kind: "accept", content: [...original, injected2.block] };
510
+ }
532
511
  }
533
512
  return decision;
534
513
  } catch (err) {
@@ -654,7 +633,7 @@ function createProjectHooksPlugin(ctx) {
654
633
  return decision;
655
634
  };
656
635
  ctx.on("tools/pre-execute", (exec) => handle("PreToolUse", exec));
657
- ctx.on("tools/post-execute", (exec) => handle("PostToolUse", exec));
636
+ ctx.on("tools/post-execute", (exec, result) => handle("PostToolUse", exec, result));
658
637
  return state;
659
638
  }
660
639
  function apply(ctx) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minidoll/agentkit-dsh-plugin",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "DeepSeek Harness 插件:项目自包含的 lifecycle hooks(配置随仓库走,per-session 发现)",
5
5
  "license": "MIT",
6
6
  "type": "module",