@dyyz1993/pi-coding-agent 0.69.9 → 0.69.11

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 (39) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/dist/core/agent-session.d.ts +8 -2
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +122 -3
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/extensions/index.d.ts +1 -1
  7. package/dist/core/extensions/index.d.ts.map +1 -1
  8. package/dist/core/extensions/index.js.map +1 -1
  9. package/dist/core/extensions/loader.d.ts.map +1 -1
  10. package/dist/core/extensions/loader.js +5 -0
  11. package/dist/core/extensions/loader.js.map +1 -1
  12. package/dist/core/extensions/runner.d.ts +8 -1
  13. package/dist/core/extensions/runner.d.ts.map +1 -1
  14. package/dist/core/extensions/runner.js +88 -2
  15. package/dist/core/extensions/runner.js.map +1 -1
  16. package/dist/core/extensions/types.d.ts +66 -1
  17. package/dist/core/extensions/types.d.ts.map +1 -1
  18. package/dist/core/extensions/types.js.map +1 -1
  19. package/dist/modes/rpc/rpc-client.d.ts +29 -1
  20. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  21. package/dist/modes/rpc/rpc-client.js +60 -0
  22. package/dist/modes/rpc/rpc-client.js.map +1 -1
  23. package/dist/modes/rpc/rpc-mode.d.ts +1 -1
  24. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  25. package/dist/modes/rpc/rpc-mode.js +123 -0
  26. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  27. package/dist/modes/rpc/rpc-types.d.ts +209 -0
  28. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  29. package/dist/modes/rpc/rpc-types.js.map +1 -1
  30. package/docs/extensions.md +106 -1
  31. package/examples/extensions/README.md +1 -0
  32. package/examples/extensions/auto-session-title.ts +82 -0
  33. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  34. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  35. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  36. package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
  37. package/examples/extensions/with-deps/package-lock.json +2 -2
  38. package/examples/extensions/with-deps/package.json +1 -1
  39. package/package.json +4 -4
@@ -14,7 +14,8 @@
14
14
  */
15
15
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
16
16
  import { basename, dirname, join, resolve } from "node:path";
17
- import { isContextOverflow, modelsAreEqual, resetApiProviders, supportsXhigh } from "@dyyz1993/pi-ai";
17
+ import { Agent, } from "@dyyz1993/pi-agent-core";
18
+ import { complete, isContextOverflow, modelsAreEqual, resetApiProviders, supportsXhigh } from "@dyyz1993/pi-ai";
18
19
  import { getDocsPath } from "../config.js";
19
20
  import { theme } from "../modes/interactive/theme/theme.js";
20
21
  import { stripFrontmatter } from "../utils/frontmatter.js";
@@ -31,7 +32,7 @@ import { CURRENT_SESSION_VERSION, getLatestCompactionEntry } from "./session-man
31
32
  import { createSyntheticSourceInfo } from "./source-info.js";
32
33
  import { buildSystemPrompt } from "./system-prompt.js";
33
34
  import { createLocalBashOperations } from "./tools/bash.js";
34
- import { createAllToolDefinitions } from "./tools/index.js";
35
+ import { createAllToolDefinitions, createTool } from "./tools/index.js";
35
36
  import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
36
37
  /**
37
38
  * Parse a skill block from message text.
@@ -1622,6 +1623,7 @@ export class AgentSession {
1622
1623
  if (bindings.registerChannel !== undefined) {
1623
1624
  this._registerChannel = bindings.registerChannel;
1624
1625
  this._extensionRunner.flushPendingChannels(bindings.registerChannel);
1626
+ this._extensionRunner.updateRegisterChannel(bindings.registerChannel);
1625
1627
  }
1626
1628
  this._applyExtensionBindings(this._extensionRunner);
1627
1629
  await this._extensionRunner.emit(this._sessionStartEvent);
@@ -1728,10 +1730,22 @@ export class AgentSession {
1728
1730
  });
1729
1731
  },
1730
1732
  appendEntry: (customType, data) => {
1731
- this.sessionManager.appendCustomEntry(customType, data);
1733
+ const id = this.sessionManager.appendCustomEntry(customType, data);
1734
+ this._emit({ type: "custom_entry", customType, data, id });
1732
1735
  },
1733
1736
  setSessionName: (name) => {
1737
+ const oldName = this.sessionManager.getSessionName();
1738
+ const trimmed = name.trim();
1739
+ if (oldName === trimmed)
1740
+ return;
1734
1741
  this.sessionManager.appendSessionInfo(name);
1742
+ runner.emit({ type: "session_rename", oldName, newName: trimmed }).catch((err) => {
1743
+ runner.emitError({
1744
+ extensionPath: "<runtime>",
1745
+ event: "session_rename",
1746
+ error: err instanceof Error ? err.message : String(err),
1747
+ });
1748
+ });
1735
1749
  },
1736
1750
  getSessionName: () => {
1737
1751
  return this.sessionManager.getSessionName();
@@ -1756,6 +1770,7 @@ export class AgentSession {
1756
1770
  ((name) => {
1757
1771
  throw new Error(`registerChannel("${name}") is only available in RPC mode`);
1758
1772
  }),
1773
+ callLLM: (options) => this.callLLM(options),
1759
1774
  }, {
1760
1775
  getModel: () => this.model,
1761
1776
  isIdle: () => !this.isStreaming,
@@ -1790,6 +1805,110 @@ export class AgentSession {
1790
1805
  },
1791
1806
  });
1792
1807
  }
1808
+ async callLLM(options) {
1809
+ const model = this.model;
1810
+ if (!model)
1811
+ throw new Error("No model selected");
1812
+ const auth = await this._modelRegistry.getApiKeyAndHeaders(model);
1813
+ if (!auth?.ok) {
1814
+ throw new Error(auth?.error ?? `No API key configured for ${model.provider}`);
1815
+ }
1816
+ if (!auth.apiKey) {
1817
+ throw new Error(`No API key configured for ${model.provider}`);
1818
+ }
1819
+ if (options.signal?.aborted) {
1820
+ throw new Error("Aborted");
1821
+ }
1822
+ const messages = options.messages.map((m) => ({
1823
+ role: m.role,
1824
+ content: [{ type: "text", text: m.content }],
1825
+ timestamp: Date.now(),
1826
+ }));
1827
+ if (!options.tools || options.tools.length === 0) {
1828
+ const context = {
1829
+ systemPrompt: options.systemPrompt,
1830
+ messages,
1831
+ };
1832
+ const response = await complete(model, context, {
1833
+ apiKey: auth.apiKey,
1834
+ headers: auth.headers,
1835
+ maxTokens: options.maxTokens,
1836
+ signal: options.signal,
1837
+ });
1838
+ return response.content
1839
+ .filter((c) => c.type === "text")
1840
+ .map((c) => c.text)
1841
+ .join("\n");
1842
+ }
1843
+ const toolInstances = options.tools
1844
+ .map((name) => {
1845
+ try {
1846
+ const registered = this._toolRegistry.get(name);
1847
+ if (registered)
1848
+ return registered;
1849
+ return createTool(name, this._cwd);
1850
+ }
1851
+ catch {
1852
+ return undefined;
1853
+ }
1854
+ })
1855
+ .filter((t) => t !== undefined);
1856
+ if (toolInstances.length === 0) {
1857
+ const context = {
1858
+ systemPrompt: options.systemPrompt,
1859
+ messages,
1860
+ };
1861
+ const response = await complete(model, context, {
1862
+ apiKey: auth.apiKey,
1863
+ headers: auth.headers,
1864
+ maxTokens: options.maxTokens,
1865
+ signal: options.signal,
1866
+ });
1867
+ return response.content
1868
+ .filter((c) => c.type === "text")
1869
+ .map((c) => c.text)
1870
+ .join("\n");
1871
+ }
1872
+ const agent = new Agent({
1873
+ getApiKey: () => auth.apiKey,
1874
+ initialState: {
1875
+ systemPrompt: options.systemPrompt ?? "",
1876
+ model,
1877
+ thinkingLevel: "off",
1878
+ tools: toolInstances,
1879
+ messages: [],
1880
+ },
1881
+ });
1882
+ if (options.signal?.aborted) {
1883
+ throw new Error("Aborted");
1884
+ }
1885
+ let resultText = "";
1886
+ const unsub = agent.subscribe((event) => {
1887
+ if (event.type === "message_end" && "message" in event) {
1888
+ const msg = event.message;
1889
+ if (msg.role === "assistant") {
1890
+ const content = msg.content;
1891
+ if (Array.isArray(content)) {
1892
+ resultText = content
1893
+ .filter((c) => c.type === "text")
1894
+ .map((c) => c.text)
1895
+ .join("\n");
1896
+ }
1897
+ }
1898
+ }
1899
+ });
1900
+ try {
1901
+ await agent.prompt({
1902
+ role: "user",
1903
+ content: [{ type: "text", text: options.messages[0]?.content ?? "" }],
1904
+ timestamp: Date.now(),
1905
+ });
1906
+ }
1907
+ finally {
1908
+ unsub();
1909
+ }
1910
+ return resultText;
1911
+ }
1793
1912
  _refreshToolRegistry(options) {
1794
1913
  const previousRegistryNames = new Set(this._toolRegistry.keys());
1795
1914
  const previousActiveToolNames = this.getActiveToolNames();