@gyoungwe/research-suite 0.1.2 → 0.1.5

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/README.md CHANGED
@@ -5,4 +5,6 @@ The suite aggregates the published `@gyoungwe/pi-core`,
5
5
  tarball bundles those dependencies so a Pi host can discover the extensions and
6
6
  skills without a second network resolution step. `research-workflow` comes
7
7
  from `@gyoungwe/pi-research`; `@gyoungwe/pi-knowledge` supplies the Vault and
8
- Show Me skills, so the suite exposes one copy of each skill.
8
+ Show Me skills, so the suite exposes one copy of each skill. `pi-core` also
9
+ provides the stable `/drone-doctor` and `/drone-example` onboarding commands;
10
+ the latter is read-only unless the user explicitly supplies `--run <question>`.
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "version": 1,
3
3
  "generator": "packages/research-suite/scripts/build.mjs",
4
- "packageVersion": "0.1.2",
4
+ "packageVersion": "0.1.5",
5
5
  "bundled": [
6
6
  "@gyoungwe/pi-core",
7
7
  "@gyoungwe/pi-knowledge",
8
8
  "@gyoungwe/pi-research"
9
9
  ],
10
- "dependenciesSha256": "226c3c4a28a71df1f571ff6a977d3798d9ccc0914297292772a636f45abf5716"
10
+ "dependenciesSha256": "ee57d5411edbbd02065e3d91ce5ac3d528c0faa77f81111aabd16c4062a1a6ca"
11
11
  }
@@ -3,6 +3,13 @@
3
3
  Portable Pi extension for Drone's task ledger and user-facing core tools:
4
4
  `ask_user`, `set_status`, `todo`, `deliver_files`, and `memory_save`.
5
5
 
6
+ It also exposes `/drone-doctor` (a stable JSON host/package diagnostic) and
7
+ `/drone-example` (a read-only example preview). The example accepts
8
+ `knowledge`, `research`, `analysis`, or `evidence` profiles, with `research`
9
+ as the default; add `--run <question>` only when an explicit read-only run is
10
+ wanted. Reports distinguish `unconfigured`, `needs-data`, `blocked`, `ready`,
11
+ and `started`, and never claim a scientific result without source receipts.
12
+
6
13
  The package also registers the `@drone/tasks` runtime. Native Pi uses the
7
14
  extension context's `ctx.ui`; Drone Desktop can inject its existing ask gate
8
15
  through `registerPiCore(pi, { ask })`. The package has no Electron, backend, or
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": 1,
3
3
  "generator": "scripts/build-pi-core.mjs",
4
- "inputsSha256": "0a7a9931d9c82a304460a498ea8611a741c5eb9cd74c865831058f357f031f73",
4
+ "inputsSha256": "de6fabddabb2c24748d325d3484d0c76bfde8ede915da8225d7f4d47927f282c",
5
5
  "outputs": {
6
- "dist/index.mjs": "34036b70dd1f62e9ec23d3f4f6c9f2ba1a0e085cac6975860bbb587f91ec3a84"
6
+ "dist/index.mjs": "6c3bdc2006cf6e329f10492c943a32fb50f1ddc8d32175fbcd99605df5fde1bb"
7
7
  }
8
8
  }
@@ -101,7 +101,8 @@ function createStandaloneRuntime(log = {}) {
101
101
  return runtime;
102
102
  }
103
103
  function currentRuntime() {
104
- if (contexts.getStore()) return contexts.getStore();
104
+ const scoped = contexts.getStore();
105
+ if (scoped) return scoped;
105
106
  if (installedRuntime) return installedRuntime;
106
107
  if (!standaloneRuntime) standaloneRuntime = createStandaloneRuntime();
107
108
  return standaloneRuntime;
@@ -144,10 +145,7 @@ function runtimeSlot(domain, slot, create) {
144
145
  }
145
146
  }
146
147
  );
147
- return (
148
- /** @type {T} */
149
- proxy
150
- );
148
+ return proxy;
151
149
  }
152
150
 
153
151
  // ../tasks/src/runtime-compiled/acceptance.mjs
@@ -2030,7 +2028,7 @@ function registerWorkbench(pi, options = {}) {
2030
2028
  };
2031
2029
  const journal = createTaskWorkbench({
2032
2030
  requireAuthorization: true,
2033
- persist: (snapshot) => pi.appendEntry(WORKBENCH_ENTRY, snapshot),
2031
+ persist: (snapshot2) => pi.appendEntry(WORKBENCH_ENTRY, snapshot2),
2034
2032
  onCheckpoint: () => send(),
2035
2033
  // 里程碑验收器(zotero_item / wiki_review / …)由各自的扩展 registerAcceptanceVerifier 登记(挂钩 2)
2036
2034
  inspect
@@ -2309,12 +2307,12 @@ ${hostLanguage() === "zh" ? "\uFF08\u4EE5\u4E0B\u4E3A\u5BBF\u4E3B\u7EA6\u675F\uF
2309
2307
  continueAuthorized(turnContext);
2310
2308
  return;
2311
2309
  }
2312
- const snapshot = journal.snapshot();
2313
- if (last?.stopReason !== "error" && !ctx?.signal?.aborted && shouldAskToContinue(snapshot ? journal.view().tasks.find((t) => t.id === snapshot.id) : null)) {
2310
+ const snapshot2 = journal.snapshot();
2311
+ if (last?.stopReason !== "error" && !ctx?.signal?.aborted && shouldAskToContinue(snapshot2 ? journal.view().tasks.find((t) => t.id === snapshot2.id) : null)) {
2314
2312
  send();
2315
2313
  try {
2316
2314
  if (activeSessionId !== turnSessionId || context !== turnContext) return;
2317
- await progressTask({ taskId: snapshot.id, revision: journal.view().revision }, turnContext);
2315
+ await progressTask({ taskId: snapshot2.id, revision: journal.view().revision }, turnContext);
2318
2316
  } catch {
2319
2317
  }
2320
2318
  return;
@@ -2748,7 +2746,7 @@ function createTaskJournal({ persist = () => {
2748
2746
  }
2749
2747
  function registerTaskRuntime(pi, options = {}) {
2750
2748
  if (process.env.DRONE_TASK_WORKBENCH !== "off") return registerWorkbench(pi, options);
2751
- const journal = createTaskJournal({ persist: (snapshot) => pi.appendEntry?.(TASK_ENTRY, snapshot) });
2749
+ const journal = createTaskJournal({ persist: (snapshot2) => pi.appendEntry?.(TASK_ENTRY, snapshot2) });
2752
2750
  const attach = (ctx, force = false) => {
2753
2751
  const id = ctx.sessionManager?.getSessionId?.() || ctx.sessionId || "isolated";
2754
2752
  const scope = createHash4("sha256").update(`${id}\0${resolve5(ctx.cwd)}`).digest("hex");
@@ -2818,6 +2816,228 @@ Use task_status for operational delivery. Verify unknown outcomes before repeati
2818
2816
  return journal;
2819
2817
  }
2820
2818
 
2819
+ // src/drone-commands.ts
2820
+ import { readFileSync } from "node:fs";
2821
+ import { createRequire } from "node:module";
2822
+ import { join } from "node:path";
2823
+ var DRONE_COMMAND_SCHEMA_VERSION = 1;
2824
+ var PI_CORE_PACKAGE_VERSION = "0.1.3";
2825
+ var PI_HOST_RANGE = ">=1.1.0 <2.0.0";
2826
+ var CORE_TOOLS = [
2827
+ "ask_user",
2828
+ "set_status",
2829
+ "todo",
2830
+ "deliver_files",
2831
+ "memory_save",
2832
+ "task_plan",
2833
+ "task_status",
2834
+ "task_wait",
2835
+ "task_reconcile",
2836
+ "task_evidence_restore"
2837
+ ];
2838
+ var EXAMPLE_PROFILES = {
2839
+ knowledge: {
2840
+ title: "Knowledge Vault example",
2841
+ steps: ["check the local Vault", "search local knowledge", "cite the retrieved note paths"],
2842
+ requiredTools: ["knowledge_status", "knowledge_search"],
2843
+ missingToolsNext: "\u5B89\u88C5\u5E76\u542F\u7528 pi-knowledge \u540E\u91CD\u8BD5 /drone-example knowledge",
2844
+ missingDataNext: "\u63D0\u4F9B\u4E00\u4E2A\u77E5\u8BC6\u95EE\u9898\uFF1A/drone-example knowledge --run <\u95EE\u9898>"
2845
+ },
2846
+ research: {
2847
+ title: "Evidence-gated local research example",
2848
+ steps: ["inspect local knowledge", "read at least two sources", "answer with source receipts"],
2849
+ requiredTools: ["research_search_sources", "research_read_source", "research_answer_sources"],
2850
+ missingToolsNext: "\u5B89\u88C5\u5E76\u542F\u7528 pi-research \u540E\u91CD\u8BD5 /drone-example research",
2851
+ missingDataNext: "\u63D0\u4F9B\u4E00\u4E2A\u7814\u7A76\u95EE\u9898\uFF1A/drone-example research --run <\u7814\u7A76\u95EE\u9898>"
2852
+ },
2853
+ analysis: {
2854
+ title: "Analysis readiness example",
2855
+ requiresContainer: true,
2856
+ steps: [
2857
+ "list compatible analysis adapters",
2858
+ "assess input readiness",
2859
+ "report missing data before execution"
2860
+ ],
2861
+ requiredTools: ["analysis_list_adapters", "analysis_assess_readiness"],
2862
+ missingToolsNext: "\u5B89\u88C5\u5E76\u542F\u7528 pi-analysis \u540E\u91CD\u8BD5 /drone-example analysis",
2863
+ missingDataNext: "\u63D0\u4F9B\u8F93\u5165\u4E0E\u5206\u6790\u95EE\u9898\uFF1A/drone-example analysis --run <\u5206\u6790\u95EE\u9898>"
2864
+ },
2865
+ evidence: {
2866
+ title: "Evidence validation example",
2867
+ steps: ["validate an artifact manifest", "validate an evidence capsule", "verify replay metadata"],
2868
+ requiredTools: ["evidence_validate_manifest", "evidence_validate_capsule", "evidence_verify_replay"],
2869
+ missingToolsNext: "\u5B89\u88C5\u5E76\u542F\u7528 pi-evidence \u540E\u91CD\u8BD5 /drone-example evidence",
2870
+ missingDataNext: "\u63D0\u4F9B\u5F85\u6838\u9A8C\u7684\u8BC1\u636E\u5BF9\u8C61\uFF1A/drone-example evidence --run <\u5BF9\u8C61>"
2871
+ }
2872
+ };
2873
+ var EXAMPLE_KINDS = new Set(Object.keys(EXAMPLE_PROFILES));
2874
+ function packageVersion() {
2875
+ const configured = process.env.PI_VERSION?.trim();
2876
+ if (configured) return { version: configured, source: "PI_VERSION" };
2877
+ try {
2878
+ const require2 = createRequire(import.meta.url);
2879
+ for (const base of require2.resolve.paths("@earendil-works/pi-coding-agent") ?? []) {
2880
+ const packagePath = join(base, "@earendil-works/pi-coding-agent", "package.json");
2881
+ try {
2882
+ const metadata = JSON.parse(readFileSync(packagePath, "utf8"));
2883
+ if (typeof metadata.version === "string" && metadata.version.length > 0)
2884
+ return { version: metadata.version, source: "resolved-package" };
2885
+ } catch {
2886
+ }
2887
+ }
2888
+ } catch {
2889
+ }
2890
+ return { version: null, source: "unavailable" };
2891
+ }
2892
+ function snapshot(pi) {
2893
+ const tools = typeof pi?.getAllTools === "function" ? pi.getAllTools().map((tool) => String(tool?.name || "")).filter(Boolean) : typeof pi?.getActiveTools === "function" ? pi.getActiveTools().map((name) => String(name)).filter(Boolean) : [];
2894
+ const commands = typeof pi?.getCommands === "function" ? pi.getCommands().map((command) => String(command?.name || "")).filter(Boolean) : [];
2895
+ return { tools: [...new Set(tools)].sort(), commands: [...new Set(commands)].sort() };
2896
+ }
2897
+ function isSupportedPiHost(version) {
2898
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(version.trim());
2899
+ if (!match) return false;
2900
+ const major = Number(match[1]);
2901
+ const minor = Number(match[2]);
2902
+ const patch = Number(match[3]);
2903
+ return major === 1 && (minor > 1 || minor === 1 && patch >= 0);
2904
+ }
2905
+ function buildDoctorReport(pi, options = {}) {
2906
+ const current = snapshot(pi);
2907
+ const missingTools = CORE_TOOLS.filter((name) => !current.tools.includes(name));
2908
+ const missingCommands = ["drone-doctor", "drone-example"].filter(
2909
+ (name) => !current.commands.includes(name)
2910
+ );
2911
+ const resolved = options.hostVersion === void 0 ? packageVersion() : { version: options.hostVersion, source: "host-contract" };
2912
+ const hostCompatible = resolved.version ? isSupportedPiHost(resolved.version) : null;
2913
+ const hostKind = options.hostKind || "native-pi";
2914
+ const checks = [
2915
+ {
2916
+ id: "core-tools",
2917
+ status: missingTools.length ? "blocked" : "pass",
2918
+ detail: missingTools.length ? "pi-core tools are missing" : "all pi-core tools are registered",
2919
+ ...missingTools.length ? { missing: missingTools } : {}
2920
+ },
2921
+ {
2922
+ id: "drone-commands",
2923
+ status: missingCommands.length ? "blocked" : "pass",
2924
+ detail: missingCommands.length ? "Drone onboarding commands are missing" : "doctor and example commands are registered",
2925
+ ...missingCommands.length ? { missing: missingCommands } : {}
2926
+ },
2927
+ {
2928
+ id: "pi-host-version",
2929
+ status: resolved.version ? hostCompatible ? "pass" : "incompatible" : "unknown",
2930
+ detail: resolved.version ? hostCompatible ? `resolved Pi host ${resolved.version}` : `Pi host ${resolved.version} is outside ${PI_HOST_RANGE}` : "Pi host version is not exposed by this host"
2931
+ }
2932
+ ];
2933
+ const blocked = checks.some((check) => check.status === "blocked");
2934
+ const incompatible = checks.some((check) => check.status === "incompatible");
2935
+ return {
2936
+ schemaVersion: DRONE_COMMAND_SCHEMA_VERSION,
2937
+ command: "drone-doctor",
2938
+ status: blocked ? "blocked" : incompatible ? "incompatible" : resolved.version ? "pass" : "unknown",
2939
+ plugin: { name: "@gyoungwe/pi-core", version: PI_CORE_PACKAGE_VERSION, piRange: PI_HOST_RANGE },
2940
+ host: { kind: hostKind, version: resolved.version || null, source: resolved.source },
2941
+ checks,
2942
+ commands: current.commands,
2943
+ tools: current.tools,
2944
+ next: blocked ? "\u5B89\u88C5\u6216\u91CD\u65B0\u52A0\u8F7D\u7F3A\u5931\u7684 Drone \u63D2\u4EF6\u540E\u91CD\u8BD5 /drone-doctor" : incompatible ? `\u5347\u7EA7 Pi \u5230 ${PI_HOST_RANGE} \u540E\u91CD\u8BD5 /drone-doctor` : null
2945
+ };
2946
+ }
2947
+ function buildExampleReport(pi, mode = "preview", question, options = {}) {
2948
+ const example = options.example ?? "research";
2949
+ const profile = EXAMPLE_PROFILES[example];
2950
+ const current = snapshot(pi);
2951
+ const missingTools = profile.requiredTools.filter((name) => !current.tools.includes(name));
2952
+ const hasQuestion = Boolean(question?.trim());
2953
+ const knowledgeStatus = example === "knowledge" ? options.knowledgeStatus ?? (process.env.DRONE_KNOWLEDGE_DIR?.trim() ? "unknown" : "unconfigured") : void 0;
2954
+ const containerAvailable = options.containerAvailable ?? Boolean(process.env.DRONE_CONTAINER_RUNTIME?.trim());
2955
+ const missingContainer = Boolean(profile.requiresContainer && !containerAvailable);
2956
+ const status2 = missingTools.length ? "blocked" : knowledgeStatus === "unconfigured" ? "unconfigured" : knowledgeStatus === "unknown" ? "needs-data" : missingContainer ? "needs-container" : mode === "run" && hasQuestion ? "started" : hasQuestion ? "ready" : "needs-data";
2957
+ return {
2958
+ schemaVersion: DRONE_COMMAND_SCHEMA_VERSION,
2959
+ command: "drone-example",
2960
+ example,
2961
+ status: status2,
2962
+ mode,
2963
+ title: profile.title,
2964
+ steps: [...profile.steps],
2965
+ requiredTools: [...profile.requiredTools],
2966
+ missingTools: [...missingTools],
2967
+ next: missingTools.length ? profile.missingToolsNext : missingContainer ? "\u767B\u8BB0\u5E76\u542F\u7528\u4E00\u4E2A\u5BB9\u5668\u8FD0\u884C\u65F6\u540E\u91CD\u8BD5 /drone-example analysis" : knowledgeStatus === "unconfigured" ? "\u5148\u8FD0\u884C /drone-init \u7ED1\u5B9A\u672C\u5730 Vault\uFF0C\u518D\u91CD\u8BD5 /drone-example knowledge" : knowledgeStatus === "unknown" ? "\u65E0\u6CD5\u786E\u8BA4\u672C\u5730 Vault \u72B6\u6001\uFF1B\u5148\u8FD0\u884C /drone-init \u6216\u68C0\u67E5\u77E5\u8BC6\u5E93\u63D2\u4EF6\u540E\u91CD\u8BD5" : hasQuestion ? mode === "run" ? `${profile.title} \u5DF2\u6392\u961F\uFF1B\u7B49\u5F85\u771F\u5B9E\u56DE\u6267` : `\u8FD0\u884C /drone-example ${example} --run <\u95EE\u9898> \u5F00\u59CB\u53EA\u8BFB\u793A\u4F8B` : profile.missingDataNext,
2968
+ ...hasQuestion ? { question: question?.trim() } : {}
2969
+ };
2970
+ }
2971
+ function parseExampleArgs(args) {
2972
+ const tokens = args.trim().split(/\s+/).filter(Boolean);
2973
+ let mode = "preview";
2974
+ const remaining = tokens.filter((token) => {
2975
+ if (token === "--run") {
2976
+ mode = "run";
2977
+ return false;
2978
+ }
2979
+ return true;
2980
+ });
2981
+ const candidate = remaining[0]?.toLowerCase();
2982
+ const example = candidate && EXAMPLE_KINDS.has(candidate) ? candidate : "research";
2983
+ if (candidate && EXAMPLE_KINDS.has(candidate)) remaining.shift();
2984
+ const question = remaining.join(" ").trim();
2985
+ return { mode, example, ...question ? { question } : {} };
2986
+ }
2987
+ async function resolveKnowledgeStatus(pi, ctx) {
2988
+ if (!process.env.DRONE_KNOWLEDGE_DIR?.trim()) return "unconfigured";
2989
+ const tool = typeof pi?.getAllTools === "function" ? pi.getAllTools().find((candidate) => candidate?.name === "knowledge_status") : void 0;
2990
+ if (typeof tool?.execute !== "function") return "unknown";
2991
+ try {
2992
+ const result = await tool.execute(
2993
+ "drone-example:knowledge-status",
2994
+ {},
2995
+ new AbortController().signal,
2996
+ () => void 0,
2997
+ ctx
2998
+ );
2999
+ const status2 = result?.details?.status ?? result?.status;
3000
+ if (status2 === "unconfigured") return "unconfigured";
3001
+ if (status2 === "configured") return "configured";
3002
+ } catch {
3003
+ }
3004
+ return "unknown";
3005
+ }
3006
+ function emitReport(report, ctx) {
3007
+ const message = JSON.stringify(report);
3008
+ if (ctx.mode === "print" || ctx.mode === "json") console.log(message);
3009
+ else
3010
+ ctx.ui.notify(
3011
+ message,
3012
+ report.status === "blocked" || report.status === "unconfigured" || report.status === "needs-container" || report.status === "incompatible" ? "warning" : "info"
3013
+ );
3014
+ }
3015
+ function registerDroneCommands(pi, options = {}) {
3016
+ pi.registerCommand("drone-doctor", {
3017
+ description: "Check the resolved Pi host, core tools and Drone command contract",
3018
+ handler: async (_args, ctx) => emitReport(buildDoctorReport(pi, options), ctx)
3019
+ });
3020
+ pi.registerCommand("drone-example", {
3021
+ description: "Preview or start a read-only Drone knowledge, research, analysis or evidence example",
3022
+ handler: async (args, ctx) => {
3023
+ const parsed = parseExampleArgs(args);
3024
+ const knowledgeStatus = parsed.example === "knowledge" ? await resolveKnowledgeStatus(pi, ctx) : void 0;
3025
+ const report = buildExampleReport(pi, parsed.mode, parsed.question, {
3026
+ example: parsed.example,
3027
+ knowledgeStatus
3028
+ });
3029
+ if (parsed.mode === "run" && report.status === "started" && typeof pi.sendUserMessage === "function") {
3030
+ await pi.sendUserMessage(
3031
+ `Run a read-only Drone ${report.example} example for this question: ${parsed.question}
3032
+ Use local evidence first, preserve source URIs and hashes, and report blocked/unknown states instead of guessing.`,
3033
+ { deliverAs: "followUp", expandPromptTemplates: true }
3034
+ );
3035
+ }
3036
+ emitReport(report, ctx);
3037
+ }
3038
+ });
3039
+ }
3040
+
2821
3041
  // ../shared/src/analysis-orchestration.ts
2822
3042
  var ANALYSIS_STAGES = Object.freeze([
2823
3043
  "intake",
@@ -16954,12 +17174,12 @@ import { stat as stat2 } from "node:fs/promises";
16954
17174
 
16955
17175
  // src/path.ts
16956
17176
  import { homedir as homedir2 } from "node:os";
16957
- import { isAbsolute as isAbsolute5, join, resolve as resolve6 } from "node:path";
17177
+ import { isAbsolute as isAbsolute5, join as join2, resolve as resolve6 } from "node:path";
16958
17178
  var UNICODE_SPACES = /[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF]/g;
16959
17179
  function resolveToolPath(rawPath, cwd, home = homedir2()) {
16960
17180
  let path = rawPath.replace(UNICODE_SPACES, " ");
16961
17181
  if (path === "~") path = home;
16962
- else if (path.startsWith("~/")) path = join(home, path.slice(2));
17182
+ else if (path.startsWith("~/")) path = join2(home, path.slice(2));
16963
17183
  return isAbsolute5(path) ? path : resolve6(cwd, path);
16964
17184
  }
16965
17185
 
@@ -17020,13 +17240,13 @@ function makeDeliverFilesTool() {
17020
17240
  }
17021
17241
 
17022
17242
  // src/memory.ts
17023
- import { mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
17024
- import { join as join2 } from "node:path";
17243
+ import { mkdirSync, readdirSync, readFileSync as readFileSync2, renameSync, rmSync, writeFileSync } from "node:fs";
17244
+ import { join as join3 } from "node:path";
17025
17245
  var MEMORY_TYPES = ["user", "feedback", "project", "reference"];
17026
17246
  var MEMORY_INDEX = "MEMORY.md";
17027
17247
  var MAX_INDEX_LINES = 200;
17028
17248
  function memoryDir(cwd) {
17029
- return join2(cwd, ".pi", "memory");
17249
+ return join3(cwd, ".pi", "memory");
17030
17250
  }
17031
17251
  function memorySlug(name) {
17032
17252
  const slug = name.trim().toLowerCase().replace(/[^\p{L}\p{N}]+/gu, "-").replace(/^-+|-+$/g, "").slice(0, 64);
@@ -17079,7 +17299,7 @@ function listMemories(cwd) {
17079
17299
  }
17080
17300
  const out = [];
17081
17301
  for (const file of files) {
17082
- const entry = parseMemory(readFileSync(join2(dir, file), "utf8"));
17302
+ const entry = parseMemory(readFileSync2(join3(dir, file), "utf8"));
17083
17303
  if (entry) out.push({ ...entry, file });
17084
17304
  }
17085
17305
  return out;
@@ -17088,14 +17308,14 @@ function writeMemory(cwd, entry) {
17088
17308
  const dir = memoryDir(cwd);
17089
17309
  mkdirSync(dir, { recursive: true });
17090
17310
  const file = `${entry.type}_${memorySlug(entry.name)}.md`;
17091
- atomicWrite(join2(dir, file), serializeMemory(entry));
17092
- atomicWrite(join2(dir, MEMORY_INDEX), renderMemoryIndex(listMemories(cwd)));
17311
+ atomicWrite(join3(dir, file), serializeMemory(entry));
17312
+ atomicWrite(join3(dir, MEMORY_INDEX), renderMemoryIndex(listMemories(cwd)));
17093
17313
  return file;
17094
17314
  }
17095
17315
  function memoryIndexPrompt(cwd) {
17096
17316
  let index;
17097
17317
  try {
17098
- index = readFileSync(join2(memoryDir(cwd), MEMORY_INDEX), "utf8");
17318
+ index = readFileSync2(join3(memoryDir(cwd), MEMORY_INDEX), "utf8");
17099
17319
  } catch {
17100
17320
  return [];
17101
17321
  }
@@ -17111,8 +17331,8 @@ ${shown.join("\n")}${lines.length > shown.length ? `
17111
17331
  function forgetMemory(cwd, file) {
17112
17332
  if (!/^[^\\/]+\.md$/.test(file) || file === MEMORY_INDEX) return false;
17113
17333
  if (!listMemories(cwd).some((e) => e.file === file)) return false;
17114
- rmSync(join2(memoryDir(cwd), file));
17115
- atomicWrite(join2(memoryDir(cwd), MEMORY_INDEX), renderMemoryIndex(listMemories(cwd)));
17334
+ rmSync(join3(memoryDir(cwd), file));
17335
+ atomicWrite(join3(memoryDir(cwd), MEMORY_INDEX), renderMemoryIndex(listMemories(cwd)));
17116
17336
  return true;
17117
17337
  }
17118
17338
 
@@ -17381,6 +17601,9 @@ function registerPiCore(pi, options = {}) {
17381
17601
  activeContext = void 0;
17382
17602
  });
17383
17603
  registerTaskRuntime(pi);
17604
+ registerDroneCommands(pi, {
17605
+ hostKind: options.host?.host === "drone-desktop" ? "drone-desktop" : "native-pi"
17606
+ });
17384
17607
  const ask = options.ask || ((request, signal, context) => askWithNativeUi(request, signal, context || activeContext));
17385
17608
  pi.registerTool(makeAskUserTool({ ask }));
17386
17609
  pi.registerTool(makeStatusTool());
@@ -17394,7 +17617,12 @@ function registerPiCore(pi, options = {}) {
17394
17617
  }
17395
17618
  var index_default = registerPiCore;
17396
17619
  export {
17620
+ DRONE_COMMAND_SCHEMA_VERSION,
17397
17621
  MEMORY_SAVE_TOOL,
17622
+ PI_CORE_PACKAGE_VERSION,
17623
+ PI_HOST_RANGE,
17624
+ buildDoctorReport,
17625
+ buildExampleReport,
17398
17626
  createNativePiHostPort,
17399
17627
  index_default as default,
17400
17628
  deliverFilesParams,
@@ -17407,6 +17635,8 @@ export {
17407
17635
  makeTodoTool,
17408
17636
  memoryIndexPrompt,
17409
17637
  normalizeTodos,
17638
+ parseExampleArgs,
17639
+ registerDroneCommands,
17410
17640
  registerPiCore,
17411
17641
  writeMemory
17412
17642
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gyoungwe/pi-core",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
4
  "description": "Portable task, authorization, status, delivery and memory tools for native Pi",
5
5
  "keywords": [
6
6
  "pi-package"
package/package.json CHANGED
@@ -1,46 +1,60 @@
1
1
  {
2
- "name": "@gyoungwe/research-suite",
3
- "version": "0.1.2",
4
- "description": "Bundled Drone native Pi research suite",
5
- "keywords": ["pi-package", "research", "evidence"],
6
- "license": "MIT",
7
- "publishConfig": {"access": "public"},
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/Gyoungwe/drone-plugins.git",
11
- "directory": "packages/research-suite"
12
- },
13
- "type": "module",
14
- "files": ["package.json", "plugin.manifest.json", "README.md", "build-manifest.json", "prompts"],
15
- "scripts": {
16
- "build": "node scripts/build.mjs",
17
- "build:check": "node scripts/build.mjs --check",
18
- "typecheck": "node -e \"process.exit(0)\""
19
- },
20
- "pi": {
21
- "extensions": [
22
- "./node_modules/@gyoungwe/pi-core/dist/index.mjs",
23
- "./node_modules/@gyoungwe/pi-knowledge/dist/index.mjs",
24
- "./node_modules/@gyoungwe/pi-research/dist/index.mjs"
25
- ],
26
- "skills": [
27
- "./node_modules/@gyoungwe/pi-core/skills/*",
28
- "./node_modules/@gyoungwe/pi-knowledge/skills/*",
29
- "./node_modules/@gyoungwe/pi-research/skills/*"
30
- ],
31
- "prompts": ["./prompts/*.md"]
32
- },
33
- "dependencies": {
34
- "@gyoungwe/pi-core": "0.1.0",
35
- "@gyoungwe/pi-knowledge": "0.1.1",
36
- "@gyoungwe/pi-research": "0.1.0"
37
- },
38
- "bundleDependencies": [
39
- "@gyoungwe/pi-core",
40
- "@gyoungwe/pi-knowledge",
41
- "@gyoungwe/pi-research"
42
- ],
43
- "peerDependencies": {
44
- "@earendil-works/pi-coding-agent": ">=1.1.0 <2.0.0"
45
- }
2
+ "name": "@gyoungwe/research-suite",
3
+ "version": "0.1.5",
4
+ "description": "Bundled Drone native Pi research suite",
5
+ "keywords": [
6
+ "pi-package",
7
+ "research",
8
+ "evidence"
9
+ ],
10
+ "license": "MIT",
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/Gyoungwe/drone-plugins.git",
17
+ "directory": "packages/research-suite"
18
+ },
19
+ "type": "module",
20
+ "files": [
21
+ "package.json",
22
+ "plugin.manifest.json",
23
+ "README.md",
24
+ "build-manifest.json",
25
+ "prompts"
26
+ ],
27
+ "scripts": {
28
+ "build": "node scripts/build.mjs",
29
+ "build:check": "node scripts/build.mjs --check",
30
+ "typecheck": "node -e \"process.exit(0)\""
31
+ },
32
+ "pi": {
33
+ "extensions": [
34
+ "./node_modules/@gyoungwe/pi-core/dist/index.mjs",
35
+ "./node_modules/@gyoungwe/pi-knowledge/dist/index.mjs",
36
+ "./node_modules/@gyoungwe/pi-research/dist/index.mjs"
37
+ ],
38
+ "skills": [
39
+ "./node_modules/@gyoungwe/pi-core/skills/*",
40
+ "./node_modules/@gyoungwe/pi-knowledge/skills/*",
41
+ "./node_modules/@gyoungwe/pi-research/skills/*"
42
+ ],
43
+ "prompts": [
44
+ "./prompts/*.md"
45
+ ]
46
+ },
47
+ "dependencies": {
48
+ "@gyoungwe/pi-core": "0.1.3",
49
+ "@gyoungwe/pi-knowledge": "0.1.1",
50
+ "@gyoungwe/pi-research": "0.1.0"
51
+ },
52
+ "bundleDependencies": [
53
+ "@gyoungwe/pi-core",
54
+ "@gyoungwe/pi-knowledge",
55
+ "@gyoungwe/pi-research"
56
+ ],
57
+ "peerDependencies": {
58
+ "@earendil-works/pi-coding-agent": ">=1.1.0 <2.0.0"
59
+ }
46
60
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "id": "drone-research-suite",
4
- "version": "0.1.2",
4
+ "version": "0.1.5",
5
5
  "pi": {
6
6
  "apiVersion": 1,
7
7
  "minHostVersion": "1.1.0",