@pippit-dev/cli 1.0.38 → 1.0.41
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 +84 -1
- package/checksums.txt +6 -6
- package/cmd/auth/auth.go +4 -3
- package/cmd/marketing.go +5 -4
- package/cmd/marketing_test.go +58 -0
- package/cmd/root.go +40 -14
- package/cmd/root_test.go +63 -0
- package/cmd/source_test.go +2 -3
- package/cmd/submit_run_test.go +20 -81
- package/cmd/update/update.go +36 -10
- package/cmd/update/update_test.go +73 -3
- package/dist/checksums.txt +6 -6
- package/dist/xyq-canvas-command-runtime.cjs +14 -14
- package/dist/xyq-canvas-command-runtime.cjs.LEGAL.txt +0 -206
- package/dist/xyq-canvas-command-runtime.cjs.sha256 +2 -2
- package/internal/adapter/adapter.go +73 -0
- package/internal/adapter/ppe.go +36 -0
- package/internal/adaptercli/commands.go +27 -0
- package/internal/adaptercli/commands_test.go +41 -0
- package/internal/auth/manager.go +25 -13
- package/internal/canvas/apply.go +3 -0
- package/internal/canvas/media_identity.go +300 -0
- package/internal/canvas/media_identity_test.go +160 -0
- package/internal/canvas/upload.go +30 -1
- package/internal/commandnames/names.go +9 -0
- package/internal/common/adapter_test.go +74 -0
- package/internal/common/client.go +37 -12
- package/internal/config/config.go +41 -0
- package/internal/config/config_test.go +41 -1
- package/internal/generate_video/generate_video.go +1 -0
- package/internal/generate_video/generate_video_test.go +25 -3
- package/internal/models/models.go +6 -2
- package/internal/models/models_test.go +7 -0
- package/package.json +2 -2
- package/scripts/canvas-command.js +4 -2
- package/skills/short-drama/SKILL.md +7 -4
- package/skills/short-drama/commands/download-result.md +9 -3
- package/skills/short-drama/commands/get-thread.md +2 -0
- package/skills/short-drama/commands/list-thread-file.md +12 -6
- package/skills/short-drama/commands/submit-run.md +3 -1
- package/skills/short-drama/examples/create-and-deliver.md +6 -2
- package/skills/short-drama/examples/reference-and-continue.md +20 -1
- package/skills/short-drama/workflows/creation.md +39 -14
- package/skills/short-drama/workflows/poll-and-deliver.md +27 -9
- package/skills/xyq-nest-skill/commands/canvas-assets.md +9 -1
package/cmd/update/update.go
CHANGED
|
@@ -14,7 +14,9 @@ import (
|
|
|
14
14
|
"sync"
|
|
15
15
|
"time"
|
|
16
16
|
|
|
17
|
+
"github.com/Pippit-dev/pippit-cli/internal/adapter"
|
|
17
18
|
"github.com/Pippit-dev/pippit-cli/internal/auth"
|
|
19
|
+
"github.com/Pippit-dev/pippit-cli/internal/commandnames"
|
|
18
20
|
"github.com/Pippit-dev/pippit-cli/internal/version"
|
|
19
21
|
"github.com/spf13/cobra"
|
|
20
22
|
)
|
|
@@ -38,29 +40,53 @@ var telemetrySkillNames = []string{
|
|
|
38
40
|
"xyq-short-drama-skill",
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
// Each update command instance owns its HTTP client so instances using different adapters do not affect each other.
|
|
44
|
+
type updater struct{ telemetryHTTPClient *http.Client }
|
|
45
|
+
|
|
46
|
+
func newUpdater(policy adapter.HTTPAdapter) *updater {
|
|
47
|
+
return &updater{telemetryHTTPClient: &http.Client{
|
|
48
|
+
Timeout: telemetryWaitTimeout,
|
|
49
|
+
Transport: adapter.HTTPOrDefault(policy).WrapTransport(nil),
|
|
50
|
+
}}
|
|
51
|
+
}
|
|
42
52
|
|
|
43
53
|
// NewCommand builds the update command.
|
|
44
54
|
func NewCommand(stdout, stderr io.Writer) *cobra.Command {
|
|
55
|
+
return NewCommandWithAdapter(stdout, stderr, adapter.Default{})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
func NewCommandWithAdapter(stdout, stderr io.Writer, policy adapter.HTTPAdapter) *cobra.Command {
|
|
59
|
+
updater := newUpdater(policy)
|
|
45
60
|
var source string
|
|
61
|
+
var channel string
|
|
46
62
|
cmd := &cobra.Command{
|
|
47
|
-
Use:
|
|
63
|
+
Use: commandnames.Update,
|
|
48
64
|
Short: "Update pippit-tool-cli and bundled skills",
|
|
49
65
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
50
66
|
if !cmd.Flags().Changed("source") {
|
|
51
67
|
source = os.Getenv("PIPPIT_CLI_SOURCE")
|
|
52
68
|
}
|
|
53
|
-
return runUpdate(stdout, stderr, source)
|
|
69
|
+
return updater.runUpdate(stdout, stderr, source, channel)
|
|
54
70
|
},
|
|
55
71
|
}
|
|
56
72
|
cmd.Flags().StringVar(&source, "source", "", "optional real host identifier reported as host_platform; defaults to PIPPIT_CLI_SOURCE when unset")
|
|
73
|
+
cmd.Flags().StringVar(&channel, "channel", "", "channel for this update only: stable (npm latest) or canary; overrides PIPPIT_CLI_INSTALL_PACKAGE")
|
|
57
74
|
return cmd
|
|
58
75
|
}
|
|
59
76
|
|
|
60
|
-
func runUpdate(stdout, stderr io.Writer,
|
|
77
|
+
func (u *updater) runUpdate(stdout, stderr io.Writer, hostPlatform, channel string) error {
|
|
61
78
|
pkg := os.Getenv("PIPPIT_CLI_INSTALL_PACKAGE")
|
|
62
|
-
|
|
79
|
+
switch channel {
|
|
80
|
+
case "":
|
|
81
|
+
if pkg == "" {
|
|
82
|
+
pkg = defaultPackage + "@latest"
|
|
83
|
+
}
|
|
84
|
+
case "stable":
|
|
63
85
|
pkg = defaultPackage + "@latest"
|
|
86
|
+
case "canary":
|
|
87
|
+
pkg = defaultPackage + "@canary"
|
|
88
|
+
default:
|
|
89
|
+
return fmt.Errorf("不支持的更新渠道 %q,可选值为 stable 或 canary", channel)
|
|
64
90
|
}
|
|
65
91
|
|
|
66
92
|
fmt.Fprintf(stderr, "Updating pippit-tool-cli via npm: %s\n", pkg)
|
|
@@ -83,7 +109,7 @@ func runUpdate(stdout, stderr io.Writer, source string) error {
|
|
|
83
109
|
return fmt.Errorf("更新 pippit-tool-cli skills 失败: %w", err)
|
|
84
110
|
}
|
|
85
111
|
|
|
86
|
-
reportBundledSkillTelemetry("update", "cli_update",
|
|
112
|
+
u.reportBundledSkillTelemetry("update", "cli_update", hostPlatform, stderr)
|
|
87
113
|
fmt.Fprintln(stdout, "pippit-tool-cli and skills updated")
|
|
88
114
|
return nil
|
|
89
115
|
}
|
|
@@ -143,7 +169,7 @@ type telemetryPayload struct {
|
|
|
143
169
|
Arch string `json:"arch"`
|
|
144
170
|
}
|
|
145
171
|
|
|
146
|
-
func reportBundledSkillTelemetry(event, source, hostPlatform string, stderr io.Writer) {
|
|
172
|
+
func (u *updater) reportBundledSkillTelemetry(event, source, hostPlatform string, stderr io.Writer) {
|
|
147
173
|
if os.Getenv("PIPPIT_CLI_DISABLE_TELEMETRY") == "1" {
|
|
148
174
|
return
|
|
149
175
|
}
|
|
@@ -161,7 +187,7 @@ func reportBundledSkillTelemetry(event, source, hostPlatform string, stderr io.W
|
|
|
161
187
|
wg.Add(1)
|
|
162
188
|
go func(payload telemetryPayload) {
|
|
163
189
|
defer wg.Done()
|
|
164
|
-
if err := reportSkillTelemetry(payload); err != nil && os.Getenv("PIPPIT_CLI_DEBUG_TELEMETRY") == "1" {
|
|
190
|
+
if err := u.reportSkillTelemetry(payload); err != nil && os.Getenv("PIPPIT_CLI_DEBUG_TELEMETRY") == "1" {
|
|
165
191
|
fmt.Fprintf(stderr, "[pippit-tool-cli] 埋点上报失败: %v\n", err)
|
|
166
192
|
}
|
|
167
193
|
}(payload)
|
|
@@ -177,7 +203,7 @@ func reportBundledSkillTelemetry(event, source, hostPlatform string, stderr io.W
|
|
|
177
203
|
}
|
|
178
204
|
}
|
|
179
205
|
|
|
180
|
-
func reportSkillTelemetry(payload telemetryPayload) error {
|
|
206
|
+
func (u *updater) reportSkillTelemetry(payload telemetryPayload) error {
|
|
181
207
|
body, err := json.Marshal(payload)
|
|
182
208
|
if err != nil {
|
|
183
209
|
return err
|
|
@@ -190,7 +216,7 @@ func reportSkillTelemetry(payload telemetryPayload) error {
|
|
|
190
216
|
req.Header.Set("Content-Type", "application/json")
|
|
191
217
|
req.Header.Set("Authorization", telemetryAuthHeader)
|
|
192
218
|
|
|
193
|
-
resp, err := telemetryHTTPClient.Do(req)
|
|
219
|
+
resp, err := u.telemetryHTTPClient.Do(req)
|
|
194
220
|
if err != nil {
|
|
195
221
|
return err
|
|
196
222
|
}
|
|
@@ -11,8 +11,78 @@ import (
|
|
|
11
11
|
"strings"
|
|
12
12
|
"testing"
|
|
13
13
|
"time"
|
|
14
|
+
|
|
15
|
+
"github.com/Pippit-dev/pippit-cli/internal/adapter"
|
|
14
16
|
)
|
|
15
17
|
|
|
18
|
+
func TestUpdateCommandSelectsChannel(t *testing.T) {
|
|
19
|
+
if runtime.GOOS == "windows" {
|
|
20
|
+
t.Skip("test uses POSIX shell scripts to stub npm and npx")
|
|
21
|
+
}
|
|
22
|
+
cases := []struct {
|
|
23
|
+
name string
|
|
24
|
+
args []string
|
|
25
|
+
override string
|
|
26
|
+
want string
|
|
27
|
+
wantErr bool
|
|
28
|
+
}{
|
|
29
|
+
{name: "default stable", want: defaultPackage + "@latest"},
|
|
30
|
+
{name: "explicit stable", args: []string{"--channel", "stable"}, want: defaultPackage + "@latest"},
|
|
31
|
+
{name: "explicit canary", args: []string{"--channel", "canary"}, want: defaultPackage + "@canary"},
|
|
32
|
+
{name: "package override preserved", override: defaultPackage + "@1.0.38", want: defaultPackage + "@1.0.38"},
|
|
33
|
+
{name: "stable overrides environment", args: []string{"--channel", "stable"}, override: defaultPackage + "@canary", want: defaultPackage + "@latest"},
|
|
34
|
+
{name: "canary overrides environment", args: []string{"--channel", "canary"}, override: defaultPackage + "@1.0.38", want: defaultPackage + "@canary"},
|
|
35
|
+
{name: "invalid channel", args: []string{"--channel", "beta"}, wantErr: true},
|
|
36
|
+
{name: "invalid channel with override", args: []string{"--channel", "beta"}, override: defaultPackage + "@1.0.38", wantErr: true},
|
|
37
|
+
}
|
|
38
|
+
for _, tc := range cases {
|
|
39
|
+
t.Run(tc.name, func(t *testing.T) {
|
|
40
|
+
binDir := t.TempDir()
|
|
41
|
+
npmRoot := t.TempDir()
|
|
42
|
+
capturePath := filepath.Join(t.TempDir(), "npm-args.txt")
|
|
43
|
+
if err := os.MkdirAll(filepath.Join(npmRoot, "@pippit-dev", "cli", "skills"), 0o755); err != nil {
|
|
44
|
+
t.Fatal(err)
|
|
45
|
+
}
|
|
46
|
+
npmScript := "#!/bin/sh\ncase \"$1\" in\ninstall) printf '%s\\n' \"$@\" > \"$CAPTURE_ARGS\";;\nroot) printf '%s\\n' \"$TEST_NPM_ROOT\";;\n*) exit 1;;\nesac\n"
|
|
47
|
+
for name, script := range map[string]string{"npm": npmScript, "npx": "#!/bin/sh\nexit 0\n"} {
|
|
48
|
+
if err := os.WriteFile(filepath.Join(binDir, name), []byte(script), 0o755); err != nil {
|
|
49
|
+
t.Fatal(err)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
|
|
53
|
+
t.Setenv("HOME", t.TempDir())
|
|
54
|
+
t.Setenv("CAPTURE_ARGS", capturePath)
|
|
55
|
+
t.Setenv("TEST_NPM_ROOT", npmRoot)
|
|
56
|
+
t.Setenv("PIPPIT_CLI_DISABLE_TELEMETRY", "1")
|
|
57
|
+
t.Setenv("PIPPIT_CLI_INSTALL_PACKAGE", tc.override)
|
|
58
|
+
var stdout, stderr bytes.Buffer
|
|
59
|
+
cmd := NewCommand(&stdout, &stderr)
|
|
60
|
+
cmd.SetArgs(append([]string{}, tc.args...))
|
|
61
|
+
err := cmd.Execute()
|
|
62
|
+
if tc.wantErr {
|
|
63
|
+
if err == nil || !strings.Contains(err.Error(), "不支持的更新渠道") {
|
|
64
|
+
t.Fatalf("error = %v, want invalid channel error", err)
|
|
65
|
+
}
|
|
66
|
+
if _, err := os.Stat(capturePath); !os.IsNotExist(err) {
|
|
67
|
+
t.Fatalf("invalid channel invoked npm or stat failed: %v", err)
|
|
68
|
+
}
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
if err != nil {
|
|
72
|
+
t.Fatalf("update failed: %v, stderr: %s", err, stderr.String())
|
|
73
|
+
}
|
|
74
|
+
got, err := os.ReadFile(capturePath)
|
|
75
|
+
if err != nil {
|
|
76
|
+
t.Fatal(err)
|
|
77
|
+
}
|
|
78
|
+
want := strings.Join([]string{"install", "-g", "--prefer-online", "--foreground-scripts", tc.want, ""}, "\n")
|
|
79
|
+
if string(got) != want {
|
|
80
|
+
t.Fatalf("npm args = %q, want %q", got, want)
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
16
86
|
func TestInstallSkillsInstallsAllBundledSkills(t *testing.T) {
|
|
17
87
|
if runtime.GOOS == "windows" {
|
|
18
88
|
t.Skip("test uses a POSIX shell script to stub npx")
|
|
@@ -92,7 +162,7 @@ func TestReportSkillTelemetry(t *testing.T) {
|
|
|
92
162
|
defer server.Close()
|
|
93
163
|
|
|
94
164
|
t.Setenv("PIPPIT_CLI_TELEMETRY_BASE_URL", server.URL+"/")
|
|
95
|
-
err := reportSkillTelemetry(telemetryPayload{
|
|
165
|
+
err := newUpdater(adapter.Default{}).reportSkillTelemetry(telemetryPayload{
|
|
96
166
|
Event: "update",
|
|
97
167
|
SkillName: "xyq-skill",
|
|
98
168
|
Source: "cli_update",
|
|
@@ -121,7 +191,7 @@ func TestReportBundledSkillTelemetryWaitsBriefly(t *testing.T) {
|
|
|
121
191
|
|
|
122
192
|
t.Setenv("PIPPIT_CLI_TELEMETRY_BASE_URL", server.URL)
|
|
123
193
|
start := time.Now()
|
|
124
|
-
reportBundledSkillTelemetry("update", "cli_update", " workbuddy ", &bytes.Buffer{})
|
|
194
|
+
newUpdater(adapter.Default{}).reportBundledSkillTelemetry("update", "cli_update", " workbuddy ", &bytes.Buffer{})
|
|
125
195
|
if elapsed := time.Since(start); elapsed > 1500*time.Millisecond {
|
|
126
196
|
t.Fatalf("reportBundledSkillTelemetry() blocked for %v, want <= 1.5s", elapsed)
|
|
127
197
|
}
|
|
@@ -143,7 +213,7 @@ func TestReportBundledSkillTelemetryReportsBothSkills(t *testing.T) {
|
|
|
143
213
|
defer server.Close()
|
|
144
214
|
|
|
145
215
|
t.Setenv("PIPPIT_CLI_TELEMETRY_BASE_URL", server.URL)
|
|
146
|
-
reportBundledSkillTelemetry("update", "cli_update", " workbuddy ", &bytes.Buffer{})
|
|
216
|
+
newUpdater(adapter.Default{}).reportBundledSkillTelemetry("update", "cli_update", " workbuddy ", &bytes.Buffer{})
|
|
147
217
|
|
|
148
218
|
got := map[string]bool{}
|
|
149
219
|
for i := 0; i < len(telemetrySkillNames); i++ {
|
package/dist/checksums.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
6f7daba79b3423b148e30373bb87e7e8998df3d76be2196e39f84af209f0ea50 pippit-tool-cli-1.0.41-darwin-amd64.tar.gz
|
|
2
|
+
9f03ae01c213a76f45b0dfa110272b45e5b5ecd54b188313c9d256ccbe512980 pippit-tool-cli-1.0.41-darwin-arm64.tar.gz
|
|
3
|
+
ea603412d1c5b0baa42efd34bec92fcd0907333babd64a6e08514d4e2dcb86e5 pippit-tool-cli-1.0.41-linux-amd64.tar.gz
|
|
4
|
+
cebd1f0f34157624c0fc8203eec306bd6c7e31a2db44089f52bca9c74c57ee03 pippit-tool-cli-1.0.41-linux-arm64.tar.gz
|
|
5
|
+
729f413373d185964a42c178a7e0eeafc3fca490670fb753dc36fb38bb47aaf7 pippit-tool-cli-1.0.41-windows-amd64.zip
|
|
6
|
+
b49491ae751e72f994da9388777a43f1b6b5781399dc2da15ced6d74f48dad6d pippit-tool-cli-1.0.41-windows-arm64.zip
|