@helpfeel/cosense-cli 1.12.0 → 1.12.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helpfeel/cosense-cli",
3
- "version": "1.12.0",
3
+ "version": "1.12.1",
4
4
  "description": "Cosense (旧Scrapbox) のページを読み・調べ・編集するAgent Skill用のCLI",
5
5
  "homepage": "https://github.com/helpfeel/cosense-cli",
6
6
  "license": "MIT",
@@ -24,13 +24,13 @@
24
24
  "format": "oxfmt"
25
25
  },
26
26
  "dependencies": {
27
- "tsx": "4.23.10"
27
+ "tsx": "4.23.12"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "24.13.3",
31
31
  "npm-run-all": "4.1.5",
32
- "oxfmt": "0.61.0",
33
- "oxlint": "1.76.0",
32
+ "oxfmt": "0.62.0",
33
+ "oxlint": "1.77.0",
34
34
  "typescript": "7.0.2"
35
35
  },
36
36
  "engines": {
package/src/cli.ts CHANGED
@@ -242,7 +242,9 @@ if (command === '--version') {
242
242
  process.exit(0);
243
243
  }
244
244
 
245
- const spec = command ? commands[command] : undefined;
245
+ // cosense constructorやcosense __proto__はObject.prototypeのpropertyを引いてしまう
246
+ const spec =
247
+ command && Object.hasOwn(commands, command) ? commands[command] : undefined;
246
248
  if (!spec) {
247
249
  process.stderr.write(
248
250
  `invalid command${command ? `: ${command}` : ''}\n` +
@@ -20,13 +20,13 @@ Usage:
20
20
  <filePath> アップロードするローカルファイルのパス
21
21
 
22
22
  オプション:
23
- --content-type <type> ファイルのMIME type。省略時は拡張子から推定し、不明な拡張子はapplication/octet-streamになる
23
+ --content-type <type> ファイルのMIME type
24
24
 
25
25
  出力(JSON):
26
- embedUrl string ページ本文への埋め込みに使うファイルURL
27
- originalname string アップロードしたファイル名
28
- contentType string embedUrlが配信するファイルのMIME type
29
- size number ファイルのbyte数
26
+ embedUrl string ページ本文への埋め込みに使うファイルURL
27
+ originalname string アップロードしたファイル名
28
+ contentType string? ファイルのMIME type
29
+ size number ファイルのbyte数
30
30
 
31
31
  例:
32
32
  cosense uploadFile 'https://scrapbox.io/example' ./photo.png
@@ -55,7 +55,7 @@ const parseArgs = (args: string[]): ParsedArgs => {
55
55
  throw new Error(`--content-type specified multiple times\n${usage}`);
56
56
  }
57
57
  const value = args[i + 1];
58
- if (value === undefined || value.startsWith('--')) {
58
+ if (!value || value.startsWith('--')) {
59
59
  throw new Error(`--content-type requires a value\n${usage}`);
60
60
  }
61
61
  contentType = value;
@@ -81,11 +81,11 @@ const parseArgs = (args: string[]): ParsedArgs => {
81
81
  const uploadToSignedUrl = async (
82
82
  url: string,
83
83
  body: Uint8Array,
84
- contentType: string
84
+ contentType: string | undefined
85
85
  ): Promise<void> => {
86
86
  const res = await fetch(url, {
87
87
  method: 'PUT',
88
- headers: { 'Content-Type': contentType },
88
+ headers: contentType ? { 'Content-Type': contentType } : {},
89
89
  body
90
90
  });
91
91
  if (res.ok) {
@@ -149,10 +149,10 @@ export const uploadFile = async (args: string[]): Promise<void> => {
149
149
  let resultContentType = contentType;
150
150
  if (uploadRequest.embedUrl) {
151
151
  // 同一ファイルがアップロード済みの場合、serverはupload-requestで即embedUrlを返す。
152
- // embedUrlが配信するのは保存済みファイルなので、contentTypeはローカル推定よりserver値を優先する
152
+ // embedUrlが配信するのは保存済みファイルなので、ローカル推定の型は当てにならない
153
153
  embedUrl = uploadRequest.embedUrl;
154
154
  originalname = uploadRequest.originalname ?? name;
155
- resultContentType = uploadRequest.contentType ?? contentType;
155
+ resultContentType = uploadRequest.contentType?.trim() || undefined;
156
156
  } else {
157
157
  const { signedUrl, fileId } = uploadRequest;
158
158
  if (!signedUrl || !fileId) {
@@ -1,7 +1,8 @@
1
1
  import { extname } from 'node:path';
2
2
 
3
- // アップロード時に申告するContent-Typeを拡張子から推定する最小マップ。
4
- // 網羅せず、外れる型は--content-typeで上書きしてもらう
3
+ // アップロード時に申告するContent-Typeを拡張子から推定するマップ。網羅はしないが、
4
+ // browsePageが<cosense:file type="...">でファイル種別をAIに伝えられるよう、判明した型は足していく。
5
+ // ここに無い型は--content-typeで上書きしてもらう
5
6
  const MIME_TYPES: Record<string, string> = {
6
7
  png: 'image/png',
7
8
  jpg: 'image/jpeg',
@@ -20,6 +21,13 @@ const MIME_TYPES: Record<string, string> = {
20
21
  weba: 'audio/webm',
21
22
  aac: 'audio/aac',
22
23
  pdf: 'application/pdf',
24
+ docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
25
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
26
+ xlsm: 'application/vnd.ms-excel.sheet.macroEnabled.12',
27
+ pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
28
+ doc: 'application/msword',
29
+ xls: 'application/vnd.ms-excel',
30
+ ppt: 'application/vnd.ms-powerpoint',
23
31
  txt: 'text/plain',
24
32
  md: 'text/markdown',
25
33
  csv: 'text/csv',
@@ -29,7 +37,11 @@ const MIME_TYPES: Record<string, string> = {
29
37
  zip: 'application/zip'
30
38
  };
31
39
 
32
- export const contentTypeForFile = (filePath: string): string => {
40
+ // 推定できない時にapplication/octet-streamを申告しない。octet-streamで申告するとserverが
41
+ // embedUrlから拡張子を落とすため、URLからファイル種別が読み取れなくなり、ページ本文での
42
+ // 埋め込み表示の判定もできなくなる
43
+ export const contentTypeForFile = (filePath: string): string | undefined => {
33
44
  const ext = extname(filePath).slice(1).toLowerCase();
34
- return MIME_TYPES[ext] ?? 'application/octet-stream';
45
+ // a.constructorやa.__proto__はObject.prototypeのpropertyを引いてしまう
46
+ return Object.hasOwn(MIME_TYPES, ext) ? MIME_TYPES[ext] : undefined;
35
47
  };