kiku-agent 1.0.8 → 1.0.9

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
@@ -87,7 +87,7 @@ Automatic installation is available for global npm installs. Source checkouts, l
87
87
 
88
88
  After an update or rollback, restart `kiku-agent` and any application hosting `kiku-mcp`. Update settings and rollback history are stored in the normal Kiku user data directory as `update-state.json`; sessions, memory, `.env`, and YouTube cookies are not modified.
89
89
 
90
- For a local checkout before the package is published, use `npm pack` followed by `npm install -g ./kiku-agent-1.0.8.tgz`.
90
+ For a local checkout before the package is published, use `npm pack` followed by `npm install -g ./kiku-agent-1.0.9.tgz`.
91
91
 
92
92
  ### ✨ Features
93
93
  - **LM Studio Integration**: Connects seamlessly to LM Studio's OpenAI-compatible server at `http://127.0.0.1:1234/v1` (default model `google/gemma-4-e4b`, with auto-detection of loaded models).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kiku-agent",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Kiku AI terminal agent and MCP server for Ju Jingyi knowledge, media, and career data.",
5
5
  "license": "GPL-3.0",
6
6
  "type": "module",
@@ -29,10 +29,10 @@
29
29
  "kikuUpdate": {
30
30
  "channel": "stable",
31
31
  "releaseSummary": [
32
+ "Added graceful 404 error handling for unpublished channels and non-existent version lookups",
33
+ "Enhanced CLI update diagnostics with active release channel switching guidance",
32
34
  "Updated production model defaults and live fallback resolution across cloud providers",
33
- "Hardened REST API key validation and isolated rate-limit probes",
34
- "Fixed discography filtering, MCP configuration isolation, and environment loading order",
35
- "Secured YouTube iframe messaging and expanded provider and API regression coverage"
35
+ "Hardened REST API key validation and isolated rate-limit probes"
36
36
  ],
37
37
  "releaseUrl": "https://www.npmjs.com/package/kiku-agent"
38
38
  },
@@ -1957,12 +1957,16 @@ export const handlers = {
1957
1957
  return 'HANDLED';
1958
1958
  }
1959
1959
  const channel = await manager.setChannel(requested);
1960
+ const lines = [
1961
+ `${C.emerald}[OK] Future /update checks will use ${C.bold}${channel}${C.reset}${C.emerald}.${C.reset}`,
1962
+ ];
1963
+ if (channel !== 'latest') {
1964
+ lines.push(`${C.amber}[NOTE] The "${channel}" channel may not have published builds on npm yet.${C.reset}`);
1965
+ }
1966
+ lines.push(`${C.dim}This changes only the release channel; it does not install anything.${C.reset}`);
1960
1967
  printSolidPanel({
1961
1968
  title: 'Update Channel Changed',
1962
- lines: [
1963
- `${C.emerald}[OK] Future /update checks will use ${C.bold}${channel}${C.reset}${C.emerald}.${C.reset}`,
1964
- `${C.dim}This changes only the release channel; it does not install anything.${C.reset}`,
1965
- ],
1969
+ lines,
1966
1970
  });
1967
1971
  return 'HANDLED';
1968
1972
  }
@@ -2047,12 +2051,16 @@ export const handlers = {
2047
2051
  return 'HANDLED';
2048
2052
  } catch (error) {
2049
2053
  const safeMessage = error instanceof UpdateError ? error.message : 'The update operation failed unexpectedly.';
2054
+ const lines = [
2055
+ `${C.red}[${error.code || 'UPDATE_ERROR'}] ${safeMessage}${C.reset}`,
2056
+ ];
2057
+ if (error.code === 'CHANNEL_NOT_FOUND') {
2058
+ lines.push(`${C.gold}Tip:${C.reset} ${C.white}Run ${C.bold}/update channel latest${C.reset}${C.white} to return to the active release channel.${C.reset}`);
2059
+ }
2060
+ lines.push(`${C.dim}No session, memory, or environment files were changed.${C.reset}`);
2050
2061
  printSolidPanel({
2051
2062
  title: 'Update Failed',
2052
- lines: [
2053
- `${C.red}[${error.code || 'UPDATE_ERROR'}] ${safeMessage}${C.reset}`,
2054
- `${C.dim}No session, memory, or environment files were changed.${C.reset}`,
2055
- ],
2063
+ lines,
2056
2064
  });
2057
2065
  return 'HANDLED';
2058
2066
  }
@@ -24,11 +24,14 @@ export class UpdateError extends Error {
24
24
  }
25
25
 
26
26
  function cleanOutput(value, maxLength = 400) {
27
- return String(value || '')
27
+ const text = String(value || '')
28
28
  .replace(/\x1b(?:\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1b\\))/g, '')
29
29
  .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '')
30
- .trim()
31
- .slice(0, maxLength);
30
+ .split('\n')
31
+ .map(line => line.replace(/^npm\s+(?:error|ERR!)\s*/i, '').trim())
32
+ .filter(Boolean)
33
+ .join(' ');
34
+ return text.slice(0, maxLength);
32
35
  }
33
36
 
34
37
  function parseSemver(value) {
@@ -281,6 +284,21 @@ export class UpdateManager {
281
284
  const spec = `${this.packageName}@${normalizedTarget}`;
282
285
  const result = await this.runner(['view', spec, '--json', '--prefer-online'], { timeoutMs: DEFAULT_TIMEOUT_MS });
283
286
  if (result.code !== 0) {
287
+ const errText = String(result.stderr || '');
288
+ if (/E404|404\s+No match found|No match found for version|not found|404\s+Not\s+Found/i.test(errText)) {
289
+ if (UPDATE_CHANNELS.includes(normalizedTarget)) {
290
+ throw new UpdateError(
291
+ `No release is currently available for channel "${normalizedTarget}" on npm. (Only "latest" is currently published).`,
292
+ 'CHANNEL_NOT_FOUND',
293
+ { target: normalizedTarget, exitCode: result.code }
294
+ );
295
+ }
296
+ throw new UpdateError(
297
+ `Version or tag "${normalizedTarget}" was not found on the npm registry.`,
298
+ 'RELEASE_NOT_FOUND',
299
+ { target: normalizedTarget, exitCode: result.code }
300
+ );
301
+ }
284
302
  throw new UpdateError(
285
303
  cleanOutput(result.stderr) || 'npm could not find the requested release.',
286
304
  'REGISTRY_LOOKUP_FAILED',